package de.ovgu.cide.util;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.Modifier;
import cide.gast.IASTNode;
import de.ovgu.cide.language.jdt.ASTBridge;
/**
* provides some methods for check preparation
*
* @author aDreiling
*
*/
public class OverridingRelationUtils {
public static List<IASTNode> getIASTNodeList(List list) {
ArrayList<IASTNode> l = new ArrayList<IASTNode>();
for (int j = 0; j < list.size(); j++) {
l.add(ASTBridge.bridge((ASTNode) list.get(j)));
}
return l;
}
public static MethodPathItem getFirstNonAbstractItem(
List<MethodPathItem> inherMethods) {
if (inherMethods == null)
return null;
for (MethodPathItem tmpItem : inherMethods) {
if (tmpItem.isAbstract())
continue;
return tmpItem;
}
return null;
}
public static void collectOverriddenMethodKeysInSuperClasses(
IMethodBinding methodBinding, List<MethodPathItem> inherMethods) {
ITypeBinding declTypeBinding = methodBinding.getDeclaringClass();
// check only for classes
if (declTypeBinding == null || !declTypeBinding.isClass())
return;
// List<MethodPathItem> methodBindings = new
// ArrayList<MethodPathItem>();
collectOverriddenMethodsInSuperClasses(methodBinding, declTypeBinding
.getSuperclass(), inherMethods);
// for (MethodPathItem tmpItem : methodBindings) {
// keys.add(tmpItem.getKey());
// }
}
public static void collectOverriddenMethodsInSuperClasses(
IMethodBinding sourceMethodBinding, ITypeBinding superClassBinding,
List<MethodPathItem> inherMethods) {
if (sourceMethodBinding == null || inherMethods == null
|| superClassBinding == null
|| !superClassBinding.isFromSource())
return;
IMethodBinding[] methodBindings = superClassBinding
.getDeclaredMethods();
// check all methods of current class
for (int j = 0; j < methodBindings.length; j++) {
IMethodBinding tmpMethodBinding = methodBindings[j];
if (!sourceMethodBinding.overrides(tmpMethodBinding))
continue;
// add the method key and information if this method is abstract
inherMethods.add(new MethodPathItem(tmpMethodBinding, Modifier
.isAbstract(superClassBinding.getModifiers())));
}
// in addition to this (recursively) check the super class of the
// current class
collectOverriddenMethodsInSuperClasses(sourceMethodBinding,
superClassBinding.getSuperclass(), inherMethods);
}
public static void collectSimilarMethodKeysInSuperClasses(
IMethodBinding implMethodBinding, ITypeBinding superClassBinding,
List<MethodPathItem> methods, Set<String> checkedInterfaces) {
if (implMethodBinding == null || superClassBinding == null
|| methods == null)
return;
IMethodBinding[] methodBindings = superClassBinding
.getDeclaredMethods();
// check all methods of current class
for (int j = 0; j < methodBindings.length; j++) {
IMethodBinding tmpMethodBinding = methodBindings[j];
// add method if current method is a sub signature of the
// implemented
// method
if (!tmpMethodBinding.isSubsignature(implMethodBinding))
continue;
// add the method binding
methods.add(new MethodPathItem(tmpMethodBinding, Modifier
.isAbstract(superClassBinding.getModifiers())));
}
// in addition to this (recursively) check the super class of the
// current class
collectSimilarMethodKeysInSuperClasses(implMethodBinding,
superClassBinding.getSuperclass(), methods, checkedInterfaces);
// in addition to this (recursively) check all interfaces of the current
// class
collectSimilarMethodKeysInInterfaces(implMethodBinding,
superClassBinding.getInterfaces(), methods, checkedInterfaces);
}
public static void collectSimilarMethodKeysInInterfaces(
IMethodBinding implMethodBinding, ITypeBinding[] interfaceBindings,
List<MethodPathItem> targetMethodKeys, Set<String> checkedInterfaces) {
if (implMethodBinding == null || interfaceBindings == null
|| targetMethodKeys == null || checkedInterfaces == null)
return;
// iterate through all interfaces of current declaring type
for (int i = 0; i < interfaceBindings.length; i++) {
ITypeBinding tmpInterBinding = interfaceBindings[i];
String tmpInterKey;
// check only new interfaces
if (checkedInterfaces.contains(tmpInterKey = tmpInterBinding
.getKey()))
continue;
checkedInterfaces.add(tmpInterKey);
IMethodBinding[] methodBindings = tmpInterBinding
.getDeclaredMethods();
// check all methods of current interface
for (int j = 0; j < methodBindings.length; j++) {
IMethodBinding tmpMethodBinding = methodBindings[j];
// add key if current method is a sub signature of the
// implemented method
if (tmpMethodBinding.isSubsignature(implMethodBinding))
// interfaces are abstract --> second param is true
targetMethodKeys.add(new MethodPathItem(tmpMethodBinding,
true));
}
// in addition to this check all super interfaces of the current
// interface
collectSimilarMethodKeysInInterfaces(implMethodBinding,
tmpInterBinding.getInterfaces(), targetMethodKeys,
checkedInterfaces);
}
}
public static void collectExtendedAndImplementedTypesInSuperClasses(
ITypeBinding classBinding, List<TypePathItem> types,
Set<String> checkedInterfaces) {
if (classBinding == null || types == null || checkedInterfaces == null)
return;
// in addition to this (recursively) check all interfaces of the current
// class
collectExtendedAndImplementedTypesInInterfaces(classBinding, types,
checkedInterfaces);
ITypeBinding superClassBinding = classBinding.getSuperclass();
if (superClassBinding == null)
return;
// add the method binding
types.add(new TypePathItem(superClassBinding, false));
// in addition to this (recursively) check the super class of the
// current class
collectExtendedAndImplementedTypesInSuperClasses(superClassBinding,
types, checkedInterfaces);
}
public static void collectExtendedAndImplementedTypesInInterfaces(
ITypeBinding typeBinding, List<TypePathItem> types,
Set<String> checkedInterfaces) {
if (types == null || typeBinding == null || checkedInterfaces == null)
return;
ITypeBinding[] interfaceBindings = typeBinding.getInterfaces();
// iterate through all interfaces of current declaring type
for (int i = 0; i < interfaceBindings.length; i++) {
ITypeBinding tmpInterBinding = interfaceBindings[i];
String tmpInterKey;
// check only new interfaces
if (checkedInterfaces.contains(tmpInterKey = tmpInterBinding
.getKey()))
continue;
checkedInterfaces.add(tmpInterKey);
types.add(new TypePathItem(tmpInterBinding, true));
// in addition to this check all super interfaces of the current
// interface
collectExtendedAndImplementedTypesInInterfaces(tmpInterBinding,
types, checkedInterfaces);
}
}
/* BACKUP SOME METHODD */
// System.out.println("CHECK: " + source.getId() + " COLOR: " +
// file.getColorManager()
// .getColors(source)) ;
// System.out.println(" <--> "+ tmpKey);
// System.out.println(" COLOR: " + typingProvider.getBindingColors()
// .getColors(tmpKey));
// public static void getOverriddenParamKeys(List<MethodPathItem> methods,
// List<List<String>> paramKeys) {
//
// if ( paramKeys == null || methods == null || methods.size() == 0)
// return;
//
//
// // add param keys of all super methods
// ArrayList<String> tmpKeys;
// for (int i = 0; i < implMethodBinding.getParameterTypes().length; i++) {
// tmpKeys = new ArrayList<String>();
//
// for (MethodPathItem tmpItem : methods) {
//
// // if (!tmpItem.isOverridden())
// // continue;
//
// tmpKeys.add(BindingProjectColorCache.getParamKey(
// tmpItem.getKey(), i));
// }
//
// paramKeys.add(tmpKeys);
// }
//
// }
// public static void getOverriddenExceptionKeys( MethodDeclaration node,
// List<MethodPathItem> methods, List<List<String>> execKeys) {
//
// if ( node == null || execKeys == null || methods == null)
// return;
//
// // checks if method overrides another one
// if (methods.size() == 0)
// return;
//
// // add cast compatible exception types of first overridden method (in
// // super class)
// for (Object curExcNode : node.thrownExceptions()) {
//
// ITypeBinding tmpExBinding = ((Name) curExcNode)
// .resolveTypeBinding();
//
// if (tmpExBinding == null)
// continue;
//
//
// IMethodBinding superMethBinding = null;
//
// //get first overridden item
// for (MethodPathItem tmpItem : methods) {
// if (!tmpItem.isOverridden())
// continue;
//
// superMethBinding = tmpItem.getBinding();
// break;
// }
//
// if (superMethBinding == null)
// continue;
//
//
// ArrayList<String> tmpExceKeys = new ArrayList<String>();
//
// for (ITypeBinding tmpMethExBinding : superMethBinding
// .getExceptionTypes()) {
//
// if (tmpExBinding.isCastCompatible(tmpMethExBinding))
// tmpExceKeys.add(BindingProjectColorCache.getExceptionKey(
// superMethBinding.getKey(), tmpMethExBinding
// .getKey()));
//
// }
//
// execKeys.add(tmpExceKeys);
//
// }
//
//
// }
// public static void collectOverriddenSignaturePartKeysInSuperClasses(
// IMethodBinding implMethodBinding, MethodDeclaration node,
// List<List<String>> paramKeys, List<List<String>> execKeys) {
//
// if (implMethodBinding == null || node == null
// || paramKeys == null || execKeys == null)
// return;
//
// List<IMethodBinding> methodBindings = new ArrayList<IMethodBinding>();
//
// collectOverriddenMethodsInSuperClasses(implMethodBinding,
// declTypeBinding.getSuperclass(), methodBindings);
//
// // checks if method overrides another one
// if (methodBindings.size() == 0)
// return;
//
// // add param keys of all super methods
// ArrayList<String> tmpKeys;
// for (int i = 0; i < implMethodBinding.getParameterTypes().length; i++) {
// tmpKeys = new ArrayList<String>();
//
// for (IMethodBinding tmpMethodBinding : methodBindings) {
// tmpKeys.add(BindingProjectColorCache.getParamKey(
// tmpMethodBinding.getKey(), i));
// }
//
// paramKeys.add(tmpKeys);
// }
//
// // add cast compatible exception types of first overridden method (in
// // super class)
// for (Object curExcNode : node.thrownExceptions()) {
//
// ITypeBinding tmpExBinding = ((Name) curExcNode)
// .resolveTypeBinding();
//
// if (tmpExBinding == null)
// continue;
//
// IMethodBinding superMethBinding = methodBindings.get(0);
// ArrayList<String> tmpExceKeys = new ArrayList<String>();
//
// for (ITypeBinding tmpMethExBinding : superMethBinding
// .getExceptionTypes()) {
//
// if (tmpExBinding.isCastCompatible(tmpMethExBinding))
// tmpExceKeys.add(BindingProjectColorCache.getExceptionKey(
// superMethBinding.getKey(), tmpMethExBinding
// .getKey()));
//
// }
//
// execKeys.add(tmpExceKeys);
//
// }
//
// }
// BACKUP
// private List<String> findAllOverriddenMethodKeys(IMethod method) {
// try {
// IType type = method.getDeclaringType();
// ITypeHierarchy hierarchy = type.newSupertypeHierarchy(null);
//
//
// ArrayList<String> keys = new ArrayList<String>();
//
// while ((type = hierarchy.getSuperclass(type)) != null) {
//
// //TEST
//
// IMethod[] overriddenMethods = type.findMethods(method);
// if (overriddenMethods!=null && overriddenMethods.length>0) {
// for (int j = 0; j < overriddenMethods.length; j++) {
// IMethod tmpMethod = overriddenMethods[j];
//
// //check also the return type
// if (!tmpMethod.getReturnType().equals(method.getReturnType()))
// continue;
//
// //check also the exception handling type
// String[] tmpExeps = tmpMethod.getExceptionTypes();
// String[] methExeps = method.getExceptionTypes();
//
// if (tmpExeps.length != methExeps.length)
// continue;
//
// HashSet<String> compareSet = new HashSet<String>();
// for (int k = 0; k < methExeps.length; k++)
// compareSet.add(methExeps[k]);
//
// for (int k = 0; k < tmpExeps.length; k++) {
// if (!compareSet.remove(tmpExeps[k]))
// break;
// }
//
// if (!compareSet.isEmpty())
// continue;
//
//
// //check modifier flag
// //super method must be at least package default
// if (Flags.isPrivate(tmpMethod.getFlags()))
// continue;
//
// //check visibility reducing conditions
// if (Flags.isPublic(tmpMethod.getFlags()) &&
// !Flags.isPublic(method.getFlags()) )
// continue;
// if (Flags.isProtected(tmpMethod.getFlags()) && !
// (Flags.isPublic(method.getFlags()) ||
// Flags.isProtected(method.getFlags())))
// continue;
// if (Flags.isPackageDefault(tmpMethod.getFlags()) &&
// Flags.isPrivate(method.getFlags()))
// continue;
//
//
// System.out.println("RETURNTYPE: " + tmpMethod.getReturnType());
//
// //TEST
// CompilationUnit ast = getAST(tmpMethod);
// if (ast == null)
// return null;
//
// ASTBindingFinder bindingFinder = new
// ASTBindingFinder(tmpMethod.getKey());
// ast.accept(bindingFinder);
//
// ASTNode result = bindingFinder.getResult();
// System.out.println("ASTNODE:" + result);
// if (result == null)
// return null;
//
//
//
// IMethod[] meths = type.getMethods();
// for(IMethod m: meths) {
// System.out.println(" ===> " + m.getKey());
// }
//
// //TEST
//
// //method overrides tmpMethod, add the tmpMethod - key accordingly
// keys.add(tmpMethod.getKey());
//
// }
// }
// }
//
// return keys.size() > 0 ? keys : null;
//
// } catch (JavaModelException e) {
// return null;
// }
// }
// private IMethod getIMethod(IMethodBinding methodBinding) {
//
// IJavaElement javaElement = methodBinding.getJavaElement();
//
// if (!(javaElement instanceof IMethod))
// return null;
//
// return ((IMethod)javaElement);
// }
/*
* BACKUP OVERRIDING SOLUTION II
*
* public static void findAllOverriddenMethodKeys(IMethodBinding
* methodBinding, List<String> keys) { try {
*
* if (methodBinding == null) return;
*
* IMethod method = getIMethod(methodBinding);
*
* //checks if method exists and is not part of a binary file if (method ==
* null || method.isBinary()) return;
*
* IType type = method.getDeclaringType(); ITypeHierarchy hierarchy =
* type.newSupertypeHierarchy(null);
*
* //get the super class
*
* while ((type = hierarchy.getSuperclass(type)) != null) {
*
* //get the ast for this super class CompilationUnit ast = getAST(type);
*
* if (ast == null) return;
*
* //try to find a method in this super class which is overriden by current
* "method" CheckUtils bindingFinder = new CheckUtils(methodBinding);
* ast.accept(bindingFinder);
*
* IMethodBinding result = bindingFinder.getResult();
*
* //check if a overriden method has been found if (result != null) //method
* overrides tmpMethod, add the tmpMethod - key accordingly
* keys.add(result.getKey()); }
*
*
* } catch (JavaModelException e) { return; } }
*
* private static IMethod getIMethod(IMethodBinding methodBinding) {
*
* IJavaElement javaElement = methodBinding.getJavaElement();
*
* if (!(javaElement instanceof IMethod)) return null;
*
* return ((IMethod)javaElement); }
*
* private static CompilationUnit getAST(IType type) {
*
* IResource res = type.getResource(); if (!(res instanceof IFile)) return
* null;
*
* try { return JDTParserWrapper.parseJavaFile((IFile) res); } catch
* (ParseException e) { e.printStackTrace(); // if in doubt no error return
* null; }
*
* }
*
* private static boolean overrideCheck(IMethodBinding methodBinding,
* IMethodBinding superMethodBinding) {
*
* IMethod method = getIMethod(methodBinding); IMethod superMethod =
* getIMethod(superMethodBinding);
*
* if (method == null || superMethod == null) return false;
*
* //checks name, number of parameters; simple names of their parameter
* types if (!method.isSimilar(superMethod)) return false;
*
* try {
*
* //checks if it is a real implementation and not only an abstract method
* //super method must be at least package default if
* (Flags.isAbstract(superMethod.getFlags())) return false;
*
* // //ADDITION (OPTIONAL) CHECK TO VERIFY OVERRIDING RELATIONSHIP // //
* //check also the return type // if
* (!superMethod.getReturnType().equals(method.getReturnType())) // return
* false; // // //check also the exception handling type // String[]
* superExeps = superMethod.getExceptionTypes(); // String[] methExeps =
* method.getExceptionTypes(); // // if (superExeps.length !=
* methExeps.length) // return false; // // HashSet<String> compareSet = new
* HashSet<String>(); // for (int k = 0; k < methExeps.length; k++) //
* compareSet.add(methExeps[k]); // // for (int k = 0; k <
* superExeps.length; k++) { // if (!compareSet.remove(superExeps[k])) //
* break; // } // // if (!compareSet.isEmpty()) // return false; // //
* //check modifier flag // //super method must be at least package default
* // if (Flags.isPrivate(superMethod.getFlags())) // return false; // //
* //check visibility reducing conditions // if
* (Flags.isPublic(superMethod.getFlags()) &&
* !Flags.isPublic(method.getFlags()) ) // return false; // if
* (Flags.isProtected(superMethod.getFlags()) && !
* (Flags.isPublic(method.getFlags()) ||
* Flags.isProtected(method.getFlags()))) // return false; // if
* (Flags.isPackageDefault(superMethod.getFlags()) &&
* Flags.isPrivate(method.getFlags())) // return false; // // //
*
* } catch (JavaModelException e) { return false; }
*
* return true;
*
* }
*
*
* public CheckUtils(IMethodBinding mBinding) { this.methodBinding =
* mBinding; }
*
* private IMethodBinding result = null;
*
* private final IMethodBinding methodBinding;
*
* public boolean visit(MethodDeclaration node) { if (result != null) return
* false; IMethodBinding curBinding = node.resolveBinding();
*
* if (curBinding != null && overrideCheck(methodBinding,curBinding)) {
* result = curBinding; return false; }
*
*
* return super.visit(node); }
*
* public IMethodBinding getResult() { return result; }
*/
}