// Path: startupheroes-checks/src/main/java/es/startuphero/checkstyle/util/AnnotationUtils.java
// public static final String OVERRIDE_ANNOTATION_NAME_BY_PACKAGE = "java.lang.Override";
// 
// Path: startupheroes-checks/src/main/java/es/startuphero/checkstyle/util/AnnotationUtils.java
// public static Boolean hasAnnotation(DetailAST ast, String fullAnnotation) {
//   return CommonUtils.getSimpleAndFullNames(fullAnnotation).stream()
//                     .anyMatch(annotation -> AnnotationUtil.containsAnnotation(ast, annotation));
// }
// 
// Path: startupheroes-checks/src/main/java/es/startuphero/checkstyle/util/ClassUtils.java
// public static String getClassName(DetailAST classAst) {
//   DetailAST type = classAst.findFirstToken(TokenTypes.LITERAL_CLASS);
//   return type.getNextSibling().getText();
// }
// 
// Path: startupheroes-checks/src/main/java/es/startuphero/checkstyle/util/ClassUtils.java
// public static Optional<DetailAST> getClassOf(DetailAST anyAstBelowClass) {
//   Optional<DetailAST> classAst = Optional.empty();
//   for (DetailAST parent = anyAstBelowClass; parent != null; parent = parent.getParent()) {
//     if (parent.getType() == TokenTypes.CLASS_DEF) {
//       classAst = Optional.of(parent);
//       break;
//     }
//   }
//   return classAst;
// }
// 
// Path: startupheroes-checks/src/main/java/es/startuphero/checkstyle/util/ClassUtils.java
// public static Map<String, String> getImportSimpleFullNameMap(DetailAST rootAst) {
//   Map<String, String> simpleFullNameMapOfImports = new LinkedHashMap<>();
//   for (DetailAST sibling = rootAst; sibling != null; sibling = sibling.getNextSibling()) {
//     if (sibling.getType() == TokenTypes.IMPORT) {
//       simpleFullNameMapOfImports.put(CommonUtils.getSimpleName(sibling),
//                                      CommonUtils.getFullName(sibling));
//     }
//   }
//   return simpleFullNameMapOfImports;
// }
// 
// Path: startupheroes-checks/src/main/java/es/startuphero/checkstyle/util/CommonUtils.java
// public static String getPackageName(DetailAST ast) {
//   String packageName = null;
//   for (DetailAST parent = ast; parent != null; parent = parent.getParent()) {
//     if (parent.getType() == TokenTypes.PACKAGE_DEF) {
//       packageName = getFullName(parent);
//       break;
//     }
//   }
//   return packageName;
// }
// 
// Path: startupheroes-checks/src/main/java/es/startuphero/checkstyle/util/MethodUtils.java
// public static String getMethodName(DetailAST methodAst) {
//   DetailAST type = methodAst.findFirstToken(TokenTypes.TYPE);
//   return type.getNextSibling().getText();
// }
// 
// Path: startupheroes-checks/src/main/java/es/startuphero/checkstyle/util/MethodUtils.java
// public static Class<?>[] getParameterTypes(DetailAST methodAst,
//                                            Map<String, String> importSimpleFullNameMap) {
//   DetailAST parameters = methodAst.findFirstToken(TokenTypes.PARAMETERS);
//   List<DetailAST> parameterNodes =
//       CommonUtils.getChildsByType(parameters, TokenTypes.PARAMETER_DEF);
//   List<Class<?>> parameterTypes = new ArrayList<>();
//   for (DetailAST parameterNode : parameterNodes) {
//     String paramTypeSimpleName = getParamTypeSimpleName(parameterNode);
//     String paramTypeFullName =
//         CommonUtils.getFullName(methodAst, importSimpleFullNameMap, paramTypeSimpleName);
//     try {
//       Class<?> parameterClass = Class.forName(paramTypeFullName);
//       parameterTypes.add(parameterClass);
//     } catch (ClassNotFoundException ignored) {
//     }
//   }
//   return parameterTypes.stream().toArray(Class<?>[]::new);
// }
// 
// Path: startupheroes-checks/src/main/java/es/startuphero/checkstyle/util/MethodUtils.java
// public static Boolean isMethodOverriden(Method method) {
//   Class<?> declaringClass = method.getDeclaringClass();
//   if (declaringClass.equals(Object.class)) {
//     return false;
//   }
//   try {
//     declaringClass.getSuperclass()
//                   .getDeclaredMethod(method.getName(), method.getParameterTypes());
//     return true;
//   } catch (NoSuchMethodException ex) {
//     for (Class<?> implementedInterface : declaringClass.getInterfaces()) {
//       try {
//         implementedInterface.getDeclaredMethod(method.getName(), method.getParameterTypes());
//         return true;
//       } catch (NoSuchMethodException ignored) {
//       }
//     }
//     return false;
//   }
// }


