public static function evaluateJoinOptions(
            ITraversable $traversable,
            Common\Join\Options $join,
            Queries\IResolvedParameterRegistry $resolvedParameters
    ) {
        $values             = self::evaluateSource($join->getSource(), $resolvedParameters);
        $joiningTraversable = $join->isGroupJoin() ? $traversable->groupJoin($values) : $traversable->join($values);

        if ($join->hasFilter()) {
            $filter = $join->getFilter();

            if ($filter instanceof Common\Join\Filter\Custom) {
                $joiningTraversable = $joiningTraversable->on(
                        $resolvedParameters[$filter->getOnFunction()->getCallableId()]
                );
            } elseif ($filter instanceof Common\Join\Filter\Equality) {
                $joiningTraversable = $joiningTraversable->onEquality(
                        $resolvedParameters[$filter->getOuterKeyFunction()->getCallableId()],
                        $resolvedParameters[$filter->getInnerKeyFunction()->getCallableId()]
                );
            }
        }

        if ($join->hasDefault()) {
            $joiningTraversable = $joiningTraversable->withDefault(
                    $resolvedParameters[$join->getDefaultValueId()],
                    $resolvedParameters[$join->getDefaultKeyId()]
            );
        }

        return $joiningTraversable;
    }