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