class JwtGenerator {

    /** Constant <code>INTERNAL_ROLES="$int_roles"</code> */
    public static final String INTERNAL_ROLES = "$int_roles";
    /** Constant <code>INTERNAL_LINKEDID="$int_linkid"</code> */
    public static final String INTERNAL_LINKEDID = "$int_linkid";

    private SignatureConfiguration signatureConfiguration;

    private EncryptionConfiguration encryptionConfiguration;

    private Date expirationTime;

    /**
     * <p>Constructor for JwtGenerator.</p>
     */
    public JwtGenerator() {}

    /**
     * <p>Constructor for JwtGenerator.</p>
     *
     * @param signatureConfiguration a {@link SignatureConfiguration} object
     */
    public JwtGenerator(final SignatureConfiguration signatureConfiguration) {
        this.signatureConfiguration = signatureConfiguration;
    }

    /**
     * <p>Constructor for JwtGenerator.</p>
     *
     * @param signatureConfiguration a {@link SignatureConfiguration} object
     * @param encryptionConfiguration a {@link EncryptionConfiguration} object
     */
    public JwtGenerator(final SignatureConfiguration signatureConfiguration, final EncryptionConfiguration encryptionConfiguration) {
        this.signatureConfiguration = signatureConfiguration;
        this.encryptionConfiguration = encryptionConfiguration;
    }

    /**
     * Generate a JWT from a map of claims.
     *
     * @param claims the map of claims
     * @return the created JWT
     */
    public String generate(final Map<String, Object> claims) {<FILL_FUNCTION_BODY>}

    /**
     * Generate a JWT from a user profile.
     *
     * @param profile the given user profile
     * @return the created JWT
     */
    public String generate(final UserProfile profile) {
        verifyProfile(profile);

        return internalGenerate(buildJwtClaimsSet(profile));
    }

    /**
     * Generate a JWT from a claims set.
     *
     * @param claimsSet the claims set
     * @return the JWT
     */
    protected String internalGenerate(final JWTClaimsSet claimsSet) {
        JWT jwt;
        // signature?
        if (signatureConfiguration == null) {
            jwt = new PlainJWT(claimsSet);
        } else {
            jwt = signatureConfiguration.sign(claimsSet);
        }

        // encryption?
        if (encryptionConfiguration != null) {
            return encryptionConfiguration.encrypt(jwt);
        } else {
            return jwt.serialize();
        }
    }

    /**
     * <p>verifyProfile.</p>
     *
     * @param profile a {@link UserProfile} object
     */
    protected void verifyProfile(final UserProfile profile) {
        CommonHelper.assertNotNull("profile", profile);
        CommonHelper.assertNull(INTERNAL_ROLES, profile.getAttribute(INTERNAL_ROLES));
        CommonHelper.assertNull(INTERNAL_LINKEDID, profile.getAttribute(INTERNAL_LINKEDID));
    }

    /**
     * <p>buildJwtClaimsSet.</p>
     *
     * @param profile a {@link UserProfile} object
     * @return a {@link JWTClaimsSet} object
     */
    protected JWTClaimsSet buildJwtClaimsSet(final UserProfile profile) {
        // claims builder with subject and issue time
        val builder = new JWTClaimsSet.Builder()
                .issueTime(new Date());

        if (this.expirationTime != null) {
            builder.expirationTime(this.expirationTime);
        }

        // add attributes
        val attributes = profile.getAttributes();
        for (val entry : attributes.entrySet()) {
            builder.claim(entry.getKey(), entry.getValue());
        }
        builder.claim(INTERNAL_ROLES, profile.getRoles());
        builder.claim(INTERNAL_LINKEDID, profile.getLinkedId());

        builder.subject(profile.getTypedId());

        // claims
        return builder.build();
    }

    /**
     * <p>Getter for the field <code>expirationTime</code>.</p>
     *
     * @return a {@link Date} object
     */
    public Date getExpirationTime() {
        return new Date(expirationTime.getTime());
    }

    /**
     * <p>Setter for the field <code>expirationTime</code>.</p>
     *
     * @param expirationTime a {@link Date} object
     */
    public void setExpirationTime(final Date expirationTime) {
        this.expirationTime = new Date(expirationTime.getTime());
    }
}

        // claims builder
        val builder = new JWTClaimsSet.Builder();

        // add claims
        for (val entry : claims.entrySet()) {
            builder.claim(entry.getKey(), entry.getValue());
        }
        if (this.expirationTime != null) {
            builder.expirationTime(this.expirationTime);
        }
        return internalGenerate(builder.build());
    
<no_super_class>