class GenericOAuth20ProfileDefinition extends OAuthProfileDefinition {

    private final Map<String,String> profileAttributes = new HashMap<>();

    private String profileUrl = null;
    private Verb profileVerb = null;
    private String firstNodePath = null;

    /**
     * <p>Setter for the field <code>profileVerb</code>.</p>
     *
     * @param value a {@link Verb} object
     */
    public void setProfileVerb(final Verb value) {
        this.profileVerb = value;
    }

    /** {@inheritDoc} */
    @Override
    public Verb getProfileVerb() {
        if (profileVerb != null) {
            return this.profileVerb;
        } else {
            return super.getProfileVerb();
        }
    }

    /**
     * <p>Setter for the field <code>profileUrl</code>.</p>
     *
     * @param profileUrl a {@link String} object
     */
    public void setProfileUrl(final String profileUrl) {
        this.profileUrl = profileUrl;
    }

    /** {@inheritDoc} */
    @Override
    public String getProfileUrl(final Token accessToken, final OAuthConfiguration configuration) {
        return profileUrl;
    }

    /** {@inheritDoc} */
    @Override
    public OAuth20Profile extractUserProfile(final String body) {<FILL_FUNCTION_BODY>}

    /**
     * <p>Getter for the field <code>profileAttributes</code>.</p>
     *
     * @return a {@link Map} object
     */
    public Map<String, String> getProfileAttributes() {
        return this.profileAttributes;
    }

    /**
     * Add an attribute as a primary one and its converter.
     *
     * @param name name of the attribute
     * @param converter converter
     */
    public void profileAttribute(final String name, final AttributeConverter converter) {
        profileAttribute(name, name, converter);
    }

    /**
     * Add an attribute as a primary one and its converter.
     *
     * @param name name of the attribute
     * @param tag json reference
     * @param converter converter
     */
    public void profileAttribute(final String name, String tag, final AttributeConverter converter) {
        profileAttributes.put(name, tag);
        getConverters().put(name, Objects.requireNonNullElseGet(converter, StringConverter::new));
    }

    /**
     * <p>Getter for the field <code>firstNodePath</code>.</p>
     *
     * @return a {@link String} object
     */
    public String getFirstNodePath() {
        return firstNodePath;
    }

    /**
     * <p>Setter for the field <code>firstNodePath</code>.</p>
     *
     * @param firstNodePath a {@link String} object
     */
    public void setFirstNodePath(final String firstNodePath) {
        this.firstNodePath = firstNodePath;
    }
}

        val profile = new OAuth20Profile();
        val json = JsonHelper.getFirstNode(body, getFirstNodePath());
        if (json != null) {
            profile.setId(ProfileHelper.sanitizeIdentifier(JsonHelper.getElement(json, getProfileId())));
            for (val attribute : getPrimaryAttributes()) {
                convertAndAdd(profile, PROFILE_ATTRIBUTE, attribute, JsonHelper.getElement(json, attribute));
            }
            for (val attribute : getSecondaryAttributes()) {
                convertAndAdd(profile, PROFILE_ATTRIBUTE, attribute, JsonHelper.getElement(json, attribute));
            }
            for (val entry : getProfileAttributes().entrySet()) {
                val key = entry.getKey();
                val value = entry.getValue();
                convertAndAdd(profile, PROFILE_ATTRIBUTE, key, JsonHelper.getElement(json, value));
            }

        } else {
            raiseProfileExtractionJsonError(body);
        }
        return profile;
    
<methods>public void <init>() ,public void <init>(org.pac4j.core.profile.factory.ProfileFactory) ,public abstract org.pac4j.core.profile.CommonProfile extractUserProfile(java.lang.String) ,public abstract java.lang.String getProfileUrl(com.github.scribejava.core.model.Token, org.pac4j.oauth.config.OAuthConfiguration) ,public com.github.scribejava.core.model.Verb getProfileVerb() <variables>