private PersonAttributeDao determineAttributeRepository(final AttributeRepositoryQuery query) {
        if (StringUtils.isNotBlank(query.getTenant())) {
            val tenantDefinition = context.getTenantExtractor().getTenantsManager().findTenant(query.getTenant()).orElseThrow();
            if (!tenantDefinition.getProperties().isEmpty()) {
                val builders = context.getApplicationContext().getBeansOfType(TenantPersonAttributeDaoBuilder.class).values();
                val tenantAttributeRepositories = builders
                    .stream()
                    .map(builder -> builder.build(tenantDefinition))
                    .filter(BeanSupplier::isNotProxy)
                    .flatMap(List::stream)
                    .toList();

                if (!tenantAttributeRepositories.isEmpty()) {
                    val mergingAttributeRepository = new MergingPersonAttributeDaoImpl();
                    mergingAttributeRepository.setEnabled(true);
                    mergingAttributeRepository.setPersonAttributeDaos((List) tenantAttributeRepositories);
                    mergingAttributeRepository.setAttributeMerger(context.getAttributeMerger());
                    return mergingAttributeRepository;
                }
            }
        }
        return context.getAttributeRepository();
    }
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