class SignedJwt {

    public static SignedJwt parseToken(String tokenContent) {
        Errors.Collector collector = Errors.collector();

        Matcher matcher = JWT_PATTERN.matcher(tokenContent);
        if (matcher.matches()) {
            String headerBase64 = matcher.group(1);
            String payloadBase64 = matcher.group(2);
            String signatureBase64 = matcher.group(3);

            // these all can fail
            String headerJsonString = decode(headerBase64, collector, "JWT header");
            String payloadJsonString = decode(payloadBase64, collector, "JWT payload");
            byte[] signatureBytes = decodeBytes(signatureBase64, collector, "JWT signature");

            // if failed, do not continue
            collector.collect().checkValid();

            String signedContent = headerBase64 + '.' + payloadBase64;

            JsonObject headerJson = parseJson(headerJsonString, collector, headerBase64, "JWT header");
            JsonObject contentJson = parseJson(payloadJsonString, collector, payloadBase64, "JWT payload");

            collector.collect().checkValid();

            return new SignedJwt(
                    tokenContent,
                    headerJson,
                    contentJson,
                    signedContent.getBytes(StandardCharsets.UTF_8),
                    signatureBytes);
        } else {
            throw new JwtException("Not a JWT token: " + tokenContent);
        }
    }

    private  SignedJwt(String tokenContent, JsonObject headerJson, JsonObject payloadJson, byte[] signedBytes, byte[] signature);

}