protocolMap

Module protocolMap |
[hide private]
[frames] | no frames]

## Source Code for Module protocolMap

      1  # Map incoming request stuff into local objects
      2  # Eg dc.title -> l5r-idx-cardname object
      3
      4  from baseObjects import ProtocolMap, Extractor
      5  from configParser import C3Object
      6  from c3errors import ConfigFileException
      7  from utils import elementType, textType, flattenTexts
      8  import sys, os, SRW
      9
     10  import srwExtensions
     11
     12  from PyZ3950.CQLParser import modifierClauseType, indexType, relationType
     13  from PyZ3950 import z3950, asn1
     14
     15 -class ZeerexProtocolMap(ProtocolMap):
     16      protocol = ""
     17      version = ""
     18      c3Namespace = "http://www.cheshire3.org/schemas/explain/"
     19
     20 -    def __init__(self, session, node, parent):
     21          ProtocolMap.__init__(self, session, node, parent)
     22          p = self.get_path(session, 'zeerexPath')
     23          if (p == None):
     24              raise(ConfigFileException('ZeerexPath not specified for CQLConfig.'))
     25          else:
     26              if ( not os.path.isabs(p)):
     27                  dfp = self.get_path(session, 'defaultPath')
     28                  p = os.path.join(dfp, p)
     29              dom = self._getDomFromFile(session, p)
     30          for c in dom.childNodes:
     31              if c.nodeType == elementType:
     32                  self._walkZeeRex(session, c)
     33
     34 -class Z3950ProtocolMap(ZeerexProtocolMap):
     35      transformerHash = {}
     36
     37 -    def __init__(self, session, node, parent):
     38          self.protocol = "http://www.loc.gov/z3950/"
     39          self.transformerHash = {}
     40          self.indexHash = {}
     41          self.prefixes = {}
     42          ZeerexProtocolMap.__init__(self, session, node, parent)
     43          self.defaultAttributeHash = {}
     44          for x in self.defaultAttribute:
     45              self.defaultAttributeHash[(x[0], x[1])] = x[2]
     46
     47 -    def _walkZeeRex(self, session, node):
     48
     49          if node.localName in ['databaseInfo', 'metaInfo']:
     50              # Ignore
     51              return
     52          elif node.localName == 'serverInfo':
     53              self.version = node.getAttribute('version')
     54              for c in node.childNodes:
     55                  self._walkZeeRex(session, c)
     56          elif node.localName == 'database':
     57              self.databaseName = str(flattenTexts(node))
     58          elif node.localName == 'host':
     59              self.host = str(flattenTexts(node))
     60          elif node.localName == 'port':
     61              self.port = int(flattenTexts(node))
     62
     63          elif node.localName == 'recordSyntax':
     64              id = node.getAttribute('identifier')
     65              # id is string dotted OID
     66              thash = {}
     67              for c in node.childNodes:
     68                  if (c.nodeType == elementType and c.localName == 'elementSet'):
     69                      name = c.getAttribute('name')
     70                      xsl = c.getAttributeNS(self.c3Namespace, 'transformer')
     71                      if (xsl):
     72                          txr = self.get_object(session, xsl)
     73                          if (txr == None):
     74                              raise ConfigFileException("[%s] No transformer to map to for %s" % (self.id, xsl))
     75                      else:
     76                          txr = None
     77                      thash[name.lower()] = txr
     78              self.transformerHash[id] = thash
     79
     80          elif node.localName == 'set':
     81              name = node.getAttribute('name')
     82              name = name.lower()
     83              uri = node.getAttribute('identifier')
     84              if not name or not uri:
     85                  raise ConfigFileException('Missing name or identifier for attribute set mappting.')
     86              if (self.prefixes.has_key(name) and uri <> self.prefixes[name]):
     87                  raise(ConfigFileException('Multiple OIDs bound to same short name: %s -> %s' % (name, uri)))
     88              self.prefixes[str(name)] = str(uri)
     89
     90          elif node.localName == 'index':
     91              # Process indexes
     92              idxName = node.getAttributeNS(self.c3Namespace, 'index')
     93              indexObject = self.get_object(session, idxName)
     94              if indexObject == None:
     95                  raise(ConfigFileException("Could not find Index object %s" % (idxName)))
     96              maps = []
     97              defaults = []
     98              supports = []
     99              # XXX Blech. Not very recursive ;P
    100              for c in node.childNodes:
    101                  if c.nodeType == elementType:
    102                      if c.localName == 'map':
    103                          maps.append(self._walkZeeRex(session, c))
    104                      elif c.localName == 'configInfo':
    105                          for c2 in c.childNodes:
    106                              if c2.nodeType == elementType:
    107                                  if c2.localName == "default":
    108                                      # Get default attributes
    109                                      for c3 in c2.childNodes:
    110                                          if c3.nodeType == elementType and c3.localName == 'map':
    111                                              defaults = self._walkZeeRex(session, c3)
    112                                  elif c2.localName == "supports":
    113                                      # Get other supported attributes
    114                                      for c3 in c2.childNodes:
    115                                          if c3.nodeType == elementType and c3.localName == 'map':
    116                                              # Can't use c3:index to redirect here Too complicated
    117                                              data = self._walkZeeRex(session, c3)
    118                                              supports.append(data)
    119
    120              # XXX This is wrong.  It doesn't respect combinations.
    121              # XXX But for the moment I just don't care :P
    122              for s in supports:
    123                  defaults.extend(s)
    124
    125              for m in maps:
    126                  curr = self.indexHash.get(tuple(m), [])
    127                  curr.append((defaults, indexObject))
    128                  self.indexHash[tuple(m)] = curr
    129
    130          elif (node.localName == 'map'):
    131              attrs = []
    132              for c in node.childNodes:
    133                  if (c.nodeType == elementType and c.localName == 'attr'):
    134                      short = c.getAttribute('set')
    135                      short = short.lower()
    136                      if not short:
    137                          short = 'bib1'
    138                      oid = self.prefixes.get(short, None)
    139                      if not oid:
    140                          raise ConfigFileException('No mapping for attribute set %s in Zeerex file' % short)
    141
    142                      type = c.getAttribute('type')
    143                      if not type:
    144                          raise ConfigFileException('No type attribute for Z39.50 attr mapping in Zeerex')
    145                      type = int(type)
    146                      if type < 1:
    147                          raise ConfigFileException('Invalid type attribute for Z39.50 attr mapping in Zeerex: %s' % type)
    148                      attrVal = flattenTexts(c).strip()
    149                      if not attrVal:
    150                          raise ConfigFileException('No value given for attribute in Z39.50 mapping')
    151                      if attrVal.isdigit():
    152                          attrVal = int(attrVal)
    153                      else:
    154                          attrVal = attrVal.lower()
    155                      attrs.append((oid, type, attrVal))
    156              return attrs
    157          elif (node.localName == 'default'):
    158              dtype = node.getAttribute('type')
    159              pname = "default" + dtype[0].capitalize() + dtype[1:]
    160              if dtype == 'attribute':
    161                  # Get map instead of text
    162                  for c in node.childNodes:
    163                      if c.nodeType == elementType and c.localName == 'map':
    164                          data = self._walkZeeRex(session, c)
    165              else:
    166                  data = flattenTexts(node)
    167                  if (data.isdigit()):
    168                      data = int(data)
    169                  elif data == 'false':
    170                      data = 0
    171                  elif data == 'true':
    172                      data = 1
    173                  elif data.lower() in self.prefixes.keys():
    174                      data = self.prefixes[data.lower()]
    175              setattr(self, pname, data)
    176          elif (node.localName =='setting'):
    177              dtype = node.getAttribute('type')
    178              data = flattenTexts(node)
    179              if (data.isdigit()):
    180                  data = int(data)
    181              elif data == 'false':
    182                  data = 0
    183              elif data == 'true':
    184                  data = 1
    185              setattr(self, dtype, data)
    186          else:
    187              for c in node.childNodes:
    188                  if c.nodeType == elementType:
    189                      self._walkZeeRex(session, c)
    190
    191 -    def attrsToCql(self, attrs):
    192          # Pull defaults off of self
    193          bib1 = z3950.Z3950_ATTRS_BIB1_ov
    194          bib1str = '.'.join(map(str, bib1.lst))
    195          xd1 = z3950.Z3950_ATTRS_XD1_ov
    196          xd1str = '.'.join(map(str, xd1.lst))
    197          attrHash = {}
    198          for c in attrs:
    199              if (not c[0]):
    200                  c[0] = asn1.OidVal(map(int, self.defaultAttributeSet.split('.')))
    201              attrHash[(c[0], c[1])] = c[2]
    202          # First check bib1
    203
    204          defaultAttribs = self.defaultAttributeHash
    205
    206          use = attrHash.get((bib1, 1))
    207          rel = attrHash.get((bib1, 2), 3)
    208          posn = attrHash.get((bib1, 3), None)
    209          struct = attrHash.get((bib1, 4), None)
    210          trunc = attrHash.get((bib1, 5), None)
    211          comp = attrHash.get((bib1, 6), None)
    212
    213          defaultPosn = self.defaultAttributeHash.get((bib1str, 3), None)
    214          defaultStruct = self.defaultAttributeHash.get((bib1str, 4), None)
    215          defaultTrunc = self.defaultAttributeHash.get((bib1str, 5), None)
    216          defaultComp = self.defaultAttributeHash.get((bib1str, 6), None)
    217
    218          if use:
    219              if not isinstance(use, int) and use[:3] == "c3.":
    220                  # Override, just grab index, if exists
    221                  idx = self.parent.get_object(None, use[3:])
    222                  if not idx:
    223                      raise ValueError(use)
    224                  indexStr = use
    225              else:
    226                  try:
    227                      use = use.lower()
    228                  except:
    229                      pass
    230                  info  = self.indexHash.get(((bib1str, 1, use),), None)
    231                  if info:
    232                      # list of possible indexes.
    233                      possibleIndexes = []
    234                      for idx in info:
    235                          if posn and ( not (bib1str, 3, posn) in idx[0]):
    236                              continue
    237                          if not posn and defaultPosn and ( not (bib1str, 3, defaultPosn) in idx[0]):
    238                              continue
    239                          if struct and ( not (bib1str, 4, struct) in idx[0]):
    240                              continue
    241                          if not struct and defaultStruct and ( not (bib1str, 4, defaultStruct) in idx[0]):
    242                              continue
    243                          if trunc and ( not (bib1str, 5, trunc) in idx[0]):
    244                              continue
    245                          if not trunc and defaultTrunc and ( not (bib1str, 5, defaultTrunc) in idx[0]):
    246                              continue
    247                          if comp and ( not (bib1str, 6, comp) in idx[0]):
    248                              continue
    249                          if not comp and defaultComp and ( not (bib1str, 6, defaultComp) in idx[0]):
    250                              continue
    251                          possibleIndexes.append([idx[1], idx[0][:4]])
    252
    253                      if not possibleIndexes:
    254                          # No match
    255                          raise ValueError("No matching index")
    256                      else:
    257                          # If >1 take first
    258                          indexInfo = possibleIndexes[0]
    259                          index = indexInfo[0]
    260                          # Assgn to struct etc.
    261                          if not posn:
    262                              posn  = indexInfo[1][0][2]
    263                          if not struct:
    264                              struct  = indexInfo[1][1][2]
    265                          if not trunc:
    266                              trunc  = indexInfo[1][2][2]
    267                          if not comp:
    268                              comp  = indexInfo[1][3][2]
    269                      indexStr = "c3.%s" % index.id
    270                  else:
    271                      raise ValueError("No matching index??")
    272          index = indexType(indexStr)
    273
    274          relations = ['', '<', '<=', '=', '>=', '>', '<>']
    275          if (comp == 3):
    276              relation = relationType("exact")
    277          elif (rel > 6):
    278              if struct in [2, 6]:
    279                  relation = relationType('any')
    280              else:
    281                  relation = relationType('=')
    282          else:
    283              relation = relationType(relations[rel])
    284
    285          if (rel == 100):
    286              relation.modifiers.append(modifierClauseType('phonetic'))
    287          elif (rel == 101):
    288              relation.modifiers.append(modifierClauseType('stem'))
    289          elif (rel == 102):
    290              relation.modifiers.append(modifierClauseType('relevant'))
    291
    292          if (struct in [2, 6]):
    293              relation.modifiers.append(modifierClauseType('word'))
    294          elif (struct in [4, 5, 100]):
    295              relation.modifiers.append(modifierClauseType('date'))
    296          elif (struct == 109):
    297              relation.modifiers.append(modifierClauseType('number'))
    298          elif (struct in [1, 108]):
    299              relation.modifiers.append(modifierClauseType('string'))
    300          elif (struct == 104):
    301              relation.modifiers.append(modifierClauseType('uri'))
    302
    303          return (index, relation)
    304
    305
    306 -class UpdateProtocolMap(ZeerexProtocolMap):
    307      transformerHash = {}
    308      workflowHash = {}
    309
    310 -    def __init__(self, session, node, parent):
    311          self.protocol = "http://www.loc.gov/zing/srw/update/"
    312          self.protocolNamespaces = SRW.protocolNamespaces
    313          self.recordNamespaces = SRW.recordNamespaces
    314          self.profileNamespaces = SRW.update.profileNamespaces
    315          self.extensionNamespaces = SRW.update.extensionNamespaces
    316
    317          self.transformerHash = {}
    318          self.workflowHash = {}
    319
    320          ZeerexProtocolMap.__init__(self, session, node, parent)
    321
    322 -    def _walkZeeRex(self, session, node):
    323
    324          if node.localName in ['databaseInfo', 'metaInfo', 'indexInfo']:
    325              # Ignore
    326              return
    327          elif node.localName == 'serverInfo':
    328              self.version = node.getAttribute('version')
    329              for c in node.childNodes:
    330                  self._walkZeeRex(session, c)
    331          elif node.localName == 'database':
    332              self.databaseUrl = str(flattenTexts(node))
    333          elif node.localName == 'host':
    334              self.host = str(flattenTexts(node))
    335          elif node.localName == 'port':
    336              self.port = int(flattenTexts(node))
    337          elif node.localName == 'schema':
    338              id = node.getAttribute('identifier')
    339              name = node.getAttribute('name')
    340              xsl = node.getAttributeNS(self.c3Namespace, 'transformer')
    341              if (xsl):
    342                  txr = self.get_object(None, xsl)
    343                  if (txr == None):
    344                      raise ConfigFileException("No transformer to map to for %s" % (xsl))
    345                  self.transformerHash[id] = txr
    346              self.recordNamespaces[name] = id
    347          elif node.localName == "supports":
    348              stype = node.getAttribute('type')
    349              data = flattenTexts(node)
    350              if (stype == 'operation'):
    351                  wflw = node.getAttributeNS(self.c3Namespace, 'workflow')
    352                  if (wflw):
    353                      flow = self.get_object(None, wflw)
    354                      if (flow == None):
    355                          raise ConfigFileException("No workflow to map to for %s" % wflw)
    356                      self.workflowHash[data] = self.get_object(None, wflw)
    357          elif (node.localName == 'default'):
    358              dtype = node.getAttribute('type')
    359              pname = "default" + dtype[0].capitalize() + dtype[1:]
    360              data = flattenTexts(node)
    361              if (data.isdigit()):
    362                  data = int(data)
    363              elif data == 'false':
    364                  data = 0
    365              elif data == 'true':
    366                  data = 1
    367              setattr(self, pname, data)
    368          elif (node.localName =='setting'):
    369              dtype = node.getAttribute('type')
    370              data = flattenTexts(node)
    371              if (data.isdigit()):
    372                  data = int(data)
    373              elif data == 'false':
    374                  data = 0
    375              elif data == 'true':
    376                  data = 1
    377              setattr(self, dtype, data)
    378          else:
    379              for c in node.childNodes:
    380                  if c.nodeType == elementType:
    381                      self._walkZeeRex(session, c)
    382
    383
    384 -class CQLProtocolMap(ZeerexProtocolMap):
    385
    386      prefixes = {}
    387      indexHash = {}
    388      transformerHash = {}
    389      recordExtensionHash = {}
    390      termExtensionHash = {}
    391      searchExtensionHash = {}
    392      scanExtensionHash = {}
    393      explainExtensionHash = {}
    394      responseExtensionHash = {}
    395
    396
    397 -    def __init__(self, session, node, parent):
    398          self.protocol = "http://www.loc.gov/zing/srw/"
    399          self.indexHash = {}
    400          self.transformerHash = {}
    401          self.prefixes = {}
    402          self.protocolNamespaces = SRW.protocolNamespaces
    403          self.recordNamespaces = SRW.recordNamespaces
    404          self.contextSetNamespaces = SRW.contextSetNamespaces
    405          self.profileNamespaces = SRW.profileNamespaces
    406          self.extensionNamespaces = SRW.extensionNamespaces
    407
    408          self.recordExtensionHash = {}
    409          self.termExtensionHash = {}
    410          self.searchExtensionHash = {}
    411          self.scanExtensionHash = {}
    412          self.explainExtensionHash = {}
    413          self.responseExtensionHash = {}
    414          self.sruExtensionMap = {}
    415
    416          ZeerexProtocolMap.__init__(self, session, node, parent)
    417
    418
    419 -    def resolvePrefix(self, name):
    420          if (self.prefixes.has_key(name)):
    421              return self.prefixes[name]
    422          elif not name:
    423              # Look for default
    424              if not hasattr(self, 'defaultContextSet'):
    425                  raise ConfigFileException('Zeerex does not have default context set.')
    426              default = self.defaultContextSet
    427              if (self.prefixes.has_key(default)):
    428                  return self.prefixes[default]
    429              else:
    430                  return default
    431          else:
    432              # YYY: Should step up to other config objects?
    433              raise(ConfigFileException("Unknown prefix: %s" % (name)))
    434
    435 -    def resolveIndex(self, session, query):
    436
    437          if query.index.prefix == "c3":
    438              # Override
    439              idx = self.parent.get_object(session, query.index.value)
    440              if not idx:
    441                  raise ValueError(query.index.value)
    442              else:
    443                  return idx
    444
    445          target = query
    446          while (target.parent):
    447              target = target.parent
    448          target.config = self
    449
    450          query.index.resolvePrefix()
    451          uri = query.index.prefixURI
    452          name = query.index.value
    453          rel = query.relation.value
    454          relMods = query.relation.modifiers
    455
    456          # XXX:  Better CQL->Index resolution
    457          # Check relevance, check stem, check str/word, check relation,
    458          # Check index
    459
    460          relv = stem = 0
    461          rms = []
    462          for r in relMods:
    463              # XXX Check context set!
    464              if (r.type.value == 'relevant'):
    465                  relv = 1
    466              elif (r.type.value == 'stem'):
    467                  stem = 1
    468              else:
    469                  rms.append(r.type.value)
    470
    471          idx = None
    472          if (relv):
    473              idx = self.indexHash.get((uri, name, ('relationModifier', 'relevant')), None)
    474          if (not idx and stem):
    475              idx = self.indexHash.get((uri, name, ('relationModifier', 'stem')), None)
    476          if (not idx and rms):
    477              for rm in rms:
    478                  idx = self.indexHash.get((uri, name, ('relationModifier', rm)), None)
    479                  if (idx):
    480                      break
    481          if (not idx):
    482              idx = self.indexHash.get((uri, name, ('relation', rel)), None)
    483          if (not idx):
    484              idx = self.indexHash.get((uri,name), None)
    485          return idx
    486
    487
    488 -    def _walkZeeRex(self, session, node):
    489
    490          if node.localName in ['databaseInfo', 'metaInfo']:
    491              # Ignore
    492              return
    493          elif node.localName == 'serverInfo':
    494              self.version = node.getAttribute('version')
    495              for c in node.childNodes:
    496                  self._walkZeeRex(session, c)
    497          elif node.localName == 'database':
    498              self.databaseUrl = str(flattenTexts(node))
    499          elif node.localName == 'host':
    500              self.host = str(flattenTexts(node))
    501          elif node.localName == 'port':
    502              self.port = int(flattenTexts(node))
    503          elif node.localName == 'schema':
    504              id = node.getAttribute('identifier')
    505              name = node.getAttribute('name')
    506              xsl = node.getAttributeNS(self.c3Namespace, 'transformer')
    507              if (xsl):
    508                  txr = self.get_object(session, xsl)
    509                  if (txr == None):
    510                      raise ConfigFileException("No transformer to map to for %s" % (xsl))
    511                  self.transformerHash[id] = txr
    512              self.recordNamespaces[name] = id
    513          elif node.localName == 'set':
    514              name = node.getAttribute('name')
    515              uri = node.getAttribute('identifier')
    516              if (self.prefixes.has_key(name) and uri <> self.prefixes[name]):
    517                  raise(ConfigFileException('Multiple URIs bound to same short name: %s -> %s' % (name, uri)))
    518              self.prefixes[str(name)] = str(uri)
    519          elif node.localName == 'index':
    520              # Process indexes
    521              idxName = node.getAttributeNS(self.c3Namespace, 'index')
    522              indexObject = self.get_object(session, idxName)
    523              if indexObject == None:
    524                  raise(ConfigFileException("[%s] No Index to map to for %s" % (self.id, idxName)))
    525              maps = []
    526
    527              for c in node.childNodes:
    528                  if (c.nodeType == elementType and c.localName == 'map'):
    529                      maps.append(self._walkZeeRex(session, c))
    530              for m in maps:
    531                  self.indexHash[m] = indexObject
    532              # Need to generate all relations and modifiers
    533              for c in node.childNodes:
    534                  if (c.nodeType == elementType and c.localName == 'configInfo'):
    535                      for c2 in c.childNodes:
    536                          if (c2.nodeType == elementType and c2.localName == 'supports'):
    537                              idxName2 = c2.getAttributeNS(self.c3Namespace, 'index')
    538                              if (not idxName2):
    539                                  indexObject2 = indexObject
    540                              else:
    541                                  indexObject2 = self.get_object(session, idxName2)
    542                                  if indexObject2 == None:
    543                                      raise(ConfigFileException("[%s] No Index to map to for %s" % (self.id, idxName2)))
    544                              st = str(c2.getAttribute('type'))
    545                              val = str(flattenTexts(c2))
    546                              for m in maps:
    547                                  self.indexHash[(m[0], m[1], (st, val))] = indexObject2
    548
    549          elif (node.localName == 'map'):
    550              for c in node.childNodes:
    551                  if (c.nodeType == elementType and c.localName == 'name'):
    552                      short = c.getAttribute('set')
    553                      index = flattenTexts(c)
    554                      index = index.lower()
    555                      uri = self.resolvePrefix(short)
    556                      if (not uri):
    557                          raise(ConfigFileException("No mapping for %s in Zeerex" % (short)))
    558                      return (str(uri), str(index))
    559          elif (node.localName == 'default'):
    560              dtype = node.getAttribute('type')
    561              pname = "default" + dtype[0].capitalize() + dtype[1:]
    562              data = flattenTexts(node)
    563              if (data.isdigit()):
    564                  data = int(data)
    565              elif data == 'false':
    566                  data = 0
    567              elif data == 'true':
    568                  data = 1
    569              setattr(self, pname, data)
    570          elif (node.localName =='setting'):
    571              dtype = node.getAttribute('type')
    572              data = flattenTexts(node)
    573              if (data.isdigit()):
    574                  data = int(data)
    575              elif data == 'false':
    576                  data = 0
    577              elif data == 'true':
    578                  data = 1
    579              setattr(self, dtype, data)
    580          elif (node.localName == 'supports'):
    581              stype = node.getAttribute('type')
    582              if stype in ['extraData', 'extraSearchData', 'extraScanData', 'extraExplainData', 'extension']:
    583                  # function, xnType, sruName
    584                  fn = node.getAttributeNS(self.c3Namespace, 'function')
    585                  if (hasattr(srwExtensions, fn)):
    586                      fn = getattr(srwExtensions, fn)
    587                  else:
    588                      raise(ConfigFileException('Cannot find handler function %s in srwExtensions.' % fn))
    589                  xn = node.getAttributeNS(self.c3Namespace, 'type')
    590                  if (not xn in ['record', 'term', 'search', 'scan', 'explain', 'response']):
    591                      raise (ConfigFileException('Incorrect extension type %s' % xn))
    592                  xform = node.getAttributeNS(self.c3Namespace, 'sruFunction')
    593                  if not xform:
    594                      sruFunction = srwExtensions.simpleRequestXform
    595                  elif hasattr(srwExtensions, xform):
    596                      sruFunction = getattr(srwExtensions, xform)
    597                  else:
    598                      raise(ConfigFileException('Cannot find transformation function %s in srwExtensions.' % xform))
    599
    600                  sru = node.getAttributeNS(self.c3Namespace, 'sruName')
    601                  data = flattenTexts(node)
    602                  data = data.strip()
    603                  data = tuple(data.split(' '))
    604                  hashAttr = xn + "ExtensionHash"
    605                  curr = getattr(self, hashAttr)
    606                  curr[data] = fn
    607                  setattr(self, hashAttr, curr)
    608                  self.sruExtensionMap[sru] = (data[0], data[1], sruFunction)
    609          else:
    610              for c in node.childNodes:
    611                  if c.nodeType == elementType:
    612                      self._walkZeeRex(session, c)
    613
    614
    615 -    def parseExtraData(self, extra):
    616          nodes = []
    617          for item in extra.items():
    618              name = item[0]
    619              map = self.sruExtensionMap.get(name, None)
    620              if map:
    621                  nodes.append(map[2](item, self))
    622          return nodes
    623
    624
    625 -class C3WepProtocolMap(ZeerexProtocolMap):
    626
    627 -    def __init__(self, session, node, parent):
    628          self.protocol = "c3WorflowExecutionProtocol"
    629          ZeerexProtocolMap.__init__(self, session, node, parent)
    630
    631 -    def _walkZeeRex(self, session, node):
    632
    633          if node.localName in ['databaseInfo', 'metaInfo']:
    634              # Ignore
    635              return
    636          elif node.localName == 'serverInfo':
    637              self.version = node.getAttribute('version')
    638              for c in node.childNodes:
    639                  self._walkZeeRex(session, c)
    640          elif node.localName == 'database':
    641              self.databaseUrl = str(flattenTexts(node))
    642          elif node.localName == 'host':
    643              self.host = str(flattenTexts(node))
    644          elif node.localName == 'port':
    645              self.port = int(flattenTexts(node))
    646          else:
    647              for c in node.childNodes:
    648                  if c.nodeType == elementType:
    649                      self._walkZeeRex(session, c)
    650