[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gnue] r7400 - trunk/gnue-common/src/datasources
From: |
reinhard |
Subject: |
[gnue] r7400 - trunk/gnue-common/src/datasources |
Date: |
Mon, 18 Apr 2005 12:16:30 -0500 (CDT) |
Author: reinhard
Date: 2005-04-18 12:16:29 -0500 (Mon, 18 Apr 2005)
New Revision: 7400
Modified:
trunk/gnue-common/src/datasources/GDataSource.py
Log:
Added some comments and put functions in a (hopefully) better order.
Modified: trunk/gnue-common/src/datasources/GDataSource.py
===================================================================
--- trunk/gnue-common/src/datasources/GDataSource.py 2005-04-18 15:47:48 UTC
(rev 7399)
+++ trunk/gnue-common/src/datasources/GDataSource.py 2005-04-18 17:16:29 UTC
(rev 7400)
@@ -38,14 +38,21 @@
# <datasource>
# =============================================================================
-class GDataSource(GObjects.GObj):
+class GDataSource (GObjects.GObj):
"""
Class that handles DataSources. This is a subclass of GObj, which
means this class can be created from XML markup and stored in an
Object tree (e.g., a Forms tree).
"""
- def __init__(self, parent=None, type="GDataSource"):
- GObjects.GObj.__init__(self, parent, type)
+
+ #
---------------------------------------------------------------------------
+ # Constructor
+ #
---------------------------------------------------------------------------
+
+ def __init__ (self, parent = None, type = "GDataSource"):
+
+ GObjects.GObj.__init__ (self, parent, type)
+
self.type = "object"
self.connection = None
self._connections = None
@@ -59,7 +66,8 @@
self._rowidField = None
self._primarykeyFields = []
- self._inits =[self.primaryInit, self.secondaryInit, self.tertiaryInit]
+ self._inits = [self.__primaryInit, self.__secondaryInit,
+ self.__tertiaryInit]
self._currentResultSet = None
self._resultSetListeners = []
self._toplevelParent = None # Needs to be set by subclass
@@ -70,42 +78,108 @@
# The master DataSource object
self.__master = None
- #
- # trigger support
- #
self._triggerGlobal = True
- self._triggerFunctions =
{'createResultSet':{'function':self.createResultSet,
- },
-
'simpleQuery':{'function':self.triggerSimpleQuery,
- },
-
'delete':{'function':self.deleteCurrentRecordsetEntry
- },
-
'call':{'function':self.callFuncOfCurrentRecordsetEntry
- },
- 'getCondition':{'function':self.getCondition},
- 'setCondition':{'function':self.setCondition},
- 'count' : {'function':self.triggerGetCount},
- 'update': {'function':
- self.updateCurrentRecordSet}
- }
- self._triggerProperties = {'extensions':{'get':self.getExtensions,
- 'direct':1},
- 'recordCount':{'get':self.triggerGetCount,
- 'direct':1},
- 'order_by':{'get':self.triggerGetOrderBy,
- 'set':self.triggerSetOrderBy,
- 'direct':1},
- }
+ self._triggerFunctions = {
+ 'createResultSet': {'function': self.__trigger_createResultSet},
+ 'simpleQuery' : {'function': self.__trigger_simpleQuery},
+ 'update' : {'function': self.__trigger_update},
+ 'delete' : {'function': self.__trigger_delete},
+ 'call' : {'function': self.__trigger_call},
+ 'getCondition' : {'function': self.getCondition},
+ 'setCondition' : {'function': self.setCondition},
+ 'count' : {'function': self.__trigger_get_recordCount}
+ }
+ self._triggerProperties = {
+ 'extensions' : {'get' : self.__trigger_get_extensions,
+ 'direct': 1},
+ 'recordCount': {'get' : self.__trigger_get_recordCount,
+ 'direct': 1},
+ 'order_by' : {'get' : self.__trigger_get_order_by,
+ 'set' : self.__trigger_set_order_by,
+ 'direct': 1}
+ }
+
+
+ # ---------------------------------------------------------------------------
+ # Functions and properties available in triggers
+ # ---------------------------------------------------------------------------
+
+ def __trigger_createResultSet (self, conditions = {}, readOnly = False):
+ self.createResultSet (conditions, readOnly)
+
+ # ---------------------------------------------------------------------------
+
+ def __trigger_simpleQuery (self, maskDict):
+ conditions = GConditions.buildConditionFromDict (
+ queryDict, GConditions.GClike)
+ resultSet = self.createResultSet (conditions)
+ return [record.getFieldsAsDict () for record in resultSet]
+
+ # ---------------------------------------------------------------------------
+
+ def __trigger_update (self):
+
+ self.postAll ()
+ self.requeryAll ()
+
+ # ---------------------------------------------------------------------------
+
+ def __trigger_delete (self):
+ (self._currentResultSet.getPostingRecordset ()).delete ()
+
+ # ---------------------------------------------------------------------------
+
+ def __trigger_call (self, name, params):
+ self.postAll ()
+ result = self._currentResultSet.current.call (name, params)
+ self.requeryAll ()
+ return result
+
+ # ---------------------------------------------------------------------------
+
+ def __trigger_get_extensions (self):
+ return self.extensions
+
+ # ---------------------------------------------------------------------------
+
+ def __trigger_get_recordCount (self):
+ if self._currentResultSet:
+ return len (self._currentResultSet)
+ else:
+ return 0
+
+ # ---------------------------------------------------------------------------
+
+ def __trigger_get_order_by (self):
+ return self.sorting
+
+ # ---------------------------------------------------------------------------
+
+ def __trigger_set_order_by (self, value):
+ self.sorting = self.__convertOrderBy (value)
+ if self._dataObject:
+ self._dataObject.sorting = self.sorting
+
+
+ # ---------------------------------------------------------------------------
+ # Hack to hide the DataObject behind the DataSource
+ # ---------------------------------------------------------------------------
+
def __getattr__(self, attr):
if self._dataObject and attr[1] != '_' and hasattr(self._dataObject,attr):
return getattr(self._dataObject,attr)
else:
raise AttributeError, attr
- def _buildObject(self):
+ # ---------------------------------------------------------------------------
+ # Initialize object after parsing from XML
+ # ---------------------------------------------------------------------------
+
+ def _buildObject (self):
+
# Added 0.5.0 -- Delete before 1.0
if hasattr(self,'database'):
self.connection = self.database
@@ -134,141 +208,78 @@
return GObjects.GObj._buildObject(self)
- def triggerGetOrderBy(self):
- return self.sorting
- def triggerSetOrderBy(self,value):
- self.sorting = self.__convertOrderBy (value)
- if self._dataObject:
- self._dataObject.sorting = self.sorting
+ # ---------------------------------------------------------------------------
+ # Initialize object after parsing from XML
+ # ---------------------------------------------------------------------------
- def triggerGetCount(self):
- if self._currentResultSet:
- return len(self._currentResultSet)
- else:
- return 0
+ def __primaryInit (self):
- def triggerSimpleQuery(self,maskDict):
- queryDict = {}
- okToProcess = True
- for key in maskDict.keys():
- queryDict[key] = "%s" % maskDict[key]
- if not len(queryDict[key]):
- okToProcess = False
- break
+ self._topObject = self.findParentOfType(self._toplevelParent)
+ gDebug (9, "Setting %s to connect mgr %s" \
+ % (self.name, self._topObject._connections))
+ self.__getSortOrder ()
+ self.setConnectionManager(self._topObject._connections)
+ self.initialize()
+ self.connect()
+ self.extensions = self._dataObject.triggerExtensions
- conditions =
GConditions.buildConditionFromDict(queryDict,GConditions.GClike)
- resultSet = self.createResultSet(conditions)
- recordCount = resultSet.getRecordCount()
- returnList = []
- for count in range(recordCount):
- record = resultSet.getRecord(count)
- resultDict = {}
- for key in record.keys():
- resultDict[key]=record.getField(key) or ""
- returnList.append(resultDict)
- return returnList
+ # ---------------------------------------------------------------------------
+ # Initialize object after parsing from XML
+ # ---------------------------------------------------------------------------
- def deleteCurrentRecordsetEntry(self):
- self._currentResultSet.getPostingRecordset().delete()
+ # TODO: Merged into GDataSource per the TODOs in reports and forms however
+ # TODO: self._topObject._datasourceDictionary implies that the top object
+ # TODO: always has a specifc structure. This is a bad thing :( Maybe
GRootObj
+ # TODO: should contain a getDatasourceDict()?
+ #
+ def __secondaryInit (self):
+ if hasattr(self, 'master') and self.master:
- # ---------------------------------------------------------------------------
- # Sync the current record with the backend
- # ---------------------------------------------------------------------------
+ self.master = string.lower(self.master)
+ gDebug (7, "Linking detail '%s' to master '%s'" \
+ % (self.name, self.master))
- def updateCurrentRecordSet (self):
- """
- Send changes to the backend and update local data to reflect changes done
- by the backend.
- """
+ if self._topObject._datasourceDictionary.has_key(self.master):
+ self.__master = self._topObject._datasourceDictionary [self.master]
+ masterDataObject = self.__master.getDataObject ()
+ detailDataObject = self.getDataObject ()
+ masterDataObject.addDetailDataObject (detailDataObject, self)
+ else:
+ tmsg = u_("Detail source '%(source)s' references non-existant master "
+ "'%(master)s'") \
+ % {'source': self.name,
+ 'master': self.master}
+ raise StandardError, tmsg
- self.postAll ()
- self.requeryAll ()
-
# ---------------------------------------------------------------------------
- # Call a backend function for the current record
+ # Initialize object after parsing from XML
# ---------------------------------------------------------------------------
- def callFuncOfCurrentRecordsetEntry (self, name, params):
- """
- Call function in the backend for the current record.
- """
+ def __tertiaryInit (self):
- self.postAll ()
- result = self._currentResultSet.current.call (name, params)
- self.requeryAll ()
- return result
+ if hasattr(self, 'prequery'):
+ if not self.hasMaster() and self.prequery:
+ self.createResultSet()
# ---------------------------------------------------------------------------
- # Post all changes in this datasource to the backend
+ # Set the Connection Manager for this DataSource
# ---------------------------------------------------------------------------
- def postAll (self):
- """
- Post all changes to the backend.
+ def setConnectionManager (self, connectionManager):
+ self._connections = connectionManager
- This function posts the top level master datasource of this datasource and
- all of that datasource's children.
- After calling postAll, L{requeryAll} must be called.
- """
-
- if self.__master:
- self.__master.postAll ()
- else:
- self._currentResultSet.post ()
-
-
# ---------------------------------------------------------------------------
- # Requery data from the backend
+ # Initialize the datasource
# ---------------------------------------------------------------------------
- def requeryAll (self):
- """
- Requery data from the backend.
+ def initialize(self):
- This must be called after L{postAll} to synchronize the datasource with
- changes that happened in the backend (through backend triggers). It
- requeries the top level master datasource of this datasource and all of
- that datasource's children.
- """
-
- if self.__master:
- self.__master.requeryAll ()
- else:
- self._currentResultSet.requery ()
-
-
- #
- # get/set the static condition assosiated with a datasource
- # the static condition is build out of the <condition> child
- # elements below a datasource XML definition
- #
- def setCondition(self, mycondition):
- self._dataObject._staticCondition = mycondition
-# dataObject.invalidateCachedConditions()
-
- def getCondition(self):
- return self._dataObject._staticCondition
-
- #
- # get the dbdriver extension object
- #
- def getExtensions(self):
- return self.extensions
-
- #
- # This method should be called after the object is created
- # but before any other methods are called
- #
- def setConnectionManager(self, connectionManager):
- self._connections = connectionManager
-
- def initialize(self):
if not self.connection:
# We are a connectionless datasource (virtual?)
# We have to bind to something, so bind to empty or static driver
@@ -356,17 +367,37 @@
self._dataObject.sorting = self.sorting
+ # ---------------------------------------------------------------------------
+ # Open a backend connection for this datasource
+ # ---------------------------------------------------------------------------
+
def connect(self):
if self.connection != None:
self._connections.requestConnection(self._dataObject)
- def getDataObject(self):
- return self._dataObject
+ # ---------------------------------------------------------------------------
+ # Set the static condition for this datasource
+ # ---------------------------------------------------------------------------
+ def setCondition (self, mycondition):
+ self._dataObject._staticCondition = mycondition
- def referenceField(self, field, defaultValue=None):
+ # ---------------------------------------------------------------------------
+ # Return the static condition for this datasource
+ # ---------------------------------------------------------------------------
+
+ def getCondition (self):
+ return self._dataObject._staticCondition
+
+
+ # ---------------------------------------------------------------------------
+ # Reference a bound field
+ # ---------------------------------------------------------------------------
+
+ def referenceField (self, field, defaultValue = None):
+
if self.type == 'unbound':
gDebug (1, "Trying to bind field %s to unbound DataSource" % field)
return
@@ -378,7 +409,12 @@
if defaultValue != None:
self._defaultData [field] = defaultValue
- def referenceFields(self, fields):
+
+ # ---------------------------------------------------------------------------
+ # Reference several bound fields
+ # ---------------------------------------------------------------------------
+
+ def referenceFields (self, fields):
for field in fields:
if isinstance (field, types.StringType) or \
isinstance (field, types.UnicodeType):
@@ -386,6 +422,11 @@
else:
self.referenceField(*field)
+
+ # ---------------------------------------------------------------------------
+ # Reference an unbound field
+ # ---------------------------------------------------------------------------
+
def referenceUnboundField(self, field, defaultValue=None):
gDebug (7,'Unbound Field %s implicitly referenced' % field)
@@ -395,90 +436,133 @@
self._defaultData [field] = defaultValue
- #
- # The following is a simple wrapper around the datasource's dataobject
- # to hide the dataobject from the app programmer
- #
- def hasMaster(self):
+ # ---------------------------------------------------------------------------
+ # Register a listener for changes of the ResultSet
+ # ---------------------------------------------------------------------------
+
+ def registerResultSetListener(self, listener):
+ self._resultSetListeners.append(listener)
+
+
+ # ---------------------------------------------------------------------------
+ # Called by dbdrivers whenever this datasource's master has changed
+ # ---------------------------------------------------------------------------
+
+ def masterResultSetChanged(self, masterResultSet, detailResultSet):
+ self._masterResultSet = masterResultSet
+ self.__setResultSet (detailResultSet)
+
+
+ # ---------------------------------------------------------------------------
+ # Get the DataObject instance
+ # ---------------------------------------------------------------------------
+
+ def getDataObject(self):
+ return self._dataObject
+
+
+ # ---------------------------------------------------------------------------
+ # Return True if this datasource is a detail
+ # ---------------------------------------------------------------------------
+
+ def hasMaster (self):
return self._dataObject != None and self._dataObject.hasMaster()
+
+ # ---------------------------------------------------------------------------
+ # Add a detail dataobject for this (master) datasource
+ # ---------------------------------------------------------------------------
+
+ def addDetailDataObject (self, dataObject, handler=None):
+ self._dataObject.addDetailDataObject(dataObject, handler)
+
+
+ # ---------------------------------------------------------------------------
+ # Create a result set
+ # ---------------------------------------------------------------------------
+
def createResultSet (self, conditions = {}, readOnly = False):
resultSet = self._dataObject.createResultSet (conditions, readOnly)
self.__setResultSet (resultSet)
return resultSet
- def addDetailDataObject(self, dataObject, handler=None):
- self._dataObject.addDetailDataObject(dataObject, handler)
+ # ---------------------------------------------------------------------------
+ # Create an empty result set
+ # ---------------------------------------------------------------------------
+
def createEmptyResultSet(self, readOnly=False,masterRecordSet=None):
resultSet = self._dataObject.createEmptyResultSet(readOnly,
masterRecordSet=masterRecordSet)
- self.__setResultSet( resultSet )
+ self.__setResultSet (resultSet)
return resultSet
- #
- # Master/detail stuff
- #
- # Called by dbdrivers whenever this datasource's master has changed
- def masterResultSetChanged(self, masterResultSet, detailResultSet):
- self._masterResultSet = masterResultSet
- self.__setResultSet( detailResultSet )
+ # ---------------------------------------------------------------------------
+ # Get the DataObject instance
+ # ---------------------------------------------------------------------------
def __setResultSet(self, resultSet):
self._currentResultSet = resultSet
self.notifyResultSetListeners ()
+
+ # ---------------------------------------------------------------------------
+ # Find a specific record in the resultset by field values
+ # ---------------------------------------------------------------------------
+
+ def findRecord(self, fieldValues):
+ self._currentResultSet.findRecord(fieldValues)
+
+
+ # ---------------------------------------------------------------------------
+ # Get the DataObject instance
+ # ---------------------------------------------------------------------------
+
def notifyResultSetListeners (self):
for listener in self._resultSetListeners:
listener (self._currentResultSet)
- def registerResultSetListener(self, listener):
- self._resultSetListeners.append(listener)
- def primaryInit(self):
- self._topObject = self.findParentOfType(self._toplevelParent)
- gDebug (9, "Setting %s to connect mgr %s" \
- % (self.name, self._topObject._connections))
- self.__getSortOrder ()
- self.setConnectionManager(self._topObject._connections)
- self.initialize()
- self.connect()
- self.extensions = self._dataObject.triggerExtensions
+ # ---------------------------------------------------------------------------
+ # Post all changes in this datasource to the backend
+ # ---------------------------------------------------------------------------
+ def postAll (self):
+ """
+ Post all changes to the backend.
- # TODO: Merged into GDataSource per the TODOs in reports and forms however
- # TODO: self._topObject._datasourceDictionary implies that the top object
- # TODO: always has a specifc structure. This is a bad thing :( Maybe
GRootObj
- # TODO: should contain a getDatasourceDict()?
- #
- def secondaryInit(self):
+ This function posts the top level master datasource of this datasource and
+ all of that datasource's children.
- if hasattr(self, 'master') and self.master:
+ After calling postAll, L{requeryAll} must be called.
+ """
- self.master = string.lower(self.master)
- gDebug (7, "Linking detail '%s' to master '%s'" \
- % (self.name, self.master))
+ if self.__master:
+ self.__master.postAll ()
+ else:
+ self._currentResultSet.post ()
- if self._topObject._datasourceDictionary.has_key(self.master):
- self.__master = self._topObject._datasourceDictionary [self.master]
- masterDataObject = self.__master.getDataObject ()
- detailDataObject = self.getDataObject ()
- masterDataObject.addDetailDataObject (detailDataObject, self)
- else:
- tmsg = u_("Detail source '%(source)s' references non-existant master "
- "'%(master)s'") \
- % {'source': self.name,
- 'master': self.master}
- raise StandardError, tmsg
+ # ---------------------------------------------------------------------------
+ # Requery data from the backend
+ # ---------------------------------------------------------------------------
+ def requeryAll (self):
+ """
+ Requery data from the backend.
- def tertiaryInit(self):
- if hasattr(self, 'prequery'):
- if not self.hasMaster() and self.prequery:
- self.createResultSet()
+ This must be called after L{postAll} to synchronize the datasource with
+ changes that happened in the backend (through backend triggers). It
+ requeries the top level master datasource of this datasource and all of
+ that datasource's children.
+ """
+ if self.__master:
+ self.__master.requeryAll ()
+ else:
+ self._currentResultSet.requery ()
+
# ---------------------------------------------------------------------------
# Make sure we have either no sort order, or one in the proper format
# ---------------------------------------------------------------------------
@@ -560,27 +644,30 @@
return result
-
- # Find a specific record in the resultset by field values
- def findRecord(self, fieldValues):
- self._currentResultSet.findRecord(fieldValues)
-
- #
+ # ---------------------------------------------------------------------------
# Hooks for record-level triggers
- #
+ # ---------------------------------------------------------------------------
def _beforeCommitInsert(self, record):
return 1
+ # ---------------------------------------------------------------------------
+
def _beforeCommitUpdate(self, record):
return 1
+ # ---------------------------------------------------------------------------
+
def _beforeCommitDelete(self, record):
return 1
+ # ---------------------------------------------------------------------------
+
def _onModification(self, record):
return 1
+ # ---------------------------------------------------------------------------
+
def _onRecordLoaded(self, record):
return 1
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [gnue] r7400 - trunk/gnue-common/src/datasources,
reinhard <=