class ContinuationToken implements SignedExpiringToken {

    public static ContinuationToken fromString(String serializedToken) throws MalformedContinuationTokenException {
        Preconditions.checkArgument(!Strings.isNullOrEmpty(serializedToken), "Serialized continuation token should not be null or empty");
        LinkedList<String> tokenParts = Lists.newLinkedList(Splitter.on(SEPARATOR).split(serializedToken));
        try {
            return ContinuationToken.builder()
                    .signature(tokenParts.removeLast())
                    .expirationDate(ZonedDateTime.parse(tokenParts.removeLast(), DateTimeFormatter.ISO_OFFSET_DATE_TIME))
                    .username(Joiner.on(SEPARATOR).join(tokenParts))
                    .build();
        } catch (NoSuchElementException | IllegalArgumentException e) {
            throw new MalformedContinuationTokenException("Token " + serializedToken + " does not have enough parts", e);
        } catch (DateTimeException e) {
            throw new MalformedContinuationTokenException("Token " + serializedToken + " as an incorrect date", e);
        }
    }

    public  ContinuationToken(String username, ZonedDateTime expirationDate, String signature);

}