package es.uniovi.reflection.patternmining.visitor.statements;

import java.util.ArrayList;
import java.util.List;

import javax.lang.model.element.Modifier;

import com.sun.source.tree.ArrayTypeTree;
import com.sun.source.tree.AssertTree;
import com.sun.source.tree.AssignmentTree;
import com.sun.source.tree.BlockTree;
import com.sun.source.tree.BreakTree;
import com.sun.source.tree.CaseTree;
import com.sun.source.tree.CatchTree;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.CompoundAssignmentTree;
import com.sun.source.tree.ContinueTree;
import com.sun.source.tree.DoWhileLoopTree;
import com.sun.source.tree.EmptyStatementTree;
import com.sun.source.tree.EnhancedForLoopTree;
import com.sun.source.tree.ExpressionStatementTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.ForLoopTree;
import com.sun.source.tree.IfTree;
import com.sun.source.tree.LabeledStatementTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.NewClassTree;
import com.sun.source.tree.ParameterizedTypeTree;
import com.sun.source.tree.PrimitiveTypeTree;
import com.sun.source.tree.ReturnTree;
import com.sun.source.tree.StatementTree;
import com.sun.source.tree.SwitchTree;
import com.sun.source.tree.SynchronizedTree;
import com.sun.source.tree.ThrowTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.TryTree;
import com.sun.source.tree.UnaryTree;
import com.sun.source.tree.VariableTree;
import com.sun.source.tree.WhileLoopTree;
import com.sun.source.util.TreeScanner;
import com.sun.tools.javac.tree.JCTree.JCNewClass;

import es.uniovi.reflection.patternmining.category.ExpressionRole;
import es.uniovi.reflection.patternmining.category.Others;
import es.uniovi.reflection.patternmining.category.StatementCategory;
import es.uniovi.reflection.patternmining.category.StatementRole;
import es.uniovi.reflection.patternmining.category.TypeParent;
import es.uniovi.reflection.patternmining.category.TypeRole;
import es.uniovi.reflection.patternmining.features.ExpressionFeatures;
import es.uniovi.reflection.patternmining.features.StatementFeatures;
import es.uniovi.reflection.patternmining.features.TypeDefFeatures;
import es.uniovi.reflection.patternmining.features.TypeFeatures;
import es.uniovi.reflection.patternmining.model.ReturnFeatures;
import es.uniovi.reflection.patternmining.model.interfaces.StatementChild;
import es.uniovi.reflection.patternmining.util.Util;

public class StatementsVisitor extends TreeScanner<ReturnFeatures, StatementFeatures>{
	
    @Override
    public ReturnFeatures visitBlock(BlockTree blockTree, StatementFeatures statementFeatures) {

    	ReturnFeatures returnFeatures = new ReturnFeatures();
    	List<StatementChild> statementChilds = new ArrayList<StatementChild>(); 
    	List<Long> statementChildIds = new ArrayList<Long>(); 
    	
        for(StatementTree st: blockTree.getStatements()) {
        	StatementFeatures statementFeaturesChild = new StatementFeatures();
        	statementFeaturesChild.setParentId(statementFeatures.getParentId());
        	statementFeaturesChild.setHeight(statementFeatures.getHeight()); // because block it is not considered an statement
        	statementFeaturesChild.setParentNode(statementFeatures.getParentNode());
        	statementFeaturesChild.setParentChild(statementFeatures.getParentChild());
        	statementFeaturesChild.setPackageName(statementFeatures.getPackageName());
        	
        	ReturnFeatures returnAuxFeatures = scan(st, statementFeaturesChild);
        	try {
        		if (statementFeatures.getParentNode() != Others.MethodDefinition) {
            		statementChilds.addAll(returnAuxFeatures.getStatementChild());
            		statementChildIds.addAll(returnAuxFeatures.getStatementChildId());
        		}

        		//Down depth - more depth of desirable
        		if(returnAuxFeatures.getDownDepth() > returnFeatures.getDownDepth()) {
        			returnFeatures.setDepth(returnAuxFeatures.getDownDepth());
        	    }
        		
        		//Update method information
        		returnFeatures.setNumberOfStatements(returnFeatures.getNumberOfStatements() + returnAuxFeatures.getNumberOfStatements());
        		returnFeatures.setMethodLocalVars(returnFeatures.getMethodLocalVars() + returnAuxFeatures.getMethodLocalVars());
        		
        		returnFeatures.setNumberOfInnerTypes(returnFeatures.getNumberOfInnerTypes() + returnAuxFeatures.getNumberOfInnerTypes());
            	returnFeatures.setNumberOfStaticNestedTypes(returnFeatures.getNumberOfStaticNestedTypes() + returnAuxFeatures.getNumberOfStaticNestedTypes());
        		
        	}catch(Exception e) {}
        	
 
        }
        
        returnFeatures.setStatementChild(statementChilds);
        returnFeatures.setStatementChildId(statementChildIds);
        
        //not counts as statement
        return returnFeatures;
    }
    
    // STATEMENTS
    
