Esempio n. 1
0
def resolve_field_value_template(tree, data, data_index):
    object_paths = as_list(resolve_path(tree, ['start', 'object_path']))
    for object_path in object_paths:
        ids = as_list(resolve_path(data, get_field_path(object_path)))
        if not ids:
            return None
        data = remove_none(list(map(lambda id: data_index.get(id), ids)))
    value_paths = as_list(resolve_path(tree, ['start', 'value_path']))
    if len(value_paths) == 1:
        return resolve_path(data, get_field_path(value_paths[0]))
    else:
        new_value = []
        for data in as_list(data):
            field_values = remove_empty(
                map(
                    lambda value_path: as_list(
                        resolve_path(data, get_field_path(value_path))) or
                    None, value_paths))
            product = itertools.product(*field_values)
            joined = map(
                lambda field_value: reduce(
                    lambda acc, s: s
                    if s.startswith(acc) else acc + " " + s, field_value, ""),
                product)
            if joined:
                new_value.extend(joined)
        return list(distinct(remove_empty(new_value)))
Esempio n. 2
0
def tree_to_dict(tree):
    if isinstance(tree, lark.tree.Tree):
        new_children = remove_none(list(map(tree_to_dict, tree.children)))
        return {'{lark}': 'TREE', tree.data: new_children}
    if isinstance(tree, lark.lexer.Token):
        return {'{lark}': 'TOKEN', tree.type: tree.value}
    return tree
def parse_template(template):
    if isinstance(template, str):
        return parse_string_template(template)
    elif isinstance(template, list):
        return list(remove_none(map(parse_template, template)))
    elif isinstance(template, dict):
        template_parsers = {
            '{if}': parse_if_template,
            '{or}': parse_or_template,
            '{join}': parse_join_template,
            '{flatten_distinct}': parse_flatten_template,
            '{list}': parse_list_template,
            '{map}': parse_map_template,
            '{merge}': parse_merge_template,
        }
        for key, parser in template_parsers.items():
            if key in template:
                return parser(template)

        new_dict = dict()
        for (key, value) in template.items():
            new_value = parse_template(value)
            if new_value:
                new_dict[key] = new_value
        return new_dict
    return template
Esempio n. 4
0
 def extract_links(id_field):
     def extract_link(entry):
         key, value = entry
         match = re.search("^(\w+)"+id_field+"(s?)$", key)
         if match and value:
             entity_name, plural = match.groups()
             return [entity_name, key, plural, value]
     return remove_none(map(extract_link, data.items()))
 def get_links(path, data):
     if is_collection(data):
         if isinstance(data, dict):
             entries = data.items()
         else:
             entries = enumerate(data)
         return itertools.chain.from_iterable(
             remove_none(map(partial(get_entry_link, path), entries)))
Esempio n. 6
0
def fetch_all_links(source, logger, entities):
    """
    Link objects across entities.
     - Internal: link an object (ex: study) to another using an identifier inside the JSON object
      (ex: link a location via study.locationDbId)
     - Internal object: link an object (ex: study) to another contained inside the first
      (ex: link a location via study.location.locationDbId)
     - External object: link an object (ex: study) to another using a dedicated call
      (ex: link to observation variables via /brapi/v1/studies/{id}/observationVariables)
    """
    for (entity_name, entity) in entities.items():
        if 'links' not in entity:
            continue

        for link in entity['links']:
            for (object_id, object) in entity['store'].items():
                linked_entity_name = link['entity']
                linked_entity = entities[linked_entity_name]
                linked_objects_by_id = {}

                if link['type'].startswith('internal'):
                    link_path = link['json-path']
                    link_path_list = remove_empty(link_path.split('.'))

                    link_values = remove_none(as_list(get_in(object, link_path_list)))
                    if not link_values:
                        if link.get('required'):
                            raise BrokenLink("Could not find required field '{}' in {} object id '{}'"
                                             .format(link_path, entity_name, object_id))
                        continue

                    if link['type'] == 'internal-object':
                        for link_value in link_values:
                            link_id = get_identifier(linked_entity_name, link_value)
                            linked_objects_by_id[link_id] = link_value

                    elif link['type'] == 'internal':
                        link_id_field = linked_entity['name'] + 'DbId'
                        link_name_field = linked_entity['name'] + 'Name'
                        for link_value in link_values:
                            link_id = link_value.get(link_id_field)
                            link_name = link_value.get(link_name_field)
                            if link_id:
                                linked_objects_by_id[link_id] = {link_id_field: link_id, link_name_field: link_name}

                elif link['type'] == 'external-object':
                    call = get_implemented_call(source, link, context=object)
                    if not call:
                        continue

                    link_values = list(BreedingAPIIterator.fetch_all(source['brapi:endpointUrl'], call, logger))
                    for link_value in link_values:
                        link_id = get_identifier(linked_entity_name, link_value)
                        linked_objects_by_id[link_id] = link_value

                link_objects(entity, object, linked_entity, linked_objects_by_id)
Esempio n. 7
0
def resolve_join_template(template, data, data_index):
    accept_none = False if template.get('{accept_none}') == False else True
    separator = template.get('{separator}') or ''
    elements = template.get('{join}')
    flattened_elements = flatten(resolve(elements, data, data_index))
    if not accept_none:
        for elem in as_list(flattened_elements):
            if not elem:
                return None
    filtered_elements = remove_none(flattened_elements)
    return coll_as_str(filtered_elements, separator)
Esempio n. 8
0
def remove_white_space_token(tree):
    if isinstance(tree, lark.tree.Tree):

        def not_ws_token(child):
            if not (isinstance(child, lark.lexer.Token)
                    and child.type == "WS"):
                return child

        without_ws = filter(not_ws_token, tree.children)
        new_children = remove_none(map(remove_white_space_token, without_ws))
        return lark.tree.Tree(tree.data, new_children)
    return tree
def resolve_field_value_template(tree, data, data_index):
    object_paths = as_list(get_in(tree, ['start', 'object_path']))
    for object_path in object_paths:
        field_path = get_field_path(object_path)
        ids = as_list(get_in(data, field_path))
        if not ids:
            return None
        field = field_path[-1]
        entity = re.sub(r"(\w+)URIs?", "\\1", field)
        entity_index = data_index[entity]
        try:
            dataList = []
            for id in ids:
                dataList.append(json.loads(entity_index[id].decode()))
            data = remove_none(dataList)
        except AttributeError:
            data = remove_none(list(map(lambda id: entity_index[id], ids)))

        if getattr(entity_index, 'close', False):
            entity_index.close()
    value_paths = as_list(get_in(tree, ['start', 'value_path']))
    if len(value_paths) == 1:
        return get_in(data, get_field_path(value_paths[0]))
    else:
        new_value = []
        for data in as_list(data):
            field_values = remove_empty(
                map(
                    lambda value_path: as_list(
                        get_in(data, get_field_path(value_path))) or None,
                    value_paths))
            product = itertools.product(*field_values)
            joined = map(
                lambda field_value: reduce(
                    lambda acc, s: s
                    if s.startswith(acc) else acc + " " + s, field_value, ""),
                product)
            if joined:
                new_value.extend(joined)
        return list(distinct(remove_empty(new_value)))