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.asset;
18  
19  import java.io.Serializable;
20  import java.util.AbstractMap;
21  import java.util.Collection;
22  import java.util.Date;
23  import java.util.HashSet;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.Set;
27  import java.util.TreeMap;
28  
29  import org.apache.commons.logging.Log;
30  
31  import com.fatwire.assetapi.common.AssetAccessException;
32  import com.fatwire.assetapi.data.AssetData;
33  import com.fatwire.assetapi.data.AssetId;
34  import com.fatwire.assetapi.data.AttributeData;
35  import com.fatwire.assetapi.data.BlobObject;
36  import com.fatwire.assetapi.def.AttributeDef;
37  import com.fatwire.gst.foundation.facade.assetapi.AttributeDataUtils;
38  import com.fatwire.gst.foundation.facade.logging.LogUtil;
39  import com.fatwire.mda.Dimension;
40  
41  /**
42   * 
43   * An asset that has loaded the attributes into memory. In the constructor all
44   * the attributes are copied into memory and and can be accessed via the
45   * {@link Map} methods.
46   * <p/>
47   * This class implements Serializable interface so the object can be serialized
48   * if needed. The serialization use-case is the best use-case for this class.
49   * The {@link AssetMapAdapter} is a better candidate to use if you are
50   * interested in accessing attribute data as a Map, for instance in a expression
51   * language like JSP EL.
52   * 
53   * 
54   * @author Dolf.Dijkstra
55   * @since Nov 23, 2009
56   * @see AssetMapAdapter
57   */
58  
59  public class ScatteredAsset extends AbstractMap<String, Object> implements Serializable {
60      private static final Log LOG = LogUtil.getLog(ScatteredAsset.class);
61  
62      /**
63  	 * 
64  	 */
65      private static final long serialVersionUID = -4978875079485732671L;
66  
67      private final AssetId id;
68  
69      private final Map<String, Object> attrMap = new TreeMap<String, Object>();
70  
71      /**
72       * This constructor checks if the attributes are meta attributes and if so,
73       * asks for the meta value. In case that you have a flex attribute with the
74       * name 'description' the flex attribute value will not be used, but the
75       * primary asset row 'description' field value.
76       * 
77       * @param delegate
78       * @param attributes the names of attributes to load the data from into
79       *            memory
80       */
81      public ScatteredAsset(AssetData delegate, String... attributes) {
82          this(delegate, true, attributes);
83  
84      }
85  
86      /**
87       * Reads all the attributes, in case of name collisions meta attributes take
88       * precedence.
89       * 
90       * @param delegate
91       */
92      public ScatteredAsset(AssetData delegate) {
93          this(delegate, true, delegate.getAttributeNames().toArray(new String[0]));
94      }
95  
96      /**
97       * This constructor checks if the attributes are meta attributes and based
98       * on the passed in <tt>meta</tt> asks for the meta value.
99       * 
100      * @param delegate
101      * @param meta true if the attributes are meta attributes
102      * @param attributes the names of attributes to load the data from into
103      *            memory
104      */
105 
106     public ScatteredAsset(AssetData delegate, boolean meta, String... attributes) {
107         super();
108         id = delegate.getAssetId();
109         Set<String> metaAttributes = new HashSet<String>();
110         for (AttributeDef d : delegate.getAssetTypeDef().getAttributeDefs()) {
111             if (d.isMetaDataAttribute() == meta)
112                 metaAttributes.add(d.getName());
113         }
114         for (String name : attributes) {
115             AttributeData attr = delegate.getAttributeData(name, metaAttributes.contains(name) == meta);
116             if ("Dimension".equals(name)) {
117                 Dimension s = AttributeDataUtils.asDimension(attr);
118                 if (s != null)
119                     attrMap.put(name, s);
120 
121             } else if (AttributeDataUtils.isSingleValued(attr)) {
122                 extractSingleValue(name, attr);
123             } else {
124                 extractMultiValue(name, attr);
125             }
126         }
127         extractParents(delegate);
128     }
129 
130     private void extractParents(AssetData delegate) {
131 
132         List<AttributeDef> parentDefs = delegate.getAssetTypeDef().getParentDefs();
133 
134         if (parentDefs != null) {
135             for (AttributeDef p : parentDefs) {
136                 String name = p.getName();
137                 try {
138                     List<AssetId> parentIds = delegate.getImmediateParents(name);
139 
140                     attrMap.put("Group_" + name, parentIds);
141                 } catch (AssetAccessException e) {
142                     LOG.debug(e.getMessage() + " when collecting parent " + name + " on " + delegate.getAssetId());
143                 }
144             }
145 
146         }
147 
148     }
149 
150     /**
151      * @param name
152      * @param attr
153      */
154     private void extractSingleValue(String name, AttributeData attr) {
155         switch (attr.getType()) {
156 
157             case STRING:
158             case LARGE_TEXT:
159                 String s = AttributeDataUtils.asString(attr);
160                 if (s != null && s.length() > 0)
161                     attrMap.put(name, s);
162                 break;
163 
164             case INT: {
165                 Integer obj = AttributeDataUtils.asInt(attr);
166                 if (obj != null)
167                     attrMap.put(name, obj);
168                 break;
169             }
170 
171             case LONG: {
172                 Long obj = AttributeDataUtils.asLong(attr);
173                 if (obj != null)
174                     attrMap.put(name, obj);
175                 break;
176             }
177             case MONEY:
178             case FLOAT: {
179                 Double obj = AttributeDataUtils.asDouble(attr);
180                 if (obj != null)
181                     attrMap.put(name, obj);
182                 break;
183             }
184             case DATE: {
185                 Date obj = AttributeDataUtils.asDate(attr);
186                 if (obj != null)
187                     attrMap.put(name, obj);
188                 break;
189             }
190 
191             case ASSET:
192             case ASSETREFERENCE: {
193                 AssetId obj = AttributeDataUtils.asAssetId(attr);
194                 if (obj != null)
195                     attrMap.put(name, obj);
196                 break;
197             }
198             case BLOB:
199             case URL: {
200                 BlobObject blob = AttributeDataUtils.asBlob(attr);
201                 if (blob != null)
202                     attrMap.put(name, blob);
203                 break;
204             }
205 
206             case ARRAY:
207             case STRUCT:
208             case LIST:
209             case ONEOF:
210                 Object o = attr.getData();
211                 int size = 0;
212                 if (o instanceof Collection<?>) {
213                     size = ((Collection<?>) o).size();
214                 } else if (o instanceof Map<?, ?>) {
215                     size = ((Map<?, ?>) o).size();
216                 } else {
217                     LOG.debug("Attribute '" + name + "' of type  " + attr.getType() + " returned a "
218                             + o.getClass().getName());
219                     size = 1;
220                 }
221                 if (size > 0)
222                     attrMap.put(name, attr.getData());
223         }
224     }
225 
226     /**
227      * @param name
228      * @param attr
229      */
230     private void extractMultiValue(String name, AttributeData attr) {
231         switch (attr.getType()) {
232 
233             case STRING:
234             case LARGE_TEXT:
235                 List<String> s = AttributeDataUtils.asStringList(attr);
236                 if (s != null && s.size() > 0)
237                     attrMap.put(name, s);
238                 break;
239 
240             case INT: {
241                 List<Integer> obj = AttributeDataUtils.asIntList(attr);
242                 if (obj != null && obj.size() > 0)
243                     attrMap.put(name, obj);
244                 break;
245             }
246 
247             case LONG: {
248                 List<Long> obj = AttributeDataUtils.asLongList(attr);
249                 if (obj != null && obj.size() > 0)
250                     attrMap.put(name, obj);
251                 break;
252             }
253             case MONEY:
254             case FLOAT: {
255                 List<Double> obj = AttributeDataUtils.asDoubleList(attr);
256                 if (obj != null && obj.size() > 0)
257                     attrMap.put(name, obj);
258                 break;
259             }
260             case DATE: {
261                 List<Date> obj = AttributeDataUtils.asDateList(attr);
262                 if (obj != null && obj.size() > 0)
263                     attrMap.put(name, obj);
264                 break;
265             }
266 
267             case ASSET:
268             case ASSETREFERENCE: {
269                 List<AssetId> obj = AttributeDataUtils.asAssetIdList(attr);
270                 if (obj != null && obj.size() > 0)
271                     attrMap.put(name, obj);
272                 break;
273             }
274             case BLOB:
275             case URL: {
276                 List<BlobObject> obj = AttributeDataUtils.asBlobList(attr);
277                 if (obj != null && obj.size() > 0)
278                     attrMap.put(name, obj);
279                 break;
280             }
281 
282             case ARRAY:
283             case STRUCT:
284             case LIST:
285             case ONEOF:
286                 Object o = attr.getData();
287                 int size = 0;
288                 if (o instanceof Collection<?>) {
289                     size = ((Collection<?>) o).size();
290                 } else if (o instanceof Map<?, ?>) {
291                     size = ((Map<?, ?>) o).size();
292                 } else {
293                     LOG.debug("Attribute '" + name + "' of type  " + attr.getType() + " returned a "
294                             + o.getClass().getName());
295                     size = 1;
296                 }
297                 if (size > 0)
298                     attrMap.put(name, attr.getData());
299         }
300     }
301 
302     /**
303      * @return the id of this asset
304      * @see com.fatwire.assetapi.data.AssetData#getAssetId()
305      */
306     public AssetId getAssetId() {
307         return id;
308     }
309 
310     @Override
311     public Set<java.util.Map.Entry<String, Object>> entrySet() {
312         return attrMap.entrySet();
313     }
314 
315 }