1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package io.wcm.wcm.ui.granite.util;
21
22 import java.util.HashMap;
23 import java.util.Map;
24
25 import org.apache.commons.lang3.StringUtils;
26 import org.apache.commons.lang3.Strings;
27 import org.apache.sling.api.SlingHttpServletRequest;
28 import org.apache.sling.api.resource.ResourceResolver;
29 import org.jetbrains.annotations.NotNull;
30 import org.osgi.annotation.versioning.ProviderType;
31
32 import com.adobe.granite.ui.components.ComponentHelper;
33 import com.adobe.granite.ui.components.Config;
34 import com.adobe.granite.ui.components.ExpressionHelper;
35 import com.day.text.Text;
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 @ProviderType
60 public final class RootPathResolver {
61
62 static final String PN_ROOT_PATH = "rootPath";
63 static final String PN_APPEND_PATH = "appendPath";
64 static final String PN_FALLBACK_PATH = "fallbackRootPath";
65 static final String DEFAULT_FALLBACK_ROOT_PATH = "/";
66
67 private final ComponentHelper cmp;
68 private final Config cfg;
69 private final ExpressionHelper ex;
70 private final SlingHttpServletRequest request;
71 private final ResourceResolver resourceResolver;
72
73 private RootPathDetector rootPathDetector;
74 private String fallbackRootPath = DEFAULT_FALLBACK_ROOT_PATH;
75
76
77
78
79
80
81 public RootPathResolver(@NotNull ComponentHelper cmp, @NotNull SlingHttpServletRequest request) {
82 this.cmp = cmp;
83 this.cfg = cmp.getConfig();
84 this.ex = cmp.getExpressionHelper();
85 this.request = request;
86 this.resourceResolver = request.getResourceResolver();
87 }
88
89
90
91
92
93 public void setRootPathDetector(@NotNull RootPathDetector rootPathDetector) {
94 this.rootPathDetector = rootPathDetector;
95 }
96
97
98
99
100
101 public void setFallbackRootPath(@NotNull String fallbackRootPath) {
102 this.fallbackRootPath = fallbackRootPath;
103 }
104
105
106
107
108
109 public @NotNull String get() {
110
111 String rootPath = getRootPath();
112
113
114 rootPath = appendPath(rootPath);
115
116
117 return getExistingPath(rootPath);
118 }
119
120
121
122
123
124 public Map<String, Object> getOverrideProperties() {
125 Map<String, Object> props = new HashMap<>();
126 props.put(PN_ROOT_PATH, get());
127 props.put(PN_APPEND_PATH, "");
128 props.put(PN_FALLBACK_PATH, "");
129 return props;
130 }
131
132
133
134
135 private @NotNull String getRootPath() {
136
137
138 String rootPath = ex.getString(cfg.get(PN_ROOT_PATH, String.class));
139 if (StringUtils.isNotBlank(rootPath)) {
140 return rootPath;
141 }
142
143
144 if (rootPathDetector != null) {
145 rootPath = rootPathDetector.detectRootPath(cmp, request);
146 if (rootPath != null && StringUtils.isNotBlank(rootPath)) {
147 return rootPath;
148 }
149 }
150
151
152 rootPath = ex.getString(cfg.get(PN_FALLBACK_PATH, String.class));
153 if (StringUtils.isNotBlank(rootPath)) {
154 return rootPath;
155 }
156
157
158 return fallbackRootPath;
159 }
160
161
162
163
164
165
166 private @NotNull String appendPath(@NotNull String rootPath) {
167 String appendPath = ex.getString(cfg.get(PN_APPEND_PATH, String.class));
168 if (StringUtils.isBlank(appendPath)) {
169 return rootPath;
170 }
171 StringBuilder combinedPath = new StringBuilder(rootPath);
172 if (!Strings.CS.startsWith(appendPath, "/")) {
173 combinedPath.append("/");
174 }
175 combinedPath.append(appendPath);
176 return combinedPath.toString();
177 }
178
179
180
181
182
183 @NotNull
184 String getExistingPath(@NotNull String rootPath) {
185 if (resourceResolver.getResource(rootPath) == null) {
186 String parentPath = Text.getRelativeParent(rootPath, 1);
187 if (StringUtils.isBlank(parentPath)) {
188 return DEFAULT_FALLBACK_ROOT_PATH;
189 }
190 return getExistingPath(parentPath);
191 }
192 else {
193 return rootPath;
194 }
195 }
196
197 }