/*
* Copyright 2008 FatWire Corporation. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fatwire.gst.foundation.facade.assetapi.asset;
import java.io.Serializable;
import java.util.AbstractMap;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fatwire.assetapi.common.AssetAccessException;
import com.fatwire.assetapi.data.AssetData;
import com.fatwire.assetapi.data.AssetId;
import com.fatwire.assetapi.data.AttributeData;
import com.fatwire.assetapi.data.BlobObject;
import com.fatwire.assetapi.def.AttributeDef;
import com.fatwire.gst.foundation.facade.assetapi.AttributeDataUtils;
import com.fatwire.mda.Dimension;
/**
*
* An asset that has loaded the attributes into memory. In the constructor all
* the attributes are copied into memory and and can be accessed via the
* {@link Map} methods.
* <p>
* This class implements Serializable interface so the object can be serialized
* if needed. The serialization use-case is the best use-case for this class.
* The {@link AssetMapAdapter} is a better candidate to use if you are
* interested in accessing attribute data as a Map, for instance in a expression
* language like JSP EL.
*
*
* @author Dolf.Dijkstra
* @since Nov 23, 2009
* @see AssetMapAdapter
* @deprecated - com.fatwire.gst.foundation.facade and all subpackages have moved to the tools.gsf.facade package
*/
public class ScatteredAsset extends AbstractMap<String, Object> implements Serializable {
protected static final Logger LOG = LoggerFactory.getLogger("tools.gsf.legacy.facade.assetapi.asset.ScatteredAsset");
/**
*
*/
private static final long serialVersionUID = -4978875079485732671L;
private final AssetId id;
private final Map<String, Object> attrMap = new TreeMap<String, Object>();
/**
* This constructor checks if the attributes are meta attributes and if so,
* asks for the meta value. In case that you have a flex attribute with the
* name 'description' the flex attribute value will not be used, but the
* primary asset row 'description' field value.
*
* @param delegate asset data object
* @param attributes the names of attributes to load the data from into
* memory
*/
public ScatteredAsset(AssetData delegate, String... attributes) {
this(delegate, true, attributes);
}
/**
* Reads all the attributes, in case of name collisions meta attributes take
* precedence.
*
* @param delegate asset data object
*/
public ScatteredAsset(AssetData delegate) {
this(delegate, true, delegate.getAttributeNames().toArray(new String[0]));
}
/**
* This constructor checks if the attributes are meta attributes and based
* on the passed in <tt>meta</tt> asks for the meta value.
*
* @param delegate asset data object
* @param meta true if the attributes are meta attributes
* @param attributes the names of attributes to load the data from into
* memory
*/
public ScatteredAsset(AssetData delegate, boolean meta, String... attributes) {
super();
id = delegate.getAssetId();
Set<String> metaAttributes = new HashSet<String>();
for (AttributeDef d : delegate.getAssetTypeDef().getAttributeDefs()) {
if (d.isMetaDataAttribute() == meta)
metaAttributes.add(d.getName());
}
for (String name : attributes) {
AttributeData attr = delegate.getAttributeData(name, metaAttributes.contains(name) == meta);
if ("Dimension".equals(name)) {
Dimension s = AttributeDataUtils.asDimension(attr);
if (s != null)
attrMap.put(name, s);
} else if (AttributeDataUtils.isSingleValued(attr)) {
extractSingleValue(name, attr);
} else {
extractMultiValue(name, attr);
}
}
extractParents(delegate);
}
private void extractParents(AssetData delegate) {
List<AttributeDef> parentDefs = delegate.getAssetTypeDef().getParentDefs();
if (parentDefs != null) {
for (AttributeDef p : parentDefs) {
String name = p.getName();
try {
List<AssetId> parentIds = delegate.getImmediateParents(name);
attrMap.put("Group_" + name, parentIds);
} catch (AssetAccessException e) {
LOG.debug(e.getMessage() + " when collecting parent " + name + " on " + delegate.getAssetId());
}
}
}
}
/**
* @param name attribute name
* @param attr attribute data
*/
private void extractSingleValue(String name, AttributeData attr) {
switch (attr.getType()) {
case STRING:
case LARGE_TEXT:
String s = AttributeDataUtils.asString(attr);
if (s != null && s.length() > 0)
attrMap.put(name, s);
break;
case INT: {
Integer obj = AttributeDataUtils.asInt(attr);
if (obj != null)
attrMap.put(name, obj);
break;
}
case LONG: {
Long obj = AttributeDataUtils.asLong(attr);
if (obj != null)
attrMap.put(name, obj);
break;
}
case MONEY:
case FLOAT: {
Double obj = AttributeDataUtils.asDouble(attr);
if (obj != null)
attrMap.put(name, obj);
break;
}
case DATE: {
Date obj = AttributeDataUtils.asDate(attr);
if (obj != null)
attrMap.put(name, obj);
break;
}
case ASSET:
case ASSETREFERENCE: {
AssetId obj = AttributeDataUtils.asAssetId(attr);
if (obj != null)
attrMap.put(name, obj);
break;
}
case BLOB:
case URL: {
BlobObject blob = AttributeDataUtils.asBlob(attr);
if (blob != null)
attrMap.put(name, blob);
break;
}
case ARRAY:
case STRUCT:
case LIST:
case ONEOF:
Object o = attr.getData();
int size = 0;
if (o instanceof Collection<?>) {
size = ((Collection<?>) o).size();
} else if (o instanceof Map<?, ?>) {
size = ((Map<?, ?>) o).size();
} else {
LOG.debug("Attribute '" + name + "' of type " + attr.getType() + " returned a "
+ o.getClass().getName());
size = 1;
}
if (size > 0)
attrMap.put(name, attr.getData());
}
}
/**
* @param name attribute name
* @param attr attribute data
*/
private void extractMultiValue(String name, AttributeData attr) {
switch (attr.getType()) {
case STRING:
case LARGE_TEXT:
List<String> s = AttributeDataUtils.asStringList(attr);
if (s != null && s.size() > 0)
attrMap.put(name, s);
break;
case INT: {
List<Integer> obj = AttributeDataUtils.asIntList(attr);
if (obj != null && obj.size() > 0)
attrMap.put(name, obj);
break;
}
case LONG: {
List<Long> obj = AttributeDataUtils.asLongList(attr);
if (obj != null && obj.size() > 0)
attrMap.put(name, obj);
break;
}
case MONEY:
case FLOAT: {
List<Double> obj = AttributeDataUtils.asDoubleList(attr);
if (obj != null && obj.size() > 0)
attrMap.put(name, obj);
break;
}
case DATE: {
List<Date> obj = AttributeDataUtils.asDateList(attr);
if (obj != null && obj.size() > 0)
attrMap.put(name, obj);
break;
}
case ASSET:
case ASSETREFERENCE: {
List<AssetId> obj = AttributeDataUtils.asAssetIdList(attr);
if (obj != null && obj.size() > 0)
attrMap.put(name, obj);
break;
}
case BLOB:
case URL: {
List<BlobObject> obj = AttributeDataUtils.asBlobList(attr);
if (obj != null && obj.size() > 0)
attrMap.put(name, obj);
break;
}
case ARRAY:
case STRUCT:
case LIST:
case ONEOF:
Object o = attr.getData();
int size = 0;
if (o instanceof Collection<?>) {
size = ((Collection<?>) o).size();
} else if (o instanceof Map<?, ?>) {
size = ((Map<?, ?>) o).size();
} else {
LOG.debug("Attribute '" + name + "' of type " + attr.getType() + " returned a "
+ o.getClass().getName());
size = 1;
}
if (size > 0)
attrMap.put(name, attr.getData());
}
}
/**
* @return the id of this asset
* @see com.fatwire.assetapi.data.AssetData#getAssetId()
*/
public AssetId getAssetId() {
return id;
}
@Override
public Set<java.util.Map.Entry<String, Object>> entrySet() {
return attrMap.entrySet();
}
}