code: package us.msu.cse.repair.core.util;
  
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.FileNotFoundException;
  import java.io.IOException;
  import java.io.InputStream;
  import java.lang.reflect.Field;
  import java.lang.reflect.Method;
  import java.lang.reflect.Modifier;
  //import java.lang.reflect.Parameter;
  import java.net.MalformedURLException;
  import java.net.URL;
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  import java.util.Set;
  
  import org.apache.commons.io.FileUtils;
  import org.eclipse.jdt.core.dom.ASTMatcher;
  import org.eclipse.jdt.core.dom.ASTNode;
  import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
  import org.eclipse.jdt.core.dom.Assignment;
  import org.eclipse.jdt.core.dom.Block;
  import org.eclipse.jdt.core.dom.CatchClause;
  import org.eclipse.jdt.core.dom.CompilationUnit;
  import org.eclipse.jdt.core.dom.DoStatement;
  import org.eclipse.jdt.core.dom.EnhancedForStatement;
  import org.eclipse.jdt.core.dom.Expression;
  import org.eclipse.jdt.core.dom.ExpressionStatement;
  import org.eclipse.jdt.core.dom.ForStatement;
  import org.eclipse.jdt.core.dom.IBinding;
  import org.eclipse.jdt.core.dom.IMethodBinding;
  import org.eclipse.jdt.core.dom.IPackageBinding;
  import org.eclipse.jdt.core.dom.ITypeBinding;
  import org.eclipse.jdt.core.dom.IVariableBinding;
  import org.eclipse.jdt.core.dom.IfStatement;
  import org.eclipse.jdt.core.dom.ImportDeclaration;
  import org.eclipse.jdt.core.dom.Initializer;
  import org.eclipse.jdt.core.dom.MethodDeclaration;
  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.StructuralPropertyDescriptor;
  import org.eclipse.jdt.core.dom.SwitchStatement;
  import org.eclipse.jdt.core.dom.ThrowStatement;
  import org.eclipse.jdt.core.dom.TryStatement;
  import org.eclipse.jdt.core.dom.Type;
  import org.eclipse.jdt.core.dom.VariableDeclarationExpression;
  import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
  import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
  
  import org.eclipse.jdt.core.dom.WhileStatement;
  
  import jmetal.util.PseudoRandom;
  import us.msu.cse.repair.core.parser.MethodInfo;
  import us.msu.cse.repair.core.parser.VarInfo;
  
  public class Helper {			
  	public static AbstractTypeDeclaration getAbstractTypeDeclaration(Statement s) {
  		ASTNode node = s;
  		while (!(node instanceof AbstractTypeDeclaration)) {
  			node = node.getParent();
  		}
  		return (AbstractTypeDeclaration) node;
  	}
  
  	public static MethodDeclaration getMethodDeclaration(Statement s) {
  		ASTNode node = s;
  		while (node != null && !(node instanceof MethodDeclaration) && !(node instanceof Initializer)) {
  			node = node.getParent();
  		}
  		if (node instanceof MethodDeclaration)
  			return (MethodDeclaration) node;
  		else
  			return null;
  	}
  
  	public static List<VariableDeclarationFragment> getVariableDeclarationFragments(VariableDeclarationStatement vs) {
  		List<VariableDeclarationFragment> fragments = new ArrayList<VariableDeclarationFragment>();
  		Iterator<?> iter = vs.fragments().iterator();
  		while (iter.hasNext()) {
  			VariableDeclarationFragment fragment = (VariableDeclarationFragment) iter.next();
  			fragments.add(fragment);
  
  		}
  		return fragments;
  	}
  
  	public static List<VariableDeclarationFragment> getVariableDeclarationFragments(VariableDeclarationExpression vde) {
  		List<VariableDeclarationFragment> fragments = new ArrayList<VariableDeclarationFragment>();
  		Iterator<?> iter = vde.fragments().iterator();
  		while (iter.hasNext()) {
  			VariableDeclarationFragment fragment = (VariableDeclarationFragment) iter.next();
  			fragments.add(fragment);
  		}
  		return fragments;
  	}
  
  	public static Map<String, VarInfo> getVarInfos(IVariableBinding[] vbs) {
  		Map<String, VarInfo> map = new HashMap<String, VarInfo>();
  
  		for (IVariableBinding vb : vbs) {
  			VarInfo vi = getVarInfo(vb);
  			map.put(vb.getName(), vi);
  		}
  
  		return map;
  	}
  
  	public static Map<String, VarInfo> getVarInfos(Field[] fields) {
  		Map<String, VarInfo> map = new HashMap<String, VarInfo>();
  
  		for (Field field : fields) {
  			String name = field.getName();
  			if (name.startsWith("this"))
  				continue;
  
  			VarInfo vi = getVarInfo(field);
  			map.put(name, vi);
  		}
  
  		return map;
  	}
  
  	public static Map<String, MethodInfo> getMethodInfos(Method[] methods) {
  		Map<String, MethodInfo> map = new HashMap<String, MethodInfo>();
  
  		for (Method method : methods) {
  			String key = getMethodKey(method);
  			MethodInfo mi = getMethodInfo(method);
  			map.put(key, mi);
  		}
  		return map;
  	}
  
  	public static Map<String, MethodInfo> getMethodInfos(IMethodBinding[] mbs) {
  		HashMap<String, MethodInfo> map = new HashMap<String, MethodInfo>();
  
  		for (IMethodBinding mb : mbs) {
  			if (mb.isConstructor())
  				continue;
  			String key = getMethodKey(mb);
  			MethodInfo mi = getMethodInfo(mb);
  			map.put(key, mi);
  		}
  
  		return map;
  	}
  
  	public static VarInfo getVarInfo(IVariableBinding vb) {
  		ITypeBinding typeBinding = vb.getVariableDeclaration().getType();
  		String typeName = typeBinding.getQualifiedName();
  		int mod = vb.getModifiers();
  		VarInfo vi = new VarInfo(typeName, vb, mod);
  		return vi;
  	}
  
  	public static VarInfo getVarInfo(Field field) {
  		String typeName = getGenericTypeNameForField(field.toGenericString());
  		int mod = field.getModifiers();
  
  		VarInfo vi = new VarInfo(typeName, null, mod);
  		return vi;
  	}
  
  	static String getGenericTypeNameForField(String genericString) {
  		String strs[] = genericString.split("\\s+");
  		return strs[strs.length - 2];
  	}
  
  	public static MethodInfo getMethodInfo(IMethodBinding mb) {
  		int mod = mb.getModifiers();
  		ITypeBinding returnTypeBinding = mb.getMethodDeclaration().getReturnType();
  		String returnTypeName = returnTypeBinding.getQualifiedName();
  		
  		ITypeBinding[] parameterTypes = mb.getMethodDeclaration().getParameterTypes();
  		String parameterTypeNames = "";	
  		if (parameterTypes.length > 0) {
  			parameterTypeNames = parameterTypes[0].getQualifiedName();
  			for (int i = 1; i < parameterTypes.length; i++) {
  				ITypeBinding tb = parameterTypes[i];
  				parameterTypeNames += (":" + tb.getQualifiedName());
  			}	
  		}
  		
  		MethodInfo mi = new MethodInfo(returnTypeName, returnTypeBinding, parameterTypeNames, mod);
  		return mi;
  	}
  
  	public static String getMethodKey(IMethodBinding mb) {
  		String key = mb.getName();
  		int len = mb.getMethodDeclaration().getParameterTypes().length;
  		key += (":" + len);
  		return key;
  	}
  
  	public static MethodInfo getMethodInfo(Method method) {
  		int mod = method.getModifiers();
  		String returnTypeName = getGenericReturnTypeNameForMethod(method.toGenericString());
  		
  		String parameterTypeNames = "";
  		if (method.getGenericParameterTypes().length > 0) 
  			parameterTypeNames += getGenericParameterTypeNamesForMethod(method.toGenericString());
  		
  		MethodInfo mi = new MethodInfo(returnTypeName, null, parameterTypeNames, mod);
  		return mi;
  	}
  
  	public static String getMethodKey(Method method) {
  		String key = method.getName();
  		int len = method.getGenericParameterTypes().length;
  		key += (":" + len);
  		return key;
  	}
  
  	static String getGenericReturnTypeNameForMethod(String genericString) {
  		String strs[] = genericString.trim().split("\\s+");
  		for (int i = 0; i < strs.length; i++) {
  			if (strs[i].indexOf("(") != -1)
  				return strs[i - 1];
  		}
  		return null;
  	}
  
  	static String getGenericParameterTypeNamesForMethod(String genericString) {
  		int beginIndex = genericString.indexOf("(");
  		int endIndex = genericString.indexOf(")");
  		return genericString.substring(beginIndex + 1, endIndex).trim().replace(",", ":");
  	}
  
  	public static String getMethodName(String key) {
  		int index = key.indexOf(":");
  		if (index == -1)
  			return key;
  		else
  			return key.substring(0, index);
  	}
  
  	public static boolean isInStaticMethod(Statement statement) {
  		MethodDeclaration md = getMethodDeclaration(statement);
  		if (md == null)
  			return false;
  		else {
  			int mod = md.getModifiers();
  			return Modifier.isStatic(mod);
  		}
  	}
  
  	public static boolean isStaticMethod(MethodInfo mi) {
  		int mod = mi.getModifiers();
  		return Modifier.isStatic(mod);
  	}
  
  	public static boolean isPublicMethod(MethodInfo mi) {
  		int mod = mi.getModifiers();
  		return Modifier.isPublic(mod);
  	}
  
  	public static boolean isProtectedMethod(MethodInfo mi) {
  		int mod = mi.getModifiers();
  		return Modifier.isProtected(mod);
  	}
  
  	public static boolean isPackagePrivateMethod(MethodInfo mi) {
  		int mod = mi.getModifiers();
  		boolean isPublic = Modifier.isPublic(mod);
  		boolean isPrivate = Modifier.isPrivate(mod);
  		boolean isProtected = Modifier.isProtected(mod);
  		return !(isPublic || isPrivate || isProtected);
  	}
  
  	public static boolean isStaticVar(VarInfo vi) {
  		int mod = vi.getModifiers();
  		return Modifier.isStatic(mod);
  	}
  
  	public static boolean isPublicVar(VarInfo vi) {
  		int mod = vi.getModifiers();
  		return Modifier.isPublic(mod);
  	}
  
  	public static boolean isProtectedVar(VarInfo vi) {
  		int mod = vi.getModifiers();
  		return Modifier.isProtected(mod);
  	}
  
  	public static boolean isPackagePrivateVar(VarInfo vi) {
  		int mod = vi.getModifiers();
  		boolean isPublic = Modifier.isPublic(mod);
  		boolean isPrivate = Modifier.isPrivate(mod);
  		boolean isProtected = Modifier.isProtected(mod);
  
  		return !(isPublic || isPrivate || isProtected);
  	}
  
  	public static boolean isDeclaredVar(SimpleName s) {
  		StructuralPropertyDescriptor property1 = VariableDeclarationFragment.NAME_PROPERTY;
  		StructuralPropertyDescriptor property2 = SingleVariableDeclaration.NAME_PROPERTY;
  
  		StructuralPropertyDescriptor spd = s.getLocationInParent();
  		return spd == property1 || spd == property2;
  	}
  
  	public static boolean isInSamePackage(String className1, String className2) {
  		int index1 = className1.lastIndexOf(".");
  		int index2 = className2.lastIndexOf(".");
  
  		String pk1 = className1.substring(0, index1);
  		String pk2 = className2.substring(0, index2);
  
  		return pk1.equals(pk2);
  	}
  
  	public static boolean isRuntimeException(ITypeBinding tb) {
  		while (tb != null) {
  			if (tb.getName().equals("RuntimeException"))
  				return true;
  			tb = tb.getSuperclass();
  		}
  		return false;
  	}
  
  	public static URL[] getURLs(Collection<String> paths) throws MalformedURLException {
  		URL[] urls = new URL[paths.size()];
  		int i = 0;
  		for (String path : paths) {
  			File file = new File(path);
  			URL url = file.toURI().toURL();
  			urls[i++] = url;
  		}
  
  		return urls;
  	}
  
  	public static InputStream getInputStreamOfClass(String parent, String binJavaClass) throws FileNotFoundException {
  		String child = binJavaClass.replace(".", File.separator) + ".class";
  		File file = new File(parent, child);
  		InputStream is = new FileInputStream(file);
  		return is;
  	}
  
  	public static void saveBinaryClassToFile(byte[] bytes, String fullClassName, String dir) throws IOException {
  		String name = fullClassName.replace(".", File.separator);
  		File file = new File(dir, name);
  		FileUtils.writeByteArrayToFile(file, bytes);
  	}
  
  	public static String getTestNameFromJUnitOutput(String line) {
  		if (line.indexOf(")") == -1)
  			return null;
  
  		String[] strArray = line.split("\\)");
  
  		if (!isInteger(strArray[0]))
  			return null;
  
  		String names[] = strArray[1].trim().split("\\(");
  
  		return names[1] + "#" + names[0];
  
  	}
  
  	public static boolean isInteger(String s) {
  		try {
  			Integer.parseInt(s);
  		} catch (NumberFormatException e) {
  			return false;
  		} catch (NullPointerException e) {
  			return false;
  		}
  		// only got here if we didn't return false
  		return true;
  	}
  
  	public static boolean isInLoop(Statement statement) {
  		ASTNode node = statement;
  		while (!(node.getParent() instanceof MethodDeclaration || node.getParent() instanceof Initializer)) {
  			ASTNode parent = node.getParent();
  
  			boolean flag1 = parent instanceof ForStatement;
  			boolean flag2 = parent instanceof EnhancedForStatement;
  			boolean flag3 = parent instanceof WhileStatement;
  			boolean flag4 = parent instanceof DoStatement;
  
  			if (flag1 || flag2 || flag3 || flag4)
  				return true;
  
  			node = node.getParent();
  		}
  
  		return false;
  	}
  
  	public static boolean isInSwitch(Statement statement) {
  		ASTNode node = statement;
  		while (!(node.getParent() instanceof MethodDeclaration || node.getParent() instanceof Initializer)) {
  			ASTNode parent = node.getParent();
  
  			boolean flag = parent instanceof SwitchStatement;
  			if (flag)
  				return true;
  
  			node = node.getParent();
  		}
  
  		return false;
  	}
  
  	public static boolean isAlternativeVariableDeclaration(VariableDeclarationStatement current,
  			VariableDeclarationStatement replace) {
  		ITypeBinding curTypeBinding = current.getType().resolveBinding();
  		ITypeBinding repTypeBinding = replace.getType().resolveBinding();
  
  		if (curTypeBinding != null && repTypeBinding != null) {
  			if (!repTypeBinding.isCastCompatible(curTypeBinding))
  				return false;
  		} else {
  			Type curType = current.getType();
  			Type repType = replace.getType();
  
  			if (!curType.subtreeMatch(new ASTMatcher(true), repType))
  				return false;
  		}
  
  		if (current.fragments().size() != replace.fragments().size())
  			return false;
  
  		Set<String> curS = new HashSet<String>();
  		Set<String> repS = new HashSet<String>();
  		for (int i = 0; i < current.fragments().size(); i++) {
  			String curID = ((VariableDeclarationFragment) current.fragments().get(i)).getName().getIdentifier();
  			String repID = ((VariableDeclarationFragment) replace.fragments().get(i)).getName().getIdentifier();
  			curS.add(curID);
  			repS.add(repID);
  		}
  
  		return curS.equals(repS);
  	}
  
  	public static boolean isLastStatementInMethod(Statement statement) {
  		ASTNode node = statement;
  		while (!(node.getParent() instanceof MethodDeclaration)) {
  			if (node.getParent() instanceof Block) {
  				Block block = (Block) node.getParent();
  				int index = block.statements().indexOf(node);
  				if (index != block.statements().size() - 1)
  					return false;
  			}
  
  			node = node.getParent();
  		}
  		return true;
  	}
  
  	public static boolean isLastStatementInBlock(Statement statement) {
  		if (!(statement.getParent() instanceof Block))
  			return true;
  
  		Block block = (Block) statement.getParent();
  
  		int index = block.statements().indexOf(statement);
  
  		return (index == block.statements().size() - 1) ? true : false;
  	}
  
  	public static boolean canReturnOrThrow(Statement statement) {
  		if (statement instanceof ReturnStatement || statement instanceof ThrowStatement)
  			return true;
  
  		if (statement instanceof IfStatement) {
  			IfStatement ifs = (IfStatement) statement;
  			if (ifs.getElseStatement() == null)
  				return false;
  
  			Statement thenS = ifs.getThenStatement();
  			Statement elseS = ifs.getElseStatement();
  
  			if (thenS instanceof Block) {
  				List<?> sList = ((Block) thenS).statements();
  				if (sList.isEmpty())
  					return false;
  				thenS = (Statement) sList.get(sList.size() - 1);
  			}
  			if (elseS instanceof Block) {
  				List<?> sList = ((Block) elseS).statements();
  				if (sList.isEmpty())
  					return false;
  				elseS = (Statement) sList.get(sList.size() - 1);
  			}
  
  			if (canReturnOrThrow(thenS) && canReturnOrThrow(elseS))
  				return true;
  			else
  				return false;
  
  		} else if (statement instanceof TryStatement) {
  			TryStatement trs = (TryStatement) statement;
  			if (trs.getFinally() != null) {
  				List<?> sList = trs.getFinally().statements();
  				if (!sList.isEmpty()) {
  					Statement finalS = (Statement) sList.get(sList.size() - 1);
  					if (canReturnOrThrow(finalS))
  						return true;
  				}
  			}
  
  			List<Block> tcBlocks = new ArrayList<Block>();
  			tcBlocks.add(trs.getBody());
  			for (Object o : trs.catchClauses()) {
  				CatchClause cc = (CatchClause) o;
  				tcBlocks.add(cc.getBody());
  			}
  
  			for (Block bl : tcBlocks) {
  				List<?> sList = bl.statements();
  				if (sList.isEmpty())
  					return false;
  
  				Statement st = (Statement) sList.get(sList.size() - 1);
  				if (!canReturnOrThrow(st))
  					return false;
  			}
  
  			return true;
  		} else
  			return false;
  	}
  
  	public static boolean isAbstractClass(Class<?> target) {
  		int mod = target.getModifiers();
  		boolean isAbstract = Modifier.isAbstract(mod);
  		boolean isInterface = Modifier.isInterface(mod);
  
  		if (isAbstract || isInterface)
  			return true;
  
  		return false;
  	}
  
  	public static boolean isAssignment(Statement statement) {
  		if (!(statement instanceof ExpressionStatement))
  			return false;
  
  		Expression expression = ((ExpressionStatement) statement).getExpression();
  		return (expression instanceof Assignment);
  	}
  
  	public static boolean isSameParentType(ITypeBinding tb1, ITypeBinding tb2) {
  		ITypeBinding tb1_sc = tb1.getSuperclass();
  		ITypeBinding tb2_sc = tb2.getSuperclass();
  
  		if (tb1_sc == tb2_sc && tb1_sc != null && !tb1_sc.getQualifiedName().startsWith("java.lang")) {
  			return true;
  		}
  
  		ITypeBinding[] tb1_its = tb1.getInterfaces();
  		ITypeBinding[] tb2_its = tb2.getInterfaces();
  
  		for (int i = 0; i < tb1_its.length; i++) {
  			for (int j = 0; j < tb2_its.length; j++) {
  				if (tb1_its[i] == tb2_its[j] && !tb1_its[i].getQualifiedName().startsWith("java.lang"))
  					return true;
  			}
  		}
  
  		return false;
  	}
  
  	public static Set<String> getVisibleTypeDeclarations(Statement statement) {
  		Set<String> typeDecls = new HashSet<String>();
  
  		CompilationUnit cu = (CompilationUnit) statement.getRoot();
  		for (Object obj : cu.imports()) {
  			ImportDeclaration ide = (ImportDeclaration) obj;
  			IBinding ib = ide.resolveBinding();
  			if (ib == null)
  				continue;
  
  			if (ib instanceof ITypeBinding) {
  				ITypeBinding tb = (ITypeBinding) ib;
  				typeDecls.add(tb.getBinaryName());
  			} else if (ib instanceof IPackageBinding) {
  				IPackageBinding pb = (IPackageBinding) ib;
  				typeDecls.add(pb.getName());
  			}
  		}
  
  		typeDecls.add(cu.getPackage().getName().toString());
  		typeDecls.add("java.lang");
  		return typeDecls;
  	}
  	
      private static String characterTable[] = {"a", "b", "c", "d", "e", "f", "g", "h", "i",
      		"j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y",
      		"z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
  
      public static String getRandomID() {
      	int count = 4;
      	String id = "";
      	for (int i = 0; i < count; i++) {
      		int index = PseudoRandom.randInt(0, characterTable.length - 1);
      		id = (id + characterTable[index]);
      	}
      	return id;
      }
  }
  