    @Override
    public ReturnFeatures visitVariable(VariableTree variableTree, StatementFeatures statementFeatures) {
        
    	statementFeatures.setId(Util.getNextNodeId());
    	statementFeatures.setStatementCategory(StatementCategory.VariableDefinition);
    	statementFeatures.setSourceCode(variableTree.toString());
    	
    	ReturnFeatures returnFeatures = new ReturnFeatures();
        
        statementFeatures.setParentChild(statementFeatures.getParentChild());
        ReturnFeatures returnAuxFeatures = scan(variableTree.getModifiers(), statementFeatures);
        Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
    	
    	TypeRole typeRole = TypeRole.VariableType;
    	
    	if (statementFeatures.isParameterType()) {
    		typeRole = TypeRole.ParameterType;
    	}
        
        TypeFeatures typeFeatures = Util.setTypeChildFeatures(statementFeatures, TypeParent.VariableDefinition, typeRole);
        returnAuxFeatures = Util.visitors.getVisitorType().scan(variableTree.getType(), typeFeatures);
        Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
        
        ExpressionFeatures expressionFeatures = Util.setExpressionChildFeatures(statementFeatures, ExpressionRole.VariableDeclarationInit);
    	returnAuxFeatures = Util.visitors.getVisitorExpressions().scan(variableTree.getInitializer(), expressionFeatures);
        Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
    	
        //variable tree
        switch(Util.getNamingCovention(variableTree.getName().toString())) {
			case Camel_Low:
				returnFeatures.setTotalsArrayVariableNaming(0, returnFeatures.getTotalsArrayVariableNaming()[0] + 1);
				break;
			case Camel_Up:
				returnFeatures.setTotalsArrayVariableNaming(1, returnFeatures.getTotalsArrayVariableNaming()[1] + 1);
				break;
			case Lower:
				returnFeatures.setTotalsArrayVariableNaming(2, returnFeatures.getTotalsArrayVariableNaming()[2] + 1);
				break;
			case Snake_Case:
				returnFeatures.setTotalsArrayVariableNaming(3, returnFeatures.getTotalsArrayVariableNaming()[3] + 1);
				break;
			case Upper:
				returnFeatures.setTotalsArrayVariableNaming(4, returnFeatures.getTotalsArrayVariableNaming()[4] + 1);
				break;
			default:
				break;
	    
	    }
        

        try {
			Util.databaseService.insertStatement(statementFeatures);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        
        returnFeatures.setNumberOfStatements(returnFeatures.getNumberOfStatements() + 1); // le digo que yo soy un statements
        returnFeatures.setDepth(statementFeatures.getDepth());
        returnFeatures.setStatementChild(Util.setStatementChild(statementFeatures.getStatementCategory()));
        returnFeatures.setStatementChildId(Util.setStatementChildId(statementFeatures.getId()));
        returnFeatures.setMethodLocalVars(returnFeatures.getMethodLocalVars() + 1);
        return returnFeatures;
    }
    
    public ReturnFeatures visitLabeledStatement(LabeledStatementTree labeledStatementTree, StatementFeatures statementFeatures) {

    	statementFeatures.setId(Util.getNextNodeId());
    	statementFeatures.setStatementCategory(StatementCategory.Label);
    	statementFeatures.setSourceCode(labeledStatementTree.toString());
    	
    	ReturnFeatures returnFeatures = new ReturnFeatures();
    	
        StatementFeatures statementChildFeatures = Util.setStatementChildFeatures(statementFeatures, StatementRole.LabelBodyStatement);
        ReturnFeatures returnAuxFeatures = scan(labeledStatementTree.getStatement(), statementChildFeatures);
        Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
        
        try {
			Util.databaseService.insertStatement(statementFeatures);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        
        returnFeatures.setNumberOfStatements(returnFeatures.getNumberOfStatements() + 1);
        returnFeatures.setDepth(statementFeatures.getDepth());
        returnFeatures.setStatementChild(Util.setStatementChild(statementFeatures.getStatementCategory()));
        returnFeatures.setStatementChildId(Util.setStatementChildId(statementFeatures.getId()));
        return returnFeatures;
	}
    
    @Override
    public ReturnFeatures visitIf(IfTree ifTree, StatementFeatures statementFeatures)  {

    	
    	statementFeatures.setId(Util.getNextNodeId());
    	statementFeatures.setStatementCategory(StatementCategory.If);
    	statementFeatures.setSourceCode(ifTree.getCondition().toString());
        
    	ReturnFeatures returnFeatures = new ReturnFeatures(); 

        ExpressionFeatures expressionFeatures = Util.setExpressionChildFeatures(statementFeatures, ExpressionRole.IfCondition);
    	ReturnFeatures returnAuxFeatures = Util.visitors.getVisitorExpressions().scan(ifTree.getCondition(), expressionFeatures);
    	Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
        
        StatementFeatures statementChildFeatures = Util.setStatementChildFeatures(statementFeatures, StatementRole.IfThenStatement);
        returnAuxFeatures = scan(ifTree.getThenStatement(), statementChildFeatures);
        Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);

        if (ifTree.getElseStatement() != null) {
        	statementChildFeatures = Util.setStatementChildFeatures(statementFeatures, StatementRole.IfElseStatement);
            returnAuxFeatures = scan(ifTree.getElseStatement(), statementChildFeatures);
            Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
        } 
        
        //third child if else (if) exists
        /*try {
        	statementFeatures.setThirdChild(returnAuxFeatures.getStatementChild().get(0));
        	statementFeatures.setThirdChildId(returnAuxFeatures.getStatementChildId().get(0));
        } catch (Exception e) {
        	statementFeatures.setThirdChild(StatementCategory.None);
        }*/
        
        try {
			Util.databaseService.insertStatement(statementFeatures);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

        returnFeatures.setNumberOfStatements(returnFeatures.getNumberOfStatements() + 1);
        returnFeatures.setDepth(statementFeatures.getDepth());
        returnFeatures.setStatementChild(Util.setStatementChild(statementFeatures.getStatementCategory()));
        returnFeatures.setStatementChildId(Util.setStatementChildId(statementFeatures.getId()));
        return returnFeatures;
    }
    
    @Override
    public ReturnFeatures visitReturn(ReturnTree returnTree, StatementFeatures statementFeatures)  {
    	
    	statementFeatures.setId(Util.getNextNodeId());
    	statementFeatures.setStatementCategory(StatementCategory.Return);
    	statementFeatures.setSourceCode(returnTree.toString());
    	
    	ReturnFeatures returnFeatures = new ReturnFeatures(); 
       
    	ExpressionFeatures expressionChildFeatures = Util.setExpressionChildFeatures(statementFeatures, ExpressionRole.ReturnExpression);
    	ReturnFeatures returnAuxFeatures = Util.visitors.getVisitorExpressions().scan(returnTree.getExpression(), expressionChildFeatures);
        Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
        
        try {
			Util.databaseService.insertStatement(statementFeatures);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	
        returnFeatures.setNumberOfStatements(returnFeatures.getNumberOfStatements() + 1);
        returnFeatures.setDepth(statementFeatures.getDepth());
        returnFeatures.setStatementChild(Util.setStatementChild(statementFeatures.getStatementCategory()));
        returnFeatures.setStatementChildId(Util.setStatementChildId(statementFeatures.getId()));
        return returnFeatures;
    }
    
    public ReturnFeatures visitCompoundAssignment(CompoundAssignmentTree compoundAssignmentTree, StatementFeatures statementFeatures) {

    	statementFeatures.setId(Util.getNextNodeId());
    	statementFeatures.setStatementCategory(StatementCategory.CompoundAssignmentStatement);
    	statementFeatures.setSourceCode(compoundAssignmentTree.toString());
		
		ReturnFeatures returnFeatures = new ReturnFeatures(); 
        
		ExpressionFeatures expressionChildFeatures = Util.setExpressionChildFeatures(statementFeatures, ExpressionRole.CompoundAssignmentVariable);
		ReturnFeatures returnAuxFeatures = Util.visitors.getVisitorExpressions().scan(compoundAssignmentTree.getVariable(), expressionChildFeatures);
		Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
        
        
        expressionChildFeatures = Util.setExpressionChildFeatures(statementFeatures, ExpressionRole.CompoundAssignmentExpression);
    	returnAuxFeatures = Util.visitors.getVisitorExpressions().scan(compoundAssignmentTree.getExpression(), expressionChildFeatures);
    	Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
        
        //llamada hijos
        try {
			Util.databaseService.insertStatement(statementFeatures);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

        returnFeatures.setNumberOfStatements(returnFeatures.getNumberOfStatements() + 1);
        returnFeatures.setDepth(statementFeatures.getDepth());
        returnFeatures.setStatementChild(Util.setStatementChild(statementFeatures.getStatementCategory()));
        returnFeatures.setStatementChildId(Util.setStatementChildId(statementFeatures.getId()));
        return returnFeatures;
	}
    
    //special case, not counted as statement or expression
    @Override
    public ReturnFeatures visitExpressionStatement(ExpressionStatementTree expressionStatementTree, StatementFeatures statementFeatures)  {
    	
    	//is the same that the father
    	StatementFeatures statementFeaturesChild = new StatementFeatures();

    	statementFeaturesChild.setParentId(statementFeatures.getParentId());
    	statementFeaturesChild.setParentNode(statementFeatures.getParentNode());
    	statementFeaturesChild.setParentChild(statementFeatures.getParentChild());
    	statementFeaturesChild.setHeight(statementFeatures.getHeight());
        
        ReturnFeatures returnFeatures = scan(expressionStatementTree.getExpression(), statementFeaturesChild); 
        return returnFeatures;
    }
    
	@Override
    public ReturnFeatures visitUnary(UnaryTree unaryTree, StatementFeatures statementFeatures)  {
        
		statementFeatures.setId(Util.getNextNodeId());
		statementFeatures.setStatementCategory(StatementCategory.valueOf(Util.getUnaryKind(unaryTree.getKind().toString())+"Statement"));
		statementFeatures.setSourceCode(unaryTree.toString());
		
		ReturnFeatures returnFeatures = new ReturnFeatures(); 
        
		ExpressionFeatures expressionChildFeatures = Util.setExpressionChildFeatures(statementFeatures, ExpressionRole.UnaryEncloses);
		ReturnFeatures returnAuxFeatures = Util.visitors.getVisitorExpressions().scan(unaryTree.getExpression(), expressionChildFeatures);
		Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
        
        try {
			Util.databaseService.insertStatement(statementFeatures);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

        returnFeatures.setNumberOfStatements(returnFeatures.getNumberOfStatements() + 1);
        returnFeatures.setDepth(returnFeatures.getDownDepth() + 1);
        returnFeatures.setStatementChild(Util.setStatementChild(statementFeatures.getStatementCategory()));
        returnFeatures.setStatementChildId(Util.setStatementChildId(statementFeatures.getId()));
        return returnFeatures;
    }
	
	@Override
    public ReturnFeatures visitNewClass(NewClassTree newClassTree, StatementFeatures statementFeatures)  {
        
		statementFeatures.setId(Util.getNextNodeId());
		statementFeatures.setStatementCategory(StatementCategory.NewClassStatement);
		statementFeatures.setSourceCode(newClassTree.toString());
		
		ReturnFeatures returnFeatures = new ReturnFeatures(); 
        
        ExpressionFeatures expressionChildFeatures = Util.setExpressionChildFeatures(statementFeatures, ExpressionRole.NewClassEnclosingExpression);
        ReturnFeatures returnAuxFeatures = Util.visitors.getVisitorExpressions().scan(newClassTree.getEnclosingExpression(), expressionChildFeatures);
        Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
       
        TypeFeatures typeFeatures = Util.setTypeChildFeatures(statementFeatures, TypeParent.NewClassStatement, TypeRole.NewClassType);
        returnAuxFeatures = Util.visitors.getVisitorType().scan(newClassTree.getIdentifier(), typeFeatures);
        Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
        
        for(ExpressionTree exp: newClassTree.getArguments()) {
    		expressionChildFeatures = Util.setExpressionChildFeatures(statementFeatures, ExpressionRole.NewClassArguments);
        	returnAuxFeatures = Util.visitors.getVisitorExpressions().scan(exp, expressionChildFeatures);
        	Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
        } 
      		
        try {
        	statementFeatures.setParentChild(StatementRole.NewClassBody);
			returnAuxFeatures = scan(newClassTree.getClassBody(), statementFeatures);
			Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
			//returnFeatures.setInnerClasses(expressionFeatures.getInnerClasses() + returnFeatures.getInnerClasses());
        }catch(Exception e) {}
        
        try {
			Util.databaseService.insertStatement(statementFeatures);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

        returnFeatures.setNumberOfStatements(returnFeatures.getNumberOfStatements() + 1);
        returnFeatures.setDepth(returnFeatures.getDownDepth() + 1);
        returnFeatures.setStatementChild(Util.setStatementChild(statementFeatures.getStatementCategory()));
        returnFeatures.setStatementChildId(Util.setStatementChildId(statementFeatures.getId()));
        return returnFeatures;
    }
    
    @Override
    public ReturnFeatures visitForLoop(ForLoopTree forLoopTree, StatementFeatures statementFeatures)  {
        
    	statementFeatures.setId(Util.getNextNodeId());
    	statementFeatures.setStatementCategory(StatementCategory.ForLoop);
    	
    	if (forLoopTree.getStatement().toString().charAt(0) == '{') {
    		statementFeatures.setSourceCode(Util.getNodeSourceCode(forLoopTree.toString()));
    	} else {
    		int statementCode = forLoopTree.toString().indexOf(forLoopTree.getStatement().toString());
    		statementFeatures.setSourceCode(forLoopTree.toString().substring(0, statementCode));
    	}
    	
    	ReturnFeatures returnFeatures = new ReturnFeatures(); 
        
        StatementFeatures statementChildFeatures = Util.setStatementChildFeatures(statementFeatures, StatementRole.ForLoopInit);
        ReturnFeatures returnAuxFeatures = scan(forLoopTree.getInitializer(), statementChildFeatures);
        Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
        
    	ExpressionFeatures expressionFeatures = Util.setExpressionChildFeatures(statementFeatures, ExpressionRole.ForLoopCondition);
    	returnAuxFeatures = Util.visitors.getVisitorExpressions().scan(forLoopTree.getCondition(), expressionFeatures);
        Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
		
        statementChildFeatures = Util.setStatementChildFeatures(statementFeatures, StatementRole.ForLoopUpdate);
		returnAuxFeatures =scan(forLoopTree.getUpdate(), statementChildFeatures);
		Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
		
		statementChildFeatures = Util.setStatementChildFeatures(statementFeatures, StatementRole.ForLoopBodyStatement);
		returnAuxFeatures = scan(forLoopTree.getStatement(), statementChildFeatures);
		Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
        
        try {
			Util.databaseService.insertStatement(statementFeatures);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	
        returnFeatures.setNumberOfStatements(returnFeatures.getNumberOfStatements() + 1);
        returnFeatures.setDepth(statementFeatures.getDepth());
        returnFeatures.setStatementChild(Util.setStatementChild(statementFeatures.getStatementCategory()));
        returnFeatures.setStatementChildId(Util.setStatementChildId(statementFeatures.getId()));
        return returnFeatures;
    }
    
    @Override
    public ReturnFeatures visitWhileLoop(WhileLoopTree whileLoopTree, StatementFeatures statementFeatures)  {
    	
    	statementFeatures.setId(Util.getNextNodeId());
    	statementFeatures.setStatementCategory(StatementCategory.WhileLoop);
    	statementFeatures.setSourceCode(whileLoopTree.getCondition().toString());
    	
    	ReturnFeatures returnFeatures = new ReturnFeatures(); 
        
    	
    	ExpressionFeatures expressionFeatures = Util.setExpressionChildFeatures(statementFeatures, ExpressionRole.WhileCondition);
    	ReturnFeatures returnAuxFeatures = Util.visitors.getVisitorExpressions().scan(whileLoopTree.getCondition(), expressionFeatures);
    	Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
    	                
        StatementFeatures statementChildFeatures = Util.setStatementChildFeatures(statementFeatures, StatementRole.WhileBodyStatement);
        returnAuxFeatures = scan(whileLoopTree.getStatement(), statementChildFeatures);
        Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
        
        try {
			Util.databaseService.insertStatement(statementFeatures);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	
        returnFeatures.setNumberOfStatements(returnFeatures.getNumberOfStatements() + 1);
        returnFeatures.setDepth(statementFeatures.getDepth());
        returnFeatures.setStatementChild(Util.setStatementChild(statementFeatures.getStatementCategory()));
        returnFeatures.setStatementChildId(Util.setStatementChildId(statementFeatures.getId()));
        return returnFeatures;
    }
    
    @Override
    public ReturnFeatures visitTry(TryTree tryTree, StatementFeatures statementFeatures)  {
        
    	statementFeatures.setId(Util.getNextNodeId());
    	statementFeatures.setStatementCategory(StatementCategory.Try);
    	statementFeatures.setSourceCode(Util.getNodeSourceCode(tryTree.toString()));
    	
    	ReturnFeatures returnFeatures = new ReturnFeatures(); 
        
    	StatementFeatures statementChildFeatures = Util.setStatementChildFeatures(statementFeatures, StatementRole.TryResource);
        ReturnFeatures returnAuxFeatures = scan(tryTree.getResources(), statementChildFeatures);
        Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
        
        statementChildFeatures = Util.setStatementChildFeatures(statementFeatures, StatementRole.TryBodyStatement);
        returnAuxFeatures = scan(tryTree.getBlock(), statementChildFeatures);
        Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
		
        statementChildFeatures = Util.setStatementChildFeatures(statementFeatures, StatementRole.CatchStatement);
		returnAuxFeatures = scan(tryTree.getCatches(), statementChildFeatures);
		Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
		
		statementChildFeatures = Util.setStatementChildFeatures(statementFeatures, StatementRole.FinallyBodyStatement);
		returnAuxFeatures = scan(tryTree.getFinallyBlock(), statementChildFeatures);
		Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
        
        try {
			Util.databaseService.insertStatement(statementFeatures);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        
        List<StatementChild> statementChilds = new ArrayList<StatementChild>(); 
    	statementChilds.add(statementFeatures.getStatementCategory());
    	List<Long> statementChildIds = new ArrayList<Long>(); 
		statementChildIds.add(statementFeatures.getId());

        returnFeatures.setNumberOfStatements(returnFeatures.getNumberOfStatements() + 1);
        returnFeatures.setDepth(statementFeatures.getDepth());
        returnFeatures.setStatementChild(statementChilds);
        returnFeatures.setStatementChildId(statementChildIds);
        return returnFeatures;
    }
    
    public ReturnFeatures visitCatch(CatchTree catchTree, StatementFeatures statementFeatures) {
    	
    	statementFeatures.setId(Util.getNextNodeId());
    	statementFeatures.setStatementCategory(StatementCategory.Catch);
    	statementFeatures.setSourceCode(catchTree.getParameter().toString());
    	
    	ReturnFeatures returnFeatures = new ReturnFeatures(); 
                
    	StatementFeatures statementChildFeatures = Util.setStatementChildFeatures(statementFeatures, StatementRole.CatchParameters);
    	ReturnFeatures returnAuxFeatures = scan(catchTree.getParameter(), statementChildFeatures);
    	Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
		
    	statementChildFeatures = Util.setStatementChildFeatures(statementFeatures, StatementRole.CatchBodyStatement);
		returnAuxFeatures = scan(catchTree.getBlock(), statementChildFeatures);
		Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
	        
        try {
			Util.databaseService.insertStatement(statementFeatures);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

        returnFeatures.setNumberOfStatements(returnFeatures.getNumberOfStatements() + 1);
        returnFeatures.setDepth(statementFeatures.getDepth());
        returnFeatures.setStatementChild(Util.setStatementChild(statementFeatures.getStatementCategory()));
        returnFeatures.setStatementChildId(Util.setStatementChildId(statementFeatures.getId()));
		return returnFeatures;
	}
    
    @Override
    public ReturnFeatures visitEnhancedForLoop(EnhancedForLoopTree enhancedForLoopTree, StatementFeatures statementFeatures)  {
        
    	statementFeatures.setId(Util.getNextNodeId());
    	statementFeatures.setStatementCategory(StatementCategory.EnhancedForLoop);
    	
    	if (enhancedForLoopTree.getStatement().toString().charAt(0) == '{') {
    		statementFeatures.setSourceCode(Util.getNodeSourceCode(enhancedForLoopTree.toString()));
    	} else {
    		int statementCode = enhancedForLoopTree.toString().indexOf(enhancedForLoopTree.getStatement().toString());
    		statementFeatures.setSourceCode(enhancedForLoopTree.toString().substring(0, statementCode));
    	}
    	
    	ReturnFeatures returnFeatures = new ReturnFeatures(); 
        
    	StatementFeatures statementChildFeatures = Util.setStatementChildFeatures(statementFeatures, StatementRole.EnhancedForLoopVariable);
        ReturnFeatures returnAuxFeatures = scan(enhancedForLoopTree.getVariable(), statementChildFeatures);
        Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
 
        ExpressionFeatures expressionChildFeatures = Util.setExpressionChildFeatures(statementFeatures, ExpressionRole.EnhancedForLoopExpression);
    	returnAuxFeatures = Util.visitors.getVisitorExpressions().scan(enhancedForLoopTree.getExpression(), expressionChildFeatures);
    	Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
        
        statementChildFeatures = Util.setStatementChildFeatures(statementFeatures, StatementRole.EnhancedForLoopBodyStatement);
		returnAuxFeatures = scan(enhancedForLoopTree.getStatement(), statementChildFeatures);
		Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);

        try {
			Util.databaseService.insertStatement(statementFeatures);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        
        List<StatementChild> statementChilds = new ArrayList<StatementChild>(); 
    	statementChilds.add(statementFeatures.getStatementCategory());
    	List<Long> statementChildIds = new ArrayList<Long>(); 
		statementChildIds.add(statementFeatures.getId());

        returnFeatures.setNumberOfStatements(returnFeatures.getNumberOfStatements() + 1);
        returnFeatures.setDepth(statementFeatures.getDepth());
        returnFeatures.setStatementChild(statementChilds);
        returnFeatures.setStatementChildId(statementChildIds);
        return returnFeatures;
    }
    
    @Override
    public ReturnFeatures visitSwitch(SwitchTree switchTree, StatementFeatures statementFeatures)  {       
        
    	statementFeatures.setId(Util.getNextNodeId());
    	statementFeatures.setStatementCategory(StatementCategory.Switch); 
    	statementFeatures.setSourceCode(Util.getNodeSourceCode(switchTree.toString()));
    	
    	ReturnFeatures returnFeatures = new ReturnFeatures(); 
        
        ExpressionFeatures expressionChildFeatures = Util.setExpressionChildFeatures(statementFeatures, ExpressionRole.SwitchExpression);
    	ReturnFeatures returnAuxFeatures = Util.visitors.getVisitorExpressions().scan(switchTree.getExpression(), expressionChildFeatures);
    	Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);

    	for(CaseTree st: switchTree.getCases()) {
    		StatementFeatures statementChildFeatures = Util.setStatementChildFeatures(statementFeatures, StatementRole.SwitchCaseStatement);
            returnAuxFeatures=st.accept(this, statementChildFeatures);
            Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
    	}
    	
        try {
			Util.databaseService.insertStatement(statementFeatures);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

        returnFeatures.setNumberOfStatements(returnFeatures.getNumberOfStatements() + 1);
        returnFeatures.setDepth(statementFeatures.getDepth());
        returnFeatures.setStatementChild(Util.setStatementChild(statementFeatures.getStatementCategory()));
        returnFeatures.setStatementChildId(Util.setStatementChildId(statementFeatures.getId()));
        return returnFeatures;
    }
    
    public ReturnFeatures visitCase(CaseTree caseTree, StatementFeatures statementFeatures) {

    	statementFeatures.setId(Util.getNextNodeId());
    	statementFeatures.setStatementCategory(StatementCategory.Case); 
    	statementFeatures.setSourceCode(caseTree.toString().substring(0, caseTree.toString().indexOf(":")));
    	
    	ReturnFeatures returnFeatures = new ReturnFeatures(); 
    	
    	ExpressionFeatures expressionChildFeatures = Util.setExpressionChildFeatures(statementFeatures, ExpressionRole.SwitchCaseExpression);
    	ReturnFeatures returnAuxFeatures = Util.visitors.getVisitorExpressions().scan(caseTree.getExpression(), expressionChildFeatures);
    	Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
    	
    	for(StatementTree st: caseTree.getStatements()) {
    		StatementFeatures statementChildFeatures = Util.setStatementChildFeatures(statementFeatures, StatementRole.SwitchCaseStatement);
    		returnAuxFeatures=st.accept(this, statementChildFeatures);
            Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
    	}
    	
    	try {
			Util.databaseService.insertStatement(statementFeatures);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	
        returnFeatures.setNumberOfStatements(returnFeatures.getNumberOfStatements() + 1);
        returnFeatures.setDepth(statementFeatures.getDepth());
        returnFeatures.setStatementChild(Util.setStatementChild(statementFeatures.getStatementCategory()));
        returnFeatures.setStatementChildId(Util.setStatementChildId(statementFeatures.getId()));
        return returnFeatures;
	}
    
    @Override
    public ReturnFeatures visitContinue(ContinueTree continueTree, StatementFeatures statementFeatures)  {

    	statementFeatures.setId(Util.getNextNodeId());
    	statementFeatures.setStatementCategory(StatementCategory.Continue);
    	statementFeatures.setSourceCode(continueTree.toString());
    	
    	ReturnFeatures returnFeatures = new ReturnFeatures(); 
        
    	//no childs
        
        try {
			Util.databaseService.insertStatement(statementFeatures);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

        returnFeatures.setNumberOfStatements(returnFeatures.getNumberOfStatements() + 1);
        returnFeatures.setDepth(statementFeatures.getDepth());
        returnFeatures.setStatementChild(Util.setStatementChild(statementFeatures.getStatementCategory()));
        returnFeatures.setStatementChildId(Util.setStatementChildId(statementFeatures.getId()));
        return returnFeatures;
    }
    
    @Override
    public ReturnFeatures visitBreak(BreakTree breakTree, StatementFeatures statementFeatures)  {
    	
    	statementFeatures.setId(Util.getNextNodeId());
    	statementFeatures.setStatementCategory(StatementCategory.Break);
    	statementFeatures.setSourceCode(Util.getNodeSourceCode(breakTree.toString()));
    	
    	ReturnFeatures returnFeatures = new ReturnFeatures(); 
    	
    	//no childs
        
        try {
			Util.databaseService.insertStatement(statementFeatures);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

        returnFeatures.setNumberOfStatements(returnFeatures.getNumberOfStatements() + 1);
        returnFeatures.setDepth(statementFeatures.getDepth());
        returnFeatures.setStatementChild(Util.setStatementChild(statementFeatures.getStatementCategory()));
        returnFeatures.setStatementChildId(Util.setStatementChildId(statementFeatures.getId()));
        return returnFeatures;
    }

    @Override
    public ReturnFeatures visitThrow(ThrowTree throwTree, StatementFeatures statementFeatures)  {
        
    	statementFeatures.setId(Util.getNextNodeId());
    	statementFeatures.setStatementCategory(StatementCategory.Throw);
    	statementFeatures.setSourceCode(Util.getNodeSourceCode(throwTree.toString()));
    	
    	ReturnFeatures returnFeatures = new ReturnFeatures(); 
        
        ExpressionFeatures expressionChildFeatures = Util.setExpressionChildFeatures(statementFeatures, ExpressionRole.ThrowExpression);
    	ReturnFeatures returnAuxFeatures = Util.visitors.getVisitorExpressions().scan(throwTree.getExpression(), expressionChildFeatures);
    	Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
        
        try {
			Util.databaseService.insertStatement(statementFeatures);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        
        returnFeatures.setNumberOfStatements(returnFeatures.getNumberOfStatements() + 1);
        returnFeatures.setDepth(statementFeatures.getDepth());
        returnFeatures.setStatementChild(Util.setStatementChild(statementFeatures.getStatementCategory()));
        returnFeatures.setStatementChildId(Util.setStatementChildId(statementFeatures.getId()));
        return returnFeatures;
    }
    
    @Override
    public ReturnFeatures visitAssert(AssertTree assertTree, StatementFeatures statementFeatures)  {
     
    	statementFeatures.setId(Util.getNextNodeId());
    	statementFeatures.setStatementCategory(StatementCategory.Assert);
    	statementFeatures.setSourceCode(Util.getNodeSourceCode(assertTree.toString()));
    	
    	ReturnFeatures returnFeatures = new ReturnFeatures(); 
    	
    	ExpressionFeatures expressionChildFeatures = Util.setExpressionChildFeatures(statementFeatures, ExpressionRole.AssertCondition);
    	ReturnFeatures returnAuxFeatures = Util.visitors.getVisitorExpressions().scan(assertTree.getCondition(), expressionChildFeatures);
    	Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
    	
    	expressionChildFeatures = Util.setExpressionChildFeatures(statementFeatures, ExpressionRole.AssertDetail);
    	returnAuxFeatures = Util.visitors.getVisitorExpressions().scan(assertTree.getDetail(), expressionChildFeatures);
    	Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);

        
        try {
			Util.databaseService.insertStatement(statementFeatures);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	
        returnFeatures.setNumberOfStatements(returnFeatures.getNumberOfStatements() + 1);
        returnFeatures.setDepth(statementFeatures.getDepth());
        returnFeatures.setStatementChild(Util.setStatementChild(statementFeatures.getStatementCategory()));
        returnFeatures.setStatementChildId(Util.setStatementChildId(statementFeatures.getId()));
        return returnFeatures;
    }
    
    @Override
    public ReturnFeatures visitDoWhileLoop(DoWhileLoopTree doWhileLoopTree, StatementFeatures statementFeatures)  {
        
    	statementFeatures.setId(Util.getNextNodeId());
    	statementFeatures.setStatementCategory(StatementCategory.DoWhileLoop);
    	statementFeatures.setSourceCode(doWhileLoopTree.getCondition().toString());
    	
    	
    	ReturnFeatures returnFeatures = new ReturnFeatures(); 
        
    	
    	ExpressionFeatures expressionFeatures = Util.setExpressionChildFeatures(statementFeatures, ExpressionRole.DoWhileCondition);
    	ReturnFeatures returnAuxFeatures = Util.visitors.getVisitorExpressions().scan(doWhileLoopTree.getCondition(), expressionFeatures);
    	Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
    	                
        StatementFeatures statementChildFeatures = Util.setStatementChildFeatures(statementFeatures, StatementRole.DoWhileBodyStatement);
        returnAuxFeatures = scan(doWhileLoopTree.getStatement(), statementChildFeatures);
        Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
        
        try {    	
			Util.databaseService.insertStatement(statementFeatures);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

        returnFeatures.setNumberOfStatements(returnFeatures.getNumberOfStatements() + 1);
        returnFeatures.setDepth(statementFeatures.getDepth());
        returnFeatures.setStatementChild(Util.setStatementChild(statementFeatures.getStatementCategory()));
        returnFeatures.setStatementChildId(Util.setStatementChildId(statementFeatures.getId()));
        return returnFeatures;
    }
    
    @Override
    public ReturnFeatures visitSynchronized(SynchronizedTree synchronizedTree, StatementFeatures statementFeatures)  {
        
    	statementFeatures.setId(Util.getNextNodeId());
    	statementFeatures.setStatementCategory(StatementCategory.Synchronized);
    	statementFeatures.setSourceCode(Util.getNodeSourceCode(synchronizedTree.toString()));
    	
    	ReturnFeatures returnFeatures = new ReturnFeatures(); 
        
        ExpressionFeatures expressionChildFeatures = Util.setExpressionChildFeatures(statementFeatures, ExpressionRole.SynchronizedExpression);
    	ReturnFeatures returnAuxFeatures = Util.visitors.getVisitorExpressions().scan(synchronizedTree.getExpression(), expressionChildFeatures);
    	Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
    	
        
        StatementFeatures statementChildFeatures = Util.setStatementChildFeatures(statementFeatures, StatementRole.SynchronizedBodyStatement);
		returnAuxFeatures = scan(synchronizedTree.getBlock(), statementChildFeatures);
		Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
        
        try {
			Util.databaseService.insertStatement(statementFeatures);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

        returnFeatures.setNumberOfStatements(returnFeatures.getNumberOfStatements() + 1);
        returnFeatures.setDepth(statementFeatures.getDepth());
        returnFeatures.setStatementChild(Util.setStatementChild(statementFeatures.getStatementCategory()));
        returnFeatures.setStatementChildId(Util.setStatementChildId(statementFeatures.getId()));
        return returnFeatures;
    }
    
    @Override
    public ReturnFeatures visitEmptyStatement(EmptyStatementTree emptyStatementTree, StatementFeatures statementFeatures) {

    	statementFeatures.setId(Util.getNextNodeId());
    	statementFeatures.setStatementCategory(StatementCategory.EmptyStatement);
    	statementFeatures.setSourceCode(Util.getNodeSourceCode(emptyStatementTree.toString()));
    	
    	ReturnFeatures returnFeatures = new ReturnFeatures(); 
        
        //no childs
        
        try {
			Util.databaseService.insertStatement(statementFeatures);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

        returnFeatures.setNumberOfStatements(returnFeatures.getNumberOfStatements() + 1);
        returnFeatures.setDepth(returnFeatures.getDownDepth() + 1);
        returnFeatures.setStatementChild(Util.setStatementChild(statementFeatures.getStatementCategory()));
        returnFeatures.setStatementChildId(Util.setStatementChildId(statementFeatures.getId()));
        return returnFeatures;
    }
    
	@Override
    public ReturnFeatures visitMethodInvocation(MethodInvocationTree methodInvocationTree, StatementFeatures statementFeatures)  {
        
		statementFeatures.setId(Util.getNextNodeId());
		statementFeatures.setStatementCategory(StatementCategory.MethodInvocationStatement);
		statementFeatures.setSourceCode(methodInvocationTree.toString());
		
		ReturnFeatures returnFeatures = new ReturnFeatures(); 
		
		ExpressionFeatures expressionChildFeatures = Util.setExpressionChildFeatures(statementFeatures, ExpressionRole.MethodInvocationMethodSelect);
    	ReturnFeatures returnAuxFeatures = Util.visitors.getVisitorExpressions().scan(methodInvocationTree.getMethodSelect(), expressionChildFeatures);
    	Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
    	
    	for(ExpressionTree exp: methodInvocationTree.getArguments()) {
    		expressionChildFeatures = Util.setExpressionChildFeatures(statementFeatures, ExpressionRole.MethodInvocationArguments);
        	returnAuxFeatures = Util.visitors.getVisitorExpressions().scan(exp, expressionChildFeatures);
        	Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
        }
    	
    	for(Tree typeArg: methodInvocationTree.getTypeArguments()) {
        	TypeFeatures typeFeatures = Util.setTypeChildFeatures(statementFeatures, TypeParent.MethodInvocationStatement, TypeRole.MethodInvocationTypeArgument);    		
        	returnAuxFeatures = Util.visitors.getVisitorType().scan(typeArg, typeFeatures);
        	Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
        }

        try {
			Util.databaseService.insertStatement(statementFeatures);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

        returnFeatures.setNumberOfStatements(returnFeatures.getNumberOfStatements() + 1);
        returnFeatures.setDepth(statementFeatures.getDepth());
        returnFeatures.setStatementChild(Util.setStatementChild(statementFeatures.getStatementCategory()));
        returnFeatures.setStatementChildId(Util.setStatementChildId(statementFeatures.getId()));
        return returnFeatures;
    }
	
	@Override
    public ReturnFeatures visitAssignment(AssignmentTree assignmentTree, StatementFeatures statementFeatures) {
        
		statementFeatures.setId(Util.getNextNodeId());
		statementFeatures.setStatementCategory(StatementCategory.AssignmentStatement);
		statementFeatures.setSourceCode(assignmentTree.toString());
		
		ReturnFeatures returnFeatures = new ReturnFeatures(); 
		
		ExpressionFeatures expressionChildFeatures = Util.setExpressionChildFeatures(statementFeatures, ExpressionRole.AssigmentLHS);
        ReturnFeatures returnAuxFeatures = Util.visitors.getVisitorExpressions().scan(assignmentTree.getVariable(), expressionChildFeatures);
        Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);

		
        expressionChildFeatures = Util.setExpressionChildFeatures(statementFeatures, ExpressionRole.AssigmentRHS);
    	returnAuxFeatures =  Util.visitors.getVisitorExpressions().scan(assignmentTree.getExpression(), expressionChildFeatures);
    	Util.updateStatementFeatures(statementFeatures, returnFeatures, returnAuxFeatures);
	       
        try {
			Util.databaseService.insertStatement(statementFeatures);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

        returnFeatures.setNumberOfStatements(returnFeatures.getNumberOfStatements() + 1);
        returnFeatures.setDepth(statementFeatures.getDepth());
        returnFeatures.setStatementChild(Util.setStatementChild(statementFeatures.getStatementCategory()));
        returnFeatures.setStatementChildId(Util.setStatementChildId(statementFeatures.getId()));
        return returnFeatures;
    }
    
	//Tree kind
    
    @Override
    public ReturnFeatures visitParameterizedType(ParameterizedTypeTree parameterizedTypeTree, StatementFeatures statementFeatures) {
    	
    	//generic
        
        TypeFeatures typeFeatures = new TypeFeatures();
		typeFeatures.setParentId(statementFeatures.getId());
		typeFeatures.setParentNode(TypeParent.VariableDefinition);
		typeFeatures.setParentChild(TypeRole.VariableType);
		typeFeatures.setHeight(statementFeatures.getDepth());
		
		ReturnFeatures returnFeatures = Util.visitors.getVisitorType().visitParameterizedType(parameterizedTypeTree, typeFeatures); 
        
        returnFeatures = new ReturnFeatures();
        //returnFeatures.setNodeType(NodeASTTypes.Generic);
        return returnFeatures;
        
    }
    
    @Override
    public ReturnFeatures visitPrimitiveType(PrimitiveTypeTree primitiveTypeTree, StatementFeatures statementFeatures) {
		
		TypeFeatures typeFeatures = new TypeFeatures();
		typeFeatures.setParentId(statementFeatures.getId());
		typeFeatures.setParentNode(TypeParent.VariableDefinition);
		typeFeatures.setParentChild(TypeRole.VariableType);
		typeFeatures.setHeight(statementFeatures.getDepth());
		
		ReturnFeatures returnFeatures = Util.visitors.getVisitorType().visitPrimitiveType(primitiveTypeTree, typeFeatures); 
        
		returnFeatures = new ReturnFeatures();
		//returnFeatures.setNodeType(Util.getTypeCategory(primitiveTypeTree.getPrimitiveTypeKind().toString()));
        return returnFeatures;
        
    }
    
    @Override
    public ReturnFeatures visitArrayType(ArrayTypeTree arrayTypeTree, StatementFeatures statementFeatures) {
		
	    TypeFeatures typeFeatures = new TypeFeatures();
		typeFeatures.setParentId(statementFeatures.getId());
		typeFeatures.setParentNode(TypeParent.VariableDefinition);
		typeFeatures.setParentChild(TypeRole.VariableType);
		typeFeatures.setHeight(statementFeatures.getDepth());
		
		ReturnFeatures returnFeatures = Util.visitors.getVisitorType().visitArrayType(arrayTypeTree, typeFeatures); 
	    
	    if(statementFeatures.getDepth() + 1 > statementFeatures.getDepth()) {
	    	statementFeatures.setDepth(statementFeatures.getDepth() + 1);
	    }
	    
	    returnFeatures = new ReturnFeatures();
	    //returnMethodFeatures.setNodeType(NodeASTTypes.Array);
	    return returnFeatures;
        
    }
    
    //class, not expression?
  	@Override
     public ReturnFeatures visitClass(ClassTree classTree, StatementFeatures statementFeatures)  {
  		
  		TypeDefFeatures typeDefFeatures = new TypeDefFeatures();
	    ReturnFeatures returnFeatures = new ReturnFeatures();
	    
      	typeDefFeatures.setParentId(statementFeatures.getParentId());
      	typeDefFeatures.setInnerClass(true);
      	typeDefFeatures.setFileId(0);
      	typeDefFeatures.setInnerId(Util.getNextNodeId()); // id just generated
      	typeDefFeatures.setHeight(statementFeatures.getDepth() + 1); //actualizo la altura
      	typeDefFeatures.setPackageName(statementFeatures.getPackageName());
      
      	//nested, inner and nested static
      	typeDefFeatures.setNestedClass(true);
      	if (classTree.getModifiers().getFlags().contains(Modifier.STATIC))
      		typeDefFeatures.setStatic(true);
      	else
      		typeDefFeatures.setInnerClass(true);
      
      	returnFeatures = Util.visitors.getVisitorTypeDefs().visitClass(classTree, typeDefFeatures);

      	returnFeatures.setDepth(statementFeatures.getDepth());
      	return returnFeatures;
     }
  	
}