def getplace(id): print('id:',id) result = shareds.driver.session().run(cypher_getplace,id=id).single() print('result:',result) if not result: return dict(status="Error",resultCount=0) p = result.get('p') largerPlaces = result['largerPlaces'] smallerPlaces = result['smallerPlaces'] places1 = [] for h1,largerPlace,id2 in largerPlaces: if largerPlace is None: break name2 = largerPlace['pname'] type2 = largerPlace['type'] place = dict(name=name2,type=type2,id=id2) datetype = h1['datetype'] if datetype: date1 = h1['date1'] date2 = h1['date2'] d = DateRange(datetype, date1, date2) timespan = d.__str__() date1 = DateRange.DateInt(h1['date1']).long_date() date2 = str(DateRange.DateInt(h1['date2'])) place['datetype'] = datetype place['date1'] = date1 place['date2'] = date2 place['timespan'] = timespan places1.append(place) places2 = [] for h2,smallerPlace,id2 in smallerPlaces: if smallerPlace is None: break name2 = smallerPlace['pname'] type2 = smallerPlace['type'] place = dict(name=name2,type=type2,id=id2) datetype = h2['datetype'] if datetype: date1 = h2['date1'] date2 = h2['date2'] d = DateRange(datetype, date1, date2) timespan = d.__str__() date1 = str(DateRange.DateInt(h2['date1'])) date2 = str(DateRange.DateInt(h2['date2'])) place['datetype'] = datetype place['date1'] = date1 place['date2'] = date2 place['timespan'] = timespan places2.append(place) #names = [dict(name=pn['name'],lang=pn['lang']) for pn in result['names']] place = PlaceBl.from_node(p) place.names = [PlaceName.from_node(pn) for pn in result['names']] print(smallerPlaces) if smallerPlaces == [[None,None,None]]: smallerPlaces = [] place.surrounds = [PlaceName.from_node(p2) for (h2,p2,id2) in smallerPlaces] place.surrounds=sorted(places2,key=itemgetter('name')) return {"status":"OK", "statusText":"OK", "resultCount": 1, "place": place, }
def read_place_w_names(uniq_id): """ Reads Place_combo nodes or selected node with PlaceName objects. TODO Remove: Not in use """ result = None with shareds.driver.session() as session: if uniq_id: result = session.run(Cypher_place.place_get_one, pid=uniq_id) else: result = session.run(Cypher_place.place_get_all) places = [] for record in result: # Create a Place_combo object from record node = record['p'] pl = Place_combo.from_node(node) names = [] for node in record['names']: # <Node id=78278 labels={'Place_name'} properties={'lang': '', # 'name': 'Kangasalan srk'}> plname = PlaceName.from_node(node) names.append(str(plname)) pl.names.append(plname) pl.clearname = ' • '.join(names) places.append(pl) return places
def get_w_notes(locid): """ Returns the Place_combo with Notes and PlaceNames included. #TODO: Luetaan Notes ja Citations vasta get_persondata_by_id() lopuksi? """ #if isinstance(locid,int): # p.uniq_id = locid #else: # p.uuid = locid with shareds.driver.session() as session: if isinstance(locid, int): place_result = session.run(Cypher_place.get_w_names_notes, place_id=locid) else: place_result = session.run(Cypher_place.get_w_names_notes_uuid, uuid=locid) for place_record in place_result: # <Record # place=<Node id=287246 labels={'Place'} # properties={'coord': [60.375, 21.943], # 'handle': '_da3b305b41147508033e318249b', 'id': 'P0335', # 'type': 'City', 'pname': 'Rymättylä', 'change': 1556954336}> # names=[ # <Node id=287247 labels={'Place_name'} # properties={'name': 'Rymättylä', 'lang': ''}>, # <Node id=287248 labels={'Place_name'} # properties={'name': 'Rimito', 'lang': 'sv'}> ] # notes=[]> node = place_record["place"] pl = Place_combo.from_node(node) for names_node in place_record["names"]: pl.names.append(PlaceName.from_node(names_node)) # if pl.names[-1].lang in ['fi', '']: # #TODO: use current_user's lang # pl.pname = pl.names[-1].name for notes_node in place_record['notes']: n = Note.from_node(notes_node) pl.notes.append(n) for medias_node in place_record['medias']: m = Media.from_node(medias_node) pl.media_ref.append(m) if not (pl.type and pl.id): logger.error( f"Place_combo.read_w_notes: missing data for {pl}") try: return pl except Exception: logger.error( f"Place_combo.read_w_notes: no Place with locid={locid}") return None
def list_top_level_places(): result = shareds.driver.session().run(cypher_list_top_level_places) places = [] for rec in result: place_node = rec['p'] place = PlaceBl.from_node(place_node) place.names = [PlaceName.from_node(pn) for (r,pn) in rec['names']] places.append(place) return {"status":"OK", "statusText":"OK", "resultCount": len(places), "places":sorted(places, key=attrgetter('pname')) }
def place_names_from_nodes(nodes): ''' Filter Name objects from a list of Cypher nodes. Create a list of place_bl.names with PlaceNames by following rules: 1. Place_names using lang == current_user.language 2. Place_names using lang == "" 3. If none found, use the last Place_name Place_names using other languages are discarded nodes=[ <Node id=305800 labels={'Place_name'} properties={'name': 'Helsingfors', 'lang': ''}>, <Node id=305799 labels={'Place_name'} properties={'name': 'Helsinki', 'lang': 'sv'}> ]> ''' from bl.place import PlaceName ret = [] own_lang = [] no_lang = [] alien_lang = [] for node in nodes: pn = PlaceName.from_node(node) if pn.lang == "": no_lang.append(pn) ##print(f"# - no lang {len(place_bl.names)} (Place_name {pn.uniq_id} {pn})") elif pn.lang == current_user.language: own_lang.append(pn) ##print(f"# - my lang (Place_name {pn.uniq_id} {pn})") else: alien_lang.append(pn) ##print(f"# - alien lang (Place_name {pn})") if own_lang: ret = own_lang elif no_lang: ret = no_lang else: ret = alien_lang # for pn in ret: # print(f"# PlaceNames: {pn}") return ret
def mergeplaces(self, id1, id2): cypher_delete_namelinks = """ match (node) -[r:NAME_LANG]-> (pn) where id(node) = $id delete r """ cypher_mergeplaces = """ match (p1:Place) where id(p1) = $id1 match (p2:Place) where id(p2) = $id2 call apoc.refactor.mergeNodes([p1,p2], {properties:'discard',mergeRels:true}) yield node with node match (node) -[r2:NAME]-> (pn2) return node, collect(pn2) as names """ self.tx.run(cypher_delete_namelinks, id=id1).single() rec = self.tx.run(cypher_mergeplaces, id1=id1, id2=id2).single() node = rec['node'] place = PlaceBl.from_node(node) name_nodes = rec['names'] name_objects = [PlaceName.from_node(n) for n in name_nodes] return place, name_objects
def get_object_from_node(node): ''' Noe4j database returns node objects, which are converted to corresponding objects by this function ''' try: label = list(node.labels)[0] except Exception as e: print("{} Empty node? {}".format(e, node)) return None if label == "Event": return Event_combo.from_node(node) elif label == "Name": return Name.from_node(node) elif label == "Person": return Person_combo.from_node(node) # elif label == "Refname": # return Refname.from_node(node) elif label == "Citation": return Citation.from_node(node) elif label == "Source": return Source.from_node(node) elif label == "Repository": return Repository.from_node(node) elif label == "Place": return PlaceBl.from_node(node) elif label == "Place_name": return PlaceName.from_node(node) elif label == "Note": return Note.from_node(node) elif label == "Family": return Family_combo.from_node(node) elif label == "Media": return Media.from_node(node) else: return None
def handle_places(self): ''' Get all the places in the collection. To create place hierarchy links, there must be a dictionary of Place handles and uniq_ids created so far. The link may use previous node or create a new one. ''' place_keys = {} # place_keys[handle] = uniq_id places = self.collection.getElementsByTagName("placeobj") print("***** {} Places *****".format(len(places))) t0 = time.time() counter = 0 # Print detail of each placeobj for placeobj in places: pl = Place_gramps() # Extract handle, change and id self._extract_base(placeobj, pl) pl.type = placeobj.getAttribute("type") # List of upper places in hierarchy as {hlink, dates} dictionaries pl.surround_ref = [] # Note. The ptitle is never saved to Place object! if len(placeobj.getElementsByTagName('ptitle')) == 1: placeobj_ptitle = placeobj.getElementsByTagName('ptitle')[0] pl.ptitle = placeobj_ptitle.childNodes[0].data elif len(placeobj.getElementsByTagName('ptitle')) > 1: self.blog.log_event({ 'title': "More than one ptitle in a place", 'level': "WARNING", 'count': pl.id }) place_order = 0 for placeobj_pname in placeobj.getElementsByTagName('pname'): if placeobj_pname.hasAttribute("value"): placename = PlaceName() placename.order = place_order place_order += 1 placename.name = placeobj_pname.getAttribute("value") #print(f"# placeobj {pl.id} pname {place_order} {placename.name}") if placename.name: if pl.pname == '': # First name is default pname for Place node pl.pname = placename.name placename.lang = placeobj_pname.getAttribute("lang") pl.names.append(placename) else: self.blog.log_event({ 'title': "An empty place name discarded", 'level': "WARNING", 'count': f"{pl.id}({place_order})" }) place_order -= 1 try: # Returns Gramps_DateRange or None placename.dates = self._extract_daterange(placeobj_pname) #TODO: val="1700-luvulla" muunnettava Noteksi except: placename.dates = None for placeobj_coord in placeobj.getElementsByTagName('coord'): if placeobj_coord.hasAttribute("lat") \ and placeobj_coord.hasAttribute("long"): lat = placeobj_coord.getAttribute("lat") long = placeobj_coord.getAttribute("long") if pl.coord: self.blog.log_event({ 'title': "More than one coordinates in a place", 'level': "WARNING", 'count': pl.id }) else: try: pl.coord = Point(lat, long) except Exception as e: self.blog.log_event({ 'title': "Invalid coordinates - {}".format(e), 'level': "WARNING", 'count': pl.id }) for placeobj_url in placeobj.getElementsByTagName('url'): n = Note() n.priv = get_priv(placeobj_url) n.url = placeobj_url.getAttribute("href") n.type = placeobj_url.getAttribute("type") n.text = placeobj_url.getAttribute("description") if n.url: pl.notes.append(n) for placeobj_placeref in placeobj.getElementsByTagName('placeref'): # Traverse links to surrounding (upper) places hlink = placeobj_placeref.getAttribute("hlink") dates = self._extract_daterange(placeobj_placeref) # surround_ref elements example # {'hlink': '_ddd3...', 'dates': <Gramps_DateRange object>} pl.surround_ref.append({'hlink': hlink, 'dates': dates}) ##print(f'# Place {pl.id} is surrouded by {pl.surround_ref[-1]["hlink"]}') for placeobj_noteref in placeobj.getElementsByTagName('noteref'): if placeobj_noteref.hasAttribute("hlink"): pl.noteref_hlink.append( placeobj_noteref.getAttribute("hlink")) ##print(f'# Place {pl.id} has note {pl.noteref_hlink[-1]}') # Handle <objref> pl.media_refs = self._extract_mediaref(placeobj) if pl.media_refs: print(f'# saving Place {pl.id}: media_refs {pl.media_refs}') # Save Place, Place_names, Notes and connect to hierarchy self.save_and_link_handle(pl, batch_id=self.batch_id, place_keys=place_keys) # The place_keys has been updated counter += 1 self.blog.log_event({ 'title': "Places", 'count': counter, 'elapsed': time.time() - t0 }) #, 'percent':1})