import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
import com.puppycrawl.tools.checkstyle.api.DetailAST;
import com.puppycrawl.tools.checkstyle.api.TokenTypes;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Optional;
import static es.startuphero.checkstyle.util.AnnotationUtils.OVERRIDE_ANNOTATION_NAME_BY_PACKAGE;
import static es.startuphero.checkstyle.util.AnnotationUtils.hasAnnotation;
import static es.startuphero.checkstyle.util.ClassUtils.getClassName;
import static es.startuphero.checkstyle.util.ClassUtils.getClassOf;
import static es.startuphero.checkstyle.util.ClassUtils.getImportSimpleFullNameMap;
import static es.startuphero.checkstyle.util.CommonUtils.getPackageName;
import static es.startuphero.checkstyle.util.MethodUtils.getMethodName;
import static es.startuphero.checkstyle.util.MethodUtils.getParameterTypes;
import static es.startuphero.checkstyle.util.MethodUtils.isMethodOverriden;
package es.startuphero.checkstyle.checks.annotation;



/**
 * @author ozlem.ulag
 */
public class MissingOverrideCheck extends AbstractCheck {

  /**
   * A key is pointing to the warning message text in "messages.properties" file.
   */
  private static final String MSG_KEY = "missing.override";

  private String packageName;

  private Map<String, String> importSimpleFullNameMap;

  @Override
  public int[] getDefaultTokens() {
    return getAcceptableTokens();
  }

  @Override
  public int[] getAcceptableTokens() {
    return new int[] {TokenTypes.METHOD_DEF};
  }

  @Override
  public int[] getRequiredTokens() {
    return getAcceptableTokens();
  }

