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.resource;
21
22 import java.util.Collections;
23 import java.util.HashMap;
24 import java.util.Iterator;
25 import java.util.LinkedHashMap;
26 import java.util.Map;
27
28 import org.apache.sling.api.resource.Resource;
29 import org.apache.sling.api.resource.ResourceMetadata;
30 import org.apache.sling.api.resource.ResourceResolver;
31 import org.apache.sling.api.resource.SyntheticResource;
32 import org.apache.sling.api.resource.ValueMap;
33 import org.apache.sling.api.wrappers.ValueMapDecorator;
34 import org.jetbrains.annotations.NotNull;
35 import org.osgi.annotation.versioning.ProviderType;
36
37 import com.day.cq.commons.jcr.JcrConstants;
38
39
40
41
42
43
44
45 @ProviderType
46 public final class GraniteUiSyntheticResource extends SyntheticResource {
47
48 private final ValueMap props;
49 private final Map<String, Resource> children;
50
51 private GraniteUiSyntheticResource(ResourceResolver resourceResolver,
52 ResourceMetadata resourceMetadata, String resourceType,
53 ValueMap props, Iterable<Resource> children) {
54 super(resourceResolver, resourceMetadata, resourceType);
55 this.props = props;
56 this.children = childrenMap(children);
57 }
58
59 private GraniteUiSyntheticResource(ResourceResolver resourceResolver,
60 String path,
61 String resourceType,
62 ValueMap props,
63 Iterable<Resource> children) {
64 super(resourceResolver, path, resourceType);
65 this.props = props;
66 this.children = childrenMap(children);
67 }
68
69 private static Map<String, Resource> childrenMap(Iterable<Resource> children) {
70 Map<String, Resource> result = new LinkedHashMap<>();
71 children.forEach(resource -> result.put(resource.getName(), resource));
72 return result;
73 }
74
75 @SuppressWarnings({
76 "unchecked", "null"
77 })
78 @Override
79 public <Type> Type adaptTo(Class<Type> type) {
80 if (ValueMap.class.equals(type)) {
81 return (Type)props;
82 }
83 else {
84 return super.adaptTo(type);
85 }
86 }
87
88 @Override
89 public Iterator<Resource> listChildren() {
90 return children.values().iterator();
91 }
92
93 @Override
94 public Iterable<Resource> getChildren() {
95 return children.values();
96 }
97
98 @Override
99 public boolean hasChildren() {
100 return !children.isEmpty();
101 }
102
103 @Override
104 public Resource getChild(String relPath) {
105
106 Resource child = children.get(relPath);
107 if (child != null) {
108 return child;
109 }
110 return super.getChild(relPath);
111 }
112
113 private void addChild(Resource child) {
114 children.put(child.getName(), child);
115 }
116
117
118
119
120
121
122
123 public static Resource create(@NotNull ResourceResolver resourceResolver, @NotNull ValueMap valueMap) {
124 return create(resourceResolver, "", JcrConstants.NT_UNSTRUCTURED, valueMap);
125 }
126
127
128
129
130
131
132
133
134 public static Resource create(@NotNull ResourceResolver resourceResolver, @NotNull String path, @NotNull String resourceType) {
135 return create(resourceResolver, path, resourceType, ValueMap.EMPTY);
136 }
137
138
139
140
141
142
143
144
145
146 public static Resource create(@NotNull ResourceResolver resourceResolver, @NotNull String path, @NotNull String resourceType,
147 @NotNull ValueMap valueMap) {
148 return new GraniteUiSyntheticResource(resourceResolver,
149 path,
150 resourceType,
151 valueMap,
152 Collections.emptyList());
153 }
154
155
156
157
158
159
160 public static Resource wrap(@NotNull Resource resource) {
161 return wrap(resource, resource.getValueMap(), resource.getChildren());
162 }
163
164
165
166
167
168
169
170 public static Resource wrap(@NotNull Resource resource, @NotNull ValueMap valueMap) {
171 return wrap(resource, valueMap, resource.getChildren());
172 }
173
174
175
176
177
178
179
180
181 public static Resource wrapMerge(@NotNull Resource resource, @NotNull ValueMap valueMap) {
182 Map<String, Object> mergedProperties = new HashMap<>();
183 mergedProperties.putAll(resource.getValueMap());
184 mergedProperties.putAll(valueMap);
185 return wrap(resource, new ValueMapDecorator(mergedProperties), resource.getChildren());
186 }
187
188 private static Resource wrap(Resource resource, ValueMap valueMap, Iterable<Resource> children) {
189 return new GraniteUiSyntheticResource(resource.getResourceResolver(),
190 resource.getResourceMetadata(),
191 resource.getResourceType(),
192 valueMap,
193 children);
194 }
195
196
197
198
199
200
201
202
203 public static Resource child(@NotNull Resource parentResource, @NotNull String name, @NotNull String resourceType) {
204 return child(parentResource, name, resourceType, ValueMap.EMPTY);
205 }
206
207
208
209
210
211
212
213
214
215 public static Resource child(@NotNull Resource parentResource, @NotNull String name, @NotNull String resourceType,
216 @NotNull ValueMap valueMap) {
217 Resource child = new GraniteUiSyntheticResource(parentResource.getResourceResolver(),
218 parentResource.getPath() + "/" + name,
219 resourceType,
220 valueMap,
221 Collections.emptyList());
222 if (parentResource instanceof GraniteUiSyntheticResource) {
223 ((GraniteUiSyntheticResource)parentResource).addChild(child);
224 }
225 else {
226 throw new IllegalArgumentException("Resource is not a GraniteUiSyntheticResource.");
227 }
228 return child;
229 }
230
231
232
233
234
235
236 public static void copySubtree(@NotNull Resource targetParent, @NotNull Resource source) {
237 Resource targetChild = child(targetParent, source.getName(), source.getResourceType(), source.getValueMap());
238 for (Resource sourceChild : source.getChildren()) {
239 copySubtree(targetChild, sourceChild);
240 }
241 }
242
243 }