PredicateProviderUtils.java
/*
* #%L
* wcm.io
* %%
* Copyright (C) 2025 wcm.io
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
package io.wcm.wcm.ui.granite.util.impl;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import org.apache.commons.collections4.Predicate;
import org.apache.sling.api.resource.Resource;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Gets predicate instances from AEM PredicateProvider.
*
* <p>
* Tries to get them from latest implementation from <code>com.day.cq.commons.predicates.PredicateProvider</code>
* first (introduced in AEMaaCS API in 2024), and if that's not available, falls back to
* <code>com.day.cq.commons.predicate.PredicateProvider</code> (also available in AEM 6.x).
* </p>
*/
public final class PredicateProviderUtils {
private static final String PREDICATE_PROVIDER_CLASS_NAME_LATEST = "com.day.cq.commons.predicates.PredicateProvider";
private static final String PREDICATE_PROVIDER_CLASS_NAME_LEGACY = "com.day.cq.commons.predicate.PredicateProvider";
private static final Logger log = LoggerFactory.getLogger(PredicateProviderUtils.class);
private PredicateProviderUtils() {
// static methods only
}
/**
* Get list of predicates for given filter names.
* @param filter Array of filter names
* @param bundleContext OSGi bundle context
* @return List of predicates
*/
@SuppressWarnings({ "java:S2583", "null" }) // filter may be null
public static @NotNull List<Predicate<Resource>> toPredicates(@NotNull String @Nullable [] filter, @NotNull BundleContext bundleContext) {
if (filter == null || filter.length == 0) {
return Collections.emptyList();
}
try (PredicateProviderWrapper predicateProvider = getPredicateProvider(bundleContext)) {
return Arrays.asList(filter).stream()
.filter(Objects::nonNull)
.map(item -> {
Predicate<Resource> predicate = predicateProvider.getPredicate(item);
if (predicate != null) {
return predicate;
}
else {
log.warn("Unable to find predicate implementation for filter: {}", item);
return null;
}
})
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
catch (Exception ex) {
log.warn("Unable to close predicate provider.", ex);
return Collections.emptyList();
}
}
private static @NotNull PredicateProviderWrapper getPredicateProvider(@NotNull BundleContext bundleContext) {
ServiceReference<?> serviceReference = bundleContext.getServiceReference(PREDICATE_PROVIDER_CLASS_NAME_LATEST);
if (serviceReference != null) {
log.debug("Using latest PredicateProvider implementation: {}", PREDICATE_PROVIDER_CLASS_NAME_LATEST);
return new LatestPredicateProviderWrapper(serviceReference, bundleContext);
}
serviceReference = bundleContext.getServiceReference(PREDICATE_PROVIDER_CLASS_NAME_LEGACY);
if (serviceReference != null) {
log.debug("Using legacy PredicateProvider implementation: {}", PREDICATE_PROVIDER_CLASS_NAME_LEGACY);
return new LegacyPredicateProviderWrapper(serviceReference, bundleContext);
}
log.warn("No PredicateProvider implementation found.");
return new FallbackPredicateProviderWrapper();
}
}