Package Gnumed :: Package pycommon :: Module gmDrugObject
[frames] | no frames]

Source Code for Module Gnumed.pycommon.gmDrugObject

  1  ############################################################################# 
  2  # 
  3  # gmDrugObject - Object hiding all drug related backend communication 
  4  # --------------------------------------------------------------------------- 
  5  # 
  6  # @author: Hilmar Berger 
  7  # @copyright: author 
  8  # @license: GPL (details at http://www.gnu.org) 
  9  # 
 10  ############################################################################ 
 11   
 12  # FIXME: likely, this should be in client/business/ 
 13   
 14  #==================================================================              
 15  # $Source: /cvsroot/gnumed/gnumed/gnumed/client/pycommon/gmDrugObject.py,v $       
 16  # $Id: gmDrugObject.py,v 1.4 2008/04/13 14:41:40 ncq Exp $ 
 17  __version__ = "$Revision: 1.4 $"                                                
 18  __author__ = "Hilmar Berger <Hilmar.Berger@gmx.net>" 
 19   
 20  import sys, string, types, os.path 
 21   
 22  _log = gmLog.gmDefLog 
 23  if __name__ == "__main__": 
 24          # running standalone means diagnostics by definition, hehe 
 25          _log.SetAllLogLevels(gmLog.lData) 
 26  _log.Log(gmLog.lData, __version__) 
 27   
 28  from gmExceptions import * 
 29   
 30  #-------------------------------------------------------------------------- 
