/**
   * @param <T>
   * @param match_class
   * @param search_key
   * @param use_parent if set to true, the search_key is applied to the search target's parent
   * @param use_other if set to true, the search target is always the opposite of the item of the
   *     element that we check the match_class to
   * @return
   */
  @SuppressWarnings("unchecked")
  private <T extends CatalogType> Collection<T> find(
      Class<T> match_class, CatalogType search_key, boolean use_parent, boolean use_other) {
    if (debug.val)
      LOG.debug(
          String.format(
              "find(match_class=%s, search_key=%s, use_parent=%s, use_other=%s)",
              match_class.getSimpleName(), search_key.fullName(), use_parent, use_other));
    assert (search_key != null) : "Invalid search key";

    Set<T> found = new HashSet<T>();
    final int use_my_idxs[][] = {{0, 0}, {1, 1}};
    final int use_other_idxs[][] = {{0, 1}, {1, 0}};
    int lookup_idxs[][] = (use_other ? use_other_idxs : use_my_idxs);

    // We're looking for Pairs where one of the elements matches the
    // search_key, and
    // the other element is of the same type of match_class
    for (Pair<CatalogType, CatalogType> pair : this) {
      if (trace.val) LOG.trace(pair);
      int ctr = 0;
      for (int idxs[] : lookup_idxs) {
        T cur = (T) pair.get(idxs[0]);
        Class<?> cur_class = pair.get(idxs[0]).getClass();
        List<Class<?>> all_classes = ClassUtil.getSuperClasses(cur_class);
        CatalogType cur_value = (CatalogType) pair.get(idxs[1]);
        if (use_parent) cur_value = cur_value.getParent();

        if (trace.val) {
          LOG.trace("[" + ctr + "] cur: " + cur);
          LOG.trace("[" + ctr + "] class: " + cur_class.equals(match_class) + " " + cur_class);
          LOG.trace("[" + (ctr++) + "] cur_value: " + cur_value);
        }
        if (cur_value != null
            && cur_value.equals(search_key)
            && all_classes.contains(match_class)) {
          found.add(cur);
          break;
        }
      } // FOR
    } // FOR
    return (found);
  }