  @Override
  public void beginTree(DetailAST rootAst) {
    packageName = getPackageName(rootAst);
// Path: startupheroes-checks/src/main/java/es/startuphero/checkstyle/util/AnnotationUtils.java
// public static final String OVERRIDE_ANNOTATION_NAME_BY_PACKAGE = "java.lang.Override";
// 
// Path: startupheroes-checks/src/main/java/es/startuphero/checkstyle/util/AnnotationUtils.java
// public static Boolean hasAnnotation(DetailAST ast, String fullAnnotation) {
//   return CommonUtils.getSimpleAndFullNames(fullAnnotation).stream()
//                     .anyMatch(annotation -> AnnotationUtil.containsAnnotation(ast, annotation));
// }
// 
// Path: startupheroes-checks/src/main/java/es/startuphero/checkstyle/util/ClassUtils.java
// public static String getClassName(DetailAST classAst) {
//   DetailAST type = classAst.findFirstToken(TokenTypes.LITERAL_CLASS);
//   return type.getNextSibling().getText();
// }
// 
// Path: startupheroes-checks/src/main/java/es/startuphero/checkstyle/util/ClassUtils.java
// public static Optional<DetailAST> getClassOf(DetailAST anyAstBelowClass) {
//   Optional<DetailAST> classAst = Optional.empty();
//   for (DetailAST parent = anyAstBelowClass; parent != null; parent = parent.getParent()) {
//     if (parent.getType() == TokenTypes.CLASS_DEF) {
//       classAst = Optional.of(parent);
//       break;
//     }
//   }
//   return classAst;
// }
// 
// Path: startupheroes-checks/src/main/java/es/startuphero/checkstyle/util/ClassUtils.java
// public static Map<String, String> getImportSimpleFullNameMap(DetailAST rootAst) {
//   Map<String, String> simpleFullNameMapOfImports = new LinkedHashMap<>();
//   for (DetailAST sibling = rootAst; sibling != null; sibling = sibling.getNextSibling()) {
//     if (sibling.getType() == TokenTypes.IMPORT) {
//       simpleFullNameMapOfImports.put(CommonUtils.getSimpleName(sibling),
//                                      CommonUtils.getFullName(sibling));
//     }
//   }
//   return simpleFullNameMapOfImports;
// }
// 
// Path: startupheroes-checks/src/main/java/es/startuphero/checkstyle/util/CommonUtils.java
// public static String getPackageName(DetailAST ast) {
//   String packageName = null;
//   for (DetailAST parent = ast; parent != null; parent = parent.getParent()) {
//     if (parent.getType() == TokenTypes.PACKAGE_DEF) {
//       packageName = getFullName(parent);
//       break;
//     }
//   }
//   return packageName;
// }
// 
// Path: startupheroes-checks/src/main/java/es/startuphero/checkstyle/util/MethodUtils.java
// public static String getMethodName(DetailAST methodAst) {
//   DetailAST type = methodAst.findFirstToken(TokenTypes.TYPE);
//   return type.getNextSibling().getText();
// }
// 
// Path: startupheroes-checks/src/main/java/es/startuphero/checkstyle/util/MethodUtils.java
// public static Class<?>[] getParameterTypes(DetailAST methodAst,
//                                            Map<String, String> importSimpleFullNameMap) {
//   DetailAST parameters = methodAst.findFirstToken(TokenTypes.PARAMETERS);
//   List<DetailAST> parameterNodes =
//       CommonUtils.getChildsByType(parameters, TokenTypes.PARAMETER_DEF);
//   List<Class<?>> parameterTypes = new ArrayList<>();
//   for (DetailAST parameterNode : parameterNodes) {
//     String paramTypeSimpleName = getParamTypeSimpleName(parameterNode);
//     String paramTypeFullName =
//         CommonUtils.getFullName(methodAst, importSimpleFullNameMap, paramTypeSimpleName);
//     try {
//       Class<?> parameterClass = Class.forName(paramTypeFullName);
//       parameterTypes.add(parameterClass);
//     } catch (ClassNotFoundException ignored) {
//     }
//   }
//   return parameterTypes.stream().toArray(Class<?>[]::new);
// }
// 
// Path: startupheroes-checks/src/main/java/es/startuphero/checkstyle/util/MethodUtils.java
// public static Boolean isMethodOverriden(Method method) {
//   Class<?> declaringClass = method.getDeclaringClass();
//   if (declaringClass.equals(Object.class)) {
//     return false;
//   }
//   try {
//     declaringClass.getSuperclass()
//                   .getDeclaredMethod(method.getName(), method.getParameterTypes());
//     return true;
//   } catch (NoSuchMethodException ex) {
//     for (Class<?> implementedInterface : declaringClass.getInterfaces()) {
//       try {
//         implementedInterface.getDeclaredMethod(method.getName(), method.getParameterTypes());
//         return true;
//       } catch (NoSuchMethodException ignored) {
//       }
//     }
//     return false;
//   }
// }


// Path: startupheroes-checks/src/main/java/es/startuphero/checkstyle/checks/annotation/MissingOverrideCheck.java
import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
import com.puppycrawl.tools.checkstyle.api.DetailAST;
import com.puppycrawl.tools.checkstyle.api.TokenTypes;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Optional;
import static es.startuphero.checkstyle.util.AnnotationUtils.OVERRIDE_ANNOTATION_NAME_BY_PACKAGE;
import static es.startuphero.checkstyle.util.AnnotationUtils.hasAnnotation;
import static es.startuphero.checkstyle.util.ClassUtils.getClassName;
import static es.startuphero.checkstyle.util.ClassUtils.getClassOf;
import static es.startuphero.checkstyle.util.ClassUtils.getImportSimpleFullNameMap;
import static es.startuphero.checkstyle.util.CommonUtils.getPackageName;
import static es.startuphero.checkstyle.util.MethodUtils.getMethodName;
import static es.startuphero.checkstyle.util.MethodUtils.getParameterTypes;
import static es.startuphero.checkstyle.util.MethodUtils.isMethodOverriden;

package es.startuphero.checkstyle.checks.annotation;



/**
 * @author ozlem.ulag
 */
public class MissingOverrideCheck extends AbstractCheck {

  /**
   * A key is pointing to the warning message text in "messages.properties" file.
   */
  private static final String MSG_KEY = "missing.override";

  private String packageName;

  private Map<String, String> importSimpleFullNameMap;

  @Override
  public int[] getDefaultTokens() {
    return getAcceptableTokens();
  }

  @Override
  public int[] getAcceptableTokens() {
    return new int[] {TokenTypes.METHOD_DEF};
  }

  @Override
  public int[] getRequiredTokens() {
    return getAcceptableTokens();
  }

  @Override
  public void beginTree(DetailAST rootAst) {
    packageName = getPackageName(rootAst);
    importSimpleFullNameMap = getImportSimpleFullNameMap(rootAst);