class ProfileDefinition {

    protected final Logger logger = LoggerFactory.getLogger(getClass());

    @Setter
    private String profileId = null;

    private final List<String> primaryAttributes = new ArrayList<>();

    private final List<String> secondaryAttributes = new ArrayList<>();

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

    @Setter
    private ProfileFactory profileFactory = parameters -> new CommonProfile();

    @Setter
    private boolean restoreProfileFromTypedId = false;

    /**
     * Return the new built or restored profile.
     *
     * @param parameters some input parameters (the first optional one is the typed id)
     * @return the new built or restored profile
     */
    public UserProfile newProfile(final Object... parameters) {
        if (restoreProfileFromTypedId) {
            val typedId = getParameter(parameters, 0);
            if (typedId instanceof String sTypedId) {
                logger.debug("Building user profile based on typedId: {}", typedId);
                if (sTypedId.contains(Pac4jConstants.TYPED_ID_SEPARATOR)) {
                    val profileClass = substringBefore(sTypedId, Pac4jConstants.TYPED_ID_SEPARATOR);
                    for (val profileClassPrefix : ProfileHelper.getProfileClassPrefixes()) {
                        if (profileClass.startsWith(profileClassPrefix)) {
                            try {
                                return ProfileHelper.buildUserProfileByClassCompleteName(profileClass);
                            } catch (final TechnicalException e) {
                                logger.error("Cannot build instance for class name: {}", profileClass, e);
                            }
                        }
                    }
                }
            }
        }
        return profileFactory.apply(parameters);
    }

    /**
     * <p>getParameter.</p>
     *
     * @param parameters an array of {@link Object} objects
     * @param num a int
     * @return a {@link Object} object
     */
    protected Object getParameter(final Object[] parameters, final int num) {<FILL_FUNCTION_BODY>}

    /**
     * Convert a profile or authentication attribute, if necessary, and add it to the profile.
     *
     * @param profile The profile.
     * @param attributeLocation Location of the attribute inside the profile: classic profile attribute, authentication attribute, ...
     * @param name The attribute name.
     * @param value The attribute value.
     */
    public void convertAndAdd(final UserProfile profile, final AttributeLocation attributeLocation, final String name,
            final Object value) {
        if (value != null) {
            final Object convertedValue;
            val converter = this.converters.get(name);
            if (converter != null) {
                convertedValue = converter.convert(value);
                if (convertedValue != null) {
                    logger.debug("converted to => key: {} / value: {} / {}", name, convertedValue, convertedValue.getClass());
                }
            } else {
                convertedValue = value;
                logger.debug("no conversion => key: {} / value: {} / {}", name, convertedValue, convertedValue.getClass());
            }

            if (attributeLocation.equals(AUTHENTICATION_ATTRIBUTE)) {
                profile.addAuthenticationAttribute(name, convertedValue);
            } else {
                profile.addAttribute(name, convertedValue);
            }
        }
    }

    /**
     * Convert the profile and authentication attributes, if necessary, and add them to the profile.
     *
     * @param profile The profile.
     * @param profileAttributes The profile attributes. May be {@code null}.
     * @param authenticationAttributes The authentication attributes. May be {@code null}.
     */
    public void convertAndAdd(final UserProfile profile,
            final Map<String, Object> profileAttributes,
            final Map<String, Object> authenticationAttributes) {
        if (profileAttributes != null) {
            profileAttributes.entrySet()
                .forEach(entry -> convertAndAdd(profile, PROFILE_ATTRIBUTE, entry.getKey(), entry.getValue()));
        }
        if (authenticationAttributes != null) {
            authenticationAttributes.entrySet()
                .forEach(entry -> convertAndAdd(profile, AUTHENTICATION_ATTRIBUTE, entry.getKey(), entry.getValue()));
        }
    }


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

    /**
     * Add an attribute as a secondary one and its converter.
     *
     * @param name name of the attribute
     * @param converter converter
     */
    protected void secondary(final String name, final AttributeConverter converter) {
        secondaryAttributes.add(name);
        converters.put(name, converter);
    }
}

        if (parameters != null && parameters.length >= num) {
            return parameters[num];
        } else {
            return null;
        }
    
<no_super_class>