@Override
    public Principal resolve(final Credential credential, final Optional<Principal> currentPrincipal,
                             final Optional<AuthenticationHandler> handler, final Optional<Service> service) throws Throwable {

        LOGGER.trace("Attempting to resolve a principal via [{}]", getName());
        var principalId = extractPrincipalId(credential, currentPrincipal);
        if (StringUtils.isBlank(principalId)) {
            LOGGER.debug("Principal id [{}] could not be found", principalId);
            return null;
        }
        if (context.getPrincipalNameTransformer() != null) {
            principalId = context.getPrincipalNameTransformer().transform(principalId);
        }
        LOGGER.trace("Creating principal for [{}]", principalId);
        if (context.isResolveAttributes()) {
            val attributes = retrievePersonAttributes(principalId, credential,
                currentPrincipal, new HashMap<>(), service, handler);
            if (attributes == null || attributes.isEmpty()) {
                LOGGER.debug("Principal id [{}] did not specify any attributes", principalId);
                if (!context.isReturnNullIfNoAttributes()) {
                    val principal = buildResolvedPrincipal(principalId, new HashMap<>(), credential, currentPrincipal, handler);
                    LOGGER.debug("Returning the principal with id [{}] without any attributes", principal);
                    return principal;
                }
                LOGGER.debug("[{}] is configured to return null if no attributes are found for [{}]", getClass().getName(), principalId);
                return null;
            }
            LOGGER.debug("Retrieved [{}] attribute(s) from the repository", attributes.size());
            val result = convertPersonAttributesToPrincipal(principalId, currentPrincipal, attributes);
            if (!result.isSuccess() && context.isReturnNullIfNoAttributes()) {
                LOGGER.warn("Principal resolution is unable to produce a result and will return null");
                return null;
            }

            val principal = buildResolvedPrincipal(result.getPrincipalId(), result.getAttributes(),
                credential, currentPrincipal, handler);
            LOGGER.debug("Final resolved principal by [{}] is [{}]", getName(), principal);
            return principal;
        }
        val principal = buildResolvedPrincipal(principalId, new HashMap<>(),
            credential, currentPrincipal, handler);
        LOGGER.debug("Final resolved principal by [{}] without resolving attributes is [{}]", getName(), principal);
        return principal;
    }
Resolves principals by querying a data source using the Person Directory API.
The {@link Principal#getAttributes()} are populated by the results of the
query and the principal ID may optionally be set by proving an attribute whose first non-null value is used;
otherwise the credential ID is used for the principal ID.

@author Marvin S. Addison
@since 4.0.0
support/cas-server-support-person-directory-core/src/main/java/org/apereo/cas/authentication/principal/resolvers/PersonDirectoryPrincipalResolver.java