1
2
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
33
35 transformerHash = {}
36
37 - def __init__(self, session, node, parent):
46
48
49 if node.localName in ['databaseInfo', 'metaInfo']:
50
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
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
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
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
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
114 for c3 in c2.childNodes:
115 if c3.nodeType == elementType and c3.localName == 'map':
116
117 data = self._walkZeeRex(session, c3)
118 supports.append(data)
119
120
121
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
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
192
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
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
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
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
255 raise ValueError("No matching index")
256 else:
257
258 indexInfo = possibleIndexes[0]
259 index = indexInfo[0]
260
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
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
323
324 if node.localName in ['databaseInfo', 'metaInfo', 'indexInfo']:
325
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
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):
417
418
420 if (self.prefixes.has_key(name)):
421 return self.prefixes[name]
422 elif not name:
423
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
433 raise(ConfigFileException("Unknown prefix: %s" % (name)))
434
436
437 if query.index.prefix == "c3":
438
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
457
458
459
460 relv = stem = 0
461 rms = []
462 for r in relMods:
463
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
489
490 if node.localName in ['databaseInfo', 'metaInfo']:
491
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
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
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
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
623
624
626
627 - def __init__(self, session, node, parent):
630
632
633 if node.localName in ['databaseInfo', 'metaInfo']:
634
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