View Javadoc
1   /*
2    * #%L
3    * wcm.io
4    * %%
5    * Copyright (C) 2025 wcm.io
6    * %%
7    * Licensed under the Apache License, Version 2.0 (the "License");
8    * you may not use this file except in compliance with the License.
9    * You may obtain a copy of the License at
10   *
11   *      http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   * #L%
19   */
20  package io.wcm.wcm.ui.granite.util.impl;
21  
22  import java.util.Arrays;
23  import java.util.Collections;
24  import java.util.List;
25  import java.util.Objects;
26  import java.util.stream.Collectors;
27  
28  import org.apache.commons.collections4.Predicate;
29  import org.apache.sling.api.resource.Resource;
30  import org.jetbrains.annotations.NotNull;
31  import org.jetbrains.annotations.Nullable;
32  import org.osgi.framework.BundleContext;
33  import org.osgi.framework.ServiceReference;
34  import org.slf4j.Logger;
35  import org.slf4j.LoggerFactory;
36  
37  /**
38   * Gets predicate instances from AEM PredicateProvider.
39   *
40   * <p>
41   * Tries to get them from latest implementation from <code>com.day.cq.commons.predicates.PredicateProvider</code>
42   * first (introduced in AEMaaCS API in 2024), and if that's not available, falls back to
43   * <code>com.day.cq.commons.predicate.PredicateProvider</code> (also available in AEM 6.x).
44   * </p>
45   */
46  public final class PredicateProviderUtils {
47  
48    private static final String PREDICATE_PROVIDER_CLASS_NAME_LATEST = "com.day.cq.commons.predicates.PredicateProvider";
49    private static final String PREDICATE_PROVIDER_CLASS_NAME_LEGACY = "com.day.cq.commons.predicate.PredicateProvider";
50  
51    private static final Logger log = LoggerFactory.getLogger(PredicateProviderUtils.class);
52  
53    private PredicateProviderUtils() {
54      // static methods only
55    }
56  
57    /**
58     * Get list of predicates for given filter names.
59     * @param filter Array of filter names
60     * @param bundleContext OSGi bundle context
61     * @return List of predicates
62     */
63    @SuppressWarnings({
64        "java:S2583", "null", // filter may be null
65        "PMD.AvoidCatchingGenericException"
66    })
67    public static @NotNull List<Predicate<Resource>> toPredicates(@NotNull String @Nullable [] filter, @NotNull BundleContext bundleContext) {
68      if (filter == null || filter.length == 0) {
69        return Collections.emptyList();
70      }
71      try (PredicateProviderWrapper predicateProvider = getPredicateProvider(bundleContext)) {
72        return Arrays.asList(filter).stream()
73          .filter(Objects::nonNull)
74          .map(item -> {
75            Predicate<Resource> predicate = predicateProvider.getPredicate(item);
76            if (predicate != null) {
77              return predicate;
78            }
79            else {
80              log.warn("Unable to find predicate implementation for filter: {}", item);
81              return null;
82            }
83          })
84          .filter(Objects::nonNull)
85          .collect(Collectors.toList());
86      }
87      catch (Exception ex) {
88        log.warn("Unable to close predicate provider.", ex);
89        return Collections.emptyList();
90      }
91    }
92  
93    private static @NotNull PredicateProviderWrapper getPredicateProvider(@NotNull BundleContext bundleContext) {
94      ServiceReference<?> serviceReference = bundleContext.getServiceReference(PREDICATE_PROVIDER_CLASS_NAME_LATEST);
95      if (serviceReference != null) {
96        log.debug("Using latest PredicateProvider implementation: {}", PREDICATE_PROVIDER_CLASS_NAME_LATEST);
97        return new LatestPredicateProviderWrapper(serviceReference, bundleContext);
98      }
99      serviceReference = bundleContext.getServiceReference(PREDICATE_PROVIDER_CLASS_NAME_LEGACY);
100     if (serviceReference != null) {
101       log.debug("Using legacy PredicateProvider implementation: {}", PREDICATE_PROVIDER_CLASS_NAME_LEGACY);
102       return new LegacyPredicateProviderWrapper(serviceReference, bundleContext);
103     }
104     log.warn("No PredicateProvider implementation found.");
105     return new FallbackPredicateProviderWrapper();
106   }
107 
108 }