'Generates archive from a given collection.
Iterates the collection and generates an archive by yielding contents
of every referenced AFF4Stream.
Args:
collection: Iterable with items that point to aff4 paths.
token: User\'s ACLToken.
Yields:
Binary chunks comprising the generated archive.'

def Generate(self, collection, token=None):

    hashes = set()
    for fd_urn_batch in utils.Grouper(self._ItemsToUrns(collection), self.BATCH_SIZE):
        fds_to_write = {}
        for fd in aff4.FACTORY.MultiOpen(fd_urn_batch, token=token):
            self.total_files += 1
            if (not self.predicate(fd)):
                self.ignored_files.append(utils.SmartUnicode(fd.urn))
                continue
            if isinstance(fd, aff4.AFF4Stream):
                archive_path = os.path.join(self.prefix, *fd.urn.Split())
                sha256_hash = fd.Get(fd.Schema.HASH, rdf_crypto.Hash()).sha256
                if (not sha256_hash):
                    continue
                self.archived_files += 1
                content_path = os.path.join(self.prefix, 'hashes', str(sha256_hash))
                if (sha256_hash not in hashes):
                    st = os.stat_result((420, 0, 0, 0, 0, 0, fd.size, 0, 0, 0))
                    fds_to_write[fd] = (content_path, st)
                    hashes.add(sha256_hash)
                up_prefix = ('../' * len(fd.urn.Split()))
                (yield self.archive_generator.WriteSymlink((up_prefix + content_path), archive_path))
        if fds_to_write:
            prev_fd = None
            for (fd, chunk, exception) in aff4.AFF4Stream.MultiStream(fds_to_write):
                if exception:
                    logging.exception(exception)
                    self.archived_files -= 1
                    self.failed_files.append(utils.SmartUnicode(fd.urn))
                    continue
                if (prev_fd != fd):
                    if prev_fd:
                        (yield self.archive_generator.WriteFileFooter())
                    prev_fd = fd
                    (content_path, st) = fds_to_write[fd]
                    (yield self.archive_generator.WriteFileHeader(content_path, st=st))
                (yield self.archive_generator.WriteFileChunk(chunk))
            if self.archive_generator.is_file_write_in_progress:
                (yield self.archive_generator.WriteFileFooter())
    for chunk in self._WriteDescription():
        (yield chunk)
    (yield self.archive_generator.Close())
