public int requiresFetch(FieldMetaData fm) {
    if (!includes(fm)) return FETCH_NONE;

    Class<?> type = fm.getRelationType();
    if (type == null) return FETCH_LOAD;
    if (_availableDepth == 0) return FETCH_NONE;

    // we can skip calculating recursion depth if this is a top-level conf:
    // the field is in our fetch groups, so can't possibly not select
    if (_parent == null) return FETCH_LOAD;

    String fieldName = fm.getFullName(false);
    int rdepth = getAvailableRecursionDepth(fm, type, fieldName, false);
    if (rdepth != FetchGroup.DEPTH_INFINITE && rdepth <= 0) return FETCH_NONE;

    if (StringUtils.equals(_directRelationOwner, fieldName)) return FETCH_REF;
    return FETCH_LOAD;
  }
  public FetchConfiguration traverse(FieldMetaData fm) {
    Class<?> type = fm.getRelationType();
    if (type == null) return this;

    FetchConfigurationImpl clone = newInstance(_state);
    clone._parent = this;
    clone._availableDepth = reduce(_availableDepth);
    clone._fromField = fm.getFullName(false);
    clone._fromType = type;
    clone._availableRecursion = getAvailableRecursionDepth(fm, type, fm.getFullName(false), true);
    if (StringUtils.equals(_directRelationOwner, fm.getFullName(false))) clone._load = false;
    else clone._load = _load;

    FieldMetaData owner = fm.getMappedByMetaData();
    if (owner != null && owner.getTypeCode() == JavaTypes.PC)
      clone._directRelationOwner = owner.getFullName(false);

    return clone;
  }