RootPathResolver.java
- /*
- * #%L
- * wcm.io
- * %%
- * Copyright (C) 2019 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;
- import java.util.HashMap;
- import java.util.Map;
- import org.apache.commons.lang3.StringUtils;
- import org.apache.sling.api.SlingHttpServletRequest;
- import org.apache.sling.api.resource.ResourceResolver;
- import org.jetbrains.annotations.NotNull;
- import org.osgi.annotation.versioning.ProviderType;
- import com.adobe.granite.ui.components.ComponentHelper;
- import com.adobe.granite.ui.components.Config;
- import com.adobe.granite.ui.components.ExpressionHelper;
- import com.day.text.Text;
- /**
- * Helper class for path-based GraniteUI components to resolve the root path.
- * <p>
- * Resolution order for root path detection:
- * </p>
- * <ul>
- * <li>Reads configured root path from <code>rootPath</code> property</li>
- * <li>Calls the provided root path detector implementation to detect root path from context</li>
- * <li>Reads fallback root path from <code>fallbackRootPath</code> property</li>
- * <li>Uses fallback root path provided for this instance</li>
- * <li>Fallback to "/"</li>
- * </ul>
- * <p>
- * Additionally the root path is modified:
- * </p>
- * <ul>
- * <li>If an <code>appendPath</code> property is configured it is appended to the detected root path</li>
- * <li>Than it is checked if the root path is valid - if not the next-valid parent path is returned</li>
- * </ul>
- */
- @ProviderType
- public final class RootPathResolver {
- static final String PN_ROOT_PATH = "rootPath";
- static final String PN_APPEND_PATH = "appendPath";
- static final String PN_FALLBACK_PATH = "fallbackRootPath";
- static final String DEFAULT_FALLBACK_ROOT_PATH = "/";
- private final ComponentHelper cmp;
- private final Config cfg;
- private final ExpressionHelper ex;
- private final SlingHttpServletRequest request;
- private final ResourceResolver resourceResolver;
- private RootPathDetector rootPathDetector;
- private String fallbackRootPath = DEFAULT_FALLBACK_ROOT_PATH;
- /**
- * @param cmp Component helper
- * @param request Request
- */
- public RootPathResolver(@NotNull ComponentHelper cmp, @NotNull SlingHttpServletRequest request) {
- this.cmp = cmp;
- this.cfg = cmp.getConfig();
- this.ex = cmp.getExpressionHelper();
- this.request = request;
- this.resourceResolver = request.getResourceResolver();
- }
- /**
- * @param rootPathDetector For detecting root path from context
- */
- public void setRootPathDetector(@NotNull RootPathDetector rootPathDetector) {
- this.rootPathDetector = rootPathDetector;
- }
- /**
- * @param fallbackRootPath Fallback root path that is used if none is configured
- */
- public void setFallbackRootPath(@NotNull String fallbackRootPath) {
- this.fallbackRootPath = fallbackRootPath;
- }
- /**
- * Get the resolved and validated root path.
- * @return Root path.
- */
- public @NotNull String get() {
- // get configured or detected or fallback root path
- String rootPath = getRootPath();
- // append path if configured
- rootPath = appendPath(rootPath);
- // resolve to existing path
- return getExistingPath(rootPath);
- }
- /**
- * Get map of override properties for super component based on the wcm.io Granite UI Extensions PathField.
- * @return Path properties
- */
- public Map<String, Object> getOverrideProperties() {
- Map<String, Object> props = new HashMap<>();
- props.put(PN_ROOT_PATH, get());
- props.put(PN_APPEND_PATH, "");
- props.put(PN_FALLBACK_PATH, "");
- return props;
- }
- /**
- * @return Configured or detected root path or fallback path
- */
- private @NotNull String getRootPath() {
- // check for configured root path
- String rootPath = ex.getString(cfg.get(PN_ROOT_PATH, String.class));
- if (StringUtils.isNotBlank(rootPath)) {
- return rootPath;
- }
- // call root path detector
- if (rootPathDetector != null) {
- rootPath = rootPathDetector.detectRootPath(cmp, request);
- if (rootPath != null && StringUtils.isNotBlank(rootPath)) {
- return rootPath;
- }
- }
- // check for configured fallback path
- rootPath = ex.getString(cfg.get(PN_FALLBACK_PATH, String.class));
- if (StringUtils.isNotBlank(rootPath)) {
- return rootPath;
- }
- // fallback to default fallback path
- return fallbackRootPath;
- }
- /**
- * Appends the "appendPath" if configured.
- * @param rootPath Root path
- * @return Path with appendix
- */
- private @NotNull String appendPath(@NotNull String rootPath) {
- String appendPath = ex.getString(cfg.get(PN_APPEND_PATH, String.class));
- if (StringUtils.isBlank(appendPath)) {
- return rootPath;
- }
- StringBuilder combinedPath = new StringBuilder(rootPath);
- if (!StringUtils.startsWith(appendPath, "/")) {
- combinedPath.append("/");
- }
- combinedPath.append(appendPath);
- return combinedPath.toString();
- }
- /**
- * Make sure the root path exists. If it does not exist go up to parent hierarchy until it returns an
- * existing resource path.
- */
- @NotNull
- String getExistingPath(@NotNull String rootPath) {
- if (resourceResolver.getResource(rootPath) == null) {
- String parentPath = Text.getRelativeParent(rootPath, 1);
- if (StringUtils.isBlank(parentPath)) {
- return DEFAULT_FALLBACK_ROOT_PATH;
- }
- return getExistingPath(parentPath);
- }
- else {
- return rootPath;
- }
- }
- }