'Expand values from various attribute types.
Strings are returned as is.
Dictionaries are returned with a key string, and an expanded set of values.
Other iterables are expanded until they flatten out.
Other items are returned in string format.
Args:
obj: The object to expand out.
parent: The parent object: Used to short-circuit infinite recursion.
Returns:
a list of expanded values as strings.'

def FanOut(self, obj, parent=None):

    if (parent and (obj == parent)):
        results = [utils.SmartUnicode(obj).strip()]
    elif isinstance(obj, (basestring, rdf_structs.EnumNamedValue)):
        results = [utils.SmartUnicode(obj).strip()]
    elif isinstance(obj, rdf_protodict.DataBlob):
        results = self.FanOut(obj.GetValue())
    elif isinstance(obj, (collections.Mapping, rdf_protodict.Dict)):
        results = []
        for (k, v) in obj.items():
            expanded_v = [utils.SmartUnicode(r) for r in self.FanOut(v)]
            results.append(('%s:%s' % (utils.SmartUnicode(k), ','.join(expanded_v))))
    elif isinstance(obj, (collections.Iterable, rdf_structs.RepeatedFieldHelper)):
        results = []
        for rslt in [self.FanOut(o, obj) for o in obj]:
            results.extend(rslt)
    else:
        results = [utils.SmartUnicode(obj).strip()]
    return results
