Changeset 28966 for main/trunk/greenstone3/src/java/org/greenstone/gsdl3/service/FedoraServiceProxy.java
- Timestamp:
- 2014-04-10T14:39:33+12:00 (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
main/trunk/greenstone3/src/java/org/greenstone/gsdl3/service/FedoraServiceProxy.java
r26311 r28966 87 87 extends ServiceRack implements OID.OIDTranslatable 88 88 { 89 90 static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.FedoraServiceProxy.class.getName()); 91 protected MacroResolver macro_resolver = null; 92 93 94 /** The handle to the fedora connection */ 95 private DigitalLibraryServicesAPIA fedoraServicesAPIA; 96 97 private String prevLanguage = ""; 98 99 public void cleanUp() { 100 super.cleanUp(); 101 } 102 103 /** sets the message router */ 104 public void setMessageRouter(MessageRouter m) { 105 this.router = m; 106 setLibraryName(m.getLibraryName()); 107 } 108 109 /** the no-args constructor */ 110 public FedoraServiceProxy() { 111 super(); 112 113 this.macro_resolver = new BasicTextMacroResolver(); 114 } 115 116 117 /* configure the service module 118 * 119 * @param info the XML node <serviceRack name="XXX"/> with name equal 120 * to the class name (of the subclass) 121 * 122 * must configure short_service_info_ and service_info_map_ 123 * @return true if configured ok 124 * must be implemented in subclasses 125 */ 126 /*public boolean configure(Element info) { 127 return configure(info, null); 128 }*/ 129 130 public boolean configure(Element info, Element extra_info) { 131 // set up the class loader 132 133 if (!super.configure(info, extra_info)){ 134 return false; 135 } 136 137 // Try to instantiate a Fedora dl handle 138 try { 139 // Fedora connection settings defaults. 140 // Read host and port from global.properties, since by default, we expect the Greenstone server to be used 141 Properties globalProperties = new Properties(); 142 globalProperties.load(Class.forName("org.greenstone.util.GlobalProperties").getClassLoader().getResourceAsStream("global.properties")); 143 String host = globalProperties.getProperty("tomcat.server", "localhost"); 144 String port = globalProperties.getProperty("tomcat.port", "8383"); 145 String protocol = "http"; 146 String username = "fedoraIntCallUser"; //"fedoraAdmin" 147 String password = "changeme"; //"<user password>" 148 149 // See if buildConfig.xml overrides any of the defaults 150 // info is the <serviceRack> Element from buildConfig.xml (extra_info are the Elements of collectionConfig.xml) 151 152 NodeList nodes = info.getElementsByTagName("fedoraConnection"); 153 if(nodes != null && nodes.getLength() > 0) { 154 155 Element fedoraElement = (Element)nodes.item(0); 156 if(fedoraElement.hasAttribute("protocol")) { 157 protocol = fedoraElement.getAttribute("protocol"); 158 } 159 if(fedoraElement.hasAttribute("host")) { 160 host = fedoraElement.getAttribute("host"); 161 } 162 if(fedoraElement.hasAttribute("port")) { 163 port = fedoraElement.getAttribute("port"); 164 } 165 if(fedoraElement.hasAttribute("username")) { 166 username = fedoraElement.getAttribute("username"); 167 } 168 if(fedoraElement.hasAttribute("password")) { 169 password = fedoraElement.getAttribute("password"); 170 } 171 } 172 173 fedoraServicesAPIA = new FedoraServicesAPIA(protocol, host, Integer.parseInt(port), username, password); 174 175 } catch(org.greenstone.fedora.services.FedoraGS3Exception.CancelledException e) { 176 // The user pressed cancel in the fedora services instantiation dialog 177 return false; 178 } catch(Exception e) { 179 logger.error("Error instantiating the interface to the Fedora Repository:\n", e); // second parameter prints e's stacktrace 180 return false; 181 } 182 183 184 // Need to put the available services into short_service_info 185 // This is used by DefaultReceptionist.process() has an exception. But DefaultReceptionist.addExtraInfo() 186 // isn't helpful, and the problem actually already occurs in 187 // Receptionist.process() -> PageAction.process() -> MessageRouter.process() 188 // -> Collection/ServiceCluster.process() -> ServiceCluster.configureServiceRackList() 189 // -> ServiceRack.process() -> ServiceRack.processDescribe() -> ServiceRack.getServiceList(). 190 // ServiceRack.getServiceList() requires this ServiceRack's services to be filled into the 191 // short_service_info Element which needs to be done in this FedoraServiceProxy.configure(). 192 193 // get the display and format elements from the coll config file for 194 // the classifiers 195 AbstractBrowse.extractExtraClassifierInfo(info, extra_info); 196 197 // Copied from IViaProxy.java: 198 String collection = fedoraServicesAPIA.describeCollection(this.cluster_name); 199 200 Element collNode = getResponseAsDOM(collection); 201 Element serviceList = (Element)collNode.getElementsByTagName(GSXML.SERVICE_ELEM+GSXML.LIST_MODIFIER).item(0); 202 203 //this.short_service_info.appendChild(short_service_info.getOwnerDocument().importNode(serviceList, true)); 204 // we want the individual service Elements, not the serviceList Element which will wrap it later 205 NodeList services = collNode.getElementsByTagName(GSXML.SERVICE_ELEM); 206 for(int i = 0; i < services.getLength(); i++) { 207 Node service = services.item(i); 208 this.short_service_info.appendChild(short_service_info.getOwnerDocument().importNode(service, true)); 209 } 210 211 // add some format info to service map if there is any 212 String path = GSPath.appendLink(GSXML.SEARCH_ELEM, GSXML.FORMAT_ELEM); 213 Element search_format = (Element) GSXML.getNodeByPath(extra_info, path); 214 if (search_format != null) { 215 this.format_info_map.put("TextQuery", this.desc_doc.importNode(search_format, true)); 216 this.format_info_map.put("FieldQuery", this.desc_doc.importNode(search_format, true)); 217 } 218 219 // look for document display format 220 path = GSPath.appendLink(GSXML.DISPLAY_ELEM, GSXML.FORMAT_ELEM); 221 Element display_format = (Element)GSXML.getNodeByPath(extra_info, path); 222 if (display_format != null) { 223 this.format_info_map.put("DocumentContentRetrieve", this.desc_doc.importNode(display_format, true)); 224 // should we make a copy? 225 } 226 227 // the format info 228 Element cb_format_info = this.desc_doc.createElement(GSXML.FORMAT_ELEM); 229 boolean format_found = false; 230 231 // look for classifier <browse><format> 232 path = GSPath.appendLink(GSXML.BROWSE_ELEM, GSXML.FORMAT_ELEM); 233 Element browse_format = (Element)GSXML.getNodeByPath(extra_info, path); 234 if (browse_format != null) { 235 cb_format_info.appendChild(GSXML.duplicateWithNewName(this.desc_doc, browse_format, GSXML.DEFAULT_ELEM, true)); 236 format_found = true; 237 } 238 239 // add in to the description a simplified list of classifiers 240 Element browse = (Element)GSXML.getChildByTagName(extra_info, "browse"); // the <browse> 241 NodeList classifiers = browse.getElementsByTagName(GSXML.CLASSIFIER_ELEM); 242 for(int i=0; i<classifiers.getLength(); i++) { 243 Element cl = (Element)classifiers.item(i); 244 Element new_cl = (Element)this.desc_doc.importNode(cl, false); // just import this node, not the children 245 246 // get the format info out, and put inside a classifier element 247 Element format_cl = (Element)new_cl.cloneNode(false); 248 Element format = (Element)GSXML.getChildByTagName(cl, GSXML.FORMAT_ELEM); 249 if (format != null) { 250 251 //copy all the children 252 NodeList elems = format.getChildNodes(); 253 for (int j=0; j<elems.getLength();j++) { 254 format_cl.appendChild(this.desc_doc.importNode(elems.item(j), true)); 255 } 256 cb_format_info.appendChild(format_cl); 257 format_found = true; 258 } 259 260 } 261 262 if (format_found) { 263 this.format_info_map.put("ClassifierBrowse", cb_format_info); 264 } 265 266 267 // set up the macro resolver 268 macro_resolver.setSiteDetails(this.site_http_address, this.cluster_name, this.getLibraryName()); 269 Element replacement_elem = (Element)GSXML.getChildByTagName(extra_info, "replaceList"); 270 if (replacement_elem != null) { 271 macro_resolver.addMacros(replacement_elem); 272 } 273 // look for any refs to global replace lists 274 NodeList replace_refs_elems = extra_info.getElementsByTagName("replaceListRef"); 275 for (int i=0; i<replace_refs_elems.getLength(); i++) { 276 String id = ((Element)replace_refs_elems.item(i)).getAttribute("id"); 277 if (!id.equals("")) { 278 Element replace_list = GSXML.getNamedElement(this.router.config_info, "replaceList", "id", id); 279 if (replace_list != null) { 280 macro_resolver.addMacros(replace_list); 281 } 282 } 283 } 284 285 // configured ok 286 return true; 287 } 288 289 290 /* "DocumentContentRetrieve", "DocumentMetadataRetrieve", "DocumentStructureRetrieve", 291 "TextQuery", "FieldQuery", "ClassifierBrowse", "ClassifierBrowseMetadataRetrieve" */ 292 293 protected Element processDocumentContentRetrieve(Element request) { 294 String[] docIDs = parse(request, GSXML.DOC_NODE_ELEM, GSXML.NODE_ID_ATT); 295 String[] relLinks = parse(request, GSXML.DOC_NODE_ELEM, "externalURL"); 296 297 //logger.error("### request:"); 298 //logger.error(GSXML.elementToString(request, true)); 299 300 if(docIDs == null) { 301 logger.error("DocumentContentRetrieve request specified no doc nodes.\n"); 302 return XMLConverter.newDOM().createElement(GSXML.RESPONSE_ELEM); // empty response 303 } else { 304 for(int i = 0; i < docIDs.length; i++) { 305 //logger.error("BEFORE: docIDs[" + i + "]: " + docIDs[i]); 306 if(relLinks[i] != null && docIDs[i].startsWith("http://")) { // need to do a look up 307 docIDs[i] = translateExternalId(docIDs[i]); 308 } else { 309 docIDs[i] = translateId(docIDs[i]); 310 } 311 //logger.error("AFTER: docIDs[" + i + "]: " + docIDs[i]); 312 } 313 } 314 315 String lang = request.getAttribute(GSXML.LANG_ATT); 316 if(!lang.equals(prevLanguage)) { 317 prevLanguage = lang; 318 fedoraServicesAPIA.setLanguage(lang); 319 } 320 321 // first param (the collection) is not used by Fedora 322 Element response = getResponseAsDOM(fedoraServicesAPIA.retrieveDocumentContent(this.cluster_name, docIDs)); 323 324 325 // resolve any collection specific macros 326 NodeList nodeContents = response.getElementsByTagName(GSXML.NODE_CONTENT_ELEM); 327 for(int i = 0; i < nodeContents.getLength(); i++) { 328 Element nodeContent = (Element)nodeContents.item(i); 329 /*if(nodeContent != null) { 330 nodeContent = (Element)nodeContent.getFirstChild(); // textNode 331 }*/ 332 //logger.error("GIRAFFE 1. content retrieve response - nodeContent: " + GSXML.nodeToFormattedString(nodeContent)); 333 String docContent = nodeContent.getFirstChild().getNodeValue(); // getTextNode and get its contents. 334 //logger.error("GIRAFFE 2. content retrieve response - docContent: " + docContent); 335 336 if(docContent != null) { 337 // get document text and resolve and macros. Rel and external links have _httpextlink_ set by HTMLPlugin 338 docContent = macro_resolver.resolve(docContent, lang, MacroResolver.SCOPE_TEXT, ""); // doc_id 339 nodeContent.getFirstChild().setNodeValue(docContent); 340 //logger.error("GIRAFFE 3. content retrieve response. Updated docContent: " + docContent); 341 } 342 } 343 344 return (Element)response.getElementsByTagName(GSXML.RESPONSE_ELEM).item(0); 345 } 346 347 protected Element processDocumentStructureRetrieve(Element request) { 348 String[] docIDs = parse(request, GSXML.DOC_NODE_ELEM, GSXML.NODE_ID_ATT); 349 String[] relLinks = parse(request, GSXML.DOC_NODE_ELEM, "externalURL"); 350 351 if(docIDs == null) { 352 logger.error("DocumentStructureRetrieve request specified no doc nodes.\n"); 353 return XMLConverter.newDOM().createElement(GSXML.RESPONSE_ELEM); // empty response 354 } else { 355 for(int i = 0; i < docIDs.length; i++) { 356 //logger.error("BEFORE: docIDs[" + i + "]: " + docIDs[i]); 357 if(relLinks[i] != null && docIDs[i].startsWith("http://")) { // need to do a look up 358 docIDs[i] = translateExternalId(docIDs[i]); 359 } else { 360 docIDs[i] = translateId(docIDs[i]); 361 } 362 } 363 } 364 365 NodeList params = request.getElementsByTagName(GSXML.PARAM_ELEM); 366 String structure=""; 367 String info=""; 368 for(int i = 0; i < params.getLength(); i++) { 369 Element param = (Element)params.item(i); 370 if(param.getAttribute("name").equals("structure")) { 371 structure = structure + param.getAttribute("value") + "|"; 372 } else if(param.getAttribute("name").equals("info")) { 373 info = info + param.getAttribute("value") + "|"; 374 } 375 } 376 377 String lang = request.getAttribute(GSXML.LANG_ATT); 378 if(!lang.equals(prevLanguage)) { 379 prevLanguage = lang; 380 fedoraServicesAPIA.setLanguage(lang); 381 } 382 Element response = getResponseAsDOM(fedoraServicesAPIA.retrieveDocumentStructure( 383 this.cluster_name, docIDs, new String[]{structure}, new String[]{info})); 384 return (Element)response.getElementsByTagName(GSXML.RESPONSE_ELEM).item(0); 385 } 386 387 protected Element processDocumentMetadataRetrieve(Element request) { 388 String[] docIDs = parse(request, GSXML.DOC_NODE_ELEM, GSXML.NODE_ID_ATT); 389 String[] relLinks = parse(request, GSXML.DOC_NODE_ELEM, "externalURL"); 390 391 if(docIDs == null) { 392 logger.error("DocumentMetadataRetrieve request specified no doc nodes.\n"); 393 return XMLConverter.newDOM().createElement(GSXML.RESPONSE_ELEM); // empty response 394 } else { 395 for(int i = 0; i < docIDs.length; i++) { 396 //logger.error("**** relLinks[i]: " + relLinks[i]); 397 //logger.error("**** docIDs[i]: " + docIDs[i]); 398 if(relLinks[i] != null && docIDs[i].startsWith("http://")) { // need to do a look up 399 docIDs[i] = translateExternalId(docIDs[i]); 400 } else { 401 docIDs[i] = translateId(docIDs[i]); 402 } 403 //logger.error("AFTER: docIDs[" + i + "]: " + docIDs[i]); 404 } 405 } 406 407 NodeList params = request.getElementsByTagName(GSXML.PARAM_ELEM); 408 String[] metafields = {}; 409 if(params.getLength() > 0) { 410 metafields = new String[params.getLength()]; 411 for(int i = 0; i < metafields.length; i++) { 412 Element param = (Element)params.item(i); 413 //if(param.hasAttribute(GSXML.NAME_ATT) && param.getAttribute(GSXML.NAME_ATT).equals("metadata") && param.hasAttribute(GSXML.VALUE_ATT)) { 414 if(param.hasAttribute(GSXML.VALUE_ATT)){ 415 metafields[i] = param.getAttribute(GSXML.VALUE_ATT); 416 } else { 417 metafields[i] = ""; 418 } 419 } 420 } 421 422 String lang = request.getAttribute(GSXML.LANG_ATT); 423 if(!lang.equals(prevLanguage)) { 424 prevLanguage = lang; 425 fedoraServicesAPIA.setLanguage(lang); 426 } 427 Element response = getResponseAsDOM(fedoraServicesAPIA.retrieveDocumentMetadata( 428 this.cluster_name, docIDs, metafields)); 429 return (Element)response.getElementsByTagName(GSXML.RESPONSE_ELEM).item(0); 430 } 431 432 protected Element processClassifierBrowseMetadataRetrieve(Element request) { 433 String[] classIDs = parse(request, GSXML.CLASS_NODE_ELEM, GSXML.NODE_ID_ATT); 434 //String[] relLinks = parse(request, GSXML.CLASS_NODE_ELEM, "externalURL"); 435 436 if(classIDs == null) { 437 logger.error("ClassifierBrowseMetadataRetrieve request specified no classifier nodes.\n"); 438 return XMLConverter.newDOM().createElement(GSXML.RESPONSE_ELEM); // empty response 439 } else { 440 for(int i = 0; i < classIDs.length; i++) { 441 classIDs[i] = translateId(classIDs[i]); 442 } 443 } 444 445 NodeList params = request.getElementsByTagName(GSXML.PARAM_ELEM); 446 String[] metafields = {}; 447 if(params.getLength() > 0) { 448 metafields = new String[params.getLength()]; 449 for(int i = 0; i < metafields.length; i++) { 450 Element param = (Element)params.item(i); 451 if(param.hasAttribute(GSXML.VALUE_ATT)){ 452 metafields[i] = param.getAttribute(GSXML.VALUE_ATT); 453 } else { 454 metafields[i] = ""; 455 } 456 } 457 } 458 459 String lang = request.getAttribute(GSXML.LANG_ATT); 460 if(!lang.equals(prevLanguage)) { 461 prevLanguage = lang; 462 fedoraServicesAPIA.setLanguage(lang); 463 } 464 Element response = getResponseAsDOM(fedoraServicesAPIA.retrieveBrowseMetadata( 465 this.cluster_name, "ClassifierBrowseMetadataRetrieve", classIDs, metafields)); 466 //logger.error("**** Response from retrieveBrowseMeta: " + GSXML.elementToString(response, true)); 467 return (Element)response.getElementsByTagName(GSXML.RESPONSE_ELEM).item(0); 468 } 469 470 protected Element processClassifierBrowse(Element request) { 471 String collection = this.cluster_name; 472 String lang = request.getAttribute(GSXML.LANG_ATT); 473 if(!lang.equals(prevLanguage)) { 474 prevLanguage = lang; 475 fedoraServicesAPIA.setLanguage(lang); 476 } 477 478 NodeList classNodes = request.getElementsByTagName(GSXML.CLASS_NODE_ELEM); 479 if(classNodes == null || classNodes.getLength() <= 0) { 480 logger.error("ClassifierBrowse request specified no classifier IDs.\n"); 481 return XMLConverter.newDOM().createElement(GSXML.RESPONSE_ELEM); // empty response 482 } 483 String classifierIDs[] = new String[classNodes.getLength()]; 484 for(int i = 0; i < classifierIDs.length; i++) { 485 Element e = (Element)classNodes.item(i); 486 classifierIDs[i] = e.getAttribute(GSXML.NODE_ID_ATT); 487 classifierIDs[i] = translateId(classifierIDs[i]); 488 } 489 490 NodeList params = request.getElementsByTagName(GSXML.PARAM_ELEM); 491 String structure=""; 492 String info=""; 493 for(int i = 0; i < params.getLength(); i++) { 494 Element param = (Element)params.item(i); 495 if(param.getAttribute("name").equals("structure")) { 496 structure = structure + param.getAttribute("value") + "|"; 497 } else if(param.getAttribute("name").equals("info")) { 498 info = info + param.getAttribute("value") + "|"; 499 } 500 } 501 ///structure = structure + "siblings"; //test for getting with classifier browse structure: siblings 502 503 Element response 504 = getResponseAsDOM(fedoraServicesAPIA.retrieveBrowseStructure(collection, "ClassifierBrowse", classifierIDs, 505 new String[] {structure}, new String[] {info})); 506 //logger.error("**** FedoraServiceProxy - Response from retrieveBrowseStructure: " + GSXML.elementToString(response, true)); 507 508 return (Element)response.getElementsByTagName(GSXML.RESPONSE_ELEM).item(0); 509 } 510 511 protected Element processTextQuery(Element request) { 512 return processQuery(request, "TextQuery"); 513 } 514 515 protected Element processFieldQuery(Element request) { 516 return processQuery(request, "FieldQuery"); 517 } 518 519 protected Element processQuery(Element request, String querytype) { 520 String collection = this.cluster_name; 521 522 String lang = request.getAttribute(GSXML.LANG_ATT); 523 if(!lang.equals(prevLanguage)) { 524 prevLanguage = lang; 525 fedoraServicesAPIA.setLanguage(lang); 526 } 527 528 NodeList paramNodes = request.getElementsByTagName(GSXML.PARAM_ELEM); 529 if(paramNodes.getLength() > 0) { 530 HashMap<String, String> params = new HashMap<String, String>(paramNodes.getLength()); 531 for(int i = 0; i < paramNodes.getLength(); i++) { 532 Element param = (Element)paramNodes.item(i); 533 params.put(param.getAttribute(GSXML.NAME_ATT), param.getAttribute(GSXML.VALUE_ATT)); 534 } 535 536 Element response = getResponseAsDOM(fedoraServicesAPIA.query(collection, querytype, params)); 537 return (Element)response.getElementsByTagName(GSXML.RESPONSE_ELEM).item(0); 538 } else { 539 logger.error("TextQuery request specified no parameters.\n"); 540 return XMLConverter.newDOM().createElement(GSXML.RESPONSE_ELEM); // empty response 541 } 542 } 543 544 // get the requested nodeIDs out of a request message 545 protected String[] parse(Element request, String nodeType, String attribute) { 546 String[] nodevalues = null; 547 int count = 0; 548 549 Element docList = (Element) GSXML.getChildByTagName(request, nodeType+GSXML.LIST_MODIFIER); 550 if (docList != null) { 551 NodeList docNodes = docList.getElementsByTagName(nodeType); 552 if(docNodes.getLength() > 0) { 553 nodevalues = new String[docNodes.getLength()]; 554 for(int i = 0; i < nodevalues.length; i++) { 555 Element e = (Element)docNodes.item(i); 556 String id = e.getAttribute(attribute); 557 // Not sure why there are at times requests for hashXXX.dir, which is not a fedora PID 558 // To skip these: if not requesting an externalURL and if requesting a docNode, 559 // then the ID has to contain the : character special to fedora PIDs 560 if(attribute == "externalURL" || (nodeType != GSXML.DOC_NODE_ELEM || id.contains(":"))) { 561 nodevalues[count++] = id; 562 } 563 } 564 } 565 } 566 567 if(count == 0) { 568 return null; 569 } 570 571 String[] tmp = new String[count]; 572 for(int i = 0; i < count; i++) { 573 tmp[i] = nodevalues[i]; 574 } 575 nodevalues = null; 576 nodevalues = tmp; 577 578 return nodevalues; 579 } 580 581 582 /** if id ends in .fc, .pc etc, then translate it to the correct id 583 * For now (for testing things work) the default implementation is to just remove the suffix */ 584 protected String translateId(String id) { 585 if (OID.needsTranslating(id)) { 586 return OID.translateOID(this, id); //return translateOID(id); 587 } 588 return id; 589 } 590 591 /** if an id is not a greenstone id (an external id) then translate 592 * it to a greenstone one 593 * default implementation: return the id. Custom implementation: 594 * the id is a url that maps to a fedorapid whose dc.title contains the required HASHID */ 595 protected String translateExternalId(String id) { 596 //logger.error("*** to translate an external ID: " + id); /////return id; 597 return this.externalId2OID(id); 598 } 599 600 /** converts an external id to greenstone OID. External ID is a URL link 601 * that, if relative, maps to a fedorapid that has an entry in fedora. 602 * The dc:title meta for that fedorapid will contain the required OID. */ 603 public String externalId2OID(String extid) { 604 if(extid.endsWith(".rt") && (extid.indexOf('.') != extid.lastIndexOf('.'))) { 605 // .rt is not file extension, but Greenstone request for root of document 606 // not relevant for external ID 607 extid = extid.substring(0, extid.length()-3); 608 } 609 610 // the following method is unique to FedoraServicesAPIA 611 String response = ((FedoraServicesAPIA)fedoraServicesAPIA).getDocIDforURL(extid, this.cluster_name); 612 if(response.indexOf(GSXML.ERROR_ELEM) != -1) { 613 logger.error("**** The following error occurred when trying to find externalID for ID " + extid); 614 logger.error(response); 615 return extid; 616 } 617 if(response.equals("")) { 618 return extid; 619 } else { 620 return response; 621 } 622 } 623 624 625 /** translates relative oids into proper oids: 626 * .pr (parent), .rt (root) .fc (first child), .lc (last child), 627 * .ns (next sibling), .ps (previous sibling) 628 * .np (next page), .pp (previous page) : links sections in the order that you'd read the document 629 * a suffix is expected to be present so test before using 630 */ 631 public String processOID(String doc_id, String top, String suff, int sibling_num) { 632 633 // send off request to get sibling etc. information from Fedora 634 Element response = null; 635 String[] children = null; 636 if(doc_id.startsWith("CL")) { // classifiernode 637 response = getResponseAsDOM(fedoraServicesAPIA.retrieveBrowseStructure(this.cluster_name, "ClassifierBrowse", new String[]{doc_id}, 638 new String[]{"children"}, new String[]{"siblingPosition"})); 639 NodeList nl = response.getElementsByTagName(GSXML.NODE_STRUCTURE_ELEM); 640 if(nl.getLength() > 0) { 641 Element nodeStructure = (Element)nl.item(0); 642 643 if(nodeStructure != null) { 644 Element root = (Element) GSXML.getChildByTagName(nodeStructure, GSXML.CLASS_NODE_ELEM); 645 if(root != null) { // get children 646 NodeList classNodes = root.getElementsByTagName(GSXML.CLASS_NODE_ELEM); 647 if(classNodes != null) { 648 children = new String[classNodes.getLength()]; 649 for(int i = 0; i < children.length; i++) { 650 Element child = (Element)classNodes.item(i); 651 children[i] = child.getAttribute(GSXML.NODE_ID_ATT); 652 } 653 } 654 } 655 } 656 } 657 } else { // documentnode 658 response = getResponseAsDOM(fedoraServicesAPIA.retrieveDocumentStructure(this.cluster_name, new String[]{doc_id}, 659 new String[]{"children"}, new String[]{"siblingPosition"})); 660 String path = GSPath.createPath(new String[]{GSXML.RESPONSE_ELEM, GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER, 661 GSXML.DOC_NODE_ELEM, GSXML.NODE_STRUCTURE_ELEM, GSXML.DOC_NODE_ELEM}); 662 Element parentDocNode = (Element) GSXML.getNodeByPath(response, path); 663 664 if (parentDocNode == null) { 665 return top; 666 } // else 667 NodeList docNodes = parentDocNode.getElementsByTagName(GSXML.DOC_NODE_ELEM); // only children should remain, since that's what we requested 668 if(docNodes.getLength() > 0) { 669 children = new String[docNodes.getLength()]; 670 671 for(int i = 0; i < children.length; i++) { 672 Element e = (Element)docNodes.item(i); 673 children[i] = e.getAttribute(GSXML.NODE_ID_ATT); 674 } 675 } else { // return root node 676 children = new String[]{doc_id}; 677 } 678 } 679 680 if (suff.equals("fc")) { 681 return children[0]; 682 } else if (suff.equals("lc")) { 683 return children[children.length-1]; 684 } else { 685 if (suff.equals("ss")) { 686 return children[sibling_num-1]; 687 } 688 // find the position that we are at. 689 int i=0; 690 while(i<children.length) { 691 if (children[i].equals(top)) { 692 break; 693 } 694 i++; 695 } 696 697 if (suff.equals("ns")) { 698 if (i==children.length-1) { 699 return children[i]; 700 } 701 return children[i+1]; 702 } else if (suff.equals("ps")) { 703 if (i==0) { 704 return children[i]; 705 } 706 return children[i-1]; 707 } 708 } 709 710 return top; 711 } 712 713 714 protected Element getResponseAsDOM(String response) { 715 if(response == null) { // will not be the case, because an empty 716 return null; // response message will be sent instead 717 } 718 719 Element message = null; 720 try{ 721 // turn the String xml response into a DOM tree: 722 DocumentBuilder builder 723 = DocumentBuilderFactory.newInstance().newDocumentBuilder(); 724 Document doc 725 = builder.parse(new InputSource(new StringReader(response))); 726 message = doc.getDocumentElement(); 727 } catch(Exception e){ 728 if(response == null) { 729 response = ""; 730 } 731 logger.error("An error occurred while trying to parse the response: "); 732 logger.error(response); 733 logger.error(e.getMessage()); 734 } 735 736 // Error elements in message will be processed outside of here, just return the message 737 return message; 738 } 739 740 /* //process method for stylesheet requests 741 protected Element processFormat(Element request) {} */ 742 743 /* returns the service list for the subclass */ 744 /* protected Element getServiceList(String lang) { 745 // for now, it is static and has no language stuff 746 return (Element) this.short_service_info.cloneNode(true); 747 }*/ 748 749 /** returns a specific service description */ 750 protected Element getServiceDescription(Document doc, String service, String lang, String subset) { 751 if(!lang.equals(prevLanguage)) { 752 prevLanguage = lang; 753 fedoraServicesAPIA.setLanguage(lang); 754 } 755 String serviceResponse = fedoraServicesAPIA.describeService(service); 756 Element response = getResponseAsDOM(serviceResponse); 757 758 // should be no chance of an npe, since FedoraGS3 lists the services, so will have descriptions for each 759 Element e = (Element)response.getElementsByTagName(GSXML.SERVICE_ELEM).item(0); 760 e = (Element)doc.importNode(e, true); 761 return e; 762 } 763 764 /** overloaded version for no args case */ 765 protected String getTextString(String key, String lang) { 766 return getTextString(key, lang, null, null); 767 } 768 769 protected String getTextString(String key, String lang, String dictionary) { 770 return getTextString(key, lang, dictionary, null); 771 } 772 protected String getTextString(String key, String lang, String [] args) { 773 return getTextString(key, lang, null, args); 774 } 775 776 /** getTextString - retrieves a language specific text string for the given 777 key and locale, from the specified resource_bundle (dictionary) 778 */ 779 protected String getTextString(String key, String lang, String dictionary, String[] args) { 780 781 // we want to use the collection class loader in case there are coll specific files 782 if (dictionary != null) { 783 // just try the one specified dictionary 784 Dictionary dict = new Dictionary(dictionary, lang, this.class_loader); 785 String result = dict.get(key, args); 786 if (result == null) { // not found 787 return "_"+key+"_"; 788 } 789 return result; 790 } 791 792 // now we try class names for dictionary names 793 String class_name = this.getClass().getName(); 794 class_name = class_name.substring(class_name.lastIndexOf('.')+1); 795 Dictionary dict = new Dictionary(class_name, lang, this.class_loader); 796 String result = dict.get(key, args); 797 if (result != null) { 798 return result; 799 } 800 801 // we have to try super classes 802 Class c = this.getClass().getSuperclass(); 803 while (result == null && c != null) { 804 class_name = c.getName(); 805 class_name = class_name.substring(class_name.lastIndexOf('.')+1); 806 if (class_name.equals("ServiceRack")) { 807 // this is as far as we go 808 break; 809 } 810 dict = new Dictionary(class_name, lang, this.class_loader); 811 result = dict.get(key, args); 812 c = c.getSuperclass(); 813 } 814 if (result == null) { 815 return "_"+key+"_"; 816 } 817 return result; 818 819 } 820 821 protected String getMetadataNameText(String key, String lang) { 822 823 String properties_name = "metadata_names"; 824 Dictionary dict = new Dictionary(properties_name, lang); 825 826 String result = dict.get(key); 827 if (result == null) { // not found 828 return null; 829 } 830 return result; 831 } 832 89 833 public static class BasicTextMacroResolver extends MacroResolver { 90 834 private static final Pattern p_back_slash = Pattern.compile("\\\"");// create a pattern "\\\"", but it matches both " and \" … … 137 881 } 138 882 139 static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.FedoraServiceProxy.class.getName()); 140 protected MacroResolver macro_resolver = null; 141 142 143 /** The handle to the fedora connection */ 144 private DigitalLibraryServicesAPIA fedoraServicesAPIA; 145 146 private String prevLanguage = ""; 147 148 public void cleanUp() { 149 super.cleanUp(); 150 } 151 152 /** sets the message router */ 153 public void setMessageRouter(MessageRouter m) { 154 this.router = m; 155 setLibraryName(m.getLibraryName()); 156 } 157 158 /** the no-args constructor */ 159 public FedoraServiceProxy() { 160 super(); 161 162 this.converter = new XMLConverter(); 163 this.doc = this.converter.newDOM(); 164 this.short_service_info = this.doc.createElement(GSXML.SERVICE_ELEM+GSXML.LIST_MODIFIER); 165 this.macro_resolver = new BasicTextMacroResolver(); 166 } 167 168 169 /* configure the service module 170 * 171 * @param info the XML node <serviceRack name="XXX"/> with name equal 172 * to the class name (of the subclass) 173 * 174 * must configure short_service_info_ and service_info_map_ 175 * @return true if configured ok 176 * must be implemented in subclasses 177 */ 178 /*public boolean configure(Element info) { 179 return configure(info, null); 180 }*/ 181 182 public boolean configure(Element info, Element extra_info) { 183 // set up the class loader 184 185 if (!super.configure(info, extra_info)){ 186 return false; 187 } 188 189 // Try to instantiate a Fedora dl handle 190 try { 191 // Fedora connection settings defaults. 192 // Read host and port from global.properties, since by default, we expect the Greenstone server to be used 193 Properties globalProperties = new Properties(); 194 globalProperties.load(Class.forName("org.greenstone.util.GlobalProperties").getClassLoader().getResourceAsStream("global.properties")); 195 String host = globalProperties.getProperty("tomcat.server", "localhost"); 196 String port = globalProperties.getProperty("tomcat.port", "8383"); 197 String protocol = "http"; 198 String username = "fedoraIntCallUser"; //"fedoraAdmin" 199 String password = "changeme"; //"<user password>" 200 201 // See if buildConfig.xml overrides any of the defaults 202 // info is the <serviceRack> Element from buildConfig.xml (extra_info are the Elements of collectionConfig.xml) 203 204 NodeList nodes = info.getElementsByTagName("fedoraConnection"); 205 if(nodes != null && nodes.getLength() > 0) { 206 207 Element fedoraElement = (Element)nodes.item(0); 208 if(fedoraElement.hasAttribute("protocol")) { 209 protocol = fedoraElement.getAttribute("protocol"); 210 } 211 if(fedoraElement.hasAttribute("host")) { 212 host = fedoraElement.getAttribute("host"); 213 } 214 if(fedoraElement.hasAttribute("port")) { 215 port = fedoraElement.getAttribute("port"); 216 } 217 if(fedoraElement.hasAttribute("username")) { 218 username = fedoraElement.getAttribute("username"); 219 } 220 if(fedoraElement.hasAttribute("password")) { 221 password = fedoraElement.getAttribute("password"); 222 } 223 } 224 225 fedoraServicesAPIA = new FedoraServicesAPIA(protocol, host, Integer.parseInt(port), username, password); 226 227 } catch(org.greenstone.fedora.services.FedoraGS3Exception.CancelledException e) { 228 // The user pressed cancel in the fedora services instantiation dialog 229 return false; 230 } catch(Exception e) { 231 logger.error("Error instantiating the interface to the Fedora Repository:\n", e); // second parameter prints e's stacktrace 232 return false; 233 } 234 235 236 // Need to put the available services into short_service_info 237 // This is used by DefaultReceptionist.process() has an exception. But DefaultReceptionist.addExtraInfo() 238 // isn't helpful, and the problem actually already occurs in 239 // Receptionist.process() -> PageAction.process() -> MessageRouter.process() 240 // -> Collection/ServiceCluster.process() -> ServiceCluster.configureServiceRackList() 241 // -> ServiceRack.process() -> ServiceRack.processDescribe() -> ServiceRack.getServiceList(). 242 // ServiceRack.getServiceList() requires this ServiceRack's services to be filled into the 243 // short_service_info Element which needs to be done in this FedoraServiceProxy.configure(). 244 245 // get the display and format elements from the coll config file for 246 // the classifiers 247 AbstractBrowse.extractExtraClassifierInfo(info, extra_info); 248 249 // Copied from IViaProxy.java: 250 String collection = fedoraServicesAPIA.describeCollection(this.cluster_name); 251 252 Element collNode = getResponseAsDOM(collection); 253 Element serviceList = (Element)collNode.getElementsByTagName(GSXML.SERVICE_ELEM+GSXML.LIST_MODIFIER).item(0); 254 255 //this.short_service_info.appendChild(short_service_info.getOwnerDocument().importNode(serviceList, true)); 256 // we want the individual service Elements, not the serviceList Element which will wrap it later 257 NodeList services = collNode.getElementsByTagName(GSXML.SERVICE_ELEM); 258 for(int i = 0; i < services.getLength(); i++) { 259 Node service = services.item(i); 260 this.short_service_info.appendChild(short_service_info.getOwnerDocument().importNode(service, true)); 261 } 262 263 // add some format info to service map if there is any 264 String path = GSPath.appendLink(GSXML.SEARCH_ELEM, GSXML.FORMAT_ELEM); 265 Element search_format = (Element) GSXML.getNodeByPath(extra_info, path); 266 if (search_format != null) { 267 this.format_info_map.put("TextQuery", this.doc.importNode(search_format, true)); 268 this.format_info_map.put("FieldQuery", this.doc.importNode(search_format, true)); 269 } 270 271 // look for document display format 272 path = GSPath.appendLink(GSXML.DISPLAY_ELEM, GSXML.FORMAT_ELEM); 273 Element display_format = (Element)GSXML.getNodeByPath(extra_info, path); 274 if (display_format != null) { 275 this.format_info_map.put("DocumentContentRetrieve", this.doc.importNode(display_format, true)); 276 // should we make a copy? 277 } 278 279 // the format info 280 Element cb_format_info = this.doc.createElement(GSXML.FORMAT_ELEM); 281 boolean format_found = false; 282 283 // look for classifier <browse><format> 284 path = GSPath.appendLink(GSXML.BROWSE_ELEM, GSXML.FORMAT_ELEM); 285 Element browse_format = (Element)GSXML.getNodeByPath(extra_info, path); 286 if (browse_format != null) { 287 cb_format_info.appendChild(GSXML.duplicateWithNewName(this.doc, browse_format, GSXML.DEFAULT_ELEM, true)); 288 format_found = true; 289 } 290 291 // add in to the description a simplified list of classifiers 292 Element browse = (Element)GSXML.getChildByTagName(extra_info, "browse"); // the <browse> 293 NodeList classifiers = browse.getElementsByTagName(GSXML.CLASSIFIER_ELEM); 294 for(int i=0; i<classifiers.getLength(); i++) { 295 Element cl = (Element)classifiers.item(i); 296 Element new_cl = (Element)this.doc.importNode(cl, false); // just import this node, not the children 297 298 // get the format info out, and put inside a classifier element 299 Element format_cl = (Element)new_cl.cloneNode(false); 300 Element format = (Element)GSXML.getChildByTagName(cl, GSXML.FORMAT_ELEM); 301 if (format != null) { 302 303 //copy all the children 304 NodeList elems = format.getChildNodes(); 305 for (int j=0; j<elems.getLength();j++) { 306 format_cl.appendChild(this.doc.importNode(elems.item(j), true)); 307 } 308 cb_format_info.appendChild(format_cl); 309 format_found = true; 310 } 311 312 } 313 314 if (format_found) { 315 this.format_info_map.put("ClassifierBrowse", cb_format_info); 316 } 317 318 319 // set up the macro resolver 320 macro_resolver.setSiteDetails(this.site_http_address, this.cluster_name, this.getLibraryName()); 321 Element replacement_elem = (Element)GSXML.getChildByTagName(extra_info, "replaceList"); 322 if (replacement_elem != null) { 323 macro_resolver.addMacros(replacement_elem); 324 } 325 // look for any refs to global replace lists 326 NodeList replace_refs_elems = extra_info.getElementsByTagName("replaceListRef"); 327 for (int i=0; i<replace_refs_elems.getLength(); i++) { 328 String id = ((Element)replace_refs_elems.item(i)).getAttribute("id"); 329 if (!id.equals("")) { 330 Element replace_list = GSXML.getNamedElement(this.router.config_info, "replaceList", "id", id); 331 if (replace_list != null) { 332 macro_resolver.addMacros(replace_list); 333 } 334 } 335 } 336 337 // configured ok 338 return true; 339 } 340 341 342 /* "DocumentContentRetrieve", "DocumentMetadataRetrieve", "DocumentStructureRetrieve", 343 "TextQuery", "FieldQuery", "ClassifierBrowse", "ClassifierBrowseMetadataRetrieve" */ 344 345 protected Element processDocumentContentRetrieve(Element request) { 346 String[] docIDs = parse(request, GSXML.DOC_NODE_ELEM, GSXML.NODE_ID_ATT); 347 String[] relLinks = parse(request, GSXML.DOC_NODE_ELEM, "externalURL"); 348 349 //logger.error("### request:"); 350 //logger.error(GSXML.elementToString(request, true)); 351 352 if(docIDs == null) { 353 logger.error("DocumentContentRetrieve request specified no doc nodes.\n"); 354 return this.doc.createElement(GSXML.RESPONSE_ELEM); // empty response 355 } else { 356 for(int i = 0; i < docIDs.length; i++) { 357 //logger.error("BEFORE: docIDs[" + i + "]: " + docIDs[i]); 358 if(relLinks[i] != null && docIDs[i].startsWith("http://")) { // need to do a look up 359 docIDs[i] = translateExternalId(docIDs[i]); 360 } else { 361 docIDs[i] = translateId(docIDs[i]); 362 } 363 //logger.error("AFTER: docIDs[" + i + "]: " + docIDs[i]); 364 } 365 } 366 367 String lang = request.getAttribute(GSXML.LANG_ATT); 368 if(!lang.equals(prevLanguage)) { 369 prevLanguage = lang; 370 fedoraServicesAPIA.setLanguage(lang); 371 } 372 373 // first param (the collection) is not used by Fedora 374 Element response = getResponseAsDOM(fedoraServicesAPIA.retrieveDocumentContent(this.cluster_name, docIDs)); 375 376 377 // resolve any collection specific macros 378 NodeList nodeContents = response.getElementsByTagName(GSXML.NODE_CONTENT_ELEM); 379 for(int i = 0; i < nodeContents.getLength(); i++) { 380 Element nodeContent = (Element)nodeContents.item(i); 381 /*if(nodeContent != null) { 382 nodeContent = (Element)nodeContent.getFirstChild(); // textNode 383 }*/ 384 //logger.error("GIRAFFE 1. content retrieve response - nodeContent: " + GSXML.nodeToFormattedString(nodeContent)); 385 String docContent = nodeContent.getFirstChild().getNodeValue(); // getTextNode and get its contents. 386 //logger.error("GIRAFFE 2. content retrieve response - docContent: " + docContent); 387 388 if(docContent != null) { 389 // get document text and resolve and macros. Rel and external links have _httpextlink_ set by HTMLPlugin 390 docContent = macro_resolver.resolve(docContent, lang, MacroResolver.SCOPE_TEXT, ""); // doc_id 391 nodeContent.getFirstChild().setNodeValue(docContent); 392 //logger.error("GIRAFFE 3. content retrieve response. Updated docContent: " + docContent); 393 } 394 } 395 396 return (Element)response.getElementsByTagName(GSXML.RESPONSE_ELEM).item(0); 397 } 398 399 protected Element processDocumentStructureRetrieve(Element request) { 400 String[] docIDs = parse(request, GSXML.DOC_NODE_ELEM, GSXML.NODE_ID_ATT); 401 String[] relLinks = parse(request, GSXML.DOC_NODE_ELEM, "externalURL"); 402 403 if(docIDs == null) { 404 logger.error("DocumentStructureRetrieve request specified no doc nodes.\n"); 405 return this.doc.createElement(GSXML.RESPONSE_ELEM); // empty response 406 } else { 407 for(int i = 0; i < docIDs.length; i++) { 408 //logger.error("BEFORE: docIDs[" + i + "]: " + docIDs[i]); 409 if(relLinks[i] != null && docIDs[i].startsWith("http://")) { // need to do a look up 410 docIDs[i] = translateExternalId(docIDs[i]); 411 } else { 412 docIDs[i] = translateId(docIDs[i]); 413 } 414 } 415 } 416 417 NodeList params = request.getElementsByTagName(GSXML.PARAM_ELEM); 418 String structure=""; 419 String info=""; 420 for(int i = 0; i < params.getLength(); i++) { 421 Element param = (Element)params.item(i); 422 if(param.getAttribute("name").equals("structure")) { 423 structure = structure + param.getAttribute("value") + "|"; 424 } else if(param.getAttribute("name").equals("info")) { 425 info = info + param.getAttribute("value") + "|"; 426 } 427 } 428 429 String lang = request.getAttribute(GSXML.LANG_ATT); 430 if(!lang.equals(prevLanguage)) { 431 prevLanguage = lang; 432 fedoraServicesAPIA.setLanguage(lang); 433 } 434 Element response = getResponseAsDOM(fedoraServicesAPIA.retrieveDocumentStructure( 435 this.cluster_name, docIDs, new String[]{structure}, new String[]{info})); 436 return (Element)response.getElementsByTagName(GSXML.RESPONSE_ELEM).item(0); 437 } 438 439 protected Element processDocumentMetadataRetrieve(Element request) { 440 String[] docIDs = parse(request, GSXML.DOC_NODE_ELEM, GSXML.NODE_ID_ATT); 441 String[] relLinks = parse(request, GSXML.DOC_NODE_ELEM, "externalURL"); 442 443 if(docIDs == null) { 444 logger.error("DocumentMetadataRetrieve request specified no doc nodes.\n"); 445 return this.doc.createElement(GSXML.RESPONSE_ELEM); // empty response 446 } else { 447 for(int i = 0; i < docIDs.length; i++) { 448 //logger.error("**** relLinks[i]: " + relLinks[i]); 449 //logger.error("**** docIDs[i]: " + docIDs[i]); 450 if(relLinks[i] != null && docIDs[i].startsWith("http://")) { // need to do a look up 451 docIDs[i] = translateExternalId(docIDs[i]); 452 } else { 453 docIDs[i] = translateId(docIDs[i]); 454 } 455 //logger.error("AFTER: docIDs[" + i + "]: " + docIDs[i]); 456 } 457 } 458 459 NodeList params = request.getElementsByTagName(GSXML.PARAM_ELEM); 460 String[] metafields = {}; 461 if(params.getLength() > 0) { 462 metafields = new String[params.getLength()]; 463 for(int i = 0; i < metafields.length; i++) { 464 Element param = (Element)params.item(i); 465 //if(param.hasAttribute(GSXML.NAME_ATT) && param.getAttribute(GSXML.NAME_ATT).equals("metadata") && param.hasAttribute(GSXML.VALUE_ATT)) { 466 if(param.hasAttribute(GSXML.VALUE_ATT)){ 467 metafields[i] = param.getAttribute(GSXML.VALUE_ATT); 468 } else { 469 metafields[i] = ""; 470 } 471 } 472 } 473 474 String lang = request.getAttribute(GSXML.LANG_ATT); 475 if(!lang.equals(prevLanguage)) { 476 prevLanguage = lang; 477 fedoraServicesAPIA.setLanguage(lang); 478 } 479 Element response = getResponseAsDOM(fedoraServicesAPIA.retrieveDocumentMetadata( 480 this.cluster_name, docIDs, metafields)); 481 return (Element)response.getElementsByTagName(GSXML.RESPONSE_ELEM).item(0); 482 } 483 484 protected Element processClassifierBrowseMetadataRetrieve(Element request) { 485 String[] classIDs = parse(request, GSXML.CLASS_NODE_ELEM, GSXML.NODE_ID_ATT); 486 //String[] relLinks = parse(request, GSXML.CLASS_NODE_ELEM, "externalURL"); 487 488 if(classIDs == null) { 489 logger.error("ClassifierBrowseMetadataRetrieve request specified no classifier nodes.\n"); 490 return this.doc.createElement(GSXML.RESPONSE_ELEM); // empty response 491 } else { 492 for(int i = 0; i < classIDs.length; i++) { 493 classIDs[i] = translateId(classIDs[i]); 494 } 495 } 496 497 NodeList params = request.getElementsByTagName(GSXML.PARAM_ELEM); 498 String[] metafields = {}; 499 if(params.getLength() > 0) { 500 metafields = new String[params.getLength()]; 501 for(int i = 0; i < metafields.length; i++) { 502 Element param = (Element)params.item(i); 503 if(param.hasAttribute(GSXML.VALUE_ATT)){ 504 metafields[i] = param.getAttribute(GSXML.VALUE_ATT); 505 } else { 506 metafields[i] = ""; 507 } 508 } 509 } 510 511 String lang = request.getAttribute(GSXML.LANG_ATT); 512 if(!lang.equals(prevLanguage)) { 513 prevLanguage = lang; 514 fedoraServicesAPIA.setLanguage(lang); 515 } 516 Element response = getResponseAsDOM(fedoraServicesAPIA.retrieveBrowseMetadata( 517 this.cluster_name, "ClassifierBrowseMetadataRetrieve", classIDs, metafields)); 518 //logger.error("**** Response from retrieveBrowseMeta: " + GSXML.elementToString(response, true)); 519 return (Element)response.getElementsByTagName(GSXML.RESPONSE_ELEM).item(0); 520 } 521 522 protected Element processClassifierBrowse(Element request) { 523 String collection = this.cluster_name; 524 String lang = request.getAttribute(GSXML.LANG_ATT); 525 if(!lang.equals(prevLanguage)) { 526 prevLanguage = lang; 527 fedoraServicesAPIA.setLanguage(lang); 528 } 529 530 NodeList classNodes = request.getElementsByTagName(GSXML.CLASS_NODE_ELEM); 531 if(classNodes == null || classNodes.getLength() <= 0) { 532 logger.error("ClassifierBrowse request specified no classifier IDs.\n"); 533 return this.doc.createElement(GSXML.RESPONSE_ELEM); // empty response 534 } 535 String classifierIDs[] = new String[classNodes.getLength()]; 536 for(int i = 0; i < classifierIDs.length; i++) { 537 Element e = (Element)classNodes.item(i); 538 classifierIDs[i] = e.getAttribute(GSXML.NODE_ID_ATT); 539 classifierIDs[i] = translateId(classifierIDs[i]); 540 } 541 542 NodeList params = request.getElementsByTagName(GSXML.PARAM_ELEM); 543 String structure=""; 544 String info=""; 545 for(int i = 0; i < params.getLength(); i++) { 546 Element param = (Element)params.item(i); 547 if(param.getAttribute("name").equals("structure")) { 548 structure = structure + param.getAttribute("value") + "|"; 549 } else if(param.getAttribute("name").equals("info")) { 550 info = info + param.getAttribute("value") + "|"; 551 } 552 } 553 ///structure = structure + "siblings"; //test for getting with classifier browse structure: siblings 554 555 Element response 556 = getResponseAsDOM(fedoraServicesAPIA.retrieveBrowseStructure(collection, "ClassifierBrowse", classifierIDs, 557 new String[] {structure}, new String[] {info})); 558 //logger.error("**** FedoraServiceProxy - Response from retrieveBrowseStructure: " + GSXML.elementToString(response, true)); 559 560 return (Element)response.getElementsByTagName(GSXML.RESPONSE_ELEM).item(0); 561 } 562 563 protected Element processTextQuery(Element request) { 564 return processQuery(request, "TextQuery"); 565 } 566 567 protected Element processFieldQuery(Element request) { 568 return processQuery(request, "FieldQuery"); 569 } 570 571 protected Element processQuery(Element request, String querytype) { 572 String collection = this.cluster_name; 573 574 String lang = request.getAttribute(GSXML.LANG_ATT); 575 if(!lang.equals(prevLanguage)) { 576 prevLanguage = lang; 577 fedoraServicesAPIA.setLanguage(lang); 578 } 579 580 NodeList paramNodes = request.getElementsByTagName(GSXML.PARAM_ELEM); 581 if(paramNodes.getLength() > 0) { 582 HashMap<String, String> params = new HashMap<String, String>(paramNodes.getLength()); 583 for(int i = 0; i < paramNodes.getLength(); i++) { 584 Element param = (Element)paramNodes.item(i); 585 params.put(param.getAttribute(GSXML.NAME_ATT), param.getAttribute(GSXML.VALUE_ATT)); 586 } 587 588 Element response = getResponseAsDOM(fedoraServicesAPIA.query(collection, querytype, params)); 589 return (Element)response.getElementsByTagName(GSXML.RESPONSE_ELEM).item(0); 590 } else { 591 logger.error("TextQuery request specified no parameters.\n"); 592 return this.doc.createElement(GSXML.RESPONSE_ELEM); // empty response 593 } 594 } 595 596 // get the requested nodeIDs out of a request message 597 protected String[] parse(Element request, String nodeType, String attribute) { 598 String[] nodevalues = null; 599 int count = 0; 600 601 Element docList = (Element) GSXML.getChildByTagName(request, nodeType+GSXML.LIST_MODIFIER); 602 if (docList != null) { 603 NodeList docNodes = docList.getElementsByTagName(nodeType); 604 if(docNodes.getLength() > 0) { 605 nodevalues = new String[docNodes.getLength()]; 606 for(int i = 0; i < nodevalues.length; i++) { 607 Element e = (Element)docNodes.item(i); 608 String id = e.getAttribute(attribute); 609 // Not sure why there are at times requests for hashXXX.dir, which is not a fedora PID 610 // To skip these: if not requesting an externalURL and if requesting a docNode, 611 // then the ID has to contain the : character special to fedora PIDs 612 if(attribute == "externalURL" || (nodeType != GSXML.DOC_NODE_ELEM || id.contains(":"))) { 613 nodevalues[count++] = id; 614 } 615 } 616 } 617 } 618 619 if(count == 0) { 620 return null; 621 } 622 623 String[] tmp = new String[count]; 624 for(int i = 0; i < count; i++) { 625 tmp[i] = nodevalues[i]; 626 } 627 nodevalues = null; 628 nodevalues = tmp; 629 630 return nodevalues; 631 } 632 633 634 /** if id ends in .fc, .pc etc, then translate it to the correct id 635 * For now (for testing things work) the default implementation is to just remove the suffix */ 636 protected String translateId(String id) { 637 if (OID.needsTranslating(id)) { 638 return OID.translateOID(this, id); //return translateOID(id); 639 } 640 return id; 641 } 642 643 /** if an id is not a greenstone id (an external id) then translate 644 * it to a greenstone one 645 * default implementation: return the id. Custom implementation: 646 * the id is a url that maps to a fedorapid whose dc.title contains the required HASHID */ 647 protected String translateExternalId(String id) { 648 //logger.error("*** to translate an external ID: " + id); /////return id; 649 return this.externalId2OID(id); 650 } 651 652 /** converts an external id to greenstone OID. External ID is a URL link 653 * that, if relative, maps to a fedorapid that has an entry in fedora. 654 * The dc:title meta for that fedorapid will contain the required OID. */ 655 public String externalId2OID(String extid) { 656 if(extid.endsWith(".rt") && (extid.indexOf('.') != extid.lastIndexOf('.'))) { 657 // .rt is not file extension, but Greenstone request for root of document 658 // not relevant for external ID 659 extid = extid.substring(0, extid.length()-3); 660 } 661 662 // the following method is unique to FedoraServicesAPIA 663 String response = ((FedoraServicesAPIA)fedoraServicesAPIA).getDocIDforURL(extid, this.cluster_name); 664 if(response.indexOf(GSXML.ERROR_ELEM) != -1) { 665 logger.error("**** The following error occurred when trying to find externalID for ID " + extid); 666 logger.error(response); 667 return extid; 668 } 669 if(response.equals("")) { 670 return extid; 671 } else { 672 return response; 673 } 674 } 675 676 677 /** translates relative oids into proper oids: 678 * .pr (parent), .rt (root) .fc (first child), .lc (last child), 679 * .ns (next sibling), .ps (previous sibling) 680 * .np (next page), .pp (previous page) : links sections in the order that you'd read the document 681 * a suffix is expected to be present so test before using 682 */ 683 public String processOID(String doc_id, String top, String suff, int sibling_num) { 684 685 // send off request to get sibling etc. information from Fedora 686 Element response = null; 687 String[] children = null; 688 if(doc_id.startsWith("CL")) { // classifiernode 689 response = getResponseAsDOM(fedoraServicesAPIA.retrieveBrowseStructure(this.cluster_name, "ClassifierBrowse", new String[]{doc_id}, 690 new String[]{"children"}, new String[]{"siblingPosition"})); 691 NodeList nl = response.getElementsByTagName(GSXML.NODE_STRUCTURE_ELEM); 692 if(nl.getLength() > 0) { 693 Element nodeStructure = (Element)nl.item(0); 694 695 if(nodeStructure != null) { 696 Element root = (Element) GSXML.getChildByTagName(nodeStructure, GSXML.CLASS_NODE_ELEM); 697 if(root != null) { // get children 698 NodeList classNodes = root.getElementsByTagName(GSXML.CLASS_NODE_ELEM); 699 if(classNodes != null) { 700 children = new String[classNodes.getLength()]; 701 for(int i = 0; i < children.length; i++) { 702 Element child = (Element)classNodes.item(i); 703 children[i] = child.getAttribute(GSXML.NODE_ID_ATT); 704 } 705 } 706 } 707 } 708 } 709 } else { // documentnode 710 response = getResponseAsDOM(fedoraServicesAPIA.retrieveDocumentStructure(this.cluster_name, new String[]{doc_id}, 711 new String[]{"children"}, new String[]{"siblingPosition"})); 712 String path = GSPath.createPath(new String[]{GSXML.RESPONSE_ELEM, GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER, 713 GSXML.DOC_NODE_ELEM, GSXML.NODE_STRUCTURE_ELEM, GSXML.DOC_NODE_ELEM}); 714 Element parentDocNode = (Element) GSXML.getNodeByPath(response, path); 715 716 if (parentDocNode == null) { 717 return top; 718 } // else 719 NodeList docNodes = parentDocNode.getElementsByTagName(GSXML.DOC_NODE_ELEM); // only children should remain, since that's what we requested 720 if(docNodes.getLength() > 0) { 721 children = new String[docNodes.getLength()]; 722 723 for(int i = 0; i < children.length; i++) { 724 Element e = (Element)docNodes.item(i); 725 children[i] = e.getAttribute(GSXML.NODE_ID_ATT); 726 } 727 } else { // return root node 728 children = new String[]{doc_id}; 729 } 730 } 731 732 if (suff.equals("fc")) { 733 return children[0]; 734 } else if (suff.equals("lc")) { 735 return children[children.length-1]; 736 } else { 737 if (suff.equals("ss")) { 738 return children[sibling_num-1]; 739 } 740 // find the position that we are at. 741 int i=0; 742 while(i<children.length) { 743 if (children[i].equals(top)) { 744 break; 745 } 746 i++; 747 } 748 749 if (suff.equals("ns")) { 750 if (i==children.length-1) { 751 return children[i]; 752 } 753 return children[i+1]; 754 } else if (suff.equals("ps")) { 755 if (i==0) { 756 return children[i]; 757 } 758 return children[i-1]; 759 } 760 } 761 762 return top; 763 } 764 765 766 protected Element getResponseAsDOM(String response) { 767 if(response == null) { // will not be the case, because an empty 768 return null; // response message will be sent instead 769 } 770 771 Element message = null; 772 try{ 773 // turn the String xml response into a DOM tree: 774 DocumentBuilder builder 775 = DocumentBuilderFactory.newInstance().newDocumentBuilder(); 776 Document doc 777 = builder.parse(new InputSource(new StringReader(response))); 778 message = doc.getDocumentElement(); 779 } catch(Exception e){ 780 if(response == null) { 781 response = ""; 782 } 783 logger.error("An error occurred while trying to parse the response: "); 784 logger.error(response); 785 logger.error(e.getMessage()); 786 } 787 788 // Error elements in message will be processed outside of here, just return the message 789 return message; 790 } 791 792 /* //process method for stylesheet requests 793 protected Element processFormat(Element request) {} */ 794 795 /* returns the service list for the subclass */ 796 /* protected Element getServiceList(String lang) { 797 // for now, it is static and has no language stuff 798 return (Element) this.short_service_info.cloneNode(true); 799 }*/ 800 801 /** returns a specific service description */ 802 protected Element getServiceDescription(String service, String lang, String subset) { 803 if(!lang.equals(prevLanguage)) { 804 prevLanguage = lang; 805 fedoraServicesAPIA.setLanguage(lang); 806 } 807 String serviceResponse = fedoraServicesAPIA.describeService(service); 808 Element response = getResponseAsDOM(serviceResponse); 809 810 // should be no chance of an npe, since FedoraGS3 lists the services, so will have descriptions for each 811 Element e = (Element)response.getElementsByTagName(GSXML.SERVICE_ELEM).item(0); 812 e = (Element)this.doc.importNode(e, true); 813 return e; 814 } 815 816 /** overloaded version for no args case */ 817 protected String getTextString(String key, String lang) { 818 return getTextString(key, lang, null, null); 819 } 820 821 protected String getTextString(String key, String lang, String dictionary) { 822 return getTextString(key, lang, dictionary, null); 823 } 824 protected String getTextString(String key, String lang, String [] args) { 825 return getTextString(key, lang, null, args); 826 } 827 828 /** getTextString - retrieves a language specific text string for the given 829 key and locale, from the specified resource_bundle (dictionary) 830 */ 831 protected String getTextString(String key, String lang, String dictionary, String[] args) { 832 833 // we want to use the collection class loader in case there are coll specific files 834 if (dictionary != null) { 835 // just try the one specified dictionary 836 Dictionary dict = new Dictionary(dictionary, lang, this.class_loader); 837 String result = dict.get(key, args); 838 if (result == null) { // not found 839 return "_"+key+"_"; 840 } 841 return result; 842 } 843 844 // now we try class names for dictionary names 845 String class_name = this.getClass().getName(); 846 class_name = class_name.substring(class_name.lastIndexOf('.')+1); 847 Dictionary dict = new Dictionary(class_name, lang, this.class_loader); 848 String result = dict.get(key, args); 849 if (result != null) { 850 return result; 851 } 852 853 // we have to try super classes 854 Class c = this.getClass().getSuperclass(); 855 while (result == null && c != null) { 856 class_name = c.getName(); 857 class_name = class_name.substring(class_name.lastIndexOf('.')+1); 858 if (class_name.equals("ServiceRack")) { 859 // this is as far as we go 860 break; 861 } 862 dict = new Dictionary(class_name, lang, this.class_loader); 863 result = dict.get(key, args); 864 c = c.getSuperclass(); 865 } 866 if (result == null) { 867 return "_"+key+"_"; 868 } 869 return result; 870 871 } 872 873 protected String getMetadataNameText(String key, String lang) { 874 875 String properties_name = "metadata_names"; 876 Dictionary dict = new Dictionary(properties_name, lang); 877 878 String result = dict.get(key); 879 if (result == null) { // not found 880 return null; 881 } 882 return result; 883 } 883 884 884 } 885 885
Note:
See TracChangeset
for help on using the changeset viewer.