Ignore:
Timestamp:
2012-09-11T16:07:13+12:00 (12 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.

File:
1 edited

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