public static function getBestMatch(ActionKeyProvider $actionKeyProvider, $resource, $context, $action) {
    $hasResource = strlen($resource) > 0;
    $hasContext = strlen($context) > 0;
    $hasAction = strlen($action) > 0;

    // check resource?context?action
    if ($hasResource && $hasContext && $hasAction) {
      $key = self::createKey($resource, $context, $action);
      if ($actionKeyProvider->containsKey($key)) {
        return $key;
      }
    }

    // check resource??action
    if ($hasResource && $hasAction) {
      $key = self::createKey($resource, '', $action);
      if ($actionKeyProvider->containsKey($key)) {
        return $key;
      }
    }

    // check resource?context?
    if ($hasResource && $hasContext) {
      $key = self::createKey($resource, $context, '');
      if ($actionKeyProvider->containsKey($key)) {
        return $key;
      }
    }

    // check ?context?action
    if ($hasContext && $hasAction) {
      $key = self::createKey('', $context, $action);
      if ($actionKeyProvider->containsKey($key)) {
        return $key;
      }
    }

    // check ??action
    if ($hasAction) {
      $key = self::createKey('', '', $action);
      if ($actionKeyProvider->containsKey($key)) {
        return $key;
      }
    }

    // check resource??
    if ($hasResource) {
      $key = self::createKey($resource, '', '');
      if ($actionKeyProvider->containsKey($key)) {
        return $key;
      }
    }

    // check ?context?
    if ($hasContext) {
      $key = self::createKey('', $context, '');
      if ($actionKeyProvider->containsKey($key)) {
        return $key;
      }
    }

    // check ??
    $key = self::createKey('', '', '');
    if ($actionKeyProvider->containsKey($key)) {
      return $key;
    }

    // no key found for requested key
    return '';
  }