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