Changeset 1347 for trunk/gsdl/src/recpt/z3950proto.cpp
- Timestamp:
- 2000-08-03T17:21:26+12:00 (24 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/gsdl/src/recpt/z3950proto.cpp
r1285 r1347 26 26 #include "z3950proto.h" 27 27 #include "comtypes.h" 28 #include <stdio.h> 29 30 /*** 31 We will use the "collection" argument as the name of the database 32 to query on the z3950 server. 33 ***/ 34 35 36 z3950_server::z3950_server() { 37 count=0; 38 info=NULL; 39 meta["iconcollection"]="/~johnmcp/gsdl/images/zserver.png"; 40 } 41 42 43 44 45 // z3950 Protocol functions 28 #include "browsefilter.h" 29 #include "queryfilter.h" 30 #include "filter.h" 31 // z39.50 yaz stuff 32 #include <stdio.h> // for (FILE *) type for yyin and fopen. 33 // config file parsing stuff 34 #include "z3950cfg.h" // for reading in config files - 35 // defines "struct z3950cfg *zserver_list" as the head of the list. 36 extern FILE *yyin; 37 extern "C" { 38 extern int zconfigparse(); 39 } 40 41 42 43 46 44 z3950proto::z3950proto() { 47 45 zserver_count=0; 48 46 } 49 47 50 void z3950proto::add_server (const z3950_server& zserver) { 48 z3950proto::~z3950proto() { 49 } 50 51 void z3950proto::add_server (z3950_server& zserver) { 51 52 52 53 // append the new server 53 54 zserver_count++; 54 zservers.push_back(zserver); 55 } 56 57 void z3950proto::configure (const text_t &/*key*/, 58 const text_tarray &/*cfgline*/) { 55 zservers.push_back(&zserver); 56 } 57 58 void z3950proto::read_config_file(const text_t &filename) { 59 struct z3950cfg *here; 60 struct z3950cfg *oldhere; 61 z3950_server *zserver; 62 ShortColInfo_t *tempinfo; 63 64 // zconfigparse() is defined in zparse.tab.c, 65 // which is the bison output of zparse.y 66 67 yyin=fopen(filename.getcstr(),"r"); 68 if (yyin==NULL) { 69 cerr << "Could not open "<<filename.getcstr()<<" for reading.\n"; 70 } 71 zconfigparse(); 72 // we now have the config files in the ptr zserver_list 73 if (zserver_list==NULL) 74 return; // no valid servers found in the config file - note that 75 // the parser will have already spat out any errors. 76 77 // now create z3950servers for each structure in server_list 78 here=zserver_list; 79 while (here!=NULL) { 80 zserver=new z3950_server; 81 tempinfo=new ShortColInfo_t; 82 83 tempinfo->host.setcstr(here->hostname); 84 tempinfo->port=here->port; 85 tempinfo->name.setcstr(here->dbname); 86 zserver->setInfo(tempinfo); 87 zserver->setName(here->shortname); 88 // now collection metadata. 89 zserver->setMeta("collectionname",here->longname); 90 if (here->icon!=NULL) 91 zserver->setMeta("iconcollection",here->icon); 92 if (here->smallicon!=NULL) 93 zserver->setMeta("iconcollectionsmall",here->smallicon); 94 95 /* filterclass *filter = new filterclass (); 96 zserver->add_filter (filter); 97 browsefilterclass *browsefilter = new browsefilterclass(); 98 zserver->add_filter (browsefilter); 99 queryfilterclass *queryfilter = new queryfilterclass(); 100 zserver->add_filter (queryfilter); 101 */ 102 103 // About list 104 if (here->about!=NULL) { 105 struct z3950aboutlist *about_here=here->about; 106 struct z3950aboutlist *oldabout; 107 108 while (about_here!=NULL) { 109 // problem with default lang (null): can't add ("",..) 110 if (about_here->lang==NULL) 111 zserver->addcfgAbout("en",about_here->text); 112 else 113 zserver->addcfgAbout(about_here->lang, about_here->text); 114 oldabout=about_here; 115 about_here=about_here->next; 116 free(oldabout->lang); 117 free(oldabout->text); 118 free(oldabout); 119 } 120 } 121 122 oldhere=here; 123 here=here->next; 124 free(oldhere->shortname); 125 free(oldhere->hostname); 126 free(oldhere->dbname); 127 free(oldhere->longname); 128 free(oldhere->icon); 129 free(oldhere->smallicon); 130 free(oldhere); 131 132 add_server(*zserver); 133 } // end of while loop. 134 135 } 136 137 void z3950proto::configure (const text_t &key, 138 const text_tarray &cfgline) { 59 139 60 140 // this is called for each line in the gsdlsite.cfg file 61 /* cerr << "z3950proto::configure called:" 62 << "key is " << key.getcstr() 63 << "\n1st line is " << cfgline[0].getcstr() << endl; 64 */ 141 142 if (0) 143 cerr << "z3950proto::configure called:" 144 << "key is " << key.getcstr() 145 << "\n1st line is " << cfgline[0].getcstr() << endl; 146 65 147 } 66 148 … … 96 178 z3950_server_array::iterator end = zservers.end(); 97 179 while (here != end) { 98 collist.push_back( here->getName());180 collist.push_back((*here)->getName()); 99 181 //const ShortColInfo_t *info=here->getInfo(); 100 182 //collist.push_back(info->name); … … 108 190 z3950_server_array::iterator end = zservers.end(); 109 191 while (here != end) { 110 if( here->getName()==collection) {192 if((*here)->getName()==collection) { 111 193 hascollection=true; 112 194 return; … … 133 215 z3950_server_array::iterator end = zservers.end(); 134 216 while (here != end) { 135 if( here->getName()==collection) {217 if((*here)->getName()==collection) { 136 218 break; 137 219 } … … 139 221 } 140 222 141 // is this right? ie does end refer to the last element, or AFTER the142 // last element?143 223 if (here==end) { 144 224 err=protocolError; … … 149 229 } 150 230 151 /* collectinfo.shortInfo.name="sdfg"; 152 collectinfo.shortInfo.host="localhost"; 153 collectinfo.shortInfo.port=0; */ 154 const ShortColInfo_t *colinfo=here->getInfo(); 231 const ShortColInfo_t *colinfo=(*here)->getInfo(); 155 232 collectinfo.shortInfo.name=colinfo->name; 156 233 collectinfo.shortInfo.host=colinfo->host; … … 163 240 // leave ccsCols empty (no cross-coll. searching - for now) 164 241 /*collectinfo.ccsCols=(text_tarray);*/ //not like this!!! 165 collectinfo.languages.push_back("en"); 166 collectinfo.languages.push_back("fr"); 242 // This info is available from the config file -- johnmcp 243 /*******collectinfo.languages.push_back("en"); 244 collectinfo.languages.push_back("fr");********/ 167 245 collectinfo.numDocs=0; 168 246 collectinfo.numWords=0; … … 170 248 // copy the text maps over. 171 249 // collectinfo.collectionmeta; // text_tmap 172 // delete collectinfo.collectionmeta; 173 collectinfo.collectionmeta=*(here->getMeta()); 174 /* collectinfo.format; //text_tmap 175 collectinfo.building; //text_tmap 250 collectinfo.collectionmeta=*((*here)->getMeta()); 251 collectinfo.format=*((*here)->getFormat()); //text_tmap 252 /* collectinfo.building; //text_tmap */ 253 254 ////collectinfo.receptionist="z3950"; 255 /* for now... this is a url, relative to .../cgi-bin. 256 NOTE: if this is empty, it defaults to _gwcgi_?a=p&p=about&c=<colname> 176 257 */ 177 178 collectinfo.receptionist="z3950"; /* for now... this is a url,179 relative to .../cgi-bin */180 258 } 181 259 182 260 void z3950proto::get_filterinfo (const text_t &/*collection*/, 183 InfoFiltersResponse_t & /*response*/,261 InfoFiltersResponse_t &response, 184 262 comerror_t &/*err*/, ostream &/*logout*/) { 185 263 // we'll fake it here, and say we have set up some filters 264 response.filterNames.insert("BrowseFilter"); 265 response.filterNames.insert("QueryFilter"); 266 response.filterNames.insert("NullFilter"); 267 268 } 269 270 void z3950proto::get_filteroptions (const text_t &/*collection*/, 271 const InfoFilterOptionsRequest_t &/*req*/, 272 InfoFilterOptionsResponse_t &response, 273 comerror_t &err, ostream &/*logout*/) { 274 // for now, assume all servers have the same characteristics 275 /* if (request.filterName=="QueryFilter") { } 276 else if (request.filterName=="BrowseFilter") { } 277 else if (request.filterName=="NullFilter") { } */ 278 response.filterOptions["Index"].type=FilterOption_t::stringt; 279 response.filterOptions["Index"].repeatable=FilterOption_t::onePerQuery; 280 response.filterOptions["Index"].defaultValue="any"; 281 response.filterOptions["Index"].validValues.push_back(".any"); 282 response.filterOptions["Index"].validValues.push_back(".title"); 283 response.filterOptions["Index"].validValues.push_back(".author"); 284 // and maybe ["Language"] option as well? 285 err=noError; 186 286 } 187 287 … … 190 290 FilterResponse_t &response, 191 291 comerror_t &err, ostream &logout) { 192 // assume this function is only called when creating the title page, 193 // and looking for the metadata regarding icons. 194 response.numDocs=0; 195 response.isApprox=Approximate; // Exact | Approximate | MoreThan 292 // this function is called when: 293 // * creating the title page,(looking for iconcoll* & collectname metadata) 294 // * creating the about page (looking for "Title" metadata) 295 // * doing the query - (note that a request for metadata comes first, then 296 // filterOptions = FRmetadata | FROID | FRtermFreq (64+4+1) 297 298 // metadata-only requests have filterName="NullFilter", else "QueryFilter". 299 // For the title page, we should not create a connection to the target 300 // (target means the actual z39.50 server, origin means us), but 301 // for the about page and query pages, we need to get information from the 302 // origin. (eg for the about page, we will print out some info such as ID, 303 // name and version. 304 305 // cerr now goes to errout.txt in etc directory 306 err=noError; 307 308 // get relevant "collection" 309 z3950_server_array::iterator zserver = zservers.begin(); 310 z3950_server_array::iterator zend = zservers.end(); 311 while (zserver != zend) { 312 if((*zserver)->getName()==collection) { 313 break; 314 } 315 zserver++; 316 } 317 // now have collection in zserver. 318 319 ColInfoResponse_t info; 320 ResultDocInfo_t *docInfo; 321 196 322 // leave response.termInfo empty 197 // leave response.docInfo empty 198 /* got the following for first query: 199 request.filterResultOptions=FRmetadata; 200 request.getParents=getParents 201 request.fields=metadata 202 request.docSet (includes OID); 323 // response.termInfo.push_back(""); ??????? (should be empty if not req.) 324 325 // See if this is for a query action 326 if (request.filterName=="QueryFilter") { 327 /* Sample OptionValue pairs 328 `StartResults'=`1' 329 `EndResults'=`20' 330 `Term'=`firstword secondword' (term is just whatever the user typed in) 331 `QueryType'=`ranked' => 'OR' (cgiarg t=1) 332 `QueryType' = `boolean' => 'AND' (cgiarg t=0) 333 `Casefold'=`true' 334 `Stem'=`false' 335 `Maxdocs'=`50' 336 */ 337 // go through options 338 text_t opt_term; // the term(s) that the user entered 339 text_t opt_fields; // which fields to search on 340 int opt_start=1, opt_end=20; // default values 341 int nummatches=0, maxdocs=50; // default values 342 OptionValue_tarray::iterator ov_here=request.filterOptions.begin(); 343 OptionValue_tarray::iterator ov_end=request.filterOptions.end(); 344 while (ov_here != ov_end) { 345 // cout << "OV pair: `" << ov_here->name.getcstr() << "'=`" 346 // << ov_here->value.getcstr() << "'\n"; 347 if (ov_here->name=="Term") 348 { 349 opt_term=ov_here->value; 350 } else if (ov_here->name=="Index") 351 { 352 opt_fields=ov_here->value; 353 } else if (ov_here->name=="StartResults") 354 { 355 opt_start=ov_here->value.getint(); 356 } else if (ov_here->name=="EndResults") 357 { 358 opt_end=ov_here->value.getint(); 359 } else if (ov_here->name=="Maxdocs") 360 { 361 maxdocs=ov_here->value.getint(); 362 } 363 ov_here++; 364 } 365 err=noError; 366 text_tarray *titles=(*zserver)->getrecordTitles(opt_term, 367 opt_fields, 368 opt_start, // first to get 369 opt_end-opt_start, //count 370 &nummatches,err); 371 if (err!=noError) { 372 // can we return an err msg in a response, or just use 373 // the more drastic Greenstone error mechanism? 374 docInfo=new ResultDocInfo_t; 375 response.docInfo.push_back(*docInfo); 376 docInfo->metadata["Title"].values.push_back("Error - query err?"); 377 logout << "\nz3950 filter query: error connecting to server\n"; 378 // for now, DON'T use GSDL protocol err. 379 err=noError; 380 return; 381 } 382 // check if (titles==NULL) - only happens on error? 383 if (nummatches>0) { 384 text_tarray::iterator titles_here=titles->begin(); 385 text_tarray::iterator titles_end=titles->end(); 386 int counter=1; 387 while (titles_here!=titles_end) { 388 docInfo=new ResultDocInfo_t; 389 docInfo->metadata["Title"].values.push_back(*titles_here); 390 docInfo->result_num=counter; 391 // we need to give some OID, so we'll just use counter for now... 392 // make it the number into the whole possible retrieved set. 393 docInfo->OID=counter+opt_start-1; 394 response.docInfo.push_back(*docInfo); 395 counter++; 396 titles_here++; 397 } 398 } 399 400 if (request.filterResultOptions & FRtermFreq) { 401 if (nummatches>maxdocs) { 402 response.numDocs=maxdocs; // eg "more than 50" (if Maxdocs==50) 403 response.isApprox=MoreThan; 404 } else { 405 response.numDocs=nummatches; // eg "36 documents" 406 response.isApprox=Exact; // Exact | Approximate | MoreThan 407 } 408 } // end of if (... & FRtermFreq) 409 410 } // end of if (... & FROID) 411 else { 412 // this wasn't a query action 413 414 if (request.filterOptions.size()>0 && 415 request.filterOptions[0].name=="ParentNode") { 416 // don't want to return anything 417 return; 418 /* } else if (request.docSet.size() && 419 request.docSet[0]!="collection") { 420 // documentaction 421 // if docSet is not empty, it is either "collection", or an array 422 // of OIDs 423 docInfo=new ResultDocInfo_t; 424 response.docInfo.push_back(*docInfo); 425 */ 426 } else { 427 // in case we need to return only metadata 428 docInfo=new ResultDocInfo_t; 429 response.docInfo.push_back(*docInfo); 430 } 431 } 432 433 // Fill in metadata for each response.docInfo (if wanted) 434 if (request.filterResultOptions & FRmetadata) { 435 get_collectinfo (collection, info, err, logout); 436 // should check err returned here.... 437 438 // get the Query out of the filterOptions. 439 text_t query=""; 440 text_t field=""; 441 OptionValue_tarray::iterator opt_here=request.filterOptions.begin(); 442 OptionValue_tarray::iterator opt_end=request.filterOptions.end(); 443 while (opt_here!=opt_end) { 444 if (opt_here->name=="Query") { 445 query=opt_here->value; 446 if (field!="") break; // break from loop if we've got both 447 } else if (opt_here->name=="Index") { 448 field=opt_here->value; 449 if (query!="") break; // break from loop if we've got both 450 } 451 opt_here++; 452 } 453 454 if (!request.fields.empty()) { 455 // loop on each document being returned 456 ResultDocInfo_tarray::iterator docs_here=response.docInfo.begin(); 457 ResultDocInfo_tarray::iterator docs_end=response.docInfo.end(); 458 while (docs_here!=docs_end) { 459 460 // loop on all the metadata fields in request.fields (type text_tset) 461 text_tset::iterator fields_here=request.fields.begin(); 462 text_tset::iterator fields_end=request.fields.end(); 463 text_tmap::iterator it; 464 while (fields_here!=fields_end) { 465 it=info.collectionmeta.find(*fields_here); 466 ////////// cerr << "filter: getting " << (*fields_here).getcstr(); 467 if (it!=info.collectionmeta.end()) 468 docs_here->metadata[*fields_here].values.push_back((*it).second); 469 else if (*fields_here=="Title" && !request.docSet.empty()) { 470 // We only do this for a document action. 471 // (This comes through as a NullQuery). 472 // hopefully docSet is only not empty for documentaction... 473 text_t doctitle; 474 int i; 475 // check that docSet isn't empty first!!!!!! 476 i=request.docSet[0].getint(); 477 text_t doctext="unneeded"; 478 (*zserver)->getfullrecord(query, field, i, doctitle, doctext, err); 479 // check err value! 480 docs_here->metadata["Title"].values.push_back(doctitle); 481 } else { 482 docs_here->metadata[*fields_here].values.push_back(""); 483 /////// cerr << " (not found)"; 484 } 485 ////////cerr << "\n"; 486 fields_here++; 487 } // end of inner while loop 488 docs_here++; 489 } // end of outer while loop 490 } // end of if (!request.fields.empty()) 491 492 else { // request.fields empty: return all metadata for about page or query 493 // we'll only put it in the first docInfo. 494 text_tmap::iterator colmeta_here=info.collectionmeta.begin(); 495 text_tmap::iterator colmeta_end=info.collectionmeta.end(); 496 while (colmeta_here!=colmeta_end) { 497 response.docInfo[0].metadata[(*colmeta_here).first]. 498 values.push_back((*colmeta_here).second); 499 /////cerr << "\t" << (*colmeta_here).first.getcstr() << "\n"; 500 colmeta_here++; 501 } 502 503 // check if "collectionextra" metadata is set. If it isn't, we should 504 // create connection to target to get it. 505 if (info.collectionmeta.find("collectionextra")==colmeta_end) { 506 // it hasn't been set yet... 507 text_t abouttext="<B>Server Online</B><br>\n"; 508 abouttext+=(*zserver)->getzAbout(); 509 // add in the "About" text we read in from config file. 510 // how do we incorporate multi-lingual metadata? 511 abouttext+="<P>\n"; 512 text_t tmpabout; 513 514 if ((*zserver)->getcfgAbout("en", tmpabout)==true) 515 abouttext+=tmpabout; 516 517 (*zserver)->setMeta("collectionextra",abouttext); 518 response.docInfo[0].metadata["collectionextra"].values.push_back(abouttext); 519 } 520 } // end of else 521 522 // do indices' names, regardless of whether asked for or not... 523 if (!response.docInfo.empty()) { 524 response.docInfo[0].metadata[".author"].values.push_back("author fields"); 525 response.docInfo[0].metadata[".title"].values.push_back("title fields"); 526 response.docInfo[0].metadata[".any"].values.push_back("any fields"); 527 } 528 } //end of if (... & FRmetadata) ... 529 } 530 531 532 533 void z3950proto::get_document (const text_t &collection, 534 const DocumentRequest_t &request, 535 DocumentResponse_t &response, 536 comerror_t &err, ostream &logout) { 537 538 err=noError; 539 540 // get relevant "collection" 541 z3950_server_array::iterator zserver = zservers.begin(); 542 z3950_server_array::iterator zend = zservers.end(); 543 while (zserver != zend) { 544 if((*zserver)->getName()==collection) { 545 break; 546 } 547 zserver++; 548 } 549 // now have collection in zserver. 550 551 /* cout << "get document:\n\tOID: " << request.OID.getcstr() 552 << "\n\tdocType: " << request.docType.getcstr() 553 << "\n\tdocFormat: " << request.docFormat.getcstr() <<"\n"; 203 554 */ 204 // fill in the metadata for each of the OIDs (if it is requested) 205 if (request.filterResultOptions & FRmetadata) { 206 // request.fields // type text_tset 207 // docInfo is type ResultDocInfo_tarray 208 ColInfoResponse_t *info = new ColInfoResponse_t; 209 get_collectinfo (collection, *info, err, logout); 210 // should check err returned here.... 211 212 ResultDocInfo_t *docInfo=new ResultDocInfo_t; 213 214 text_tmap::iterator it=info->collectionmeta.find("collectionname"); 215 // cerr now goes to errout.txt in etc directory 216 // "(*it).first" is key, "(*it).second" is value(s). 217 if (it!=info->collectionmeta.end()) 218 docInfo->metadata["collectionname"].values.push_back((*it).second); 219 else // needs to exist, but be empty 220 docInfo->metadata["collectionname"].values.push_back(""); 221 222 it=info->collectionmeta.find("iconcollection"); 223 if (it!=info->collectionmeta.end()) 224 docInfo->metadata["iconcollection"].values.push_back((*it).second); 225 else // needs to exist, but be empty 226 docInfo->metadata["iconcollection"].values.push_back(""); 227 228 it=info->collectionmeta.find("iconcollectionsmall"); 229 if (it!=info->collectionmeta.end()) 230 docInfo->metadata["iconcollectionsmall"].values.push_back((*it).second); 231 else // needs to exist, but be empty 232 docInfo->metadata["iconcollectionsmall"].values.push_back(""); 233 234 235 response.docInfo.push_back(*docInfo); 236 } 237 238 err=noError; 239 } 240 241 void z3950proto::get_document (const text_t &/*collection*/, 242 const DocumentRequest_t &/*request*/, 243 DocumentResponse_t &/*response*/, 244 comerror_t &err, ostream &logout) { 245 555 556 /* docresponse consists of 557 text_t response.doc */ 558 text_t title="unneeded"; 559 text_t doctext; 560 text_t query; // this should not be needed, as we have already connected to 561 // get the title.... 562 text_t field; // ditto... 563 (*zserver)->getfullrecord(query,field,request.OID.getint(), 564 title,doctext,err); 565 // check return value of above? (false=>not connected) 566 if (err==noError) 567 response.doc=doctext; 568 else { 569 // could print out different messages based on error type.... 570 response.doc="<h2>Error</h2>There was an error while connecting to the "; 571 response.doc+="z39.50 server (ie target). Most likely this was a \n"; 572 response.doc+="\"Connection Refused\" error.\n"; 573 574 } 246 575 if (0) { 247 576 err=protocolError; … … 249 578 } 250 579 } 251 252 253 #endif
Note:
See TracChangeset
for help on using the changeset viewer.