Changeset 25979

Show
Ignore:
Timestamp:
19.07.2012 14:30:48 (7 years ago)
Author:
sjm84
Message:

Reformatting this file

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • main/trunk/greenstone3/src/java/org/greenstone/gsdl3/service/FedoraServiceProxy.java

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