'Returns all the versions of the object as AFF4 objects.
Args:
urn: The urn to open.
mode: The mode to open the file with.
token: The Security Token to use for opening this item.
local_cache: A dict containing a cache as returned by GetAttributes. If
set, this bypasses the factory cache.
age: The age policy used to build this object. Should be one of
ALL_TIMES or a time range
diffs_only: If True, will return only diffs between the versions (instead
of full objects).
follow_symlinks: If object opened is a symlink, follow it.
Yields:
An AFF4Object for each version.
Raises:
IOError: On bad open or wrong time range specified.
This iterates through versions of an object, returning the newest version
first, then each older version until the beginning of time.
Note that versions are defined by changes to the TYPE attribute, and this
takes the version between two TYPE attributes.
In many cases as a user you don\'t want this, as you want to be returned an
object with as many attributes as possible, instead of the subset of them
that were Set between these two times.'

def OpenDiscreteVersions(self, urn, mode='r', token=None, local_cache=None, age=ALL_TIMES, diffs_only=False, follow_symlinks=True):

    if ((age == NEWEST_TIME) or (len(age) == 1)):
        raise IOError('Bad    age    policy    NEWEST_TIME    for    OpenDiscreteVersions.')
    aff4object = FACTORY.Open(urn, mode=mode, token=token, local_cache=local_cache, age=age, follow_symlinks=follow_symlinks)
    type_iter = aff4object.GetValuesForAttribute(aff4object.Schema.TYPE)
    versions = sorted((t.age for t in type_iter))
    additional_aff4object = None
    if diffs_only:
        versions.insert(0, rdfvalue.RDFDatetime(0))
        pairs = zip(versions, versions[1:])
    else:
        if ((len(age) == 2) and age[0]):
            additional_aff4object = FACTORY.Open(urn, mode=mode, token=token, local_cache=local_cache, age=age[0])
        pairs = [(rdfvalue.RDFDatetime(0), v) for v in versions]
    for (start, end) in pairs:
        clone_attrs = {}
        if additional_aff4object:
            attributes = itertools.chain(aff4object.synced_attributes.iteritems(), additional_aff4object.synced_attributes.iteritems())
        else:
            attributes = aff4object.synced_attributes.iteritems()
        for (k, values) in attributes:
            reduced_v = []
            for v in values:
                if ((v.age > start) and (v.age <= end)):
                    reduced_v.append(v)
            clone_attrs.setdefault(k, []).extend(reduced_v)
        cur_type = clone_attrs[aff4object.Schema.TYPE][0].ToRDFValue()
        obj_cls = AFF4Object.classes[str(cur_type)]
        new_obj = obj_cls(urn, mode=mode, parent=aff4object.parent, clone=clone_attrs, token=token, age=(start, end), local_cache=local_cache, follow_symlinks=follow_symlinks)
        new_obj.Initialize()
        (yield new_obj)
