Ignore:
Timestamp:
2012-07-19T14:30:48+12:00 (12 years ago)
Author:
sjm84
Message:

Reformatting this file

File:
1 edited

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 
Note: See TracChangeset for help on using the changeset viewer.