def replace_variables_in_blocks(self, var_to_replace): """Replace variables in blocks Parameters ---------- var_to_replace : list of tuples var to replace in block """ for var_source, var_target in var_to_replace: # Interate throught blocks for nblock, block in enumerate(self.triples_blocks): # Iterate over sub-blocks for nsblock, sblock in enumerate(block["sblocks"]): # Iterate over triples for ntriple, triple_dict in enumerate(sblock["triples"]): for key, value in triple_dict.items(): if key != "optional": self.triples_blocks[nblock]["sblocks"][nsblock]["triples"][ntriple][key] = value.replace(var_source, var_target) for i, filtr in enumerate(sblock["filters"]): self.triples_blocks[nblock]["sblocks"][nsblock]["filters"][i] = filtr.replace(var_source, var_target) for i, value in enumerate(sblock["values"]): self.triples_blocks[nblock]["sblocks"][nsblock]["values"][i] = value.replace(var_source, var_target) self.triples_blocks[nblock]["sblocks"][nsblock]["triples"] = Utils.unique(self.triples_blocks[nblock]["sblocks"][nsblock]["triples"])
def set_graphs_and_endpoints(self, entities=None, graphs=None, endpoints=None): """Get all public and private graphs containing the given entities Parameters ---------- entities : list, optional list of entity uri """ substrlst = [] filter_entity_string = '' if entities: for entity in entities: substrlst.append("?entity_uri = <{}>".format(entity)) filter_entity_string = 'FILTER (' + ' || '.join(substrlst) + ')' filter_public_string = 'FILTER (?public = <true>)' if 'user' in self.session: filter_public_string = 'FILTER (?public = <true> || ?creator = <{}>)'.format( self.session["user"]["username"]) query = ''' SELECT DISTINCT ?graph ?endpoint WHERE {{ ?graph :public ?public . ?graph dc:creator ?creator . GRAPH ?graph {{ ?graph prov:atLocation ?endpoint . ?entity_uri a :entity . }} {} {} }} '''.format(filter_public_string, filter_entity_string) query_launcher = SparqlQueryLauncher(self.app, self.session) header, results = query_launcher.process_query( self.prefix_query(query)) self.graphs = [] self.endpoints = [] for res in results: if not graphs or res["graph"] in graphs: self.graphs.append(res["graph"]) # If local triplestore url is not accessible by federetad query engine if res["endpoint"] == self.settings.get( 'triplestore', 'endpoint') and self.local_endpoint_f is not None: endpoint = self.local_endpoint_f else: endpoint = res["endpoint"] if not endpoints or endpoint in endpoints: self.endpoints.append(endpoint) self.endpoints = Utils.unique(self.endpoints) self.federated = len(self.endpoints) > 1
def replace_variables_in_triples(self, var_to_replace): """Replace variables in triples Parameters ---------- var_to_replace : list of tuples var to replace in triples """ for tpl_var in var_to_replace: var_source = tpl_var[0] var_target = tpl_var[1] for i, triple_dict in enumerate(self.triples): for key, value in triple_dict.items(): if key != "optional": self.triples[i][key] = value.replace(var_source, var_target) for i, select in enumerate(self.selects): self.selects[i] = select.replace(var_source, var_target) for i, filtr in enumerate(self.filters): self.filters[i] = filtr.replace(var_source, var_target) # uniq lists self.triples = Utils.unique(self.triples) self.selects = Utils.unique(self.selects)
def build_query_from_json(self, json_query, preview=False, for_editor=False): """Build a sparql query for the json dict of the query builder Parameters ---------- json_query : dict The json query from the query builder Returns ------- str SPARQL query """ entities = [] attributes = {} linked_attributes = [] self.selects = [] triples_relations = [] triples_attributes = [] values = [] filters = [] start_end = [] strands = [] var_to_replace = [] # Browse node to get graphs for node in json_query["nodes"]: if not node["suggested"]: entities.append(node["uri"]) self.set_graphs_and_endpoints(entities=entities) # self.log.debug(json_query) # Browse links (relations) for link in json_query["links"]: if not link["suggested"]: source = self.format_sparql_variable("{}{}_uri".format( link["source"]["label"], link["source"]["id"])) target = self.format_sparql_variable("{}{}_uri".format( link["target"]["label"], link["target"]["id"])) # Position if link["uri"] in ('included_in', 'overlap_with'): common_block = self.format_sparql_variable( "block_{}_{}".format(link["source"]["id"], link["target"]["id"])) # Get start & end sparql variables for attr in json_query["attr"]: if not attr["faldo"]: continue if attr["nodeId"] == link["source"]["id"]: if attr["faldo"].endswith("faldoStart"): start_end.append(attr["id"]) start_1 = self.format_sparql_variable( "{}{}_{}".format(attr["entityLabel"], attr["nodeId"], attr["label"])) if attr["faldo"].endswith("faldoEnd"): start_end.append(attr["id"]) end_1 = self.format_sparql_variable( "{}{}_{}".format(attr["entityLabel"], attr["nodeId"], attr["label"])) if attr["faldo"].endswith("faldoStrand"): strand_1 = self.format_sparql_variable( "{}{}_{}_faldoStrand".format( attr["entityLabel"], attr["nodeId"], attr["label"])) strands.append(attr["id"]) if attr["nodeId"] == link["target"]["id"]: if attr["faldo"].endswith("faldoStart"): start_end.append(attr["id"]) start_2 = self.format_sparql_variable( "{}{}_{}".format(attr["entityLabel"], attr["nodeId"], attr["label"])) if attr["faldo"].endswith("faldoEnd"): start_end.append(attr["id"]) end_2 = self.format_sparql_variable( "{}{}_{}".format(attr["entityLabel"], attr["nodeId"], attr["label"])) if attr["faldo"].endswith("faldoStrand"): strand_2 = self.format_sparql_variable( "{}{}_{}_faldoStrand".format( attr["entityLabel"], attr["nodeId"], attr["label"])) strands.append(attr["id"]) triples_relations.append({ "subject": source, "predicate": "askomics:{}".format("includeInReference" if link["sameRef"] else "includeIn"), "object": common_block, "optional": False }) triples_relations.append({ "subject": target, "predicate": "askomics:{}".format("includeInReference" if link["sameRef"] else "includeIn"), "object": common_block, "optional": False }) if link["sameStrand"]: var_to_replace.append((strand_1, strand_2)) else: strands = [] equal_sign = "" if link["strict"] else "=" if link["uri"] == "included_in": filters.append( "FILTER ({start1} >{equalsign} {start2} && {end1} <{equalsign} {end2}) ." .format(start1=start_1, start2=start_2, end1=end_1, end2=end_2, equalsign=equal_sign)) elif link["uri"] == "overlap_with": filters.append( "FILTER (({start2} >{equalsign} {start1} && {start2} <{equalsign} {end1}) || ({end2} >{equalsign} {start1} && {end2} <{equalsign} {end1}))" .format(start1=start_1, start2=start_2, end1=end_1, end2=end_2, equalsign=equal_sign)) # Classic relation else: relation = "<{}>".format(link["uri"]) triples_relations.append({ "subject": source, "predicate": relation, "object": target, "optional": False }) # Store linked attributes for attribute in json_query["attr"]: attributes[attribute["id"]] = { "label": attribute["label"], "entity_label": attribute["entityLabel"], "entity_id": attribute["nodeId"] } if attribute["linked"]: linked_attributes.extend( (attribute["id"], attribute["linkedWith"])) # Browse attributes for attribute in json_query["attr"]: # URI --- if attribute["type"] == "uri": subject = self.format_sparql_variable("{}{}_uri".format( attribute["entityLabel"], attribute["nodeId"])) predicate = attribute["uri"] obj = "<{}>".format(attribute["entityUri"]) if not self.is_bnode(attribute["entityUri"], json_query["nodes"]): triples_attributes.append({ "subject": subject, "predicate": predicate, "object": obj, "optional": False }) if attribute["visible"]: self.selects.append(subject) # filters/values if attribute["filterValue"] != "" and not attribute["linked"]: filter_value = self.get_uri_filter_value( attribute["filterValue"]) if attribute["filterType"] == "regexp": negative_sign = "" if attribute["negative"]: negative_sign = "!" filters.append("FILTER ({}regex({}, {}, 'i'))".format( negative_sign, subject, filter_value)) elif attribute["filterType"] == "exact": if attribute["negative"]: filters.append("FILTER (str({}) != {}) .".format( subject, filter_value)) else: values.append("VALUES {} {{ {} }} .".format( subject, filter_value)) if attribute["linked"]: var_2 = self.format_sparql_variable("{}{}_uri".format( attributes[attribute["linkedWith"]]["entity_label"], attributes[attribute["linkedWith"]]["entity_id"])) var_to_replace.append((subject, var_2)) # Text if attribute["type"] == "text": if attribute["visible"] or attribute[ "filterValue"] != "" or attribute[ "id"] in linked_attributes: subject = self.format_sparql_variable("{}{}_uri".format( attribute["entityLabel"], attribute["nodeId"])) if attribute["uri"] == "rdfs:label": predicate = attribute["uri"] else: predicate = "<{}>".format(attribute["uri"]) obj = self.format_sparql_variable("{}{}_{}".format( attribute["entityLabel"], attribute["nodeId"], attribute["label"])) triples_attributes.append({ "subject": subject, "predicate": predicate, "object": obj, "optional": True if attribute["optional"] else False }) if attribute["visible"]: self.selects.append(obj) # filters/values if attribute["filterValue"] != "" and not attribute[ "optional"] and not attribute["linked"]: if attribute["filterType"] == "regexp": negative_sign = "" if attribute["negative"]: negative_sign = "!" filters.append( "FILTER ({}regex({}, '{}', 'i'))".format( negative_sign, obj, attribute["filterValue"])) elif attribute["filterType"] == "exact": if attribute["negative"]: filters.append("FILTER (str({}) != '{}') .".format( obj, attribute["filterValue"])) else: values.append( "VALUES {} {{ '{}'^^xsd:string }} .".format( obj, attribute["filterValue"])) if attribute["linked"]: var_2 = self.format_sparql_variable("{}{}_{}".format( attributes[attribute["linkedWith"]]["entity_label"], attributes[attribute["linkedWith"]]["entity_id"], attributes[attribute["linkedWith"]]["label"])) var_to_replace.append((obj, var_2)) # Numeric if attribute["type"] == "decimal": if attribute["visible"] or attribute[ "filterValue"] != "" or attribute[ "id"] in start_end or attribute[ "id"] in linked_attributes: subject = self.format_sparql_variable("{}{}_uri".format( attribute["entityLabel"], attribute["nodeId"])) if attribute["faldo"]: predicate = "faldo:location/faldo:{}/faldo:position".format( "begin" if attribute["faldo"]. endswith("faldoStart") else "end") else: predicate = "<{}>".format(attribute["uri"]) obj = self.format_sparql_variable("{}{}_{}".format( attribute["entityLabel"], attribute["nodeId"], attribute["label"])) triples_attributes.append({ "subject": subject, "predicate": predicate, "object": obj, "optional": True if attribute["optional"] else False }) if attribute["visible"]: self.selects.append(obj) # filters if attribute["filterValue"] != "" and not attribute[ "optional"] and not attribute["linked"]: if attribute['filterSign'] == "=": values.append("VALUES {} {{ {} }} .".format( obj, attribute["filterValue"])) else: filter_string = "FILTER ( {} {} {} ) .".format( obj, attribute["filterSign"], attribute["filterValue"]) filters.append(filter_string) if attribute["linked"]: var_2 = self.format_sparql_variable("{}{}_{}".format( attributes[attribute["linkedWith"]]["entity_label"], attributes[attribute["linkedWith"]]["entity_id"], attributes[attribute["linkedWith"]]["label"])) var_to_replace.append((obj, var_2)) # Category if attribute["type"] == "category": if attribute["visible"] or attribute[ "filterSelectedValues"] != [] or attribute[ "id"] in strands or attribute[ "id"] in linked_attributes: node_uri = self.format_sparql_variable("{}{}_uri".format( attribute["entityLabel"], attribute["nodeId"])) category_value_uri = self.format_sparql_variable( "{}{}_{}Category".format(attribute["entityLabel"], attribute["nodeId"], attribute["label"])) category_label = self.format_sparql_variable( "{}{}_{}".format(attribute["entityLabel"], attribute["nodeId"], attribute["label"])) faldo_strand = self.format_sparql_variable( "{}{}_{}_faldoStrand".format(attribute["entityLabel"], attribute["nodeId"], attribute["label"])) if attribute["faldo"] and attribute["faldo"].endswith( "faldoReference"): category_name = 'faldo:location/faldo:begin/faldo:reference' triples_attributes.append({ "subject": node_uri, "predicate": category_name, "object": category_value_uri, "optional": True if attribute["optional"] else False }) if attribute["visible"]: triples_attributes.append({ "subject": category_value_uri, "predicate": "rdfs:label", "object": category_label, "optional": True if attribute["optional"] else False }) elif attribute["faldo"] and attribute["faldo"].endswith( "faldoStrand"): category_name = 'faldo:location/faldo:begin/rdf:type' triples_attributes.append({ "subject": node_uri, "predicate": category_name, "object": category_value_uri, "optional": True if attribute["optional"] else False }) triples_attributes.append({ "subject": faldo_strand, "predicate": "a", "object": category_value_uri, "optional": True if attribute["optional"] else False }) if attribute["visible"]: triples_attributes.append({ "subject": faldo_strand, "predicate": "rdfs:label", "object": category_label, "optional": False }) values.append( "VALUES {} {{ faldo:ReverseStrandPosition faldo:ForwardStrandPosition }} ." .format(category_value_uri)) else: category_name = "<{}>".format(attribute["uri"]) triples_attributes.append({ "subject": node_uri, "predicate": category_name, "object": category_value_uri, "optional": True if attribute["optional"] else False }) if attribute["visible"]: triples_attributes.append({ "subject": category_value_uri, "predicate": "rdfs:label", "object": category_label, "optional": True if attribute["optional"] else False }) if attribute["visible"]: self.selects.append(category_label) # values if attribute["filterSelectedValues"] != [] and not attribute[ "optional"] and not attribute["linked"]: uri_val_list = [] for value in attribute["filterSelectedValues"]: if attribute["faldo"] and attribute["faldo"].endswith( "faldoStrand"): value_var = faldo_strand uri_val_list.append("<{}>".format(value)) else: value_var = category_value_uri uri_val_list.append("<{}>".format(value)) if uri_val_list: values.append("VALUES {} {{ {} }}".format( value_var, ' '.join(uri_val_list))) if attribute["linked"]: var_2 = self.format_sparql_variable( "{}{}_{}Category".format( attributes[ attribute["linkedWith"]]["entity_label"], attributes[attribute["linkedWith"]]["entity_id"], attributes[attribute["linkedWith"]]["label"])) var_to_replace.append((category_value_uri, var_2)) from_string = self.get_froms_from_graphs(self.graphs) federated_from_string = self.get_federated_froms_from_graphs( self.graphs) endpoints_string = self.get_endpoints_string() # Linked attributes: replace SPARQL variable target by source for tpl_var in var_to_replace: var_source = tpl_var[0] var_target = tpl_var[1] for i, triple_dict in enumerate(triples_relations): for key, value in triple_dict.items(): if key != "optional": triples_relations[i][key] = value.replace( var_source, var_target) for i, triple_dict in enumerate(triples_attributes): for key, value in triple_dict.items(): if key != "optional": triples_attributes[i][key] = value.replace( var_source, var_target) for i, select in enumerate(self.selects): self.selects[i] = select.replace(var_source, var_target) for i, filtr in enumerate(filters): filters[i] = filtr.replace(var_source, var_target) # uniq lists triples_relations = Utils.unique(triples_relations) triples_attributes = Utils.unique(triples_attributes) self.selects = Utils.unique(self.selects) # Write the query # query is for editor (no froms, no federated) if for_editor: query = """ SELECT DISTINCT {selects} WHERE {{ {relations} {attributes} {filters} {values} }} """.format(selects=' '.join(self.selects), relations='\n '.join([ self.triple_dict_to_string(triple_dict) for triple_dict in triples_relations ]), attributes='\n '.join([ self.triple_dict_to_string(triple_dict) for triple_dict in triples_attributes ]), filters='\n '.join(filters), values='\n '.join(values)) # Query is federated, add federated lines @federate & @from) elif self.federated: query = """ {endpoints} {federated} SELECT DISTINCT {selects} WHERE {{ {relations} {attributes} {filters} {values} }} """.format(endpoints=endpoints_string, federated=federated_from_string, selects=' '.join(self.selects), relations='\n '.join([ self.triple_dict_to_string(triple_dict) for triple_dict in triples_relations ]), attributes='\n '.join([ self.triple_dict_to_string(triple_dict) for triple_dict in triples_attributes ]), filters='\n '.join(filters), values='\n '.join(values)) # Query on the local endpoint (add froms) elif self.endpoints == [self.local_endpoint_f]: query = """ SELECT DISTINCT {selects} {froms} WHERE {{ {relations} {attributes} {filters} {values} }} """.format(selects=' '.join(self.selects), froms=from_string, relations='\n '.join([ self.triple_dict_to_string(triple_dict) for triple_dict in triples_relations ]), attributes='\n '.join([ self.triple_dict_to_string(triple_dict) for triple_dict in triples_attributes ]), filters='\n '.join(filters), values='\n '.join(values)) # Query an external endpoint (no froms) else: query = """ SELECT DISTINCT {selects} WHERE {{ {relations} {attributes} {filters} {values} }} """.format(selects=' '.join(self.selects), relations='\n '.join([ self.triple_dict_to_string(triple_dict) for triple_dict in triples_relations ]), attributes='\n '.join([ self.triple_dict_to_string(triple_dict) for triple_dict in triples_attributes ]), filters='\n '.join(filters), values='\n '.join(values)) if preview: query += "\nLIMIT {}".format( self.settings.getint('triplestore', 'preview_limit')) return self.prefix_query(textwrap.dedent(query))