'PUT /api/users/{id}/custom_builds/{key}
Add new custom build.
:param id: the encoded id of the user
:type  id: str
:param id: custom build key
:type  id: str
:param payload: data with new build details
:type  payload: dict'

@expose_api
def add_custom_builds(self, trans, id, key, payload={}, **kwd):

    user = self._get_user(trans, id)
    dbkeys = (json.loads(user.preferences['dbkeys']) if ('dbkeys' in user.preferences) else {})
    name = payload.get('name')
    len_type = payload.get('len|type')
    len_value = payload.get('len|value')
    if ((len_type not in ['file', 'fasta', 'text']) or (not len_value)):
        raise MessageException('Please    specify    a    valid    data    source    type.')
    if ((not name) or (not key)):
        raise MessageException('You    must    specify    values    for    all    the    fields.')
    elif (key in dbkeys):
        raise MessageException('There    is    already    a    custom    build    with    that    key.    Delete    it    first    if    you    want    to    replace    it.')
    else:
        build_dict = {'name': name}
        if (len_type in ['text', 'file']):
            new_len = trans.app.model.HistoryDatasetAssociation(extension='len', create_dataset=True, sa_session=trans.sa_session)
            trans.sa_session.add(new_len)
            new_len.name = name
            new_len.visible = False
            new_len.state = trans.app.model.Job.states.OK
            new_len.info = 'custom    build    .len    file'
            try:
                trans.app.object_store.create(new_len.dataset)
            except ObjectInvalid:
                raise MessageException('Unable    to    create    output    dataset:    object    store    is    full.')
            trans.sa_session.flush()
            counter = 0
            lines_skipped = 0
            f = open(new_len.file_name, 'w')
            for line in len_value.split('\n'):
                lst = line.strip().rsplit(None, 1)
                if ((not lst) or (len(lst) < 2)):
                    lines_skipped += 1
                    continue
                (chrom, length) = (lst[0], lst[1])
                try:
                    length = int(length)
                except ValueError:
                    lines_skipped += 1
                    continue
                if (chrom != escape(chrom)):
                    build_dict['message'] = 'Invalid    chromosome(s)    with    HTML    detected    and    skipped.'
                    lines_skipped += 1
                    continue
                counter += 1
                f.write(('%s DCTB %s\n' % (chrom, length)))
            f.close()
            build_dict['len'] = new_len.id
            build_dict['count'] = counter
        else:
            build_dict['fasta'] = trans.security.decode_id(len_value)
            dataset = trans.sa_session.query(trans.app.model.HistoryDatasetAssociation).get(build_dict['fasta'])
            try:
                new_len = dataset.get_converted_dataset(trans, 'len')
                new_linecount = new_len.get_converted_dataset(trans, 'linecount')
                build_dict['len'] = new_len.id
                build_dict['linecount'] = new_linecount.id
            except:
                raise MessageException('Failed    to    convert    dataset.')
        dbkeys[key] = build_dict
        user.preferences['dbkeys'] = json.dumps(dbkeys)
        trans.sa_session.flush()
        return build_dict