31 -class cQueryGroup:
32 """Object holding query strings and associated variable lists grouped together. 33 34 - Every query has to be identified by a unique identifier (string or number). 35 - mQueryStrings holds the query strings returning one or more parameters. 36 - mVarNames holds a list of variables that are to be filled by the query, 37 for this the order of the returned column names map 1:1 onto the 38 variable names 39 - mMappings holds the variables that should be mapped to the query. 40 - mInfos holds arbitrary infos (in a single string) about the query. 41 This can be used for format strings and so on. 42 - These three dictionaries are accessible from other objects. 43 - You must use addEntry to add entries to the dictionaries, though, 44 else the data will be written to the class as static variables. 45 """ 46
47 - def __init__(self):
48 self.mVarNames = {} 49 self.mQueryStrings = {} 50 self.mMappings = {}
51
52 - def addEntry(self, aEntry = None):
53 if aEntry != None: 54 self.mVarNames[aEntry] = None 55 self.mQueryStrings[aEntry] = None 56 self.mMappings[aEntry] = None
57 58 #--------------------------------------------------------------------------
59 -class cDrug:
60 """High level API to access drug data 61 62 FIXME: should class Drug not, perhaps, be derived from gmBusinessDBObject ? 63 """ 64 _db = None 65 #--------------------------------------------------------------------------
66 - def __init__(self, fastInit=0, queryCfgSource = None):
67 """initialize static variables""" 68 69 self.mVars = {} # variables usable for mapping 70 self.__mQueryGroups = {} 71 self.__mQueryGroupHandlers = {} 72 self.__fastInit=0 73 74 # get queries from configuration source (currently only files are supported) 75 if queryCfgSource is None: 76 _log.Log(gmLog.lWarn, "No query configuration source specified") 77 # we want to return an error here 78 # in that case we'll have to raise an exception... can't return 79 # anything else than None from an __init__ method 80 raise TypeError, "No query configuration source specified" 81 else: 82 self.__mQueryCfgSource = queryCfgSource 83 if not self.__getQueries(): 84 raise IOError, "cannot load queries" 85 86 # try to fetch all data at once if fastInit is true 87 self.__fastInit = fastInit 88 if fastInit: 89 self.getAllData()
90 #--------------------------------------------------------------------------
91 - def GetData(self, groupName = None, refresh=0):
92 """Get data of QueryGroupHandlers identified by groupName. 93 94 Returns None if the group does not exist or if the query was not 95 successful. Else it returns a dictionary containing all the variables 96 defined for this query. 97 If the query should be repeated instead of the cached data used, you will 98 have to set refresh to 1 (you should do this if some mapped variable was 99 changed). 100 """ 101 # return None if no sub object was named 102 if groupName is None: 103 return None 104 105 if self.__mQueryGroupHandlers.has_key(groupName): 106 # get query group data 107 result = self.__mQueryGroupHandlers[groupName].getData(refresh) 108 return result 109 else: 110 return None
111 #--------------------------------------------------------------------------
112 - def GetAllData(self):
113 """fetch data of all standard sub objects""" 114 for s in self.__QueryGroupHandlers.keys(): 115 self.GetData(s)
116 117 #--------------------------------------------------------------------------
118 - def __getQueries(self):
119 """get query strings and initialize query group objects""" 120 121 # open configuration source 122 try: 123 cfgSource = gmCfg.cCfgFile(aFile = self.__mQueryCfgSource, \ 124 flags=gmCfg.cfg_SEARCH_STD_DIRS | gmCfg.cfg_IGNORE_CMD_LINE) 125 # handle all exceptions including 'config file not found' 126 except: 127 exc = sys.exc_info() 128 _log.LogException("Unhandled exception while opening config file [%s]" % self.__mQueryCfgSource, exc, verbose = 0) 129 return None 130 131 cfgData = cfgSource.getCfg() 132 groups = cfgSource.getGroups() 133 134 # every group holds one query consisting of three items: variables, the 135 # query itself and the mappings 136 # queries are identified by the item 'type=query' 137 for entry_group in groups: 138 gtype = cfgSource.get(entry_group, "type") 139 # groups not containing queries are silently ignored 140 if gtype != 'query': 141 continue 142 143 qname = cfgSource.get(entry_group, "querygroup") 144 if qname is None: 145 _log.Log(gmLog.lWarn,"query definition invalid in entry_group %s." % entry_group) 146 continue 147 148 qvars = cfgSource.get(entry_group, "variables") 149 if qvars is None: 150 _log.Log(gmLog.lWarn,"query definition invalid in entry_group %s." % entry_group) 151 continue 152 153 # query is gonna be a list because of issues 154 # with special characters in simple string items 155 query = cfgSource.get(entry_group, "query") 156 if query is None or not type(query) == types.ListType: 157 _log.Log(gmLog.lWarn,"query definition invalid in entry_group %s." % entry_group) 158 continue 159 160 qstring = query[0] 161 162 qmappings = cfgSource.get(entry_group, "mappings") 163 if qmappings is None: 164 _log.Log(gmLog.lWarn,"query definition invalid in entry_group %s." % entry_group) 165 continue 166 167 # add new query group to QueryGroups dictionary 168 if not self.__mQueryGroups.has_key(qname): 169 self.__mQueryGroups[qname] = cQueryGroup() 170 self.__mQueryGroups[qname].addEntry(entry_group) 171 172 # set the parameters read from config file 173 self.__mQueryGroups[qname].mVarNames[entry_group] = string.split(qvars, ',') 174 self.__mQueryGroups[qname].mMappings[entry_group] = string.split(qmappings, ',') 175 self.__mQueryGroups[qname].mQueryStrings[entry_group] = qstring 176 177 # inititalize variables used for mapping 178 for v in string.split(qmappings, ','): 179 # print "var %s" % v 180 if v != '': 181 self.mVars[v] = None 182 183 # initialize new QueryGroupHandler objects using configuration data 184 for so in self.__mQueryGroups.keys(): 185 self.__mQueryGroupHandlers[so] = cQueryGroupHandler(self, so, self.__mQueryGroups[so]) 186 187 return 1
188 #--------------------------------------------------------------------------
189 -class cQueryGroupHandler:
190 """Object covering groups of related items. 191 192 used to access the backend to fetch all those items at once 193 194 """ 195 #--------------------------------------------------------------------------
196 - def __init__(self, aParent=None, aName=None, aQueryGroup=None):
197 self.__mParent = None # points to the parent Drug object, used to access mVars 198 self.__mDBObject = None # reference to DBObject 199 self.__mObjectName = None # this DrugQueryGroupHandler's name 200 self.__mQueries = cQueryGroup() # a QueryGroup holding queries to get the data for this QueryGroupHandlers. 201 self.__mData = {} # a dictionary holding all items belonging to this QueryGroupHandler 202 203 if aParent != None: 204 self.__mParent = aParent 205 if aQueryGroup != None: 206 self.__mQueries = aQueryGroup 207 if aName != None: 208 self.__mObjectName = aName
209 #--------------------------------------------------------------------------
210 - def getData(self,refresh=0):
211 """returns a dictionary of entry names and its values""" 212 213 # if data must be refreshed, clear data cache 214 if refresh == 1: 215 self.__mData = {} 216 217 if len(self.__mData) == 0: 218 # if data has not been fetched until now, get the data from backend 219 if self.__fetchBackendData(): 220 return self.__mData 221 else: 222 return None 223 else: 224 # else return the data already available 225 return self.__mData
226 227 #--------------------------------------------------------------------------
228 - def __fetchBackendData(self):
229 """try to fetch data from backend""" 230 231 # cycle through query strings and get data 232 for queryName in self.__mQueries.mQueryStrings.keys(): 233 # get variable mappings 234 mappings = self.__mQueries.mMappings[queryName] 235 allVars = [] 236 for var in mappings: 237 # get variables from parent 238 if var != '': 239 allVars.append(self.__mParent.mVars[var]) 240 241 # print "QUERY ", self.__mQueries.mQueryStrings[queryName] % tuple(allVars) 242 # set query string 243 if len(allVars) > 0: 244 querystring = self.__mQueries.mQueryStrings[queryName] % tuple(allVars) 245 else: 246 querystring = self.__mQueries.mQueryStrings[queryName] 247 248 # _log.Log(gmLog.lInfo, "Running query: %s" % querystring) 249 try: 250 result = gmPG.run_ro_query('pharmaceutica',querystring) 251 except: 252 _log.Log(gmLog.lWarn, "Query failed.") 253 254 # maybe we should raise an exception here 255 if result is None: 256 return None 257 258 # get results 259 VarNames = self.__mQueries.mVarNames[queryName] 260 VarNumMax = len(VarNames) 261 # init missing vars (keys) in data cache dict 262 for vn in VarNames: 263 if not self.__mData.has_key(vn): 264 self.__mData[vn] = [] 265 266 # if we got just one row in the result 267 if len(result) == 1: 268 row = result[0] # the row we fetched 269 col_idx = 0 # column counter 270 cols_avail = len(row) # number of available columns in row 271 for col_val in row: # loop through all columns 272 # don't try to map more columns than we have variable name mappings for 273 if col_idx > VarNumMax: 274 break 275 # map column (field) name to variable name in cache object 276 VarName = VarNames[col_idx] 277 # and cache the value 278 self.__mData[VarName] = col_val 279 # increase column count 280 col_idx = col_idx + 1 281 282 else: 283 # if multiple rows in result 284 for row in result[:]: 285 col_idx = 0 286 cols_avail = len(row) 287 for col_val in row: 288 if col_idx > VarNumMax: 289 break 290 VarName = VarNames[col_idx] 291 self.__mData[VarName].append(col_val) 292 col_idx = col_idx + 1 293 294 # return TRUE if everything went right 295 return 1
296 #==================================================================================== 297 # MAIN 298 #==================================================================================== 299 300 if __name__ == "__main__": 301 import os.path 302 tmp = os.path.join(os.path.expanduser("~"), ".gnumed", "amis.conf") 303 a = cDrug(0, tmp) 304 x = a.GetData('brand') 305 if x: 306 print x 307 else: 308 print "Query wasn't successful." 309 310 print "-----------------------------------------------------" 311 a.mVars['ID']="3337631600" 312 y=a.GetData('product_info') 313 print y 314 # y = a.GetData('brand_all') 315 # print y 316 # print len(x['brandname']) 317 #==================================================================================== 318 # $Log: gmDrugObject.py,v $ 319 # Revision 1.4 2008/04/13 14:41:40 ncq 320 # - old style logging is out 321 # 322 # Revision 1.3 2005/03/17 20:32:14 hinnef 323 # -fixed module dependencies 324 # 325 # Revision 1.2 2005/01/19 11:15:41 ncq 326 # - lots of FIXME stuff and some cleanup 327 # 328 # Revision 1.1 2004/02/25 09:30:13 ncq 329 # - moved here from python-common 330 # 331 # Revision 1.2 2003/11/17 10:56:36 sjtan 332 # 333 # synced and commiting. 334 # 335 # Revision 1.1 2003/10/23 06:02:39 sjtan 336 # 337 # manual edit areas modelled after r.terry's specs. 338 # 339 # Revision 1.1 2003/08/24 13:38:24 hinnef 340 # moved to main-tree, some bug fixes 341 # 342 # Revision 1.7 2002/11/17 16:44:23 hinnef 343 # fixed some bugs regarding display of non-string items and list entries in PI 344 # 345 # Revision 1.6 2002/10/29 15:40:48 ncq 346 # - first try at making this runnable standalone 347 # 348 # Revision 1.5 2002/10/28 23:26:02 hinnef 349 # first partially functional DrugReferenceBrowser version 350 # 351 # Revision 1.4 2002/10/24 13:04:18 ncq 352 # - just add two silly comments 353 # 354 # Revision 1.3 2002/10/23 22:41:54 hinnef 355 # more cleanup, fixed some bugs regarding variable mapping 356 # 357 # Revision 1.2 2002/10/22 21:18:11 ncq 358 # - fixed massive whitespace lossage 359 # - sprinkled some comments throughout 360 # - killed a few levels of indentation 361 # - tried to rename a few variable to be more self-documenting 362 # 363