code: package gr.uom.java.ast.util;
  
  import gr.uom.java.ast.decomposition.cfg.AbstractVariable;
  import gr.uom.java.ast.decomposition.cfg.CompositeVariable;
  import gr.uom.java.ast.decomposition.cfg.PlainVariable;
  
  import java.util.ArrayList;
  import java.util.List;
  
  import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
  import org.eclipse.jdt.core.dom.ArrayAccess;
  import org.eclipse.jdt.core.dom.Assignment;
  import org.eclipse.jdt.core.dom.Block;
  import org.eclipse.jdt.core.dom.BodyDeclaration;
  import org.eclipse.jdt.core.dom.EnumDeclaration;
  import org.eclipse.jdt.core.dom.Expression;
  import org.eclipse.jdt.core.dom.ExpressionStatement;
  import org.eclipse.jdt.core.dom.FieldAccess;
  import org.eclipse.jdt.core.dom.IBinding;
  import org.eclipse.jdt.core.dom.IVariableBinding;
  import org.eclipse.jdt.core.dom.MethodDeclaration;
  import org.eclipse.jdt.core.dom.MethodInvocation;
  import org.eclipse.jdt.core.dom.Name;
  import org.eclipse.jdt.core.dom.QualifiedName;
  import org.eclipse.jdt.core.dom.ReturnStatement;
  import org.eclipse.jdt.core.dom.SimpleName;
  import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
  import org.eclipse.jdt.core.dom.Statement;
  import org.eclipse.jdt.core.dom.ThisExpression;
  import org.eclipse.jdt.core.dom.TypeDeclaration;
  
  public class MethodDeclarationUtility {
  
  	public static MethodInvocation isDelegate(MethodDeclaration methodDeclaration) {
  		AbstractTypeDeclaration parentClass = (AbstractTypeDeclaration)methodDeclaration.getParent();
  		Block methodBody = methodDeclaration.getBody();
  		if(methodBody != null) {
  			List<Statement> statements = methodBody.statements();
  			if(statements.size() == 1) {
  				Statement statement = statements.get(0);
  				MethodInvocation methodInvocation = null;
  	    		if(statement instanceof ReturnStatement) {
  	    			ReturnStatement returnStatement = (ReturnStatement)statement;
  	    			if(returnStatement.getExpression() instanceof MethodInvocation) {
  	    				methodInvocation = (MethodInvocation)returnStatement.getExpression();
  	    			}
  	    		}
  	    		else if(statement instanceof ExpressionStatement) {
  	    			ExpressionStatement expressionStatement = (ExpressionStatement)statement;
  	    			if(expressionStatement.getExpression() instanceof MethodInvocation) {
  	    				methodInvocation = (MethodInvocation)expressionStatement.getExpression();
  	    			}
  	    		}
  	    		if(methodInvocation != null) {
  	    			Expression methodInvocationExpression = methodInvocation.getExpression();
  	    			if(methodInvocationExpression instanceof MethodInvocation) {
  	    				MethodInvocation previousChainedMethodInvocation = (MethodInvocation)methodInvocationExpression;
  	    				List<MethodDeclaration> parentClassMethods = new ArrayList<MethodDeclaration>();
  	    				if(parentClass instanceof TypeDeclaration) {
  	    					MethodDeclaration[] parentClassMethodArray = ((TypeDeclaration)parentClass).getMethods();
  	    					for(MethodDeclaration method : parentClassMethodArray) {
  	    						parentClassMethods.add(method);
  	    					}
  	    				}
  	    				else if(parentClass instanceof EnumDeclaration) {
  	    					EnumDeclaration enumDeclaration = (EnumDeclaration)parentClass;
  	    					List<BodyDeclaration> bodyDeclarations = enumDeclaration.bodyDeclarations();
  	    					for(BodyDeclaration bodyDeclaration : bodyDeclarations) {
  	    						if(bodyDeclaration instanceof MethodDeclaration) {
  	    							parentClassMethods.add((MethodDeclaration)bodyDeclaration);
  	    						}
  	    					}
  	    				}
  	    				boolean isDelegationChain = false;
  		    			boolean foundInParentClass = false;
  	    				for(MethodDeclaration parentClassMethod : parentClassMethods) {
  	    					if(parentClassMethod.resolveBinding().isEqualTo(previousChainedMethodInvocation.resolveMethodBinding())) {
  	    						foundInParentClass = true;
  	    						SimpleName getterField = isGetter(parentClassMethod);
  	    						if(getterField == null)
  	    							isDelegationChain = true;
  	    						break;
  	    					}
  	    				}
  	    				if(!isDelegationChain && foundInParentClass) {
  	    					return methodInvocation;
  	    				}
  	    			}
  	    			else if(methodInvocationExpression instanceof FieldAccess) {
  	    				FieldAccess fieldAccess = (FieldAccess)methodInvocationExpression;
  	    				IVariableBinding variableBinding = fieldAccess.resolveFieldBinding();
  	    				if(variableBinding.getDeclaringClass().isEqualTo(parentClass.resolveBinding()) ||
  	    						parentClass.resolveBinding().isSubTypeCompatible(variableBinding.getDeclaringClass())) {
  	    					return methodInvocation;
  	    				}
  	    			}
  	    			else if(methodInvocationExpression instanceof SimpleName) {
  	    				SimpleName simpleName = (SimpleName)methodInvocationExpression;
  	    				IBinding binding = simpleName.resolveBinding();
  	    				if(binding != null && binding.getKind() == IBinding.VARIABLE) {
  	    					IVariableBinding variableBinding = (IVariableBinding)binding;
  	    					if(variableBinding.isField() || variableBinding.isParameter()) {
  	    						return methodInvocation;
  	    					}
  	    				}
  	    			}
  	    			else if(methodInvocationExpression instanceof ThisExpression) {
  	    				return methodInvocation;
  	    			}
  	    			else if(methodInvocationExpression == null) {
  	    				return methodInvocation;
  	    			}
  	    		}
  			}
  		}
  		return null;
  	}
  
  	public static SimpleName isGetter(MethodDeclaration methodDeclaration) {
  		Block methodBody = methodDeclaration.getBody();
  		List<SingleVariableDeclaration> parameters = methodDeclaration.parameters();
  		if(methodBody != null) {
  			List<Statement> statements = methodBody.statements();
  			if(statements.size() == 1 && parameters.size() == 0) {
  				Statement statement = statements.get(0);
  	    		if(statement instanceof ReturnStatement) {
  	    			ReturnStatement returnStatement = (ReturnStatement)statement;
  	    			Expression returnStatementExpression = returnStatement.getExpression();
  	    			if(returnStatementExpression instanceof SimpleName) {
  	    				return (SimpleName)returnStatementExpression;
  	    			}
  	    			else if(returnStatementExpression instanceof FieldAccess) {
  	    				FieldAccess fieldAccess = (FieldAccess)returnStatementExpression;
  	    				return fieldAccess.getName();
  	    			}
  	    		}
  			}
  		}
  		return null;
  	}
  
  	public static SimpleName isSetter(MethodDeclaration methodDeclaration) {
  		Block methodBody = methodDeclaration.getBody();
  		List<SingleVariableDeclaration> parameters = methodDeclaration.parameters();
  		if(methodBody != null) {
  			List<Statement> statements = methodBody.statements();
  			if(statements.size() == 1 && parameters.size() == 1) {
  				Statement statement = statements.get(0);
  	    		if(statement instanceof ExpressionStatement) {
  	    			ExpressionStatement expressionStatement = (ExpressionStatement)statement;
  	    			Expression expressionStatementExpression = expressionStatement.getExpression();
  	    			if(expressionStatementExpression instanceof Assignment) {
  	    				Assignment assignment = (Assignment)expressionStatementExpression;
  	    				Expression rightHandSide = assignment.getRightHandSide();
  	    				if(rightHandSide instanceof SimpleName) {
  	    					SimpleName rightHandSideSimpleName = (SimpleName)rightHandSide;
  	    					if(rightHandSideSimpleName.resolveBinding().isEqualTo(parameters.get(0).resolveBinding())) {
  	    						Expression leftHandSide = assignment.getLeftHandSide();
  	    						if(leftHandSide instanceof SimpleName) {
  	    		    				return (SimpleName)leftHandSide;
  	    		    			}
  	    		    			else if(leftHandSide instanceof FieldAccess) {
  	    		    				FieldAccess fieldAccess = (FieldAccess)leftHandSide;
  	    		    				return fieldAccess.getName();
  	    		    			}
  	    					}
  	    				}
  	    			}
  	    		}
  			}
  		}
  		return null;
  	}
  
  	public static AbstractVariable createVariable(SimpleName simpleName, AbstractVariable rightPart) {
  		IBinding binding = simpleName.resolveBinding();
  		if(binding != null && binding.getKind() == IBinding.VARIABLE) {
  			IVariableBinding variableBinding = (IVariableBinding)binding;
  			AbstractVariable currentVariable = null;
  			if(rightPart == null)
  				currentVariable = new PlainVariable(variableBinding);
  			else
  				currentVariable = new CompositeVariable(variableBinding, rightPart);
  			
  			if(simpleName.getParent() instanceof QualifiedName) {
  				QualifiedName qualifiedName = (QualifiedName)simpleName.getParent();
  				Name qualifier = qualifiedName.getQualifier();
  				if(qualifier instanceof SimpleName) {
  					SimpleName qualifierSimpleName = (SimpleName)qualifier;
  					if(!qualifierSimpleName.equals(simpleName))
  						return createVariable(qualifierSimpleName, currentVariable);
  					else
  						return currentVariable;
  				}
  				else if(qualifier instanceof QualifiedName) {
  					QualifiedName qualifiedName2 = (QualifiedName)qualifier;
  					return createVariable(qualifiedName2.getName(), currentVariable);
  				}
  			}
  			else if(simpleName.getParent() instanceof FieldAccess) {
  				FieldAccess fieldAccess = (FieldAccess)simpleName.getParent();
  				Expression fieldAccessExpression = fieldAccess.getExpression();
  				if(fieldAccessExpression instanceof FieldAccess) {
  					FieldAccess fieldAccess2 = (FieldAccess)fieldAccessExpression;
  					return createVariable(fieldAccess2.getName(), currentVariable);
  				}
  				else if(fieldAccessExpression instanceof SimpleName) {
  					SimpleName fieldAccessSimpleName = (SimpleName)fieldAccessExpression;
  					return createVariable(fieldAccessSimpleName, currentVariable);
  				}
  				else if(fieldAccessExpression instanceof ThisExpression) {
  					return currentVariable;
  				}
  			}
  			else {
  				return currentVariable;
  			}
  		}
  		return null;
  	}
  
  	public static AbstractVariable processMethodInvocationExpression(Expression expression) {
  		if(expression != null) {
  			if(expression instanceof QualifiedName) {
  				QualifiedName qualifiedName = (QualifiedName)expression;
  				return createVariable(qualifiedName.getName(), null);
  			}
  			else if(expression instanceof FieldAccess) {
  				FieldAccess fieldAccess = (FieldAccess)expression;
  				return createVariable(fieldAccess.getName(), null);
  			}
  			else if(expression instanceof SimpleName) {
  				SimpleName simpleName = (SimpleName)expression;
  				return createVariable(simpleName, null);
  			}
  		}
  		return null;
  	}
  
  
  	public static SimpleName getRightMostSimpleName(Expression expression) {
  		SimpleName simpleName = null;
  		if(expression instanceof SimpleName) {
  			simpleName = (SimpleName)expression;
  		}
  		else if(expression instanceof QualifiedName) {
  			QualifiedName leftHandSideQualifiedName = (QualifiedName)expression;
  			simpleName = leftHandSideQualifiedName.getName();
  		}
  		else if(expression instanceof FieldAccess) {
  			FieldAccess leftHandSideFieldAccess = (FieldAccess)expression;
  			simpleName = leftHandSideFieldAccess.getName();
  		}
  		else if(expression instanceof ArrayAccess) {
  			ArrayAccess leftHandSideArrayAccess = (ArrayAccess)expression;
  			Expression array = leftHandSideArrayAccess.getArray();
  			if(array instanceof SimpleName) {
  				simpleName = (SimpleName)array;
  			}
  			else if(array instanceof QualifiedName) {
  				QualifiedName arrayQualifiedName = (QualifiedName)array;
  				simpleName = arrayQualifiedName.getName();
  			}
  			else if(array instanceof FieldAccess) {
  				FieldAccess arrayFieldAccess = (FieldAccess)array;
  				simpleName = arrayFieldAccess.getName();
  			}
  		}
  		return simpleName;
  	}
  }
  