Changeset 26170

Show
Ignore:
Timestamp:
11.09.2012 16:07:13 (7 years ago)
Author:
ak19
Message:

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

Files:
1 modified

Legend:

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

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