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