/**
   * @param to
   * @param name
   * @return <code>true</code> if the name is equal to the fromName, or if the name represents a
   *     superclass or superinterface of the fromName, <code>false</code> otherwise
   */
  private boolean isAssignableTo(DotName name, Class<?> to) {
    if (to.getName().equals(name.toString())) {
      return true;
    }
    if (OBJECT_NAME.equals(name)) {
      return false; // there's nothing assignable from Object.class except for Object.class
    }

    ClassInfo fromClassInfo = index.getClassByName(name);
    if (fromClassInfo == null) {
      // We reached a class that is not in the index. Let's use reflection.
      final Class<?> clazz = loadClass(name.toString());
      return to.isAssignableFrom(clazz);
    }

    DotName superName = fromClassInfo.superName();

    if (superName != null && isAssignableTo(superName, to)) {
      return true;
    }

    if (fromClassInfo.interfaces() != null) {
      for (DotName interfaceName : fromClassInfo.interfaces()) {
        if (isAssignableTo(interfaceName, to)) {
          return true;
        }
      }
    }
    return false;
  }
  private boolean containsAnnotation(
      ClassInfo classInfo,
      DotName requiredAnnotationName,
      Class<? extends Annotation> requiredAnnotation) {
    // Type and members
    if (classInfo.annotations().containsKey(requiredAnnotationName)) {
      return true;
    }
    // Meta-annotations
    for (DotName annotation : classInfo.annotations().keySet()) {
      try {
        if (annotationClassAnnotationsCache
            .get(annotation)
            .contains(requiredAnnotationName.toString())) {
          return true;
        }
      } catch (ExecutionException e) {
        throw new RuntimeException(e);
      }
    }
    // Superclass
    final DotName superName = classInfo.superName();

    if (superName != null && !OBJECT_NAME.equals(superName)) {
      final ClassInfo superClassInfo = index.getClassByName(superName);
      if (superClassInfo == null) {
        // we are accessing a class that is outside of the jandex index
        // fallback to using reflection
        return SEReflections.containsAnnotation(
            loadClass(superName.toString()), requiredAnnotation);
      }
      if (containsAnnotation(superClassInfo, requiredAnnotationName, requiredAnnotation)) {
        return true;
      }
    }
    return false;
  }
 // @Table, @CollectionTable, @JoinTable, @SecondaryTable
 private void overrideSchemaCatalogByDefault(
     DotName annName,
     Map<DotName, List<AnnotationInstance>> indexedAnnotationMap,
     EntityMappingsMocker.Default defaults) {
   List<AnnotationInstance> annotationInstanceList = indexedAnnotationMap.get(annName);
   if (annotationInstanceList == null || annotationInstanceList.isEmpty()) {
     return;
   }
   List<AnnotationInstance> newAnnotationInstanceList =
       new ArrayList<AnnotationInstance>(annotationInstanceList.size());
   for (AnnotationInstance annotationInstance : annotationInstanceList) {
     if (annName.equals(IndexedAnnotationFilter.SECONDARY_TABLES)) {
       AnnotationInstance[] secondaryTableAnnotationInstanceArray =
           annotationInstance.value().asNestedArray();
       AnnotationValue[] newAnnotationValueArray =
           new AnnotationValue[secondaryTableAnnotationInstanceArray.length];
       for (int i = 0; i < secondaryTableAnnotationInstanceArray.length; i++) {
         newAnnotationValueArray[i] =
             MockHelper.nestedAnnotationValue(
                 "",
                 overrideSchemaCatalogByDefault(
                     secondaryTableAnnotationInstanceArray[i], defaults));
       }
       AnnotationInstance secondaryTablesAnnotationInstance =
           MockHelper.create(
               annName,
               annotationInstance.target(),
               new AnnotationValue[] {
                 AnnotationValue.createArrayValue("value", newAnnotationValueArray)
               });
       newAnnotationInstanceList.add(secondaryTablesAnnotationInstance);
     } else {
       newAnnotationInstanceList.add(overrideSchemaCatalogByDefault(annotationInstance, defaults));
     }
   }
   indexedAnnotationMap.put(annName, newAnnotationInstanceList);
 }