View Javadoc

1   /*
2    * Copyright 2008 FatWire Corporation. All Rights Reserved.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *    http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package com.fatwire.gst.foundation.facade.assetapi;
18  
19  import java.util.Arrays;
20  import java.util.Collection;
21  import java.util.Collections;
22  import java.util.Iterator;
23  import java.util.LinkedList;
24  import java.util.List;
25  
26  import COM.FutureTense.Interfaces.ICS;
27  import COM.FutureTense.Interfaces.IList;
28  
29  import com.fatwire.assetapi.common.AssetAccessException;
30  import com.fatwire.assetapi.common.SiteAccessException;
31  import com.fatwire.assetapi.data.AssetData;
32  import com.fatwire.assetapi.data.AssetDataManager;
33  import com.fatwire.assetapi.data.AssetId;
34  import com.fatwire.assetapi.query.ConditionFactory;
35  import com.fatwire.assetapi.query.OpTypeEnum;
36  import com.fatwire.assetapi.query.Query;
37  import com.fatwire.assetapi.query.SimpleQuery;
38  import com.fatwire.assetapi.site.Site;
39  import com.fatwire.assetapi.site.SiteInfo;
40  import com.fatwire.assetapi.site.SiteManager;
41  import com.fatwire.gst.foundation.facade.runtag.asset.AssetList;
42  import com.fatwire.system.Session;
43  import com.fatwire.system.SessionFactory;
44  import com.openmarket.xcelerate.asset.AssetIdImpl;
45  
46  /**
47   * 
48   * This class is a one-stop-shop for all read-only access to AssetData. It acts
49   * as a helper class to facilitate {@link AssetDataManager} use in a simplified
50   * way in delivery ContentServer templates.
51   * <p/>
52   * This class is inspired by springframework data access template classes like
53   * org.springframework.jdbc.core.JdbcTemplate.
54   * <p/>
55   * This class is not thread safe and should not be shared between threads.
56   * 
57   * @author Dolf.Dijkstra
58   * @since Nov 23, 2009
59   * 
60   */
61  public class AssetAccessTemplate {
62  
63      private final Session session;
64      private AssetDataManager assetDataManager;
65  
66      /**
67       * @param session
68       */
69      public AssetAccessTemplate(final Session session) {
70          super();
71          if (session == null) {
72              throw new IllegalArgumentException("session cannot be null.");
73          }
74          this.session = session;
75      }
76  
77      /**
78       * Constructor that accepts ICS as an argument.
79       * 
80       * @param ics
81       */
82      public AssetAccessTemplate(final ICS ics) {
83          if (ics == null) {
84              throw new IllegalArgumentException("ics cannot be null.");
85          }
86          session = SessionFactory.getSession(ics);
87      }
88  
89      /**
90       * Helper method to create an AssetId from c and cid as string values.
91       * 
92       * @param c
93       * @param cid
94       * @return the assetId for c/cid.
95       */
96      public AssetId createAssetId(final String c, final String cid) {
97          return new AssetIdImpl(c, Long.parseLong(cid));
98      }
99  
100     /**
101      * Helper method to create an AssetId from c and cid as string values.
102      * 
103      * @param c
104      * @param cid
105      * @return the assetId for c/cid.
106      */
107     public AssetId createAssetId(final String c, final long cid) {
108         return new AssetIdImpl(c, cid);
109     }
110 
111     /**
112      * Method to read an asset and use the AssetMapper to transform the
113      * AssetData into another object as specified by the AssetMapper.
114      * 
115      * @param <T>
116      * @param id
117      * @param mapper
118      * @return the Object created by the mapper.
119      */
120     public <T> T readAsset(final AssetId id, final AssetMapper<T> mapper) {
121         final AssetDataManager m = getAssetDataManager();
122 
123         T t = null;
124         try {
125             final Iterable<AssetData> assets = m.read(Arrays.asList(id));
126             for (final AssetData assetData : assets) {
127                 t = mapper.map(assetData);
128             }
129         } catch (final AssetAccessException e) {
130             throw new RuntimeAssetAccessException(e);
131         }
132         return t;
133     }
134 
135     /**
136      * Method to read an asset and use the AssetMapper to transform the
137      * AssetData into another object as specified by the AssetMapper interface..
138      * 
139      * @param <T>
140      * @param c the assetType
141      * @param cid the asset id
142      * @param mapper
143      * @return the object created by the mapper.
144      */
145     public <T> T readAsset(final String c, final String cid, final AssetMapper<T> mapper) {
146         return readAsset(this.createAssetId(c, cid), mapper);
147     }
148 
149     /**
150      * Method to read an asset and use the AssetMapper to transform the
151      * AssetData into another object as specified by the AssetMapper.
152      * 
153      * @param <T>
154      * @param c the assetType
155      * @param cid the asset id
156      * @param mapper
157      * @return the object created by the mapper.
158      */
159     public <T> T readAsset(final String c, final long cid, final AssetMapper<T> mapper) {
160         return readAsset(new AssetIdImpl(c, cid), mapper);
161     }
162 
163     /**
164      * Method to read an asset and use the AssetMapper to transform the
165      * AssetData into another object as specified by the AssetMapper. Only the
166      * list of lister attributes is retrieved from the asset.
167      * 
168      * @param <T>
169      * @param id
170      * @param mapper
171      * @param attributes
172      * @return the object created by the mapper.
173      */
174     public <T> T readAsset(final AssetId id, final AssetMapper<T> mapper, final String... attributes) {
175         final AssetDataManager m = getAssetDataManager();
176 
177         T t = null;
178         try {
179             final AssetData asset = m.readAttributes(id, Arrays.asList(attributes));
180             t = mapper.map(asset);
181         } catch (final AssetAccessException e) {
182             throw new RuntimeAssetAccessException(e);
183         }
184         return t;
185     }
186 
187     /**
188      * Method to read an asset and provide the AssetClosure with the AssetData.
189      * Only the list of lister attributes is retrieved from the asset.
190      * 
191      * @param id
192      * @param closure
193      * @param attributes
194      * 
195      */
196     public void readAsset(final AssetId id, final AssetClosure closure, final String... attributes) {
197         final AssetDataManager m = getAssetDataManager();
198 
199         try {
200             final AssetData asset = m.readAttributes(id, Arrays.asList(attributes));
201             if (asset != null) {
202                 if (!closure.work(asset)) {
203                     return;
204                 }
205             }
206         } catch (final AssetAccessException e) {
207             throw new RuntimeAssetAccessException(e);
208         }
209     }
210 
211     /**
212      * Method to read an asset and pass the results to the closure for further
213      * handling.
214      * 
215      * @param id the assetid to read
216      * @param closure the closure
217      */
218     public void readAsset(final AssetId id, final AssetClosure closure) {
219         final AssetDataManager m = getAssetDataManager();
220 
221         try {
222             final Iterable<AssetData> assets = m.read(Arrays.asList(id));
223             for (final AssetData assetData : assets) {
224                 if (!closure.work(assetData)) {
225                     return;
226                 }
227 
228             }
229         } catch (final AssetAccessException e) {
230             throw new RuntimeAssetAccessException(e);
231         }
232 
233     }
234 
235     /**
236      * Method to read an asset and pass the results to the closure for further
237      * handling.
238      * 
239      * @param ids a list of AssetIds
240      * @param closure the closure
241      */
242     public void readAsset(final List<AssetId> ids, final AssetClosure closure) {
243         final AssetDataManager m = getAssetDataManager();
244 
245         try {
246             final Iterable<AssetData> assets = m.read(ids);
247             for (final AssetData assetData : assets) {
248                 if (!closure.work(assetData)) {
249                     return;
250                 }
251 
252             }
253         } catch (final AssetAccessException e) {
254             throw new RuntimeAssetAccessException(e);
255         }
256 
257     }
258 
259     /**
260      * Method to read an asset and pass the results to the closure for further
261      * handling.
262      * 
263      * @param ids a list of AssetIds
264      * @param closure the closure
265      */
266     public void readAsset(final Iterable<AssetId> ids, final AssetClosure closure, final String... attributes) {
267         final AssetDataManager m = getAssetDataManager();
268 
269         try {
270             for (final AssetId id : ids) {
271                 final AssetData asset = m.readAttributes(id, Arrays.asList(attributes));
272                 if (asset != null) {
273                     if (!closure.work(asset)) {
274                         return;
275                     }
276                 }
277 
278             }
279         } catch (final AssetAccessException e) {
280             throw new RuntimeAssetAccessException(e);
281         }
282 
283     }
284 
285     /**
286      * Reads an asset based on the listed attribute names
287      * <p/>
288      * TODO: do we need to load the attribute values and prevent access to
289      * non-listed attributes (prevent lazy loading)
290      * 
291      * @param id the assetid
292      * @param attributes the list of attributes to return
293      * @return the asset found
294      * 
295      * 
296      */
297     public AssetData readAsset(final AssetId id, final String... attributes) {
298         final AssetDataManager m = getAssetDataManager();
299 
300         Iterable<AssetData> assets;
301         try {
302             assets = m.read(Arrays.asList(id));
303         } catch (final AssetAccessException e) {
304             throw new RuntimeAssetAccessException(e);
305         }
306         if (assets == null) {
307             return null;
308         }
309         if (assets instanceof List<?>) {
310             final List<AssetData> x = (List<AssetData>) assets;
311             if (x.isEmpty()) {
312                 return null;
313             } else {
314                 return x.get(0);
315             }
316         }
317         final Iterator<AssetData> i = assets.iterator();
318         if (i.hasNext()) {
319             return i.next();
320         }
321         return null;
322     }
323 
324     /**
325      * @return the manager
326      */
327     protected AssetDataManager getAssetDataManager() {
328         if (assetDataManager == null) {
329             assetDataManager = (AssetDataManager) session.getManager(AssetDataManager.class.getName());
330         }
331         return assetDataManager;
332     }
333 
334     /**
335      * @param id the assetid to read
336      * @return the assetdata for this id
337      */
338     public AssetData readAsset(final AssetId id) {
339 
340         final AssetDataManager m = getAssetDataManager();
341 
342         Iterable<AssetData> assets;
343         try {
344             assets = m.read(Collections.singletonList(id));
345         } catch (final AssetAccessException e) {
346             throw new RuntimeAssetAccessException(e);
347         }
348         if (assets == null) {
349             return null;
350         }
351         if (assets instanceof List<?>) {
352             final List<AssetData> x = (List<AssetData>) assets;
353             if (x.isEmpty()) {
354                 return null;
355             } else {
356                 return x.get(0);
357             }
358         }
359         final Iterator<AssetData> i = assets.iterator();
360         if (i.hasNext()) {
361             return i.next();
362         }
363         return null;
364     }
365 
366     /**
367      * @param query
368      * @return iterable with AssetData from the query result.
369      */
370     public Iterable<AssetData> readAssets(final Query query) {
371         final AssetDataManager m = getAssetDataManager();
372 
373         Iterable<AssetData> assets;
374         try {
375             assets = m.read(query);
376         } catch (final AssetAccessException e) {
377             throw new RuntimeAssetAccessException(e);
378         }
379 
380         return assets;
381     }
382 
383     /**
384      * Invokes the work(asset) method on the provided Closure for assets
385      * returned by the Query.
386      * 
387      * @param query the query
388      * @param closure the closure
389      */
390     public void readAssets(final Query query, final AssetClosure closure) {
391         final AssetDataManager m = getAssetDataManager();
392 
393         try {
394             for (final AssetData asset : m.read(query)) {
395                 if (!closure.work(asset)) {
396                     return;
397                 }
398 
399             }
400         } catch (final AssetAccessException e) {
401             throw new RuntimeAssetAccessException(e);
402         }
403     }
404 
405     /**
406      * Reading assets with the Query and using the mapper to transform the
407      * AssetData into another object, as specified by T.
408      * 
409      * @param <T>
410      * @param query
411      * @param mapper
412      * @return the objects created by the mapper.
413      */
414     public <T> Iterable<T> readAssets(final Query query, final AssetMapper<T> mapper) {
415 
416         final List<T> r = new LinkedList<T>();
417 
418         for (final AssetData data : readAssets(query)) {
419             r.add(mapper.map(data));
420         }
421 
422         return r;
423     }
424 
425     /**
426      * Finds the assetid by the name of the asset in a particular site. The
427      * asset can not be voided.
428      * 
429      * @param ics
430      * @param assetType the type of the asset.
431      * @param name the name of the asset.
432      * @param siteid the Site id.
433      * @return the assetid, null if asset is not found.
434      */
435     public AssetId findByName(final ICS ics, final String assetType, final String name, final long siteid) {
436         // TODO: name does not need to be unique, how do we handle this?
437         final AssetList tag = new AssetList();
438         tag.setType(assetType);
439         tag.setField("name", name);
440         tag.setExcludeVoided(true);
441         tag.setPubid(Long.toString(siteid));
442         tag.setList("name__");
443         tag.execute(ics);
444 
445         final IList list = ics.GetList("name__");
446         ics.RegisterList("name__", null);
447         if (list != null && list.hasData()) {
448             list.moveTo(1);
449             try {
450                 return new AssetIdImpl(assetType, Long.parseLong(list.getValue("id")));
451             } catch (final NoSuchFieldException e) {
452                 throw new RuntimeException(e);
453             }
454         } else {
455             return null;
456         }
457 
458     }
459 
460     /**
461      * Finds the assetid by the name of the asset. The asset can not be voided.
462      * 
463      * @param ics
464      * @param assetType the type of the asset.
465      * @param name the name of the asset.
466      * @return the assetid, null if asset is not found.
467      */
468 
469     public AssetId findByName(final ICS ics, final String assetType, final String name) {
470         // TODO: name does not need to be unique, how do we handle this?
471         final AssetList x = new AssetList();
472         x.setType(assetType);
473         x.setField("name", name);
474         x.setExcludeVoided(true);
475         x.setList("name__");
476         x.execute(ics);
477 
478         final IList list = ics.GetList("name__");
479         ics.RegisterList("name__", null);
480         if (list != null && list.hasData()) {
481             list.moveTo(1);
482             try {
483                 return new AssetIdImpl(assetType, Long.parseLong(list.getValue("id")));
484             } catch (final NoSuchFieldException e) {
485                 throw new RuntimeException(e);
486             }
487         } else {
488             return null;
489         }
490 
491     }
492 
493     /**
494      * Creates a Query to retrieve the asset by it's name.
495      * 
496      * @param assetType
497      * @param assetName
498      * @return the simple query
499      */
500     public SimpleQuery createNameQuery(final String assetType, final String assetName) {
501         final SimpleQuery q = new SimpleQuery(assetType, null, ConditionFactory.createCondition("name",
502                 OpTypeEnum.EQUALS, assetName), Arrays.asList("id"));
503         q.getProperties().setIsBasicSearch(true);
504         return q;
505     }
506 
507     /**
508      * Finds the Site object by the given name.
509      * 
510      * @param name the name of the site.
511      * @return the Site object.
512      */
513     public Site readSite(final String name) {
514         final SiteManager sm = (SiteManager) session.getManager(SiteManager.class.getName());
515         try {
516 
517             final List<Site> list = sm.read(Arrays.asList(name));
518             if (list == null || list.isEmpty()) {
519                 return null;
520             }
521             return list.get(0);
522         } catch (final SiteAccessException e) {
523             throw new SiteAccessRuntimeException(e);
524         }
525     }
526 
527     /**
528      * @param name
529      * @return the site info object
530      */
531     public SiteInfo readSiteInfo(final String name) {
532         final SiteManager sm = (SiteManager) session.getManager(SiteManager.class.getName());
533         try {
534 
535             for (SiteInfo si : sm.list()) {
536                 if (name.equals(si.getName())) {
537                     return si;
538                 }
539             }
540         } catch (final SiteAccessException e) {
541             throw new SiteAccessRuntimeException(e);
542         }
543         throw new SiteAccessRuntimeException("Site " + name + " does not exist in Content Server.");
544     }
545 
546     /**
547      * Reads the associated assets of the asset and returns the AssetIds.
548      * 
549      * @param id
550      * @param associationType
551      * @return the assets from the associations.
552      */
553     public Collection<AssetId> readAssociatedAssetIds(final AssetId id, final String associationType) {
554         final List<AssetId> list = readAsset(id).getAssociatedAssets(associationType);
555         if (list == null) {
556             return Collections.emptyList();
557         }
558         return list;
559 
560     }
561 
562     /**
563      * Reads the associated assets of an asset and returns them as a
564      * ScatteredAsset. This takes care of the asset read operation of the
565      * associated assets. The returned ScatteredAssets are only loaded with the
566      * mentioned attributes.
567      * 
568      * @param id the parent asset
569      * @param associationType the name of the association or '-' for an unnamed
570      *            association
571      * @param closure the AssetClosure to work on.
572      * @param attributes the list of attributes to load
573      * 
574      */
575     public void readAssociatedAssets(final AssetId id, final String associationType, final AssetClosure closure,
576             final String... attributes) {
577         final List<AssetId> list = this.readAsset(id).getAssociatedAssets(associationType);
578         if (list == null || list.isEmpty()) {
579             return;
580         }
581 
582         for (final AssetId child : list) {
583             readAsset(child, closure, attributes);
584         }
585 
586     }
587 
588     /**
589      * Queries for a list of objects as mapped by the AssetMapper.
590      * <p/>
591      * Sample queries are:
592      * <ul>
593      * <li>name='foo'</li>
594      * <li>name = 'foo'</li>
595      * <li>name = foo</li>
596      * <li>name= 'foo bar'</li>
597      * <li>size=[1,2]</li>
598      * <li>size{10,250}</li>
599      * <li>name!='foo'</li>
600      * 
601      * 
602      * @param <T>
603      * @param assetType
604      * @param subType
605      * @param query
606      * @param mapper
607      * @param attributes
608      * @return a iterable of assets.
609      * @see AssetAccessTemplate#query(String, String, String, AssetMapper,
610      *      String...)
611      */
612     public <T> Iterable<T> query(final String assetType, final String subType, final String query,
613             AssetMapper<T> mapper, final String... attributes) {
614         final Query q = new QueryBuilder(assetType, subType).condition(query).attributes(attributes).toQuery();
615         return this.readAssets(q, mapper);
616     }
617 
618     /**
619      * Queries for a list of objects as mapped by the AssetMapper.
620      * <p/>
621      * Sample queries are:
622      * <ul>
623      * <li>name='foo'</li>
624      * <li>name = 'foo'</li>
625      * <li>name = foo</li>
626      * <li>name= 'foo bar'</li>
627      * <li>size=[1,2]</li>
628      * <li>size{10,250}</li>
629      * <li>name!='foo'</li>
630      * 
631      * @param <T>
632      * @param assetType
633      * @param subType
634      * @param query
635      * @param mapper
636      * 
637      * @return a iterable of assets.
638      */
639     public <T> Iterable<T> query(final String assetType, final String subType, final String query, AssetMapper<T> mapper) {
640         final Query q = new QueryBuilder(assetType, subType).condition(query).setReadAll(true).toQuery();
641         return this.readAssets(q, mapper);
642     }
643 
644 }