'Generates a reference map for a record
@param table: the database table
@param record: the record
@param fields: list of reference field names in this table'

def rmap(self, table, record, fields):

    reference_map = []
    DELETED = self.DELETED
    REPLACEDBY = self.REPLACEDBY
    if ((DELETED in record) and record[DELETED] and (REPLACEDBY in record) and record[REPLACEDBY]):
        fields = [REPLACEDBY]
    else:
        fields = [f for f in fields if ((f in record) and record[f])]
    if (not fields):
        return reference_map
    db = current.db
    UID = self.UID
    MCI = self.MCI
    export_uid = self.export_uid
    represent = self.represent
    filter_mci = self.filter_mci
    tablename = table._tablename
    gtablename = current.auth.settings.table_group_name
    load_table = current.s3db.table
    for f in fields:
        if (f == REPLACEDBY):
            val = ogetattr(record, f)
            if (not val):
                continue
            row = db((table._id == val)).select(table[UID], limitby=(0, 1)).first()
            if (not row):
                continue
            else:
                uids = [export_uid(row[UID])]
            entry = {'field': f, 'table': tablename, 'multiple': False, 'id': [val], 'uid': uids, 'text': None, 'lazy': False, 'value': None}
            reference_map.append(Storage(entry))
            continue
        try:
            dbfield = ogetattr(table, f)
        except:
            continue
        (ktablename, pkey, multiple) = s3_get_foreign_key(dbfield)
        if (not ktablename):
            continue
        val = ids = ogetattr(record, f)
        ktable = load_table(ktablename)
        if (not ktable):
            continue
        ktable_fields = ktable.fields
        k_id = ktable._id
        uid = None
        uids = None
        if (pkey is None):
            pkey = k_id.name
        if ((pkey != 'id') and ('instance_type' in ktable_fields)):
            if multiple:
                continue
            else:
                query = (k_id == ids)
            srecord = db(query).select(ogetattr(ktable, UID), ktable.instance_type, limitby=(0, 1)).first()
            if (not srecord):
                continue
            ktablename = srecord.instance_type
            uid = ogetattr(srecord, UID)
            if ((ktablename == tablename) and (UID in record) and (ogetattr(record, UID) == uid) and (not self.show_ids)):
                continue
            ktable = load_table(ktablename)
            if (not ktable):
                continue
            query = (current.auth.s3_accessible_query('read', ktable) & (ktable[UID] == uid))
            krecord = db(query).select(ktable._id, limitby=(0, 1)).first()
            if (not krecord):
                continue
            ids = [krecord[ktable._id]]
            uids = [export_uid(uid)]
        else:
            query = current.auth.s3_accessible_query('read', ktable)
            if multiple:
                query &= k_id.belongs(ids)
                limitby = None
            else:
                query &= (k_id == ids)
                limitby = (0, 1)
            if (DELETED in ktable_fields):
                query = ((ktable.deleted != True) & query)
            if (filter_mci and (MCI in ktable_fields)):
                query = ((ktable.mci >= 0) & query)
            if (UID in ktable_fields):
                krecords = db(query).select(ogetattr(ktable, UID), limitby=limitby)
                if krecords:
                    uids = [r[UID] for r in krecords if r[UID]]
                    if (ktablename != gtablename):
                        uids = map(export_uid, uids)
                else:
                    continue
            else:
                krecord = db(query).select(k_id, limitby=(0, 1)).first()
                if (not krecord):
                    continue
        value = s3_unicode(dbfield.formatter(val))
        lazy = None
        renderer = dbfield.represent
        if (renderer is not None):
            if hasattr(renderer, 'bulk'):
                text = None
                lazy = S3RepresentLazy(val, renderer)
            else:
                text = represent(table, f, val)
        else:
            text = value
        entry = {'field': f, 'table': ktablename, 'multiple': multiple, 'id': (ids if (type(ids) is list) else [ids]), 'uid': uids, 'text': text, 'lazy': lazy, 'value': value}
        reference_map.append(Storage(entry))
    return reference_map
