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 if (asset == null) {
214 log.warn("Trying to get asset with item key {} returned null.", itemKey);
215 return null;
216 }
217 return getRendition(asset, MediaType.parse(asset.getMimeType()), renditionName);
218 }
219
220 public AssetRendition getRendition(String itemKey, MediaType mediaType, String renditionName) {
221 return getRendition(getAsset(itemKey), mediaType, renditionName);
222 }
223
224
225
226
227 public boolean provides(String providerId, MediaType mediaType) {
228 try {
229 return providerRegistry.getProviderById(providerId).provides(mediaType);
230 } catch (Exception e) {
231 log.warn("Exception occurred for the following reason {}. False will be retruned. ", e.getMessage());
232 return false;
233 }
234 }
235
236
237
238
239
240
241 public Map<String, Object> getAssetMap(Asset asset) {
242
243 Map<String, Class<? extends AssetMetadata>> supportedMetadata = new HashMap<String, Class<? extends AssetMetadata>>();
244 supportedMetadata.put("mgnl", MagnoliaAssetMetadata.class);
245 supportedMetadata.put("dc", DublinCore.class);
246
247 List<String> rejectedGetter = Arrays.asList("getAssetProvider", "getMetadata", "getContentStream", "getParent", "getClass");
248
249
250 Map<String, Object> rootMap = convertBeanToMap(asset, rejectedGetter);
251
252 Map<String, Object> metaDatasMap = new HashMap<String, Object>();
253
254 for (Entry<String, Class<? extends AssetMetadata>> entry : supportedMetadata.entrySet()) {
255 AssetMetadata metaData = asset.getMetadata(entry.getValue());
256 Map<String, Object> metaDataMap = convertBeanToMap(metaData, rejectedGetter);
257 metaDatasMap.put(entry.getKey(), Collections.unmodifiableMap(metaDataMap));
258 }
259 rootMap.put(METADATA_KEY_ACCESS, Collections.unmodifiableMap(metaDatasMap));
260
261 return Collections.unmodifiableMap(rootMap);
262 }
263
264 public Map<String, Object> getAssetMap(String itemKey) {
265 return getAssetMap(getAsset(itemKey));
266 }
267
268
269
270
271 public String getAssetLink(String assetKey) {
272 Asset asset = getAsset(assetKey);
273 if (asset != null) {
274 return asset.getLink();
275 }
276 return null;
277 }
278
279
280
281
282 public String getAssetLink(String itemKey, String renditionName) {
283 AssetRendition rendition = getRendition(itemKey, renditionName);
284 if (rendition != null) {
285 return rendition.getLink();
286 }
287 return null;
288 }
289
290
291
292
293 public String getAssetLink(Asset asset, MediaType mediaType, String renditionName) {
294 AssetRendition rendition = getRendition(asset, mediaType, renditionName);
295 if (rendition != null) {
296 return rendition.getLink();
297 }
298 return null;
299 }
300
301
302
303
304 public Map<String, Object> getAssetMapForAssetId(String assetKey) {
305 Asset asset = getAsset(assetKey);
306 if (asset != null) {
307 return getAssetMap(asset);
308 }
309 return null;
310 }
311
312
313
314
315
316
317
318
319
320
321 @Deprecated
322 public List<Asset> getAssetsFromFolderId(String folderKey) {
323 Folder folder = getFolder(folderKey);
324 if (folder != null) {
325 return Lists.newArrayList(onlyAssets(folder.getChildren()));
326 }
327 return new ArrayList<Asset>();
328 }
329
330
331
332
333
334 @Deprecated
335 public Asset getAssetForPath(String assetPath) {
336 return getAssetForAbsolutePath(DAM_VERSION_1_PROVIDER_ID, assetPath);
337 }
338
339
340
341
342 @Deprecated
343 public Asset getAssetForId(String assetIdentifier) {
344 return getAsset(assetIdentifier);
345 }
346
347
348
349
350
351
352
353 @Deprecated
354 public Asset getAssetRendition(Asset asset, String renditionName) {
355 AssetRendition assetRendition = getRendition(asset, renditionName);
356 if (assetRendition != null) {
357 return getAssetRendition(assetRendition);
358 }
359 return asset;
360 }
361
362
363
364
365
366
367
368 @Deprecated
369 public Asset getAssetRenditionForAssetId(String itemKey, String renditionName) {
370 AssetRendition assetRendition = getRendition(itemKey, renditionName);
371 if (assetRendition != null) {
372 return getAssetRendition(assetRendition);
373 }
374 return getAsset(itemKey);
375 }
376
377
378
379
380 private Asset getAssetRendition(AssetRendition assetRendition) {
381 if (assetRendition != null) {
382 if (assetRendition instanceof Asset) {
383 return (Asset) assetRendition;
384 }
385 return assetRendition.getAsset();
386 }
387 return null;
388 }
389
390
391
392
393
394 @Deprecated
395 public String getAssetLinkForId(String assetKey) {
396 return getAssetLink(assetKey);
397 }
398
399
400
401
402
403 @Deprecated
404 public String getAssetLinkForId(String itemKey, String renditionName) {
405 return getAssetLink(itemKey, renditionName);
406 }
407
408
409
410
411
412
413 @Deprecated
414 public List<Asset> getAssetsForFilter(AssetQuery assetQuery) {
415 Iterator<Item> items = getItems(DAM_VERSION_1_PROVIDER_ID, assetQuery);
416 if (items != null) {
417 return Lists.newArrayList(onlyAssets(items));
418 }
419 return new ArrayList<Asset>();
420 }
421
422 @SuppressWarnings("unchecked")
423
424 private static UnmodifiableIterator<Asset> onlyAssets(Iterator<? extends Item> unfiltered) {
425 return (UnmodifiableIterator<Asset>) Iterators.filter(unfiltered, new Predicate<Item>() {
426 @Override
427 public boolean apply(Item input) {
428 return input.isAsset();
429 }
430 });
431 }
432
433
434
435
436
437
438 private Map<String, Object> convertBeanToMap(Object source, List<String> rejectedGetter) {
439 Map<String, Object> map = new HashMap<String, Object>();
440 try {
441 BeanInfo info = Introspector.getBeanInfo(source.getClass());
442 for (PropertyDescriptor pd : info.getPropertyDescriptors()) {
443 Method reader = pd.getReadMethod();
444 if (reader != null && !rejectedGetter.contains(reader.getName()))
445 map.put(pd.getName(), reader.invoke(source));
446 }
447 } catch (Exception e) {
448 log.warn("Could not populate the map with the bean property", e);
449 }
450 return map;
451 }
452
453
454
455
456 private Item getItem(String itemKey, boolean assetItem) {
457 try {
458 validateItemKey(itemKey);
459 ItemKey key = ItemKey.from(itemKey);
460 Item item = this.providerRegistry.getProviderFor(key).getItem(key);
461
462 return determineItemToReturn(item, assetItem);
463 } catch (Exception e) {
464 log.warn("The following ItemKey '{}' generate exeptions when trying to retrieve the associated Item : {}", itemKey, e.getMessage());
465 }
466 return null;
467 }
468
469
470
471
472 private Item determineItemToReturn(Item item, boolean assetItem) {
473 boolean isAsset = assetItem && item.isAsset();
474 boolean isFolder = !assetItem && item.isFolder();
475 boolean isJcrAsset = isAsset && (item instanceof JcrAsset && item.getAssetProvider() instanceof JcrAssetProvider);
476 boolean isJcrFolder = isFolder && (item instanceof JcrFolder && item.getAssetProvider() instanceof JcrAssetProvider);
477
478 if(isJcrAsset) {
479 return new JcrAsset((JcrAssetProvider) item.getAssetProvider(), new HTMLEscapingNodeWrapper(((JcrAsset)item).getNode(), true));
480
481 } else if(isJcrFolder) {
482 return new JcrFolder((JcrAssetProvider) item.getAssetProvider(), new HTMLEscapingNodeWrapper(((JcrFolder)item).getNode(), true));
483
484 } else if(isAsset || isFolder){
485 return item;
486 }
487 log.warn("An '{}' was requested, but a '{}' was found", (assetItem ? "Asset" : "Folder"), (!assetItem ? "Asset" : "Folder"));
488 return null;
489 }
490
491
492
493
494
495
496 private void validateItemKey(String itemKey) {
497 if (StringUtils.isBlank(itemKey)) {
498 throw new IllegalArgumentException("ItemKey is null or blank.");
499 }
500 if (!ItemKey.isValid(itemKey)) {
501 throw new IllegalArgumentException("ItemKey is not valide.");
502 }
503 }
504
505
506
507
508
509 private Item getItem(String providerId, String itemPath, boolean assetItem) {
510 AssetProvider provider = getProviderForId(providerId);
511 if (provider != null) {
512
513 if (!(provider instanceof PathAwareAssetProvider)) {
514 throw new IllegalArgumentException("The provider '" + providerId + "' does not provide implementation for '" + PathAwareAssetProvider.class.getName() + "'. Retrieving an Item by path is not a supported operation ");
515 }
516 try {
517 Item item = ((PathAwareAssetProvider) provider).getItem(itemPath);
518 return determineItemToReturn(item, assetItem);
519 } catch (Exception e) {
520 log.warn("The following itemPath '{}' for the provider '{}' generated exeptions when trying to retrieve the associated Asset : {}", itemPath, providerId, e.getMessage());
521 }
522 }
523 return null;
524 }
525
526
527
528
529 private AssetProvider getProviderForId(String providerId) {
530 try {
531 return this.providerRegistry.getProviderById(providerId);
532 } catch (Exception e) {
533 log.warn("Exception occurred during the retrieval of the desired Asset Provider", e);
534 return null;
535 }
536 }
537
538 }