class CommonProfile extends BasicUserProfile {

    @Serial
    private static final long serialVersionUID = -1856159870249261877L;

    /**
     * <p>Constructor for CommonProfile.</p>
     */
    public CommonProfile() {
        this(true);
    }

    /**
     * Create a profile with possibility to merge attributes with the same name and collection-type values
     *
     * @param canMergeAttributes if true - merge attributes with the same name and collection-type values, if false -
     * overwrite them
     * @since 3.1.0
     */
    public CommonProfile(final boolean canMergeAttributes) {
        super(canMergeAttributes);
    }

    /**
     * Return the email of the user.
     *
     * @return the email of the user
     */
    @JsonIgnore
    public String getEmail() {
        return getAttributeAsString(CommonProfileDefinition.EMAIL);
    }

    /**
     * Return the first name of the user.
     *
     * @return the first name of the user
     */
    @JsonIgnore
    public String getFirstName() {
        return getAttributeAsString(CommonProfileDefinition.FIRST_NAME);
    }

    /**
     * Return the family name of the user.
     *
     * @return the family name of the user
     */
    @JsonIgnore
    public String getFamilyName() {
        return getAttributeAsString(CommonProfileDefinition.FAMILY_NAME);
    }

    /**
     * Return the displayed name of the user. It can be the username or the first and last names (separated by a space).
     *
     * @return the displayed name of the user
     */
    @JsonIgnore
    public String getDisplayName() {
        return getAttributeAsString(CommonProfileDefinition.DISPLAY_NAME);
    }

    /**
     * {@inheritDoc}
     *
     * Return the username of the user. It can be a login or a specific username.
     */
    @JsonIgnore
    @Override
    public String getUsername() {
        return getAttributeAsString(Pac4jConstants.USERNAME);
    }

    /**
     * Return the gender of the user.
     *
     * @return the gender of the user
     */
    @JsonIgnore
    public Gender getGender() {
        return getAttributeAsType(CommonProfileDefinition.GENDER, Gender.class, Gender.UNSPECIFIED);
    }

    /**
     * Return the locale of the user.
     *
     * @return the locale of the user
     */
    @JsonIgnore
    public Locale getLocale() {
        return getAttributeAsType(CommonProfileDefinition.LOCALE, Locale.class, null);
    }

    /**
     * Return the url of the picture of the user.
     *
     * @return the url of the picture of the user.
     */
    @JsonIgnore
    public URI getPictureUrl() {
        return getAttributeAsType(CommonProfileDefinition.PICTURE_URL, URI.class, null);
    }

    /**
     * Return the url of the profile of the user.
     *
     * @return the url of the profile of the user.
     */
    @JsonIgnore
    public URI getProfileUrl() {
        return getAttributeAsType(CommonProfileDefinition.PROFILE_URL, URI.class, null);
    }

    /**
     * Return the location of the user.
     *
     * @return the location of the user
     */
    @JsonIgnore
    public String getLocation() {
        return getAttributeAsString(CommonProfileDefinition.LOCATION);
    }

    @JsonIgnore
    @Override
    public boolean isExpired() {
        return false;
    }

    /**
     * <p>getAttributeAsString.</p>
     *
     * @param name a {@link String} object
     * @return a {@link String} object
     */
    protected String getAttributeAsString(final String name) {
        val value = getAttribute(name);
        if (value != null) {
            return value.toString();
        }
        else {
            return null;
        }
    }

    /**
     * <p>getAttributeAsType.</p>
     *
     * @param name a {@link String} object
     * @param clazz a {@link Class} object
     * @param defaultValue a T object
     * @param <T> a T class
     * @return a T object
     */
    protected <T> T getAttributeAsType(final String name, Class<T> clazz, T defaultValue) {
        val value = getAttribute(name);
        if (value != null && clazz.isAssignableFrom(value.getClass())) {
            return clazz.cast(value);
        }
        else {
            return defaultValue;
        }
    }

    /**
     * <p>getAttributeAsDate.</p>
     *
     * @param name a {@link String} object
     * @return a {@link Date} object
     */
    protected Date getAttributeAsDate(final String name) {<FILL_FUNCTION_BODY>}
}

        val value = getAttribute(name);
        // it should be a Date, but in case it's a Long (Vertx issue with profiles serialized to JSON and restored)
        if (value instanceof Long l) {
            return new Date(l);
        }
        else if (value instanceof Double d) {
            return new Date(d.longValue());
        }
        else {
            return (Date) getAttribute(name);
        }
    
<methods>public void <init>() ,public void <init>(boolean) ,public void addAttribute(java.lang.String, java.lang.Object) ,public void addAttributes(Map<java.lang.String,java.lang.Object>) ,public void addAuthenticationAttribute(java.lang.String, java.lang.Object) ,public void addAuthenticationAttributes(Map<java.lang.String,java.lang.Object>) ,public void addRole(java.lang.String) ,public void addRoles(Collection<java.lang.String>) ,public java.security.Principal asPrincipal() ,public void build(java.lang.Object, Map<java.lang.String,java.lang.Object>) ,public void build(java.lang.Object, Map<java.lang.String,java.lang.Object>, Map<java.lang.String,java.lang.Object>) ,public boolean containsAttribute(java.lang.String) ,public boolean containsAuthenticationAttribute(java.lang.String) ,public List<java.lang.String> extractAttributeValues(java.lang.String) ,public java.lang.Object getAttribute(java.lang.String) ,public T getAttribute(java.lang.String, Class<T>) ,public Map<java.lang.String,java.lang.Object> getAttributes() ,public java.lang.Object getAuthenticationAttribute(java.lang.String) ,public T getAuthenticationAttribute(java.lang.String, Class<T>) ,public Map<java.lang.String,java.lang.Object> getAuthenticationAttributes() ,public Set<java.lang.String> getRoles() ,public java.lang.String getTypedId() ,public java.lang.String getUsername() ,public boolean isExpired() ,public void readExternal(java.io.ObjectInput) throws java.io.IOException, java.lang.ClassNotFoundException,public void removeAttribute(java.lang.String) ,public void removeAuthenticationAttribute(java.lang.String) ,public void removeLoginData() ,public void setId(java.lang.String) ,public void setRoles(Set<java.lang.String>) ,public void writeExternal(java.io.ObjectOutput) throws java.io.IOException<variables>private Map<java.lang.String,java.lang.Object> attributes,private Map<java.lang.String,java.lang.Object> authenticationAttributes,private final non-sealed boolean canAttributesBeMerged,private java.lang.String clientName,private java.lang.String id,private boolean isRemembered,private java.lang.String linkedId,protected final transient org.slf4j.Logger logger,private Set<java.lang.String> roles,private static final long serialVersionUID