ParsysConfigManagerImpl.java
- /*
- * #%L
- * wcm.io
- * %%
- * Copyright (C) 2014 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.parsys.componentinfo.impl;
- import java.util.ArrayList;
- import java.util.Collection;
- import java.util.Collections;
- import java.util.List;
- import java.util.Map;
- import java.util.regex.Pattern;
- import org.apache.commons.collections4.IterableUtils;
- import org.apache.commons.lang3.StringUtils;
- import org.apache.sling.api.resource.Resource;
- import org.apache.sling.api.resource.ResourceResolver;
- import org.apache.sling.commons.osgi.Order;
- import org.apache.sling.commons.osgi.RankedServices;
- import org.jetbrains.annotations.NotNull;
- import org.osgi.service.component.annotations.Component;
- import org.osgi.service.component.annotations.Reference;
- import org.osgi.service.component.annotations.ReferenceCardinality;
- import org.osgi.service.component.annotations.ReferencePolicy;
- import io.wcm.sling.commons.resource.ResourceType;
- import io.wcm.wcm.parsys.componentinfo.ParsysConfig;
- import io.wcm.wcm.parsys.componentinfo.ParsysConfigManager;
- /**
- * Collects paragraph system configurations from repository and OSGi configuration.
- * Apply super resource type based inheritance to both configuration types.
- */
- @Component(service = ParsysConfigManager.class, immediate = true, reference = {
- @Reference(service = ParsysConfig.class, name = "parsysConfig",
- bind = "bindParsysConfig", unbind = "unbindParsysConfig",
- cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
- })
- public final class ParsysConfigManagerImpl implements ParsysConfigManager {
- private final RankedServices<ParsysConfig> osgiParsysConfigs = new RankedServices<>(Order.ASCENDING);
- @Override
- public @NotNull Iterable<ParsysConfig> getParsysConfigs(@NotNull String pageComponentPath, @NotNull ResourceResolver resolver) {
- Resource pageComponentResource = resolver.getResource(pageComponentPath);
- if (pageComponentResource != null) {
- return Collections.unmodifiableCollection(getParsysConfigsWithInheritance(pageComponentResource, resolver));
- }
- else {
- return Collections.emptyList();
- }
- }
- @Override
- public @NotNull Iterable<ParsysConfig> getParsysConfigs(@NotNull final String pageComponentPath, @NotNull final String relativePath,
- @NotNull final ResourceResolver resolver) {
- Iterable<ParsysConfig> configs = getParsysConfigs(pageComponentPath, resolver);
- return IterableUtils.filteredIterable(configs, parsysConfig -> {
- // sanity check
- if (parsysConfig == null || parsysConfig.getPathPattern() == null) {
- return false;
- }
- Pattern pathPattern = parsysConfig.getPathPattern();
- if (pathPattern == null) {
- return false;
- }
- return pathPattern.matcher(relativePath).matches();
- });
- }
- private Collection<ParsysConfig> getParsysConfigs(Resource pageComponentResource) {
- List<ParsysConfig> configs = new ArrayList<>();
- // get first jcr parsys configurations for this page component
- ResourceParsysConfigProvider resourceParsysConfigProvider = new ResourceParsysConfigProvider(pageComponentResource);
- configs.addAll(resourceParsysConfigProvider.getPathDefs());
- // add osgi parsys configurations
- for (ParsysConfig osgiParsysConfig : osgiParsysConfigs) {
- if (ResourceType.equals(pageComponentResource.getPath(), osgiParsysConfig.getPageComponentPath(), pageComponentResource.getResourceResolver())) {
- configs.add(osgiParsysConfig);
- }
- }
- return configs;
- }
- @SuppressWarnings("null")
- private Collection<ParsysConfig> getParsysConfigsWithInheritance(Resource pageComponentResource, ResourceResolver resolver) {
- List<ParsysConfig> configs = new ArrayList<>();
- // get path definitions from this page component
- configs.addAll(getParsysConfigs(pageComponentResource));
- // add path definitions from for super page components
- String resourceSuperType = pageComponentResource.getResourceSuperType();
- if (StringUtils.isNotEmpty(resourceSuperType)) {
- Resource superResource = resolver.getResource(resourceSuperType);
- if (superResource != null) {
- Collection<ParsysConfig> configsFromSupertype = getParsysConfigsWithInheritance(superResource, resolver);
- List<ParsysConfig> inheritedConfigs = new ArrayList<>();
- for (ParsysConfig configFromSupertype : configsFromSupertype) {
- if (existingPathParentConfigAllowsInheritance(configFromSupertype, configs)) {
- inheritedConfigs.add(configFromSupertype);
- }
- }
- configs.addAll(inheritedConfigs);
- }
- }
- return configs;
- }
- private boolean existingPathParentConfigAllowsInheritance(ParsysConfig item, List<ParsysConfig> existingItems) {
- for (ParsysConfig existingItem : existingItems) {
- if (matchesPathParent(item, existingItem) && !existingItem.isInherit()) {
- return false;
- }
- }
- return true;
- }
- private boolean matchesPathParent(ParsysConfig item1, ParsysConfig item2) {
- Pattern pattern1 = item1.getPathPattern();
- Pattern pattern2 = item2.getPathPattern();
- String pathPattern1 = pattern1 != null ? pattern1.pattern() : "";
- String pathPattern2 = pattern2 != null ? pattern2.pattern() : "";
- return pathPattern1.equals(pathPattern2)
- && item1.getParentAncestorLevel() == item2.getParentAncestorLevel()
- && item1.getAllowedParents().equals(item2.getAllowedParents());
- }
- void bindParsysConfig(ParsysConfig service, Map<String, Object> props) {
- osgiParsysConfigs.bind(service, props);
- }
- void unbindParsysConfig(ParsysConfig service, Map<String, Object> props) {
- osgiParsysConfigs.unbind(service, props);
- }
- }