class RequestImpl implements Request {

    public Variant selectVariant(List<Variant> vars) throws IllegalArgumentException {
        if (vars == null || vars.isEmpty()) {
            throw new IllegalArgumentException("List of Variants is either null or empty");
        }
        List<MediaType> acceptMediaTypes = headers.getAcceptableMediaTypes();
        List<Locale> acceptLangs = headers.getAcceptableLanguages();
        List<String> acceptEncs = parseAcceptEnc(
            headers.getRequestHeaders().getFirst(HttpHeaders.ACCEPT_ENCODING));
        List<Variant> requestVariants = sortAllCombinations(acceptMediaTypes, acceptLangs, acceptEncs);
        List<Object> varyValues = new LinkedList<>();
        for (Variant requestVar : requestVariants) {
            for (Variant var : vars) {
                MediaType mt = var.getMediaType();
                Locale lang = var.getLanguage();
                String enc = var.getEncoding();

                boolean mtMatched = mt == null || requestVar.getMediaType().isCompatible(mt);
                if (mtMatched) {
                    handleVaryValues(varyValues, HttpHeaders.ACCEPT);
                }

                boolean langMatched = lang == null || isLanguageMatched(requestVar.getLanguage(), lang);
                if (langMatched) {
                    handleVaryValues(varyValues, HttpHeaders.ACCEPT_LANGUAGE);
                }

                boolean encMatched = acceptEncs.isEmpty() || enc == null 
                    || isEncMatached(requestVar.getEncoding(), enc);
                if (encMatched) {
                    handleVaryValues(varyValues, HttpHeaders.ACCEPT_ENCODING);
                }

                if (mtMatched && encMatched && langMatched) {
                    addVaryHeader(varyValues);
                    return var;
                }
            }
        }
        return null;
    }

    public  RequestImpl(Message m);

}