gramps/src/GrampsDb/_GrampsInMemDB.py
Alex Roitman 581989107b * src/GrampsDb/_GrampsDbBase.py (transaction_commit): Remove
backend-specific call.
	* src/GrampsDb/_GrampsBSDDB.py (transaction_commit): Move surname
	list build to work for any batch transaction.
	* src/GrampsDb/_GrampsInMemDB.py (transaction_commit): Add method.


svn: r7939
2007-01-20 16:55:08 +00:00

368 lines
12 KiB
Python

#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2006 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"""
Provides the common infrastructure for database formats that
must hold all of their data in memory.
"""
#-------------------------------------------------------------------------
#
# Python modules
#
#-------------------------------------------------------------------------
import time
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
from RelLib import *
from _GrampsDbBase import *
class GrampsInMemCursor(GrampsCursor):
"""
Cursor class for in-memory database classes. Since the in-memory
classes use python dictionaries, the python iter class is used
to provide the cursor function.
"""
def __init__(self,src_map):
self.src_map = src_map
self.current = iter(src_map)
def first(self):
self.current = iter(self.src_map)
return self.next()
def next(self):
try:
index = self.current.next()
return (index,self.src_map[index])
except StopIteration:
return None
def close(self):
pass
#-------------------------------------------------------------------------
#
# GrampsInMemDB
#
#-------------------------------------------------------------------------
class GrampsInMemDB(GrampsDbBase):
"""GRAMPS database object. This object is a base class for other
objects."""
ID_INDEX = 1 # an index of the gramps id in the data tuple
def __init__(self):
"""creates a new GrampsDB"""
GrampsDbBase.__init__(self)
self.person_map = {}
self.name_group = {}
self.family_map = {}
self.place_map = {}
self.source_map = {}
self.repository_map = {}
self.media_map = {}
self.event_map = {}
self.metadata = {}
self.filename = ""
self.id_trans = {}
self.pid_trans = {}
self.fid_trans = {}
self.eid_trans = {}
self.sid_trans = {}
self.rid_trans = {}
self.oid_trans = {}
self.undodb = []
def load(self,name,callback,mode="w"):
self.full_name = name
self.readonly = mode == "r"
self.open_undodb()
# Re-set the undo history to a fresh session start
self.undoindex = -1
self.translist = [None] * len(self.translist)
self.abort_possible = True
self.undo_history_timestamp = time.time()
def transaction_commit(self,transaction,msg):
GrampsDbBase.transaction_commit(self,transaction,msg)
if transaction.batch:
self.build_surname_list()
def get_person_cursor(self):
return GrampsInMemCursor(self.person_map)
def get_family_cursor(self):
return GrampsInMemCursor(self.family_map)
def get_event_cursor(self):
return GrampsInMemCursor(self.event_map)
def get_place_cursor(self):
return GrampsInMemCursor(self.place_map)
def get_source_cursor(self):
return GrampsInMemCursor(self.source_map)
def get_repository_cursor(self):
return GrampsInMemCursor(self.repository_map)
def get_media_cursor(self):
return GrampsInMemCursor(self.media_map)
def close(self):
self.close_undodb()
def set_name_group_mapping(self,name,group):
if group == None and self.name_group.has_key(name):
del self.name_group[name]
else:
self.name_group[name] = group
def build_surname_list(self):
a = set()
for person_id in iter(self.person_map):
p = self.get_person_from_handle(person_id)
a.add(unicode(p.get_primary_name().get_surname()))
self.surname_list = list(a)
self.sort_surname_list()
def remove_from_surname_list(self,person):
"""
Check whether there are persons with the same surname left in
the database. If not then we need to remove the name from the list.
The function must be overridden in the derived class.
"""
name = str(person.get_primary_name().get_surname())
count = 0
do_remove = True
for person_id in iter(self.person_map):
p = self.get_person_from_handle(person_id)
pn = str(p.get_primary_name().get_surname())
if pn == name:
count += 1
if count > 1:
do_remove = False
break
if do_remove:
self.surname_list.remove(unicode(name))
def _del_person(self,handle):
person = self.get_person_from_handle(str(handle))
del self.id_trans[person.get_gramps_id()]
del self.person_map[str(handle)]
def _del_source(self,handle):
source = self.get_source_from_handle(str(handle))
del self.sid_trans[source.get_gramps_id()]
del self.source_map[str(handle)]
def _del_repository(self,handle):
repository = self.get_repository_from_handle(str(handle))
del self.rid_trans[repository.get_gramps_id()]
del self.repository_map[str(handle)]
def _del_place(self,handle):
place = self.get_place_from_handle(str(handle))
del self.pid_trans[place.get_gramps_id()]
del self.place_map[str(handle)]
def _del_media(self,handle):
obj = self.get_object_from_handle(str(handle))
del self.oid_trans[obj.get_gramps_id()]
del self.media_map[str(handle)]
def _del_family(self,handle):
family = self.get_family_from_handle(str(handle))
del self.fid_trans[family.get_gramps_id()]
del self.family_map[str(handle)]
def _del_event(self,handle):
event = self.get_event_from_handle(str(handle))
del self.eid_trans[event.get_gramps_id()]
del self.event_map[str(handle)]
def get_trans_map(self,signal_root):
"""
A silly method to get the secondary index map based on the
signal name root for a given object type. The BDB backend
manages this transparently, but we need to manually take
care of secondary indices in the InMem backend.
"""
trans_maps = {
'person': self.id_trans,
'family': self.fid_trans,
'source': self.sid_trans,
'event' : self.eid_trans,
'media' : self.oid_trans,
'place' : self.pid_trans,
'repository': self.rid_trans}
return trans_maps[signal_root]
def undo_data(self, data, handle, db_map, signal_root):
"""
The BDB backend manages secondary indices transparently,
but we need to manually take care of secondary indices
in the InMem backend.
"""
trans_map = self.get_trans_map(signal_root)
obj = db_map.get(handle)
if data == None:
self.emit(signal_root + '-delete', ([handle], ))
del trans_map[obj[self.ID_INDEX]]
del db_map[handle]
else:
if obj:
signal = signal_root + '-update'
if obj[self.ID_INDEX] != data[self.ID_INDEX]:
del trans_map[obj[self.ID_INDEX]]
else:
signal = signal_root + '-add'
db_map[handle] = data
trans_map[data[self.ID_INDEX]] = str(handle)
self.emit(signal, ([handle], ))
def _commit_inmem_base(self,obj,db_map,trans_map):
if self.readonly or not obj or not obj.get_handle():
return False
gid = obj.gramps_id
old_data = db_map.get(obj.handle)
if old_data:
old_id = old_data[self.ID_INDEX]
if obj.gramps_id != old_id:
del trans_map[old_id]
trans_map[gid] = obj.handle
return True
def commit_person(self,person,transaction,change_time=None):
if not self._commit_inmem_base(person,self.person_map,self.id_trans):
return
GrampsDbBase.commit_person(self,person,transaction,change_time)
def commit_place(self,place,transaction,change_time=None):
if not self._commit_inmem_base(place,self.place_map,self.pid_trans):
return
GrampsDbBase.commit_place(self,place,transaction,change_time)
def commit_family(self,family,transaction,change_time=None):
if not self._commit_inmem_base(family,self.family_map,self.fid_trans):
return
GrampsDbBase.commit_family(self,family,transaction,change_time)
def commit_event(self,event,transaction,change_time=None):
if not self._commit_inmem_base(event,self.event_map,self.eid_trans):
return
GrampsDbBase.commit_event(self,event,transaction,change_time)
def commit_media_object(self,obj,transaction,change_time=None):
if not self._commit_inmem_base(obj,self.media_map,self.oid_trans):
return
GrampsDbBase.commit_media_object(self,obj,transaction,change_time)
def commit_source(self,source,transaction,change_time=None):
if not self._commit_inmem_base(source,self.source_map,self.sid_trans):
return
GrampsDbBase.commit_source(self,source,transaction,change_time)
def commit_repository(self,repository,transaction,change_time=None):
if not self._commit_inmem_base(repository,self.repository_map,
self.rid_trans):
return
GrampsDbBase.commit_repository(self,repository,transaction,change_time)
def get_person_from_gramps_id(self,val):
handle = self.id_trans.get(str(val))
if handle:
data = self.person_map[handle]
if data:
person = Person()
person.unserialize(data)
return person
return None
def get_family_from_gramps_id(self,val):
handle = self.fid_trans.get(str(val))
if handle:
data = self.family_map[handle]
if data:
family = Family()
family.unserialize(data)
return family
return None
def get_event_from_gramps_id(self,val):
handle = self.eid_trans.get(str(val))
if handle:
data = self.event_map[handle]
if data:
event = Event()
event.unserialize(data)
return event
return None
def get_place_from_gramps_id(self,val):
handle = self.pid_trans.get(str(val))
if handle:
data = self.place_map[handle]
if data:
place = Place()
place.unserialize(data)
return place
return None
def get_source_from_gramps_id(self,val):
handle = self.sid_trans.get(str(val))
if handle:
data = self.source_map[handle]
if data:
source = Source()
source.unserialize(data)
return source
return None
def get_repository_from_gramps_id(self,val):
handle = self.rid_trans.get(str(val))
if handle:
data = self.repository_map[handle]
if data:
repository = Repository()
repository.unserialize(data)
return repository
return None
def get_object_from_gramps_id(self,val):
handle = self.oid_trans.get(str(val))
if handle:
data = self.media_map[handle]
if data:
obj = MediaObject()
obj.unserialize(data)
return obj
return None