1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.dam.templating.functions;
35
36 import info.magnolia.dam.api.Asset;
37 import info.magnolia.dam.api.AssetProvider;
38 import info.magnolia.dam.api.AssetProviderRegistry;
39 import info.magnolia.dam.api.AssetProviderRegistry.NoSuchAssetRendererException;
40 import info.magnolia.dam.api.AssetQuery;
41 import info.magnolia.dam.api.AssetRenderer;
42 import info.magnolia.dam.api.AssetRendition;
43 import info.magnolia.dam.api.Folder;
44 import info.magnolia.dam.api.Item;
45 import info.magnolia.dam.api.ItemKey;
46 import info.magnolia.dam.api.PathAwareAssetProvider;
47 import info.magnolia.dam.api.metadata.AssetMetadata;
48 import info.magnolia.dam.api.metadata.AssetMetadataDefinition;
49 import info.magnolia.dam.api.metadata.AssetMetadataRegistry;
50 import info.magnolia.dam.jcr.JcrAsset;
51 import info.magnolia.dam.jcr.JcrAssetProvider;
52 import info.magnolia.dam.jcr.JcrFolder;
53 import info.magnolia.jcr.wrapper.HTMLEscapingNodeWrapper;
54 import info.magnolia.objectfactory.Components;
55
56 import java.beans.BeanInfo;
57 import java.beans.Introspector;
58 import java.beans.PropertyDescriptor;
59 import java.lang.reflect.Method;
60 import java.util.ArrayList;
61 import java.util.Arrays;
62 import java.util.Collections;
63 import java.util.HashMap;
64 import java.util.Iterator;
65 import java.util.List;
66 import java.util.Map;
67 import java.util.Map.Entry;
68
69 import javax.inject.Inject;
70 import javax.inject.Singleton;
71
72 import org.apache.commons.lang3.StringUtils;
73 import org.slf4j.Logger;
74 import org.slf4j.LoggerFactory;
75
76 import com.google.common.base.Predicate;
77 import com.google.common.collect.Iterators;
78 import com.google.common.collect.Lists;
79 import com.google.common.collect.UnmodifiableIterator;
80 import com.google.common.net.MediaType;
81
82
83
84
85 @Singleton
86 public class DamTemplatingFunctions {
87
88 private static final Logger log = LoggerFactory.getLogger(DamTemplatingFunctions.class);
89
90 public static final String METADATA_KEY_ACCESS = "metadata";
91 public static final String DAM_VERSION_1_PROVIDER_ID = "jcr";
92
93 private final AssetProviderRegistry providerRegistry;
94 private final AssetMetadataRegistry metadataRegistry;
95
96
97
98
99 @Deprecated
100 public DamTemplatingFunctions(AssetProviderRegistry providerRegistry) {
101 this(providerRegistry, Components.getComponent(AssetMetadataRegistry.class));
102 }
103
104 @Inject
105 public DamTemplatingFunctions(AssetProviderRegistry providerRegistry, AssetMetadataRegistry metadataRegistry) {
106 this.providerRegistry = providerRegistry;
107 this.metadataRegistry = metadataRegistry;
108 }
109
110
111
112
113
114 public Asset getAsset(String itemKey) {
115 Item item = getItem(itemKey, true);
116 if (item != null) {
117 return (Asset) item;
118 }
119 return null;
120 }
121
122 public Asset getAsset(String providerId, String assetPath) {
123 Item item = getItem(providerId, assetPath, true);
124 if (item != null) {
125 return (Asset) item;
126 }
127 return null;
128 }
129
130 public Asset getAssetForAbsolutePath(String providerId, String absoluteAssetPath) {
131 AssetProvider provider = getProviderForId(providerId);
132 if (provider != null) {
133 String providerRootPath = provider.getRootFolder().getPath();
134 if (!StringUtils.endsWith(providerRootPath, "/")) {
135 providerRootPath += "/";
136 }
137 String relativeAssetPath = StringUtils.removeStart(absoluteAssetPath, providerRootPath);
138 log.debug("Convert absolute '{}' to relative '{}' path", absoluteAssetPath, relativeAssetPath);
139 return getAsset(providerId, relativeAssetPath);
140 }
141 return null;
142 }
143
144
145
146
147
148 public Folder getFolder(String itemKey) {
149 Item item = getItem(itemKey, false);
150 if (item != null) {
151 return (Folder) item;
152 }
153 return null;
154 }
155
156
157
158
159
160
161 public Folder getFolder(String providerId, String folderPath) {
162 Item item = getItem(providerId, folderPath, false);
163 if (item != null) {
164 return (Folder) item;
165 }
166 return null;
167 }
168
169
170
171
172 public Iterator<Item> getItems(String providerId, AssetQuery assetQuery) {
173 AssetProvider provider = getProviderForId(providerId);
174 if (provider != null) {
175 try {
176 return provider.list(assetQuery);
177 } catch (Exception e) {
178 log.warn("Exception occurred for the following query '{}' and asset provider '{}' : {}", assetQuery.toString(), providerId, e.getMessage());
179 }
180 }
181 return null;
182 }
183
184
185
186
187
188 public AssetRendition getRendition(Asset asset, MediaType mediaType, String renditionName) {
189 try {
190 final AssetRenderer renderer = providerRegistry.getRendererFor(asset, mediaType);
191 if (renderer.canRender(asset, mediaType)) {
192 return renderer.render(asset, mediaType, renditionName);
193 }
194 } catch (NoSuchAssetRendererException nsare) {
195 log.warn("No rendition found for the following assetId '{}', mediaType '{}' and renditionName '{}'. Exception: {} ", asset.getItemKey().asString(), mediaType.toString(), renditionName, nsare);
196 }
197 return null;
198 }
199
200
201
202
203 public AssetRendition getRendition(Asset asset, String renditionName) {
204 return getRendition(asset, MediaType.parse(asset.getMimeType()), renditionName);
205 }
206
207 public AssetRendition getRendition(String itemKey, String renditionName) {
208 Asset asset = getAsset(itemKey);
209 if (asset == null) {
210 log.warn("Trying to get asset with item key {} returned null.", itemKey);
211 return null;
212 }
213 return getRendition(asset, MediaType.parse(asset.getMimeType()), renditionName);
214 }
215
216 public AssetRendition getRendition(String itemKey, MediaType mediaType, String renditionName) {
217 return getRendition(getAsset(itemKey), mediaType, renditionName);
218 }
219
220
221
222
223 public boolean provides(String providerId, MediaType mediaType) {
224 try {
225 return providerRegistry.getProviderById(providerId).provides(mediaType);
226 } catch (Exception e) {
227 log.warn("Exception occurred for the following reason {}. False will be retruned. ", e.getMessage());
228 return false;
229 }
230 }
231
232
233
234
235
236
237 public Map<String, Object> getAssetMap(Asset asset) {
238 Map<String, Class<? extends AssetMetadata>> supportedMetadata = new HashMap<String, Class<? extends AssetMetadata>>();
239 for (AssetMetadataDefinition metadataDefinition : metadataRegistry.getAll()) {
240 if (asset.supports(metadataDefinition.getMetadataClass())) {
241 supportedMetadata.put(metadataDefinition.getNamespace(), metadataDefinition.getMetadataClass());
242 }
243 }
244
245 List<String> rejectedGetter = Arrays.asList("getAssetProvider", "getMetadata", "getContentStream", "getParent", "getClass", "supports");
246
247
248 Map<String, Object> rootMap = convertBeanToMap(asset, rejectedGetter);
249
250 Map<String, Object> metaDatasMap = new HashMap<String, Object>();
251
252 for (Entry<String, Class<? extends AssetMetadata>> entry : supportedMetadata.entrySet()) {
253 AssetMetadata metaData = asset.getMetadata(entry.getValue());
254 Map<String, Object> metaDataMap = convertBeanToMap(metaData, rejectedGetter);
255 metaDatasMap.put(entry.getKey(), Collections.unmodifiableMap(metaDataMap));
256 }
257 rootMap.put(METADATA_KEY_ACCESS, Collections.unmodifiableMap(metaDatasMap));
258
259 return Collections.unmodifiableMap(rootMap);
260 }
261
262 public Map<String, Object> getAssetMap(String itemKey) {
263 return getAssetMap(getAsset(itemKey));
264 }
265
266
267
268
269 public String getAssetLink(String assetKey) {
270 Asset asset = getAsset(assetKey);
271 if (asset != null) {
272 return asset.getLink();
273 }
274 return null;
275 }
276
277
278
279
280 public String getAssetLink(String itemKey, String renditionName) {
281 AssetRendition rendition = getRendition(itemKey, renditionName);
282 if (rendition != null) {
283 return rendition.getLink();
284 }
285 return null;
286 }
287
288
289
290
291 public String getAssetLink(Asset asset, String renditionName) {
292 return getAssetLink(asset, MediaType.parse(asset.getMimeType()), renditionName);
293 }
294
295
296
297
298 public String getAssetLink(Asset asset, MediaType mediaType, String renditionName) {
299 AssetRendition rendition = getRendition(asset, mediaType, renditionName);
300 if (rendition != null) {
301 return rendition.getLink();
302 }
303 return null;
304 }
305
306
307
308
309 public Map<String, Object> getAssetMapForAssetId(String assetKey) {
310 Asset asset = getAsset(assetKey);
311 if (asset != null) {
312 return getAssetMap(asset);
313 }
314 return null;
315 }
316
317
318
319
320
321
322
323
324
325
326 @Deprecated
327 public List<Asset> getAssetsFromFolderId(String folderKey) {
328 Folder folder = getFolder(folderKey);
329 if (folder != null) {
330 return Lists.newArrayList(onlyAssets(folder.getChildren()));
331 }
332 return new ArrayList<Asset>();
333 }
334
335
336
337
338
339 @Deprecated
340 public Asset getAssetForPath(String assetPath) {
341 return getAssetForAbsolutePath(DAM_VERSION_1_PROVIDER_ID, assetPath);
342 }
343
344
345
346
347 @Deprecated
348 public Asset getAssetForId(String assetIdentifier) {
349 return getAsset(assetIdentifier);
350 }
351
352
353
354
355
356
357
358 @Deprecated
359 public Asset getAssetRendition(Asset asset, String renditionName) {
360 AssetRendition assetRendition = getRendition(asset, renditionName);
361 if (assetRendition != null) {
362 return getAssetRendition(assetRendition);
363 }
364 return asset;
365 }
366
367
368
369
370
371
372
373 @Deprecated
374 public Asset getAssetRenditionForAssetId(String itemKey, String renditionName) {
375 AssetRendition assetRendition = getRendition(itemKey, renditionName);
376 if (assetRendition != null) {
377 return getAssetRendition(assetRendition);
378 }
379 return getAsset(itemKey);
380 }
381
382
383
384
385 private Asset getAssetRendition(AssetRendition assetRendition) {
386 if (assetRendition != null) {
387 if (assetRendition instanceof Asset) {
388 return (Asset) assetRendition;
389 }
390 return assetRendition.getAsset();
391 }
392 return null;
393 }
394
395
396
397
398
399 @Deprecated
400 public String getAssetLinkForId(String assetKey) {
401 return getAssetLink(assetKey);
402 }
403
404
405
406
407
408 @Deprecated
409 public String getAssetLinkForId(String itemKey, String renditionName) {
410 return getAssetLink(itemKey, renditionName);
411 }
412
413
414
415
416
417
418 @Deprecated
419 public List<Asset> getAssetsForFilter(AssetQuery assetQuery) {
420 Iterator<Item> items = getItems(DAM_VERSION_1_PROVIDER_ID, assetQuery);
421 if (items != null) {
422 return Lists.newArrayList(onlyAssets(items));
423 }
424 return new ArrayList<Asset>();
425 }
426
427 @SuppressWarnings("unchecked")
428
429 private static UnmodifiableIterator<Asset> onlyAssets(Iterator<? extends Item> unfiltered) {
430 return (UnmodifiableIterator<Asset>) Iterators.filter(unfiltered, new Predicate<Item>() {
431 @Override
432 public boolean apply(Item input) {
433 return input.isAsset();
434 }
435 });
436 }
437
438
439
440
441
442
443 private Map<String, Object> convertBeanToMap(Object source, List<String> rejectedGetter) {
444 Map<String, Object> map = new HashMap<String, Object>();
445 try {
446 BeanInfo info = Introspector.getBeanInfo(source.getClass());
447 for (PropertyDescriptor pd : info.getPropertyDescriptors()) {
448 Method reader = pd.getReadMethod();
449 if (reader != null && !rejectedGetter.contains(reader.getName()))
450 map.put(pd.getName(), reader.invoke(source));
451 }
452 } catch (Exception e) {
453 log.warn("Could not populate the map with the bean property", e);
454 }
455 return map;
456 }
457
458
459
460
461 private Item getItem(String itemKey, boolean assetItem) {
462 try {
463 validateItemKey(itemKey);
464 ItemKey key = ItemKey.from(itemKey);
465 Item item = this.providerRegistry.getProviderFor(key).getItem(key);
466
467 return determineItemToReturn(item, assetItem);
468 } catch (Exception e) {
469 log.warn("The following ItemKey '{}' generated exceptions when trying to retrieve the associated Item : {}", itemKey, e.getMessage());
470 }
471 return null;
472 }
473
474
475
476
477
478 private Item determineItemToReturn(Item item, boolean assetItem) {
479 boolean isAsset = assetItem && item.isAsset();
480 boolean isFolder = !assetItem && item.isFolder();
481 boolean isJcrAsset = isAsset && (item instanceof JcrAsset && item.getAssetProvider() instanceof JcrAssetProvider);
482 boolean isJcrFolder = isFolder && (item instanceof JcrFolder && item.getAssetProvider() instanceof JcrAssetProvider);
483
484 if (isJcrAsset) {
485 return new JcrAsset((JcrAssetProvider) item.getAssetProvider(), new HTMLEscapingNodeWrapper(((JcrAsset) item).getNode(), true));
486 } else if (isJcrFolder) {
487 return new JcrFolder((JcrAssetProvider) item.getAssetProvider(), new HTMLEscapingNodeWrapper(((JcrFolder) item).getNode(), true));
488 } else if (isAsset || isFolder) {
489 return item;
490 }
491
492 log.warn("An '{}' was requested, but a '{}' was found", (assetItem ? "Asset" : "Folder"), (!assetItem ? "Asset" : "Folder"));
493 return null;
494 }
495
496
497
498
499
500
501 private void validateItemKey(String itemKey) {
502 if (StringUtils.isBlank(itemKey)) {
503 throw new IllegalArgumentException("ItemKey is null or blank.");
504 }
505 if (!ItemKey.isValid(itemKey)) {
506 throw new IllegalArgumentException("ItemKey is not valid.");
507 }
508 }
509
510
511
512
513
514 private Item getItem(String providerId, String itemPath, boolean assetItem) {
515 AssetProvider provider = getProviderForId(providerId);
516 if (provider != null) {
517
518 if (!(provider instanceof PathAwareAssetProvider)) {
519 throw new IllegalArgumentException("The provider '" + providerId + "' does not provide implementation for '" + PathAwareAssetProvider.class.getName() + "'. Retrieving an Item by path is not a supported operation ");
520 }
521 try {
522 Item item = ((PathAwareAssetProvider) provider).getItem(itemPath);
523 return determineItemToReturn(item, assetItem);
524 } catch (Exception e) {
525 log.warn("The following itemPath '{}' for the provider '{}' generated exceptions when trying to retrieve the associated Asset : {}", itemPath, providerId, e.getMessage());
526 }
527 }
528 return null;
529 }
530
531
532
533
534 private AssetProvider getProviderForId(String providerId) {
535 try {
536 return this.providerRegistry.getProviderById(providerId);
537 } catch (Exception e) {
538 log.warn("Exception occurred during the retrieval of the desired Asset Provider", e);
539 return null;
540 }
541 }
542
543 }