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