'@param tags: list of strings
@param append: If True existing tags are not removed'

def set_tags(self, id, tags, append=False, notify=True, commit=True, allow_case_change=False):

    if (not tags):
        tags = []
    if (not append):
        self.conn.execute('DELETE    FROM    books_tags_link    WHERE    book=?', (id,))
    otags = self.get_tags(id)
    tags = self.cleanup_tags(tags)
    books_to_refresh = {id}
    for tag in (set(tags) - otags):
        case_changed = False
        tag = tag.strip()
        if (not tag):
            continue
        if (not isinstance(tag, unicode)):
            tag = tag.decode(preferred_encoding, 'replace')
        existing_tags = self.all_tags()
        lt = [t.lower() for t in existing_tags]
        try:
            idx = lt.index(tag.lower())
        except ValueError:
            idx = (-1)
        if (idx > (-1)):
            etag = existing_tags[idx]
            tid = self.conn.get('SELECT    id    FROM    tags    WHERE    name=?', (etag,), all=False)
            if (allow_case_change and (etag != tag)):
                self.conn.execute('UPDATE    tags    SET    name=?    WHERE    id=?', (tag, tid))
                case_changed = True
        else:
            tid = self.conn.execute('INSERT    INTO    tags(name)    VALUES(?)', (tag,)).lastrowid
        if (not self.conn.get('SELECT    book    FROM    books_tags_link\n                                                                                                                                                WHERE    book=?    AND    tag=?', (id, tid), all=False)):
            self.conn.execute('INSERT    INTO    books_tags_link(book,    tag)\n                                                                                                                                                    VALUES    (?,?)', (id, tid))
        if case_changed:
            bks = self.conn.get('SELECT    book    FROM    books_tags_link    WHERE    tag=?', (tid,))
            books_to_refresh |= set([bk[0] for bk in bks])
    self.conn.execute('DELETE    FROM    tags    WHERE    (SELECT    COUNT(id)\n                                                                                                                                FROM    books_tags_link    WHERE    tag=tags.id)    <    1')
    self.dirtied((set([id]) | books_to_refresh), commit=False)
    if commit:
        self.conn.commit()
    tags = u','.join(self.get_tags(id))
    self.data.set(id, self.FIELD_MAP['tags'], tags, row_is_id=True)
    if notify:
        self.notify('metadata', [id])
    return books_to_refresh
