source: main/trunk/greenstone3/src/java/org/greenstone/gsdl3/service/FedoraServiceProxy.java@ 26170

Last change on this file since 26170 was 26170, checked in by ak19, 12 years ago

Committing many changes to FedoraServiceProxy code that weren't committed for ages. Added in Sam's changes that were made since, except for the eclipse style reformatting.

File size: 31.6 KB
Line 
1/*
2 * ServiceRack.java
3 * Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19package org.greenstone.gsdl3.service;
20
21// greenstone classes
22import java.io.StringReader;
23import java.util.HashMap;
24import java.util.Properties;
25import java.util.regex.Matcher;
26import java.util.regex.Pattern;
27
28import javax.xml.parsers.DocumentBuilder;
29import javax.xml.parsers.DocumentBuilderFactory;
30
31import org.apache.log4j.Logger;
32import org.greenstone.gs3client.dlservices.DigitalLibraryServicesAPIA;
33import org.greenstone.gs3client.dlservices.FedoraServicesAPIA;
34import org.greenstone.gsdl3.core.MessageRouter;
35import org.greenstone.gsdl3.util.Dictionary;
36import org.greenstone.gsdl3.util.GSPath;
37import org.greenstone.gsdl3.util.GSXML;
38import org.greenstone.gsdl3.util.MacroResolver;
39import org.greenstone.gsdl3.util.OID;
40import org.greenstone.gsdl3.util.XMLConverter;
41import org.w3c.dom.Document;
42import org.w3c.dom.Element;
43import org.w3c.dom.Node;
44import org.w3c.dom.NodeList;
45import org.xml.sax.InputSource;
46
47
48/*
49// greenstone classes
50import org.greenstone.gsdl3.util.*;
51import org.greenstone.gsdl3.core.*;
52
53// for fedora
54import org.greenstone.gs3client.dlservices.*;
55import org.greenstone.fedora.services.FedoraGS3Exception.CancelledException;
56
57// xml classes
58import org.w3c.dom.Node;
59import org.w3c.dom.NodeList;
60import org.w3c.dom.Element;
61import org.w3c.dom.Document;
62import org.xml.sax.InputSource;
63import javax.xml.parsers.*;
64import org.apache.xpath.XPathAPI;
65
66// general java classes
67import java.io.Reader;
68import java.io.StringReader;
69import java.io.File;
70import java.util.HashMap;
71import java.util.Locale;
72import java.util.Properties;
73import java.util.ResourceBundle;
74import java.util.regex.*;
75import java.lang.reflect.Method;
76*/
77
78import org.apache.log4j.*;
79
80/**
81 * FedoraServiceProxy - communicates with the FedoraGS3 interface.
82 *
83 * @author Anupama Krishnan
84 */
85public class FedoraServiceProxy
86 extends ServiceRack implements OID.OIDTranslatable
87{
88 public static class BasicTextMacroResolver extends MacroResolver {
89 public String resolve(String text, String lang, String scope, String doc_oid)
90 {
91
92 if (text == null || text.equals("")) {
93 return text;
94 }
95 if (!scope.equals(SCOPE_TEXT) || text_macros.size()==0) {
96 return text;
97 }
98
99 java.util.ArrayList macros = text_macros;
100 for (int i=0; i<macros.size(); i++) {
101 String new_text = null;
102 Macro m = (Macro)macros.get(i);
103 if(m.type == TYPE_TEXT) {
104 // make sure we resolve any macros in the text
105 // the (?s) treats the string as a single line, cos .
106 // doesn't necessarily match line breaks
107 //if (text.matches("(?s).*"+m.macro+".*")) {
108 Pattern p_text = Pattern.compile(".*" + m.macro + ".*",Pattern.DOTALL);
109 Matcher match_text = p_text.matcher(text);
110 if (match_text.matches()) {
111 if (m.resolve) {
112 new_text = this.resolve(m.text, lang, scope, doc_oid);
113 } else {
114 new_text = m.text;
115 }
116 text = text.replaceAll(m.macro, new_text);
117 if (m.macro.endsWith("\\\\")){ // to get rid of "\" from the string likes: "src="http://www.greenstone.org:80/.../mw.gif\">"
118 Pattern p_back_slash = Pattern.compile("\\\"");// create a pattern "\\\"", but it matches both " and \"
119 Matcher m_slash = p_back_slash.matcher(text);
120 String clean_str = "";
121 int s=0;
122 while (m_slash.find()){
123 if (!text.substring(m_slash.end()-2,m_slash.end()-1).equals("\\")){
124 clean_str = clean_str + text.substring(s,m_slash.end()-1); // it matches ", so get a substring before "
125 }else{
126 clean_str = clean_str + text.substring(s,m_slash.end()-2);// it matches \", so get a substring before \
127 }
128 s = m_slash.end();// get the index of the last match
129 clean_str = clean_str + "\"";
130 }
131 text = clean_str + text.substring(s,text.length());
132 }
133 }
134 }
135 }
136 return text;
137 }
138 }
139
140 static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.FedoraServiceProxy.class.getName());
141 protected MacroResolver macro_resolver = null;
142
143
144 /** The handle to the fedora connection */
145 private DigitalLibraryServicesAPIA fedoraServicesAPIA;
146
147 private String prevLanguage = "";
148
149 public void cleanUp() {
150 super.cleanUp();
151 }
152
153 /** sets the message router */
154 public void setMessageRouter(MessageRouter m) {
155 this.router = m;
156 setLibraryName(m.getLibraryName());
157 }
158
159 /** the no-args constructor */
160 public FedoraServiceProxy() {
161 super();
162
163 this.converter = new XMLConverter();
164 this.doc = this.converter.newDOM();
165 this.short_service_info = this.doc.createElement(GSXML.SERVICE_ELEM+GSXML.LIST_MODIFIER);
166 this.macro_resolver = new BasicTextMacroResolver();
167 }
168
169
170 /* configure the service module
171 *
172 * @param info the XML node <serviceRack name="XXX"/> with name equal
173 * to the class name (of the subclass)
174 *
175 * must configure short_service_info_ and service_info_map_
176 * @return true if configured ok
177 * must be implemented in subclasses
178 */
179 /*public boolean configure(Element info) {
180 return configure(info, null);
181 }*/
182
183 public boolean configure(Element info, Element extra_info) {
184 // set up the class loader
185
186 if (!super.configure(info, extra_info)){
187 return false;
188 }
189
190 // Try to instantiate a Fedora dl handle
191 try {
192 // Fedora connection settings defaults.
193 // Read host and port from global.properties, since by default, we expect the Greenstone server to be used
194 Properties globalProperties = new Properties();
195 globalProperties.load(Class.forName("org.greenstone.util.GlobalProperties").getClassLoader().getResourceAsStream("global.properties"));
196 String host = globalProperties.getProperty("tomcat.server", "localhost");
197 String port = globalProperties.getProperty("tomcat.port", "8383");
198 String protocol = "http";
199 String username = "fedoraIntCallUser"; //"fedoraAdmin"
200 String password = "changeme"; //"<user password>"
201
202 // See if buildConfig.xml overrides any of the defaults
203 // info is the <serviceRack> Element from buildConfig.xml (extra_info are the Elements of collectionConfig.xml)
204
205 NodeList nodes = info.getElementsByTagName("fedoraConnection");
206 if(nodes != null && nodes.getLength() > 0) {
207
208 Element fedoraElement = (Element)nodes.item(0);
209 if(fedoraElement.hasAttribute("protocol")) {
210 protocol = fedoraElement.getAttribute("protocol");
211 }
212 if(fedoraElement.hasAttribute("host")) {
213 host = fedoraElement.getAttribute("host");
214 }
215 if(fedoraElement.hasAttribute("port")) {
216 port = fedoraElement.getAttribute("port");
217 }
218 if(fedoraElement.hasAttribute("username")) {
219 username = fedoraElement.getAttribute("username");
220 }
221 if(fedoraElement.hasAttribute("password")) {
222 password = fedoraElement.getAttribute("password");
223 }
224 }
225
226 fedoraServicesAPIA = new FedoraServicesAPIA(protocol, host, Integer.parseInt(port), username, password);
227
228 } catch(org.greenstone.fedora.services.FedoraGS3Exception.CancelledException e) {
229 // The user pressed cancel in the fedora services instantiation dialog
230 return false;
231 } catch(Exception e) {
232 logger.error("Error instantiating the interface to the Fedora Repository:\n", e); // second parameter prints e's stacktrace
233 return false;
234 }
235
236
237 // Need to put the available services into short_service_info
238 // This is used by DefaultReceptionist.process() has an exception. But DefaultReceptionist.addExtraInfo()
239 // isn't helpful, and the problem actually already occurs in
240 // Receptionist.process() -> PageAction.process() -> MessageRouter.process()
241 // -> Collection/ServiceCluster.process() -> ServiceCluster.configureServiceRackList()
242 // -> ServiceRack.process() -> ServiceRack.processDescribe() -> ServiceRack.getServiceList().
243 // ServiceRack.getServiceList() requires this ServiceRack's services to be filled into the
244 // short_service_info Element which needs to be done in this FedoraServiceProxy.configure().
245
246 // get the display and format elements from the coll config file for
247 // the classifiers
248 AbstractBrowse.extractExtraClassifierInfo(info, extra_info);
249
250 // Copied from IViaProxy.java:
251 String collection = fedoraServicesAPIA.describeCollection(this.cluster_name);
252
253 Element collNode = getResponseAsDOM(collection);
254 Element serviceList = (Element)collNode.getElementsByTagName(GSXML.SERVICE_ELEM+GSXML.LIST_MODIFIER).item(0);
255
256//this.short_service_info.appendChild(short_service_info.getOwnerDocument().importNode(serviceList, true));
257 // we want the individual service Elements, not the serviceList Element which will wrap it later
258 NodeList services = collNode.getElementsByTagName(GSXML.SERVICE_ELEM);
259 for(int i = 0; i < services.getLength(); i++) {
260 Node service = services.item(i);
261 this.short_service_info.appendChild(short_service_info.getOwnerDocument().importNode(service, true));
262 }
263
264 // add some format info to service map if there is any
265 String path = GSPath.appendLink(GSXML.SEARCH_ELEM, GSXML.FORMAT_ELEM);
266 Element search_format = (Element) GSXML.getNodeByPath(extra_info, path);
267 if (search_format != null) {
268 this.format_info_map.put("TextQuery", 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.nodeToFormattedString(request));
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 return (Element)response.getElementsByTagName(GSXML.RESPONSE_ELEM).item(0);
519 }
520
521 protected Element processClassifierBrowse(Element request) {
522 String collection = this.cluster_name;
523 String lang = request.getAttribute(GSXML.LANG_ATT);
524 if(!lang.equals(prevLanguage)) {
525 prevLanguage = lang;
526 fedoraServicesAPIA.setLanguage(lang);
527 }
528
529 NodeList classNodes = request.getElementsByTagName(GSXML.CLASS_NODE_ELEM);
530 if(classNodes == null || classNodes.getLength() <= 0) {
531 logger.error("ClassifierBrowse request specified no classifier IDs.\n");
532 return this.doc.createElement(GSXML.RESPONSE_ELEM); // empty response
533 }
534 String classifierIDs[] = new String[classNodes.getLength()];
535 for(int i = 0; i < classifierIDs.length; i++) {
536 Element e = (Element)classNodes.item(i);
537 classifierIDs[i] = e.getAttribute(GSXML.NODE_ID_ATT);
538 classifierIDs[i] = translateId(classifierIDs[i]);
539 }
540
541 NodeList params = request.getElementsByTagName(GSXML.PARAM_ELEM);
542 String structure="";
543 String info="";
544 for(int i = 0; i < params.getLength(); i++) {
545 Element param = (Element)params.item(i);
546 if(param.getAttribute("name").equals("structure")) {
547 structure = structure + param.getAttribute("value") + "|";
548 } else if(param.getAttribute("name").equals("info")) {
549 info = info + param.getAttribute("value") + "|";
550 }
551 }
552 ///structure = structure + "siblings"; //test for getting with classifier browse structure: siblings
553
554 Element response
555 = getResponseAsDOM(fedoraServicesAPIA.retrieveBrowseStructure(collection, "ClassifierBrowse", classifierIDs,
556 new String[] {structure}, new String[] {info}));
557 ///logger.error("**** FedoraServiceProxy - Response from retrieveBrowseStructure: " + GSXML.nodeToFormattedString(response));
558
559 return (Element)response.getElementsByTagName(GSXML.RESPONSE_ELEM).item(0);
560 }
561
562 protected Element processTextQuery(Element request) {
563 return processQuery(request, "TextQuery");
564 }
565
566 protected Element processFieldQuery(Element request) {
567 return processQuery(request, "FieldQuery");
568 }
569
570 protected Element processQuery(Element request, String querytype) {
571 String collection = this.cluster_name;
572
573 String lang = request.getAttribute(GSXML.LANG_ATT);
574 if(!lang.equals(prevLanguage)) {
575 prevLanguage = lang;
576 fedoraServicesAPIA.setLanguage(lang);
577 }
578
579 NodeList paramNodes = request.getElementsByTagName(GSXML.PARAM_ELEM);
580 if(paramNodes.getLength() > 0) {
581 HashMap<String, String> params = new HashMap<String, String>(paramNodes.getLength());
582 for(int i = 0; i < paramNodes.getLength(); i++) {
583 Element param = (Element)paramNodes.item(i);
584 params.put(param.getAttribute(GSXML.NAME_ATT), param.getAttribute(GSXML.VALUE_ATT));
585 }
586
587 Element response = getResponseAsDOM(fedoraServicesAPIA.query(collection, querytype, params));
588 return (Element)response.getElementsByTagName(GSXML.RESPONSE_ELEM).item(0);
589 } else {
590 logger.error("TextQuery request specified no parameters.\n");
591 return this.doc.createElement(GSXML.RESPONSE_ELEM); // empty response
592 }
593 }
594
595 protected String[] parse(Element request, String nodeType, String attribute) {
596 String[] nodevalues = null;
597
598 Element docList = (Element) GSXML.getChildByTagName(request, nodeType+GSXML.LIST_MODIFIER);
599 if (docList != null) {
600 NodeList docNodes = docList.getElementsByTagName(nodeType);
601 if(docNodes.getLength() > 0) {
602 nodevalues = new String[docNodes.getLength()];
603 for(int i = 0; i < nodevalues.length; i++) {
604 Element e = (Element)docNodes.item(i);
605 nodevalues[i] = e.getAttribute(attribute);
606 }
607 }
608 }
609 return nodevalues;
610 }
611
612
613 /** if id ends in .fc, .pc etc, then translate it to the correct id
614 * For now (for testing things work) the default implementation is to just remove the suffix */
615 protected String translateId(String id) {
616 if (OID.needsTranslating(id)) {
617 return OID.translateOID(this, id); //return translateOID(id);
618 }
619 return id;
620 }
621
622 /** if an id is not a greenstone id (an external id) then translate
623 * it to a greenstone one
624 * default implementation: return the id. Custom implementation:
625 * the id is a url that maps to a fedorapid whose dc.title contains the required HASHID */
626 protected String translateExternalId(String id) {
627 //logger.error("*** to translate an external ID: " + id); /////return id;
628 return this.externalId2OID(id);
629 }
630
631 /** converts an external id to greenstone OID. External ID is a URL link
632 * that, if relative, maps to a fedorapid that has an entry in fedora.
633 * The dc:title meta for that fedorapid will contain the required OID. */
634 public String externalId2OID(String extid) {
635 if(extid.endsWith(".rt") && (extid.indexOf('.') != extid.lastIndexOf('.'))) {
636 // .rt is not file extension, but Greenstone request for root of document
637 // not relevant for external ID
638 extid = extid.substring(0, extid.length()-3);
639 }
640
641 // the following method is unique to FedoraServicesAPIA
642 String response = ((FedoraServicesAPIA)fedoraServicesAPIA).getDocIDforURL(extid, this.cluster_name);
643 if(response.indexOf(GSXML.ERROR_ELEM) != -1) {
644 logger.error("**** The following error occurred when trying to find externalID for ID " + extid);
645 logger.error(response);
646 return extid;
647 }
648 if(response.equals("")) {
649 return extid;
650 } else {
651 return response;
652 }
653 }
654
655
656 /** translates relative oids into proper oids:
657 * .pr (parent), .rt (root) .fc (first child), .lc (last child),
658 * .ns (next sibling), .ps (previous sibling)
659 * .np (next page), .pp (previous page) : links sections in the order that you'd read the document
660 * a suffix is expected to be present so test before using
661 */
662 public String processOID(String doc_id, String top, String suff, int sibling_num) {
663
664 // send off request to get sibling etc. information from Fedora
665 Element response = null;
666 String[] children = null;
667 if(doc_id.startsWith("CL")) { // classifiernode
668 response = getResponseAsDOM(fedoraServicesAPIA.retrieveBrowseStructure(this.cluster_name, "ClassifierBrowse", new String[]{doc_id},
669 new String[]{"children"}, new String[]{"siblingPosition"}));
670 NodeList nl = response.getElementsByTagName(GSXML.NODE_STRUCTURE_ELEM);
671 if(nl.getLength() > 0) {
672 Element nodeStructure = (Element)nl.item(0);
673
674 if(nodeStructure != null) {
675 Element root = (Element) GSXML.getChildByTagName(nodeStructure, GSXML.CLASS_NODE_ELEM);
676 if(root != null) { // get children
677 NodeList classNodes = root.getElementsByTagName(GSXML.CLASS_NODE_ELEM);
678 if(classNodes != null) {
679 children = new String[classNodes.getLength()];
680 for(int i = 0; i < children.length; i++) {
681 Element child = (Element)classNodes.item(i);
682 children[i] = child.getAttribute(GSXML.NODE_ID_ATT);
683 }
684 }
685 }
686 }
687 }
688 } else { // documentnode
689 response = getResponseAsDOM(fedoraServicesAPIA.retrieveDocumentStructure(this.cluster_name, new String[]{doc_id},
690 new String[]{"children"}, new String[]{"siblingPosition"}));
691 String path = GSPath.createPath(new String[]{GSXML.RESPONSE_ELEM, GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER,
692 GSXML.DOC_NODE_ELEM, GSXML.NODE_STRUCTURE_ELEM, GSXML.DOC_NODE_ELEM});
693 Element parentDocNode = (Element) GSXML.getNodeByPath(response, path);
694
695 if (parentDocNode == null) {
696 return top;
697 } // else
698 NodeList docNodes = parentDocNode.getElementsByTagName(GSXML.DOC_NODE_ELEM); // only children should remain, since that's what we requested
699 if(docNodes.getLength() > 0) {
700 children = new String[docNodes.getLength()];
701
702 for(int i = 0; i < children.length; i++) {
703 Element e = (Element)docNodes.item(i);
704 children[i] = e.getAttribute(GSXML.NODE_ID_ATT);
705 }
706 } else { // return root node
707 children = new String[]{doc_id};
708 }
709 }
710
711 if (suff.equals("fc")) {
712 return children[0];
713 } else if (suff.equals("lc")) {
714 return children[children.length-1];
715 } else {
716 if (suff.equals("ss")) {
717 return children[sibling_num-1];
718 }
719 // find the position that we are at.
720 int i=0;
721 while(i<children.length) {
722 if (children[i].equals(top)) {
723 break;
724 }
725 i++;
726 }
727
728 if (suff.equals("ns")) {
729 if (i==children.length-1) {
730 return children[i];
731 }
732 return children[i+1];
733 } else if (suff.equals("ps")) {
734 if (i==0) {
735 return children[i];
736 }
737 return children[i-1];
738 }
739 }
740
741 return top;
742 }
743
744
745 protected Element getResponseAsDOM(String response) {
746 if(response == null) { // will not be the case, because an empty
747 return null; // response message will be sent instead
748 }
749
750 Element message = null;
751 try{
752 // turn the String xml response into a DOM tree:
753 DocumentBuilder builder
754 = DocumentBuilderFactory.newInstance().newDocumentBuilder();
755 Document doc
756 = builder.parse(new InputSource(new StringReader(response)));
757 message = doc.getDocumentElement();
758 } catch(Exception e){
759 if(response == null) {
760 response = "";
761 }
762 logger.error("An error occurred while trying to parse the response: ");
763 logger.error(response);
764 logger.error(e.getMessage());
765 }
766
767 // Error elements in message will be processed outside of here, just return the message
768 return message;
769 }
770
771 /* //process method for stylesheet requests
772 protected Element processFormat(Element request) {} */
773
774 /* returns the service list for the subclass */
775 /* protected Element getServiceList(String lang) {
776 // for now, it is static and has no language stuff
777 return (Element) this.short_service_info.cloneNode(true);
778 }*/
779
780 /** returns a specific service description */
781 protected Element getServiceDescription(String service, String lang, String subset) {
782 if(!lang.equals(prevLanguage)) {
783 prevLanguage = lang;
784 fedoraServicesAPIA.setLanguage(lang);
785 }
786 String serviceResponse = fedoraServicesAPIA.describeService(service);
787 Element response = getResponseAsDOM(serviceResponse);
788
789 // should be no chance of an npe, since FedoraGS3 lists the services, so will have descriptions for each
790 Element e = (Element)response.getElementsByTagName(GSXML.SERVICE_ELEM).item(0);
791 e = (Element)this.doc.importNode(e, true);
792 return e;
793 }
794
795 /** overloaded version for no args case */
796 protected String getTextString(String key, String lang) {
797 return getTextString(key, lang, null, null);
798 }
799
800 protected String getTextString(String key, String lang, String dictionary) {
801 return getTextString(key, lang, dictionary, null);
802 }
803 protected String getTextString(String key, String lang, String [] args) {
804 return getTextString(key, lang, null, args);
805 }
806
807 /** getTextString - retrieves a language specific text string for the given
808key and locale, from the specified resource_bundle (dictionary)
809 */
810 protected String getTextString(String key, String lang, String dictionary, String[] args) {
811
812 // we want to use the collection class loader in case there are coll specific files
813 if (dictionary != null) {
814 // just try the one specified dictionary
815 Dictionary dict = new Dictionary(dictionary, lang, this.class_loader);
816 String result = dict.get(key, args);
817 if (result == null) { // not found
818 return "_"+key+"_";
819 }
820 return result;
821 }
822
823 // now we try class names for dictionary names
824 String class_name = this.getClass().getName();
825 class_name = class_name.substring(class_name.lastIndexOf('.')+1);
826 Dictionary dict = new Dictionary(class_name, lang, this.class_loader);
827 String result = dict.get(key, args);
828 if (result != null) {
829 return result;
830 }
831
832 // we have to try super classes
833 Class c = this.getClass().getSuperclass();
834 while (result == null && c != null) {
835 class_name = c.getName();
836 class_name = class_name.substring(class_name.lastIndexOf('.')+1);
837 if (class_name.equals("ServiceRack")) {
838 // this is as far as we go
839 break;
840 }
841 dict = new Dictionary(class_name, lang, this.class_loader);
842 result = dict.get(key, args);
843 c = c.getSuperclass();
844 }
845 if (result == null) {
846 return "_"+key+"_";
847 }
848 return result;
849
850 }
851
852 protected String getMetadataNameText(String key, String lang) {
853
854 String properties_name = "metadata_names";
855 Dictionary dict = new Dictionary(properties_name, lang);
856
857 String result = dict.get(key);
858 if (result == null) { // not found
859 return null;
860 }
861 return result;
862 }
863}
864
Note: See TracBrowser for help on using the repository browser.