Changeset 22300

Show
Ignore:
Timestamp:
24.06.2010 13:45:34 (9 years ago)
Author:
ak19
Message:

1. Changes to get Fedora to work with Greenstone3: to let the Greenstone3 Reader Interface work with a Fedora Repository behind the scenes. 2. No longer returns XML Strings formatted for display, but unformatted, since when it's converted to XML DOM on the Greenstone end, new lines introduced due to whitespace interfere with Greenstone 3's default parsing of the XML.

Location:
other-projects/gs3-webservices-java-client/trunk/src/GS3Fedora/org/greenstone/fedora/services
Files:
5 modified

Legend:

Unmodified
Added
Removed
  • other-projects/gs3-webservices-java-client/trunk/src/GS3Fedora/org/greenstone/fedora/services/FedoraCommons.java

    r15222 r22300  
    8888    } 
    8989     
    90     /** Given an Element, this will return its String representation properly  
     90    /** Given a DOM node, this will return its String representation properly  
    9191     * indented for display. 
    92      * @return a string representation of e, formatted for display.  
    93      * @param e is the element to be converted to its string representation. 
     92     * @return a string representation of n, formatted for display.  
     93     * @param n is the DOM node to be converted to its string representation. 
    9494    */ 
    95     public static String elementToFormattedString(Element e)  
    96         throws TransformerException  
     95    public static String displayAsString(Node n)  
    9796    { 
    98         DOMSource domSource = new DOMSource(e); 
    99         Transformer transformer = TransformerFactory.newInstance().newTransformer(); 
    100         transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); 
    101         //transformer.setOutputProperty(OutputKeys.METHOD, "xml"); 
    102         //transformer.setOutputProperty(OutputKeys.ENCODING, "ISO-8859-1"); 
    103         transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); 
    104         transformer.setOutputProperty(OutputKeys.INDENT, "yes"); 
     97        try { 
     98         
     99        DOMSource domSource = new DOMSource(n); 
     100        Transformer transformer = TransformerFactory.newInstance().newTransformer(); 
     101        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); 
     102        //transformer.setOutputProperty(OutputKeys.METHOD, "xml"); 
     103        //transformer.setOutputProperty(OutputKeys.ENCODING, "ISO-8859-1"); 
     104        transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); 
     105        transformer.setOutputProperty(OutputKeys.INDENT, "yes"); 
     106         
     107        StringWriter sw = new StringWriter(); 
     108        transformer.transform(domSource, new StreamResult(sw)); 
     109        return sw.toString(); 
     110        } catch(Exception e) { 
     111        System.err.println("Couldn't display node as String."); 
     112        return ""; 
     113        } 
     114         
     115    } 
    105116 
    106         StringWriter sw = new StringWriter(); 
    107         transformer.transform(domSource, new StreamResult(sw)); 
    108         return sw.toString(); 
    109     } 
     117     
    110118} 
  • other-projects/gs3-webservices-java-client/trunk/src/GS3Fedora/org/greenstone/fedora/services/FedoraConnection.java

    r21855 r22300  
    2020 
    2121package org.greenstone.fedora.services; 
    22  
     22import org.greenstone.gsdl3.util.GSXML; 
    2323 
    2424import fedora.client.utility.AutoFinder; 
     
    9595     
    9696    /* Some fixed strings of known literals */ 
    97     protected static final String TYPE = "type"; 
    98     protected static final String INTERNAL_NODE = "internalNode"; 
    9997    protected static final String GET= "/get/"; 
    10098     
     
    632630     * @see <a href="http://www.fedora.info/definitions/1/0/api/Fedora-API-A.html">Fedora access API, API-A for method findObjects</a> 
    633631     * @see <a href="http://www.fedora.info/definitions/1/0/types/&#035;complexType_FieldSearchQuery_Link031D7D80">XML type definition of FieldSearchQuery</a>  
    634      * @see <a href="http://www.fedora.info/download/2.2.1/javadocs/fedora/server/types/gen/FieldSearchQuery.html>Type definition of 2.2.1 FieldSearchQuery</a> 
     632     * @see <a href="http://www.fedora.info/download/2.2.1/javadocs/fedora/server/types/gen/FieldSearchQuery.html">Type definition of 2.2.1 FieldSearchQuery</a> 
    635633     * @see <a href="http://www.fedora.info/download/2.1.1/userdocs/server/serverdocs/fedora/server/search/FieldSearchQuery.html">does not apply: type definition of 2.1.1 FieldSearchQuery</a> 
    636634     * @see <a href="http://john.drc-dev.ohiolink.edu/browser/drc-core/trunk/src/java/edu/ohiolink/drc/drcdl/BrowseController.java?rev=462">BrowseController.java for an example</a>  
     
    12371235    } 
    12381236 
    1239     /** @return the XML content of the TOC of just that portion of the TOC which    
    1240      * contains the section denoted by sectionID and its direct child subsections.  
    1241      * The children are returned in the order they are encountered, which  
    1242      * happens to be in the required order of ascending sectionID.  
    1243      * @param docPID - a fedora pid identifying a greenstone document object. 
    1244      * @param sectionID - identifyies the particular section in the 
    1245      * document denoted by docPID, may be a section name or number. */ 
    1246     public Element getChildrenOfSectionXML(String docPID, String sectionID) 
    1247         throws RemoteException, UnsupportedEncodingException,  
    1248             SAXException, IOException  
    1249     { 
    1250         // Store just the number 
    1251         String sectionNumber = removePrefix(sectionID, SECTION);  
    1252         // get the TOC XML datastream as a String  
    1253         String xmlTOC = getTOC(docPID); 
    1254          
    1255         // convert it into a DOM document 
    1256         InputSource source = new InputSource(new StringReader(xmlTOC)); 
    1257         Document doc = builder.parse(source); 
    1258         // toplevel element docEl = <Section id="1"></Section> 
    1259         Element docEl = doc.getDocumentElement(); 
    1260          
    1261         // check whether we're requested to return the toplevel element itself 
    1262         if(sectionID.equals("") || // subSection of entire docPID is requested 
    1263            (docEl.hasAttribute(ID) && docEl.getAttribute(ID).equals(sectionNumber)))  
    1264             return getSubstructure(docEl, false); 
    1265          
    1266         // Otherwise, get all <Section> elements and find the 
    1267         // <Section id="sectionNumber"></Section> and return that and its 
    1268         // children 
    1269         NodeList sections = docEl.getElementsByTagName(SECTION_ELEMENT); 
    1270         for(int i = 0; i < sections.getLength(); i++) { 
    1271             Element e = (Element)sections.item(i); 
    1272             if(e.hasAttribute(ID)  
    1273                     && e.getAttribute(ID).equals(sectionNumber))  
    1274             { 
    1275                 //System.err.println("Found: " + e.getAttribute(ID)); 
    1276                 return getSubstructure(e, false); // false: get just e and children 
    1277             } 
    1278         } 
    1279         return null; // not found 
    1280     } 
    1281      
    1282     /** @return a string representing the XML content of the TOC of just 
    1283      * that portion of the TOC which contains the section denoted by sectionID   
    1284      * and its direct child subsections.  
    1285      * The children are returned in the order they are encountered, which  
    1286      * happens to be in the required order of ascending sectionID.  
    1287      * @param docPID - a fedora pid identifying a greenstone document object. 
    1288      * @param sectionID - identifyies the particular section in the 
    1289      * document denoted by docPID, may be a section name or number. */ 
    1290     public String getChildrenOfSection(String docPID, String sectionID) 
    1291         throws RemoteException, UnsupportedEncodingException,  
    1292             SAXException, IOException, TransformerException 
    1293     { 
    1294         Element children = getChildrenOfSectionXML(docPID, sectionID); 
    1295         return (children == null) ? "" : FedoraCommons.elementToString(children); 
    1296     } 
    1297      
    1298     /** @return the part of the TOC XML file (which outlines doc structure)   
    1299      * relating to the given section. This includes the section denoted by 
    1300      * sectionID as well as all descendent subsections thereof.  
    1301      * @param docPID - a fedora pid identifying a greenstone document object. 
    1302      * @param sectionID - identifyies the particular section in the 
    1303      * document denoted by docPID, may be a section name or number. */ 
    1304     public Element getSubsectionXML(String docPID, String sectionID) 
    1305         throws RemoteException, UnsupportedEncodingException,  
    1306             SAXException, IOException  
    1307     { 
    1308         // get the TableOfContents (TOC) XML datastream as a String  
    1309         String xmlTOC = getTOC(docPID); 
    1310          
    1311         // convert it into a DOM document 
    1312         InputSource source = new InputSource(new StringReader(xmlTOC)); 
    1313         Document doc = builder.parse(source); 
    1314         // toplevel element docEl = <Section id="1"></Section> 
    1315         Element docEl = doc.getDocumentElement(); 
    1316          
    1317         if(sectionID.equals("")) // subSection of entire docPID is requested  
    1318             return docEl; 
    1319          
    1320         // Store just the number 
    1321         String sectionNumber = removePrefix(sectionID, SECTION); 
    1322         // Check whether we're requested to return the toplevel element itself 
    1323         // If sectionNumber=1, then the top-level element/document element 
    1324         // of the TOC XML is requested, so return the TOC as is. 
    1325         if(sectionNumber.equals("1")) { 
    1326             return docEl; 
    1327         } 
    1328          
    1329         // Get all <Section> elements and find the 
    1330         // <Section id="sectionNumber"></Section> and return that 
    1331         NodeList sections = docEl.getElementsByTagName(SECTION_ELEMENT); 
    1332         for(int i = 0; i < sections.getLength(); i++) { 
    1333             Element e = (Element)sections.item(i); 
    1334             if(e.hasAttribute(ID)  
    1335                     && e.getAttribute(ID).equals(sectionNumber)) { 
    1336                 //System.err.println("Found: " + e.getAttribute(ID)); 
    1337                 return getSubstructure(e, true); // true:get all descendents 
    1338             } 
    1339         } 
    1340         return null; // not found 
    1341     } 
    1342      
    1343     /** @return a String representation of the part of the TOC XML file    
    1344      * (which outlines doc structure) relating to the given section. This     
    1345      * includes the section denoted by sectionID as well as all descendent   
    1346      * subsections thereof. 
    1347      * @param docPID a fedora pid identifying a greenstone document object. 
    1348      * @param sectionID identifyies the particular section in the 
    1349      * document denoted by docPID, may be a section name or number. */ 
    1350     public String getSubsection(String docPID, String sectionID) 
    1351         throws RemoteException, UnsupportedEncodingException, SAXException,   
    1352             IOException, TransformerException 
    1353     { 
    1354         // Store just the number 
    1355         String sectionNumber = removePrefix(sectionID, SECTION); 
    1356         // get the TableOfContents (TOC) XML datastream as a String  
    1357         String xmlTOC = getTOC(docPID); 
    1358          
    1359         // Check whether we're requested to return the toplevel element itself 
    1360         // If sectionNumber=1, then the top-level element/document element 
    1361         // of the TOC XML is requested, so return the TOC as is. 
    1362         if(sectionNumber.equals("1"))  
    1363             return xmlTOC; 
    1364          
    1365         // else 
    1366         Element subsection = getSubsectionXML(docPID, sectionID); 
    1367         return (subsection == null) ? "" : FedoraCommons.elementToString(subsection); 
    1368     } 
     1237    /** Given a documentNode element, adds the nodetype attribute to all of its 
     1238     * docNode descendants. The nodetype is either Root, Internal or Leaf to indicate 
     1239     * whether the docnode is a toplevel document Node, or has children or has none. 
     1240     * @param e - the documentNode element whose descendants' nodetypes will be set 
     1241     * at method's end. */ 
     1242    protected void addNodeTypeToDescendants(Element e) { 
     1243    NodeList sections = e.getElementsByTagName(SECTION_ELEMENT); 
     1244    for(int i = 0; i < sections.getLength(); i++) { 
     1245        Element section = (Element)sections.item(i); 
     1246        NodeList descendants = section.getElementsByTagName(SECTION_ELEMENT); 
     1247        if(descendants.getLength() > 0) {  
     1248        // if there are any descendants (which includes children) that are SECTIONS 
     1249        section.setAttribute(GSXML.NODE_TYPE_ATT, GSXML.NODE_TYPE_INTERNAL); 
     1250        } else { 
     1251        section.setAttribute(GSXML.NODE_TYPE_ATT, GSXML.NODE_TYPE_LEAF); 
     1252        } 
     1253    } 
     1254    } 
     1255 
     1256 
     1257    /** @return the part of the TOC XML file (which outlines doc structure)   
     1258     * relating to the given section. This includes the section denoted by 
     1259     * sectionID as well as all descendent subsections thereof.  
     1260     * @param docPID - a fedora pid identifying a greenstone document object. 
     1261     * @param sectionID - identifyies the particular section in the 
     1262     * document denoted by docPID, may be a section name or number.  
     1263     * @param structure can contain any combination of: ancestors, parent,  
     1264     * siblings, children, descendants, entire, specifying the portion of  
     1265     * the structure to retrieve. 
     1266     * @param info can contain any combination of: siblingPosition, numSiblings,  
     1267     * numChildren, requesting additional information about the structure. */ 
     1268    public Element getSectionStructureXML(String docPID, String sectionID, String structure, String info) 
     1269        throws RemoteException, UnsupportedEncodingException, SAXException, IOException  
     1270    { 
     1271    // get the TableOfContents (TOC) XML datastream as a String  
     1272    String xmlTOC = getTOC(docPID); 
     1273     
     1274    // convert it into a DOM document 
     1275    InputSource source = new InputSource(new StringReader(xmlTOC)); 
     1276    Document doc = builder.parse(source); 
     1277    // toplevel element docEl = <Section id="1"></Section> 
     1278    Element docEl = doc.getDocumentElement(); 
     1279    addNodeTypeToDescendants(docEl); 
     1280    docEl.setAttribute(GSXML.NODE_TYPE_ATT, GSXML.NODE_TYPE_ROOT); 
     1281 
     1282    if(structure.indexOf("entire") != -1) { // don't need to find the specific section, doc root is what's required 
     1283        docEl = getStructureInfo(docEl.getOwnerDocument(), docEl, info); 
     1284        return docEl; 
     1285    } 
     1286 
     1287    if(sectionID.equals("")) { 
     1288        sectionID = "1"; 
     1289    } 
     1290     
     1291    // Store just the number 
     1292    String sectionNumber = removePrefix(sectionID, SECTION); 
     1293    // Check whether we're requested to return the toplevel element itself 
     1294    // If sectionNumber=1, then the top-level element/document element 
     1295    // of the TOC XML is requested, so return the TOC as is.     
     1296    if(sectionNumber.equals("1") && structure.indexOf("descendants") != -1) {  
     1297        docEl = getStructureInfo(docEl.getOwnerDocument(), docEl, info); 
     1298        return docEl;        
     1299    } 
     1300     
     1301    // if the root is the section required, return that 
     1302    if(docEl.getTagName().equals(SECTION_ELEMENT)  
     1303       && docEl.getAttribute(ID).equals(sectionNumber)) { 
     1304        Element substructure = getSubstructure(docEl, structure); 
     1305        return getStructureInfo(substructure.getOwnerDocument(), docEl, info); 
     1306        //return docEl;  
     1307    } 
     1308     
     1309 
     1310    // Else, get all <Section> elements and find the 
     1311    // <Section id="sectionNumber"></Section> and return that 
     1312    NodeList sections = docEl.getElementsByTagName(SECTION_ELEMENT); 
     1313    for(int i = 0; i < sections.getLength(); i++) { 
     1314         
     1315        Element e = (Element)sections.item(i); 
     1316        if(e.hasAttribute(ID) && e.getAttribute(ID).equals(sectionNumber)) { 
     1317        Element substructure = getSubstructure(e, structure); 
     1318        return getStructureInfo(substructure.getOwnerDocument(), e, info); 
     1319        } 
     1320    } 
     1321 
     1322    return null; // not found 
     1323    } 
     1324 
    13691325     
    13701326    /** Implements browsing document titles of a greenstone collection stored in  
    13711327     * the fedora repository by letter.  
    13721328     * @return the document pids whose titles start with the given letter. 
     1329     * @param collName - the name of the collection. 
    13731330     * @param letter - the starting letter to browse by. 
    13741331     */  
     
    14351392        // We want to do the following kind of search (when written in Fedora's  
    14361393        // REST format - see http://localhost:8080/fedora/search):  
    1437         // pid~greenstone:<colname>* title~<1st word of titleContents> 
     1394        // pid~greenstone:<colname>-* title~<1st word of titleContents> 
    14381395         
    14391396        // We don't need to normalise the word first (to search titles starting  
     
    14521409        // only pids of those titles that contain the entire phrase titleContents 
    14531410         
    1454         final String pid = GREENSTONE_+collName+WILDCARD;  
     1411        final String pid = GREENSTONE_+collName+HYPHEN+WILDCARD;  
    14551412         
    14561413        int indexOfFirstSpace = titleContents.indexOf(' '); // check for space 
     
    15621519        throws RemoteException, FedoraVersionNotSupportedException 
    15631520    { 
    1564         // Searching for pids of the form "greenstone:gs2mgdemo*"; 
    1565         final String pid = GREENSTONE_+collName+WILDCARD; 
     1521        // Searching for pids of the form "greenstone:gs2mgdemo-*"; 
     1522        final String pid = GREENSTONE_+collName+HYPHEN+WILDCARD; 
    15661523         
    15671524        Condition[] conditions = new Condition[2]; 
     
    16141571        return collPID.substring(collPID.indexOf(':')+1, collPID.indexOf('-')); 
    16151572    } 
    1616          
    1617     /** Convert the given Element to a String representing the same XML. 
    1618      * @return an element containing a copy element e with either only its child 
    1619      * elements or with all its descendents (depending on whether parameter 
    1620      * descendents is true or false). 
    1621      * @param e - the element to start copying from. 
    1622      * @param descendents - if true, e is copied with all its descendetns into the  
    1623      * element that's returned. If false, only e and its direct children are copied   
    1624      * @see <a href="http://forum.java.sun.com/thread.jspa?threadID=678472&tstart=30">Sun java thread on transforming a DOM XML to a String</a> 
    1625     */ 
    1626     protected Element getSubstructure(Element e, boolean descendents)  
    1627     { 
    1628         Document doc = builder.newDocument(); 
    1629         Node n = doc.importNode(e, descendents);  
    1630                 // descendents=true: import/copy descendents. 
    1631                 // Else, copy just current node e (later copy its direct children) 
    1632         doc.appendChild(n); // need to put the copied node into a document 
    1633             // else it won't have a parent doc (DOMSource can't work with it 
    1634             // without it having a document parent). 
    1635      
    1636         // if we are not recursively copying all descendents, then copy just  
    1637         // the childnodes: 
    1638         if(!descendents) { // then copy just the children 
    1639             // get e's children and copy them into the new document 
    1640             NodeList children = e.getChildNodes(); 
    1641             for(int i = 0; i < children.getLength(); i++) { 
    1642                 // create copy 
    1643                 n = doc.importNode(children.item(i), false); 
    1644                 // attach it to parent 
    1645                 doc.getDocumentElement().appendChild(n); 
    1646                  
    1647                 // Now we need to indicate whether this new node (child) is a leaf 
    1648                 // or not. (This is necessary for getChildrenOfSection(), else  
    1649                 // it's hard to know if the children are leaves or have further  
    1650                 // subsections. 
    1651                 if(n.getNodeName().equals(SECTION_ELEMENT)) { 
    1652                     // we're dealing only with section children 
    1653                      
    1654                     // Check if the matching original had children: 
    1655                     Element originalsChild = (Element)children.item(i); 
    1656                     NodeList grandchildren =  
    1657                         originalsChild.getElementsByTagName(SECTION_ELEMENT); 
    1658                     if(grandchildren.getLength() > 0) { 
    1659                         // original's child has children, so indicate this 
    1660                         // in the copied child: 
    1661                         Element child = (Element)n; 
    1662                         child.setAttribute(TYPE, INTERNAL_NODE); 
    1663                     } 
    1664                 } 
     1573     
     1574     
     1575    /** Return the TOC substructure requested 
     1576     * @return an element containing a copy if element e with either only its child 
     1577     * elements or with all its descendants and/or its ancestors or only its parent  
     1578     * and/or its siblings (depending on what the parameter structure specifies). 
     1579     * @param e - the element to start copying from and whose structure is requested. 
     1580     * @param structure - a string containing any combination of the values: 
     1581     * ancestors, parent, siblings, children, descendants, 
     1582     * specifying the portion of the structure to retrieve. 
     1583     * @see <a href="http://forum.java.sun.com/thread.jspa?threadID=678472&tstart=30">Sun java thread on transforming a DOM XML to a String</a> 
     1584     */ 
     1585    protected Element getSubstructure(Element original, String structure)  
     1586    { 
     1587    Document doc = builder.newDocument(); 
     1588     
     1589    boolean descendants = (structure.indexOf("descendants") != -1) ? true : false; 
     1590    Node current = doc.importNode(original, descendants); 
     1591 
     1592    // descendants=true: import/copy descendants. 
     1593    // Else, copy just current node original (later copy its direct children)    
     1594     
     1595    Node parentOfCurrent = null; 
     1596    Node parentOfOriginal = original.getParentNode(); 
     1597    if(parentOfOriginal == original.getOwnerDocument()) { // don't want document node (original is docRoot) 
     1598        parentOfOriginal = null; 
     1599    } 
     1600     
     1601    if(parentOfOriginal == null) { // no parentNode, so current is the root node. 
     1602        // can't get ancestors/parent/siblings, since all these need parentNode 
     1603        doc.appendChild(current); 
     1604    } else { // siblings, ancestors and parent requests all require parent node to exist 
     1605        // First check if we need to get ancestors, else for whether parent is required 
     1606        if(structure.indexOf("ancestors") != -1) { 
     1607        parentOfCurrent = doc.importNode(parentOfOriginal, false); 
     1608         
     1609        Node child = null; 
     1610        Node parent = parentOfCurrent;      // the copy 
     1611        Node n = parentOfOriginal.getParentNode(); // the doc to copy from 
     1612         
     1613        while(n != null && n != original.getOwnerDocument()) { 
     1614            child = parent; 
     1615            parent = doc.importNode(n, false); // no descendants 
     1616            parent.appendChild(child); 
     1617            n = n.getParentNode(); 
     1618        } 
     1619         
     1620        doc.appendChild(parent); // need to put the copied node into a document 
     1621        // else it won't have a parent doc (DOMSource can't work with it 
     1622        // without it having a document parent). 
     1623         
     1624        } else if(structure.indexOf("parent") != -1) { 
     1625        parentOfCurrent = doc.importNode(parentOfOriginal, false); 
     1626        //parentOfCurrent.appendChild(current); 
     1627        doc.appendChild(parentOfCurrent); 
     1628        } 
     1629         
     1630        // a request for siblings is independently tested for 
     1631        if(structure.indexOf("siblings") != -1) { 
     1632        // only import parent if we didn't already import 
     1633        // it for a request for ancestors or parent 
     1634        if(parentOfCurrent == null) {  
     1635            parentOfCurrent = doc.importNode(parentOfOriginal, false); 
     1636            doc.appendChild(parentOfCurrent);     // this becomes the root 
     1637        } 
     1638        // now the siblings of current (children of parentOfCurrent) 
     1639        NodeList children = parentOfOriginal.getChildNodes();            
     1640        for(int i = 0; i < children.getLength(); i++) { 
     1641            Node n = children.item(i); 
     1642 
     1643            if(n.getNodeName().equals(SECTION_ELEMENT)) {  
     1644            if((Element)n != original) { // skip original which was already imported 
     1645                Node child = doc.importNode(n, false); // no descendants 
     1646                parentOfCurrent.appendChild(child); 
     1647            } else { // already imported Current element, insert at this position                
     1648                parentOfCurrent.appendChild(current); 
     1649            }            
     1650             
     1651            }            
     1652        } 
     1653        } else if(parentOfCurrent != null) { // include current node for ancestors and parent requests 
     1654        // (sibling request adds the current node into a particular position)  
     1655        parentOfCurrent.appendChild(current); 
     1656             // need to put the copied node into a document 
     1657             // else it won't have a parent doc (DOMSource can't work with it 
     1658             // without it having a document parent). 
     1659        } else { // when only children or descendants were requested, current becomes root document 
     1660        doc.appendChild(current); 
     1661        } 
     1662    } 
     1663 
     1664    // if we are not recursively copying all descendants, then copy just  
     1665    // the childnodes of current: 
     1666    if(structure.indexOf("children") != -1 && !descendants) { // then copy just the children 
     1667 
     1668        // get e's children and copy them into the new document 
     1669        NodeList children = original.getChildNodes(); 
     1670        for(int i = 0; i < children.getLength(); i++) { 
     1671        // create copy 
     1672        Node n = doc.importNode(children.item(i), false); 
     1673        // attach it to parent 
     1674        current.appendChild(n); 
     1675         
     1676        // Now we need to indicate whether this new node (child) is a leaf 
     1677        // or not. (This is necessary for getChildrenOfSection(), else  
     1678        // it's hard to know if the children are leaves or have further  
     1679        // subsections. 
     1680        if(n.getNodeName().equals(SECTION_ELEMENT)) { 
     1681            // we're dealing only with section children 
     1682             
     1683            // Check if the matching original had children: 
     1684            Element originalsChild = (Element)children.item(i); 
     1685            NodeList grandchildren = originalsChild.getElementsByTagName(SECTION_ELEMENT); 
     1686            if(grandchildren.getLength() > 0) { 
     1687            // original's child has children, so indicate this 
     1688            // in the copied child: 
     1689            Element child = (Element)current;            
     1690            //  child.setAttribute(TYPE, INTERNAL_NODE); 
     1691             
     1692            } 
     1693        } 
     1694        } 
     1695    } 
     1696 
     1697    return doc.getDocumentElement(); 
     1698    }     
     1699 
     1700 
     1701    /** Return the TOC substructure with the requested structural info. 
     1702     * @return an element containing a copy if element e with either only its child 
     1703     * elements or with all its descendants and/or its ancestors or only its parent  
     1704     * and/or its siblings (depending on what the parameter structure specifies). 
     1705     * Returns null if the element, e, passed in is null. 
     1706     * @param doc - the new document into whose root element the structural information 
     1707     * will be inserted as attributes. 
     1708     * @param e - the element to start copying from and whose structure is requested. 
     1709     * @param info - a string containing any combination of the values: numChildren,  
     1710     * numSiblings, siblingPosition. The requested info gets added as attributes to 
     1711     * the returned root element. 
     1712     * @see <a href="http://forum.java.sun.com/thread.jspa?threadID=678472&tstart=30">Sun java thread on transforming a DOM XML to a String</a> 
     1713     */ 
     1714    protected Element getStructureInfo(Document doc, Element e, String info)  
     1715    { 
     1716    if(e == null) { 
     1717        return null; 
     1718    } 
     1719     
     1720    Element root = doc.getDocumentElement(); 
     1721 
     1722    if(!info.equals("")) {    
     1723        if(info.indexOf("numChildren") != -1) { 
     1724        //int numChildren = e.getElementsByTagName(SECTION_ELEMENT).getLength(); 
     1725        int numChildren = 0; 
     1726         
     1727        NodeList children = e.getChildNodes(); 
     1728        for(int i = 0; i < children.getLength(); i++) { 
     1729            Node n = children.item(i);  
     1730            if(n.getNodeName().equals(SECTION_ELEMENT)) { 
     1731            numChildren++; 
     1732            } 
     1733        } 
     1734         
     1735        root.setAttribute("numChildren", Integer.toString(numChildren)); 
     1736        } 
     1737         
     1738        if(info.indexOf("ibling") != -1) { // siblingPosition or numSiblings 
     1739        int numSiblings = 0; 
     1740        int siblingPosition = 0; 
     1741             
     1742        Node parent = e.getParentNode(); 
     1743        if(parent == null) { 
     1744            numSiblings = 0; 
     1745            siblingPosition = 1; 
     1746        } else { 
     1747            //numSiblings = parent.getChildNodes().getLength(); 
     1748            NodeList siblings = parent.getChildNodes(); 
     1749             
     1750            for(int i = 0; i < siblings.getLength(); i++) { 
     1751            Node n = siblings.item(i);  
     1752            if(n.getNodeName().equals(SECTION_ELEMENT)) { 
     1753                if(e == (Element)n) { 
     1754                siblingPosition = numSiblings+1; 
     1755                } else { // count every sibling section element, except e itself 
     1756                numSiblings++; 
     1757                }                
    16651758            } 
    1666         } 
    1667         return doc.getDocumentElement(); 
    1668     } 
    1669      
    1670      
     1759            } 
     1760        }        
     1761         
     1762        if(info.indexOf("numSiblings") != -1) { 
     1763            root.setAttribute("numSiblings", Integer.toString(numSiblings)); 
     1764        } 
     1765         
     1766        if(info.indexOf("siblingPosition") != -1) { 
     1767            root.setAttribute("siblingPosition", Integer.toString(siblingPosition)); 
     1768        } 
     1769        } 
     1770    } 
     1771     
     1772    return root; 
     1773    } 
     1774 
     1775 
    16711776    /**  
    16721777     * Return a datastream of a document, given the document's id 
     
    17901895            String sectionID = "SECTION1"; //SECTION1.5 
    17911896            System.out.println("\n"); 
    1792             System.out.println(sectionID+ " - entire subsection:\n"  
    1793                     + fedoraCon.getSubsection(docPID, sectionID)); 
    1794              
    1795             System.out.println(sectionID + " and children:\n"  
    1796                     + fedoraCon.getChildrenOfSection(docPID, sectionID)); 
    17971897                     
    17981898            System.out.println( 
     
    18161916            System.out.println("Unable to instantiate FedoraConnection\n" + e); 
    18171917            e.printStackTrace(); 
    1818             //LOG.error("Unable to instantiate FedoraConnection\n" + e); 
     1918            //LOG.error("Unable to instantiate FedoraConnection\n" + e, e); 
    18191919        } 
    18201920    } 
  • other-projects/gs3-webservices-java-client/trunk/src/GS3Fedora/org/greenstone/fedora/services/FedoraGS3Connection.java

    r21924 r22300  
    9090     * then query services will not be offered */ 
    9191    protected String[] serviceNames; 
    92          
    93     /** constant CHILDREN indicates that a DocumentStructureRetrieve is to 
    94      * return only the child nodes of a section, not any further descendants */ 
    95     protected static final int CHILDREN = 0; 
    96      
    97     /** constant DESCENDANTS indicates that a DocumentStructureRetrieve is to 
    98      * return all descendants of a section */ 
    99     protected static final int DESCENDANTS = 1; 
    10092     
    10193    /** The object used to connect to FedoraGenericSearch, which is used  
     
    362354     * @return a GS3 DocumentMetadataRetrieve response message containing the 
    363355     * EX metadata for all the requested collections */ 
    364     public String getCollectionMetadata(String[] collIDs) { 
    365         return getMetadata(collIDs); 
     356    public String getCollectionMetadata(String[] collIDs) { 
     357    return getMetadata(collIDs, new String[] {"all"}); 
    366358    } 
    367359     
     
    372364     * "&lt;pid&gt;-sectionNumber".  
    373365     * @return a GS3 DocumentMetadataRetrieve response message containing the 
    374      * EX, DC, DLS metadata for all the requested documents */ 
    375     public String getDocumentMetadata(String[] docIDs) { 
    376         return getMetadata(docIDs); 
     366     * EX, DC, DLS metadata for all the requested documents  
     367     * @param metadata is the list of metadata elements to be retrieved for each doc */ 
     368    public String getDocumentMetadata(String[] docIDs, String[] metadata) { 
     369        return getMetadata(docIDs, metadata); 
    377370    } 
    378371     
     
    381374     * @param collID is a fedora pid identifying a collection in its repository 
    382375     * @return a GS3 DocumentMetadataRetrieve response message containing the 
    383      * EX metadata for the requested collection */ 
     376     * EX metadata for the requested collection 
     377     * @param metadata is the list of metadata elements to be retrieved for each doc */ 
    384378    public String getCollectionMetadata(String collID) { 
    385         return getMetadata(new String[] {collID}); 
     379        return getMetadata(new String[] {collID}, new String[] {"all"}); 
    386380    } 
    387381     
     
    393387     * @return a GS3 DocumentMetadataRetrieve response message containing the 
    394388     * EX, DC, DLS metadata for the requested document */ 
    395     public String getDocumentMetadata(String docID) { 
    396         return getMetadata(new String[] {docID}); 
     389    public String getDocumentMetadata(String docID, String[] metadata)  { 
     390    return getMetadata(new String[] {docID}, metadata); 
    397391    } 
    398392 
     
    402396     * fedora pids for collections, or otherwise may be a document identifier. 
    403397     * In the last case, the document ID may consist of either 
    404      * "documentPID-sectionNumber" or may just be just fedora documentPID */ 
    405     public String getMetadata(String[] docIDsOrCollIDs) 
     398     * "documentPID-sectionNumber" or may just be just fedora documentPID  
     399     * @param metadata is the list of metadata elements to be retrieved for each doc */ 
     400    public String getMetadata(String[] docIDsOrCollIDs, String[] metadata) 
    406401    { 
    407402        Document doc = builder.newDocument(); 
     
    415410                // create the <documentNode> containing the metadata  
    416411                // for each document docID 
    417                 Element docNode = getMetadata(doc, docIDsOrCollIDs[i]);  
     412                Element docNode = getMetadata(doc, docIDsOrCollIDs[i], metadata);  
    418413                docNodeList.appendChild(docNode); 
    419414            } 
     
    426421                GSXML.REQUEST_TYPE_PROCESS, "DocumentMetadataRetrieve"); 
    427422        try{ 
    428             return FedoraCommons.elementToFormattedString(responseMsg); 
     423            return FedoraCommons.elementToString(responseMsg); 
    429424        } catch(TransformerException e) { 
    430425            return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg 
     
    444439     * document given by parameter ID 
    445440     * @param id denotes a collection pid, a document pid or a docID of the   
    446      * form "documentpid-sectionNumber" */ 
    447     protected Element getMetadata(Document doc, String id)  
     441     * form "documentpid-sectionNumber" 
     442     * @param metadata is the list of metadata elements to be retrieved for each doc */ 
     443    protected Element getMetadata(Document doc, String id, String[] metadata)  
    448444        throws RemoteException, UnsupportedEncodingException,  
    449445            SAXException, IOException  
     
    500496        } 
    501497         
     498        String metafields = ""; 
     499        for(int i = 0; i < metadata.length; i++) { 
     500            metafields = metafields + metadata[i] + "|";             
     501        } 
     502 
    502503        // Adding in metadata sets in alphabetical order 
    503504        // DC metadata for a top-level document is different from EX, DLS:  
     
    506507        if(!dc.equals("")) { 
    507508            addMetadataWithNamespacedTagNames(doc, metadataList, 
    508                     dc, DC); 
     509                              dc, DC, metafields); 
    509510        } 
    510511         
     
    513514        // in which case, dls and dc will be non-empty strings 
    514515        if(!dls.equals("")) { 
    515             addMetadataWithFixedTagName(doc, metadataList, dls, DLS); 
     516            addMetadataWithFixedTagName(doc, metadataList, dls, DLS, metafields); 
    516517        } 
    517518         
     
    519520        // collection object, top-level document object,  
    520521        // and document section item  
    521         addMetadataWithFixedTagName(doc, metadataList, ex, EX); 
     522        addMetadataWithFixedTagName(doc, metadataList, ex, EX, metafields); 
    522523         
    523524        // now the metadataList has been built up 
     
    539540     * Dublin Core metadata stored in the Fedora repository). 
    540541     * @param metadataSet is the constant datastream identifier, e.g. "DC". 
    541      * At present this method only applies to the DC metadata as that's the only  
    542      * one where each tagname is different except for the constant dc: namespace. 
     542     * At present this method applies to the DC metadata and any others like it 
     543     * where each tagname is different except for the constant dc: namespace. 
     544     * @param metafields is a | separated string containing the metadatafields to 
     545     * extract or "all" if all fields are requested 
    543546    */ 
    544     protected void addMetadataWithNamespacedTagNames(Document doc,  
    545             Element metadataList, String metaDatastream, String metadataSet) 
     547    protected void addMetadataWithNamespacedTagNames(Document doc, Element metadataList,  
     548                             String metaDatastream, String metadataSet, String metafields) 
    546549        throws SAXException, IOException 
    547550    { 
     
    551554        // The following doesn't work for some reason: to retrieve all elements  
    552555        // whose namespace prefix starts with "dc", we pass "*" for localName 
    553         //NodeList dcMetaTags = src.getElementsByTagNameNS(DC.toLowerCase(), "*"); 
     556        //NodeList dcMetaTags = src.getElementsByTagNameNS(metadataSet.toLowerCase(), "*"); 
    554557         
    555558        // Longer way: get the children of the root document 
     
    558561        for(int i = 0; i < children.getLength(); i++) { 
    559562            String nodeName = children.item(i).getNodeName(); 
    560             // check that the nodename starts with the "dc" namespace, 
     563            // check that the nodename starts with the metadataSet ("dc") namespace, 
    561564            // which simultaneously ensures that the node's an element: 
    562             if(nodeName.startsWith(DC.toLowerCase())) { 
    563                 // need to have a period for Greenstone instead of Fedora's colon 
    564                 nodeName = nodeName.replace(COLON, PERIOD); 
     565            if(nodeName.toLowerCase().startsWith(metadataSet.toLowerCase())) { 
     566                // need to have a period for Greenstone instead of Fedora's colon 
     567                nodeName = nodeName.replace(COLON, PERIOD); 
     568                if(metadataSet.equals(DC)) { // dc:title -> dc.Title 
     569                nodeName = "dc" + PERIOD + Character.toString(Character.toUpperCase(nodeName.charAt(3))) 
     570                    + nodeName.substring(4); 
     571                } 
     572 
     573                // get the requested metadata fields 
     574                if(metafields.indexOf("all") != -1 || metafields.indexOf(nodeName) != -1) { 
    565575                Element metatag = (Element)children.item(i); 
    566576                String value = FedoraCommons.getValue(metatag); 
    567577                // <dc:tagname>value</dc:tagname> 
    568                 // we're going to put use this in our metadata element as  
    569                 // <metadata name="dc:tagname">value</metadata> 
     578                // we're going to put this in our metadata element as  
     579                // <metadata name="dc.Tagname">value</metadata> 
    570580                 
    571581                // create metadata of (name, value) pairs in target DOM (doc) 
    572582                Element metadata = doc.createElement(GSXML.METADATA_ELEM); 
    573583                Attr attribute = doc.createAttribute(GSXML.NAME_ATT); 
     584                 
    574585                attribute.setValue(nodeName); 
    575586                metadata.setAttributeNode(attribute); 
     
    577588                metadata.appendChild(content); 
    578589                metadataList.appendChild(metadata); 
     590                } 
    579591            } 
    580592        }        
     
    586598     * is the name of the metadata (like author, title). For each element 
    587599     * it creates a corresponding new element of the form  
    588      * &lt;metadata name="namespace:metadataName"&gt;value&lt;/metadata&gt;. Each of these  
    589      * are then appended to the metadataList parameter. 
     600     * &lt;metadata name="namespace:metadataName"&gt;value&lt;/metadata&gt;.  
     601     * Each of these are then appended to the metadataList parameter. 
    590602     * @param doc is the Document object using which the new metadata Elements 
    591603     * are to be constructed 
     
    599611     * At present this method applies to the DLS and EX metadata as they have 
    600612     * constant tagnames throughout. 
     613     * @param metafields is a | separated string containing the metadatafields to 
     614     * extract or "all" if all fields are requested. 
    601615    */ 
    602     protected void addMetadataWithFixedTagName(Document doc,  
    603             Element metadataList, String metaDatastream, String metadataSet)  
     616    protected void addMetadataWithFixedTagName(Document doc, Element metadataList,  
     617                           String metaDatastream, String metadataSet, String metafields)  
    604618        throws SAXException, IOException 
    605619    { 
     
    630644                name = name + HYPHEN + metatag.getAttribute(QUALIFIER); 
    631645            } 
    632             String value = FedoraCommons.getValue(metatag); 
    633              
    634             // create metadata of (name, value) pairs in target DOM (doc) 
    635             Element metadata = doc.createElement(GSXML.METADATA_ELEM); 
    636             Attr attribute = doc.createAttribute(GSXML.NAME_ATT); 
    637             attribute.setValue(namespacePrefix + name);   
    638                                     // prefix with namespace, if any 
    639             metadata.setAttributeNode(attribute); 
    640             Text content = doc.createTextNode(value); 
    641             metadata.appendChild(content); 
    642              
    643             metadataList.appendChild(metadata); 
     646            name = namespacePrefix + name; // prefix with namespace, if any 
     647            if(metafields.indexOf("all") != -1 || metafields.indexOf(name) != -1) { 
     648                String value = FedoraCommons.getValue(metatag); 
     649                 
     650                // create metadata of (name, value) pairs in target DOM (doc) 
     651                Element metadata = doc.createElement(GSXML.METADATA_ELEM); 
     652                Attr attribute = doc.createAttribute(GSXML.NAME_ATT); 
     653                attribute.setValue(name);  
     654                metadata.setAttributeNode(attribute); 
     655                Text content = doc.createTextNode(value); 
     656                metadata.appendChild(content); 
     657                 
     658                metadataList.appendChild(metadata); 
     659            } 
    644660        } 
    645661    } 
     
    688704                GSXML.REQUEST_TYPE_PROCESS, "DocumentMetadataRetrieve"); 
    689705        try{ 
    690             return FedoraCommons.elementToFormattedString(responseMsg); 
     706            return FedoraCommons.elementToString(responseMsg); 
    691707        } catch(TransformerException e) { 
    692708            return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg 
     
    747763    }  
    748764     
    749          
    750     /** @return the documentStructure of the document or section given by docID.  
    751      * The structure is returned in the XML format of a Greenstone3  
    752      * DocumentStructureRetrieve response message. This method returns the entire 
    753      * subSection of the docID (that is, all descendants included). 
    754      * @param docID the identifier for the document whose structure is required. 
    755      * This is of the format "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;" 
    756      * OR "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;-&lt;sectioNumber&gt;"   
    757      * where "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;-1" is the same as  
    758      * "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;" and will return the  
    759      * same response */ 
    760     public String getDocumentStructure(String docID) { 
    761         return getStructure(new String[]{docID}, DESCENDANTS); 
    762     } 
    763      
    764     /** @return a view of the structure of the document or section given by docID 
    765      * which contains only the section and its direct children. This structure is  
    766      * returned in the XML format of a Greenstone3 DocumentStructureRetrieve  
    767      * response message.  
    768      * @param docID the identifier for the document whose structure is required. 
    769      * This is of the format "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;" 
    770      * OR "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;-&lt;sectioNumber&gt;"   
    771      * where "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;-1" is the same as  
    772      * "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;" and will return the  
    773      * same response */ 
    774     public String getChildren(String docID) { 
    775         return getStructure(new String[]{docID}, CHILDREN); 
    776     } 
    777      
    778     /** @return the documentStructure of the documents or sections given by docIDs.  
    779      * The structure is returned in the XML format of a Greenstone3  
    780      * DocumentStructureRetrieve response message. This method returns the entire 
    781      * subSection of each docID (that is, all descendants included). 
    782      * @param docIDs is an array of identifiers for the documents whose structures 
    783      * are required. 
    784      * This is of the format "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;" 
    785      * OR "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;-&lt;sectioNumber&gt;"   
    786      * where "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;-1" is the same as  
    787      * "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;" and will return the  
    788      * same response */ 
    789     public String getDocumentStructure(String[] docIDs) { 
    790         return getStructure(docIDs, DESCENDANTS); 
    791     } 
    792      
    793     /** @return the documentStructure of the documents or sections given by docIDs 
    794      * but only the sections and their children (not any further descendants).  
    795      * The structure is returned in the XML format of a Greenstone3  
    796      * DocumentStructureRetrieve response message. 
    797      * @param docIDs the identifiers for the documents whose structures are  
    798      * required. The docids are of the format "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;" 
    799      * OR "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;-&lt;sectioNumber&gt;"   
    800      * where "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;-1" is the same as  
    801      * "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;" and will return the  
    802      * same response */ 
    803     public String getChildren(String[] docIDs) { 
    804         return getStructure(docIDs, CHILDREN); 
    805     } 
    806      
    807     /**  
     765    /** @return a String representing Greenstone3 DocumentMetadataRetrieve XML 
     766     * containing the requested portion of the document structure of the documents  
     767     * indicated by docIDs:  
     768     * @param docID is the document identifier of the document whose hierarchical 
     769     * structure is requested. The name of the collection is already included in the 
     770     * docID for a Fedora DL. 
     771     * @param structure - strings specifying the required structure of the document.  
     772     * It can be a combination of: ancestors, parent, siblings, children, descendants, entire. 
     773     * @param info - strings specifying the required structural info of the document.  
     774     * It can be any combination of: siblingPosition, numSiblings, numChildren. 
     775    */ 
     776    public String getDocumentStructure(String docID, String[] structure, String[] info) { 
     777    return getStructure(new String[]{docID}, structure, info); 
     778    } 
     779     
     780 
     781     /** @return a String representing Greenstone3 DocumentMetadataRetrieve XML 
     782     * containing the requested portion of the document structure of the documents  
     783     * indicated by docIDs:  
     784     * @param docIDs is an array of document identifiers of documents whose 
     785     * hierarchical structures are requested. The name of the collection is already 
     786     * included in the docID for a Fedora DL. 
     787     * @param structure - strings specifying the required structure of each document.  
     788     * It can be a combination of: ancestors, parent, siblings, children, descendants, entire. 
     789     * @param info - strings specifying the required structural info of each document.  
     790     * It can be any combination of: siblingPosition, numSiblings, numChildren. 
     791    */ 
     792    public String getDocumentStructure(String[] docIDs, String[] structure, String[] info) { 
     793    return getStructure(docIDs, structure, info); 
     794    } 
     795 
     796        /**  
    808797     * Returns a greenstone3 DocumentStructureRetrieve XML response message  
    809798     * containing the document structures for the given docIDs. 
     
    814803     * @param docIDs the documentIDs for which the section's structure is returned;  
    815804     * where a docID is either a fedora pid &lt;docPID&gt; or &lt;docPID&gt;-&lt;sectionNumber&gt;. 
    816      * @param levels - either CHILDREN or DESCENDANTS.  
    817      * CHILDREN returns only the first-level descendants (children) of the  
    818      * requested document sections indicated by docIDs. 
    819      * DESCENDANTS returns all descendants of all the document-sections denoted by  
    820      * docIDs. 
     805     * @param structure - the structure of the sections to return. Can be any combination of: 
     806     * ancestors, parent, siblings, children, descendants, entire. 
     807     * @param infos - strings containing any combination of the values: numChildren, numSiblings,  
     808     * siblingPosition. The requested info gets added as attributes to the returned root element. 
    821809     * @return a greenstone3 DocumentStructureRetrieve XML response message in 
    822810     * String format with the structure of the docIDs requested. 
    823811    */ 
    824     protected String getStructure(String[] docIDs, int levels)  
     812    protected String getStructure(String[] docIDs, String[] structure, String[] infos)  
    825813    { 
    826814        Document doc = builder.newDocument(); 
     
    833821            // append the <documentNodes> for the docIDs 
    834822            // to the docNodeList 
    835             getStructureElement(docNodeList, docIDs, levels);  
     823            //getStructureElement(docNodeList, docIDs, levels); 
     824            getStructureElement(docNodeList, docIDs, structure, infos); 
    836825        } catch(Exception e) {  
    837826            ex = new FedoraGS3RunException(e); 
     
    842831                GSXML.REQUEST_TYPE_PROCESS, "DocumentStructureRetrieve"); 
    843832        try{ 
    844             return FedoraCommons.elementToFormattedString(responseMsg); 
     833            return FedoraCommons.elementToString(responseMsg); 
    845834        } catch(TransformerException e) { 
    846835            return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg 
     
    848837        } 
    849838    } 
    850      
    851     /** Given a &lt;documentNodeList&gt; portion of a greenstone3  
     839 
     840 
     841    /** Given a &lt;documentNodeList&gt; portion of a greenstone3  
    852842     * DocumentStructureRetrieve XML response message, this method will populate  
    853843     * it with the &lt;documentNodes&gt; that represent the structure of the given docIDs. 
     
    856846     * @param docIDs the documentIDs for which the section's structure is returned;  
    857847     * where a docID is either a fedora pid &lt;docPID&gt; or &lt;docPID&gt;-&lt;sectionNumber&gt;. 
    858      * @param levels - either CHILDREN or DESCENDANTS.  
    859      * CHILDREN returns only the first-level descendants (children) of the  
    860      * requested document sections indicated by docIDs. 
    861      * DESCENDANTS returns all descendants of all the document-sections denoted by  
    862      * docIDs. 
     848     * @param structures - the structure of the sections to return. Can be any combination of: 
     849     * ancestors, parent, siblings, children, descendants, entire. 
     850     * @param infos - a string containing any combination of the values: numChildren, numSiblings,  
     851     * siblingPosition. The requested info gets added as attributes to the returned root element. 
    863852    */ 
    864     protected void getStructureElement(Element docNodeList,  
    865             String[] docIDs, int levels)  
     853    protected void getStructureElement(Element docNodeList, String[] docIDs, 
     854                       String[] structures, String[] infos) 
    866855        throws RemoteException, UnsupportedEncodingException, SAXException,  
    867856            IOException  
    868857    { 
    869         // process each docID 
    870         for(int i = 0; i < docIDs.length; i++) { 
    871             // work out the document's fedora PID and section ID 
    872             String sectionID = getSectionIDFromDocID(docIDs[i]); 
    873             String docPID = getDocPIDFromDocID(docIDs[i]); 
    874              
    875             // get the required section, along with children or descendants 
    876             Element srcDocElement = null; 
    877             if(levels == CHILDREN) // get the requested section with its children  
    878                 srcDocElement = this.getChildrenOfSectionXML(docPID, sectionID); 
    879             else // levels == DESCENDANTS, get the section with all its descendants 
    880                 srcDocElement = this.getSubsectionXML(docPID, sectionID); 
    881              
    882             // copy-and-convert that structure into a structure format for GS3 
    883             Element docNode = getStructure(docNodeList.getOwnerDocument(),  
    884                     docIDs[i], docPID, srcDocElement); 
    885              
    886             // add it to our list of documentNodes 
    887             docNodeList.appendChild(docNode); 
    888         } 
    889     } 
     858        // Make one string out of requested structure components, and one string from info components 
     859        String structure = ""; 
     860        String info = ""; 
     861        for(int i = 0; i < structures.length; i++) { 
     862        structure = structure + structures[i] + "|"; 
     863        } 
     864        for(int i = 0; i < infos.length; i++) { 
     865        info = info + infos[i] + "|"; 
     866        } 
     867         
     868        // process each docID 
     869        for(int i = 0; i < docIDs.length; i++) { 
     870        // work out the document's fedora PID and section ID 
     871        String sectionID = getSectionIDFromDocID(docIDs[i]); 
     872        String docPID = getDocPIDFromDocID(docIDs[i]); 
     873        if(sectionID.equals("")) { 
     874            sectionID = "1"; 
     875        } 
     876 
     877        // get the required section, along with children or descendants 
     878        Element srcDocElement = getSectionStructureXML(docPID, sectionID, structure, info); 
     879        Document doc = docNodeList.getOwnerDocument(); 
     880         
     881        // copy-and-convert that structure into a structure format for GS3 
     882        Element docNode = getStructure(doc, docIDs[i], docPID, srcDocElement); 
     883         
     884        if(!info.equals("")) { 
     885            // <nodeStructureInfo> 
     886            //    <info name="" value="" /> 
     887            //    <info name="" value="" /> 
     888            //    ... 
     889            // </nodeStructureInfo> 
     890            Element nodeStructureInfo = doc.createElement(GSXML.NODE_STRUCTURE_ELEM+GSXML.INFO_ATT); 
     891            Element root = srcDocElement.getOwnerDocument().getDocumentElement(); 
     892             
     893            if(root.hasAttribute("numSiblings")) { 
     894            String numSiblings = root.getAttribute("numSiblings"); 
     895            Element infoEl = doc.createElement(GSXML.INFO_ATT); 
     896            infoEl.setAttribute(GSXML.NAME_ATT, "numSiblings"); 
     897            infoEl.setAttribute(GSXML.VALUE_ATT, numSiblings); 
     898            nodeStructureInfo.appendChild(infoEl); 
     899            } 
     900             
     901            if(root.hasAttribute("siblingPosition")) { 
     902            String siblingPosition = root.getAttribute("siblingPosition"); 
     903            Element infoEl = doc.createElement(GSXML.INFO_ATT); 
     904            infoEl.setAttribute(GSXML.NAME_ATT, "siblingPosition"); 
     905            infoEl.setAttribute(GSXML.VALUE_ATT, siblingPosition); 
     906            nodeStructureInfo.appendChild(infoEl); 
     907            } 
     908             
     909            if(root.hasAttribute("numChildren")) { 
     910            String numChildren = root.getAttribute("numChildren"); 
     911            Element infoEl = doc.createElement(GSXML.INFO_ATT);      
     912            infoEl.setAttribute(GSXML.NAME_ATT, "numChildren"); 
     913            infoEl.setAttribute(GSXML.VALUE_ATT, numChildren); 
     914            nodeStructureInfo.appendChild(infoEl); 
     915            } 
     916            docNode.appendChild(nodeStructureInfo); 
     917        } 
     918         
     919        // add it to our list of documentNodes 
     920        docNodeList.appendChild(docNode); 
     921        } 
     922    } 
     923 
    890924         
    891925    /**  
     
    916950        Attr attribute = doc.createAttribute(GSXML.NODE_ID_ATT); 
    917951        attribute.setValue(requestingDocID); //requestingDocID.replace(HYPHEN+SECTION, "") 
    918         docNode.setAttributeNode(attribute); 
     952        docNode.setAttributeNode(attribute);         
    919953         
    920954        // <nodeStructure> 
     
    932966        return docNode;      
    933967    } 
    934      
     968 
     969 
    935970    /** Recursive method that creates a documentStructure mirroring parameter 
    936971     * section, starting from parameter parent down to all descendants 
     
    9831018        String sectionID = subSection.hasAttribute(ID) ? 
    9841019                subSection.getAttribute(ID) : ""; 
    985         nodeID.setValue(docID + HYPHEN + sectionID); 
     1020        if(sectionID.equals("1")  
     1021           && subSection.getElementsByTagName(SECTION_ELEMENT).getLength() > 0) { // root, non-leaf case 
     1022            // reset the attribute without the section number 
     1023            nodeID.setValue(docID+ HYPHEN + sectionID); // maybe important for democlient? 
     1024        } else { 
     1025            nodeID.setValue(docID + HYPHEN + sectionID); 
     1026        } 
     1027        //nodeID.setValue(docID + HYPHEN + sectionID); 
    9861028        docNode.setAttributeNode(nodeID); 
    9871029         
    9881030        Attr nodeType = doc.createAttribute(GSXML.NODE_TYPE_ATT); 
    989         if(sectionID.equals("1")) { // root case 
    990             nodeType.setValue(GSXML.NODE_TYPE_ROOT); 
    991             // reset the attribute without the section number 
    992             docNode.setAttribute(GSXML.NODE_ID_ATT, docID); 
    993         } 
    994         else if(subSection.getElementsByTagName(SECTION_ELEMENT).getLength() > 0) 
    995             // this section has further <Section> children, so it's an internal node  
    996             nodeType.setValue(GSXML.NODE_TYPE_INTERNAL); 
    997         else if(subSection.hasAttribute(TYPE))  
    998             nodeType.setValue(GSXML.NODE_TYPE_INTERNAL); 
    999         else // leaf 
    1000             nodeType.setValue(GSXML.NODE_TYPE_LEAF); 
     1031        if(subSection.hasAttribute(GSXML.NODE_TYPE_ATT)) { 
     1032            nodeType.setValue(subSection.getAttribute(GSXML.NODE_TYPE_ATT)); 
     1033        }  
    10011034        docNode.setAttributeNode(nodeType); 
    10021035        return docNode; 
     
    10681101                GSXML.REQUEST_TYPE_PROCESS, "DocumentContentRetrieve"); 
    10691102        try{ 
    1070             return FedoraCommons.elementToFormattedString(responseMsg); 
     1103            return FedoraCommons.elementToString(responseMsg); 
    10711104        } catch(TransformerException e) { 
    10721105            return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg 
     
    12021235                GSXML.REQUEST_TYPE_DESCRIBE, ""); 
    12031236        try { 
    1204             return FedoraCommons.elementToFormattedString(responseMsg); 
     1237            return FedoraCommons.elementToString(responseMsg); 
    12051238        }catch(TransformerException e) { 
    12061239            return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg 
     
    12471280                GSXML.REQUEST_TYPE_DESCRIBE, ""); 
    12481281        try{ 
    1249             return FedoraCommons.elementToFormattedString(responseMsg); 
     1282            return FedoraCommons.elementToString(responseMsg); 
    12501283        }catch(TransformerException e) { 
    12511284            return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg 
     
    13051338                GSXML.REQUEST_TYPE_DESCRIBE, collectionName); 
    13061339        try{ 
    1307             return FedoraCommons.elementToFormattedString(responseMsg); 
     1340            return FedoraCommons.elementToString(responseMsg); 
    13081341        }catch(TransformerException e) { 
    13091342            return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg 
     
    13371370                GSXML.REQUEST_TYPE_DESCRIBE, collectionName); 
    13381371        try{ 
    1339             return FedoraCommons.elementToFormattedString(responseMsg); 
     1372            return FedoraCommons.elementToString(responseMsg); 
    13401373        }catch(TransformerException e) { 
    13411374            return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg 
     
    14201453                GSXML.REQUEST_TYPE_DESCRIBE, from); 
    14211454        try{  
    1422             return FedoraCommons.elementToFormattedString(responseMsg); 
     1455            return FedoraCommons.elementToString(responseMsg); 
    14231456        }catch(TransformerException e) { 
    14241457            return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg 
     
    16941727     * user to browse the titles of documents in the given collection by letter 
    16951728     * and returning the results. 
     1729     * @param collectionName is the name of the collection whose documents  
     1730     * starting with the given letter will be returned. 
    16961731     * @param classifierIDs are the ids of the classifiers on which to browse. In 
    16971732     * this case, the classifier indicates whether we browse titles by letter, or 
    16981733     * browse (documents) by collection; and it is of the form &lt;CL(letter)&gt;. 
    1699      * @param collectionName is the name of the collection whose documents  
    1700      * starting with the given letter will be returned. 
    1701      * @return a GS3 DocumentStructureRetrieve response message which lists all  
     1734     * @param structures - the requested browse substructure. Can be any combination 
     1735     * of ancestors, parent, siblings, children, descendants. 
     1736     * @param infos - the requested structural info. Can be numSiblings,  
     1737     * siblingPosition, numChildren. 
     1738     * @return a GS3 ClassifierBrowse response message which lists all  
    17021739     * the documents that start with the letter indicated by parameter classifier. 
    17031740    */ 
    1704     public String browse(String collectionName, String[] classifierIDs) 
     1741    public String browse(String collectionName, String[] classifierIDs,  
     1742                 String[] structures, String[] infos) 
    17051743    { 
    1706         Document doc = builder.newDocument(); 
    1707         FedoraGS3RunException ex = null; //any RemoteException or UnsupportedEncodingException 
    1708          
    1709         // <classifierNodeList> 
    1710         Element classifierNodeList = doc.createElement( 
    1711                 GSXML.CLASS_NODE_ELEM+GSXML.LIST_MODIFIER); 
    1712          
    1713     for(int i = 0; i < classifierIDs.length; i++) { 
    1714         // <classifierNode nodeID="classifierNum"> 
    1715         Element requestedClassifierNode = doc.createElement( 
    1716                 GSXML.CLASS_NODE_ELEM); 
     1744        // Construct one string from the structures and structural info arrays 
     1745        String structure = ""; 
     1746        String info = ""; 
     1747        for(int i = 0; i < structures.length; i++) { 
     1748        structure = structure + structures[i] + "|"; 
     1749        } 
     1750        for(int i = 0; i < infos.length; i++) { 
     1751        info = info + infos[i] + "|"; 
     1752        } 
     1753         
     1754        Document doc = builder.newDocument(); 
     1755        FedoraGS3RunException ex = null; //any RemoteException or UnsupportedEncodingException 
     1756         
     1757        // <classifierNodeList> 
     1758        Element classifierNodeList = doc.createElement(GSXML.CLASS_NODE_ELEM+GSXML.LIST_MODIFIER); 
     1759         
     1760        for(int i = 0; i < classifierIDs.length; i++) { 
     1761        if(classifierIDs[i].startsWith("CL1")) { // browse by titles 
     1762            browseTitlesByLetterClassifier(doc, classifierNodeList, 
     1763                           collectionName, classifierIDs[i], 
     1764                           structure, info);             
     1765        } 
     1766        } 
     1767 
     1768        Element responseMsg = createResponseMessage(doc, classifierNodeList, ex, 
     1769                    GSXML.REQUEST_TYPE_DESCRIBE, /*collectionName+/ */"ClassifierBrowse"); 
     1770        try { 
     1771        return FedoraCommons.elementToString(responseMsg); 
     1772        } catch(TransformerException e) { 
     1773        return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg 
     1774            + " " + e; 
     1775        } 
     1776    } 
     1777 
     1778    /** CL1 browsing classifier: browsing titles by starting letter.  
     1779     * The browsing structure is retrieved. 
     1780     * @param doc - the document object that will contain the CL1 browsing structure. 
     1781     * @param classifierNodeList - the classifiers will be added to this nodeList. 
     1782     * @param collectionName - name of the collection through which we are browsing CL1. 
     1783     * @param classifierID - the ID of the (sub)classifier. Can be CL1, CL1.x, where x is 
     1784     * a letter. 
     1785     * @param structure - the requested browse substructure. Can be any combination 
     1786     * of ancestors, parent, siblings, children, descendants. siblings not yet implemented. 
     1787     * @param info - the requested structural info. Can be numSiblings, siblingPosition, 
     1788     * numChildren. 
     1789     * @return the classifierNodeList with the CL1 classifier browse structure. 
     1790     */ 
     1791    public Element browseTitlesByLetterClassifier(Document doc, Element classifierNodeList,  
     1792                         String collectionName, String classifierID,  
     1793                         String structure, String info) 
     1794    { 
     1795    FedoraGS3RunException ex = null; //any RemoteException or UnsupportedEncodingException 
     1796 
     1797    // TODO 
     1798    if(structure.indexOf("siblings") != -1) { 
     1799        LOG.error("Structure: siblings. Not yet implemented\n"); 
     1800    } 
     1801 
     1802    if(structure.indexOf("entire") != -1) { 
     1803        structure = structure + "ancestors|descendants"; 
     1804    }  
     1805     
     1806    // Structure of ancestors and children only at this stage 
     1807    int firstLevel = classifierID.indexOf('.'); 
     1808    int secondLevel = classifierID.lastIndexOf('.'); 
     1809     
     1810    // <nodeStructure> 
     1811    Element nodeStructure = doc.createElement(GSXML.NODE_STRUCTURE_ELEM); 
     1812 
     1813    // requested classifier node 
     1814    Element classNode = doc.createElement(GSXML.CLASS_NODE_ELEM); 
     1815    Attr attribute = doc.createAttribute(GSXML.NODE_ID_ATT); 
     1816    attribute.setValue(classifierID); 
     1817    classNode.setAttributeNode(attribute); 
     1818 
     1819    if(firstLevel == -1) { // CL1 - toplevel node       
     1820        Element root = (Element)classNode.cloneNode(true); // clone the node before appending children 
     1821 
     1822        classifierNodeList.appendChild(classNode); 
     1823        classNode.appendChild(nodeStructure); 
     1824         
     1825        nodeStructure.appendChild(root); 
     1826        if(structure.indexOf("descendants") != -1) { 
     1827        getTitlesByLetterStructure(collectionName, root, classifierID, true); 
     1828        } else if(structure.indexOf("children") != -1) { 
     1829        getTitlesByLetterStructure(collectionName, root, classifierID, false); 
     1830        } 
     1831    }  
     1832    else if(firstLevel == secondLevel) { // CL1.x, where x is a number 
     1833         
     1834        if(structure.indexOf("parent") != -1 || structure.indexOf("ancestors") != -1) { 
     1835        String toplevelID = classifierID.substring(0, firstLevel); 
     1836        Element toplevelNode = doc.createElement(GSXML.CLASS_NODE_ELEM); 
     1837        attribute = doc.createAttribute(GSXML.NODE_ID_ATT); 
     1838        attribute.setValue(toplevelID); 
     1839        toplevelNode.setAttributeNode(attribute); 
     1840        Element node = (Element)toplevelNode.cloneNode(true); // clone nodes before appending children 
     1841 
     1842        classifierNodeList.appendChild(toplevelNode); 
     1843        toplevelNode.appendChild(nodeStructure);         
     1844            
     1845        nodeStructure.appendChild(node); 
     1846        node.appendChild(classNode); 
     1847        } else { 
     1848        Element node = (Element)classNode.cloneNode(true); 
     1849        classifierNodeList.appendChild(node); 
     1850        node.appendChild(nodeStructure); 
     1851        nodeStructure.appendChild(classNode); 
     1852        } 
     1853         
     1854        int num = Integer.parseInt(classifierID.substring(firstLevel+1)); // get x from CL1.x 
     1855        char ch = (char)(num - 1 + 'A'); 
     1856        if(structure.indexOf("descendants") != -1) { 
     1857        getTitlesForLetter(ch, collectionName, classNode, "descendants"); 
     1858        } else if(structure.indexOf("children") != -1) { 
     1859        getTitlesForLetter(ch, collectionName, classNode, "children"); 
     1860        } 
     1861    } 
     1862    else { // ought to be a doc structure retrieve request, not classifierbrowse structure retrieve 
     1863        LOG.error("ClassifierID: " + classifierID + ". Shouldn't be in browse method"); 
     1864    } 
     1865 
     1866    return classifierNodeList; 
     1867    } 
     1868 
     1869    /** Creates a (CL1) subclassifier element for the docs whose titles start with  
     1870     * the given letter. 
     1871     * @param ch - the starting letter of the document titles to retrieve. 
     1872     * @param collectionName - name of the collection through which we are browsing CL1. 
     1873     * @param classifierNode - the docNodes found will be appended to this node. 
     1874     * @param depthStructure - can be descendants or children. Specifies what to retrieve: 
     1875     * gets descendants of any documents found, otherwise gets just the children. 
     1876     * @return the given classifierNode which will have the child (or descendant) documents 
     1877     * appended to it. 
     1878     */ 
     1879    public Element getTitlesForLetter(char ch, String collectionName,  
     1880                      Element classifierNode, String depthStructure) 
     1881    { 
     1882    Document doc = classifierNode.getOwnerDocument(); 
     1883    FedoraGS3RunException ex = null; //any RemoteException or UnsupportedEncodingException 
     1884 
     1885     
     1886    // Retrieve the document structure for each subClassifierID:  
     1887    // all the documents that begin with its letter. 
     1888    String letter = String.valueOf(ch); 
     1889    try { 
     1890        String[] docPIDs = this.browseTitlesByLetter(collectionName, letter); 
     1891        if(docPIDs.length == 0) { 
     1892        return classifierNode; // skip letters that don't have any kids 
     1893        }        
     1894         
     1895        for(int i = 0; i < docPIDs.length; i++) { 
     1896        // work out the document's fedora PID and section ID 
     1897        String sectionID = getSectionIDFromDocID(docPIDs[i]); 
     1898        String docPID = getDocPIDFromDocID(docPIDs[i]); 
     1899         
     1900        // get the required section, along with children or descendants 
     1901        Element section = getSectionStructureXML(docPID, sectionID, depthStructure, ""); 
     1902         
     1903        // <documentNode nodeID="docID" docType="hierarchy" nodeType="root"> 
     1904        Element docRootNode = createDocNodeFromSubsection(doc, section, docPID);         
     1905         
     1906        // fills in the subtree of the rootNode in our nodeStructure element 
     1907        createDocStructure(doc, section, docRootNode, docPID); //where section represents the root section 
     1908        classifierNode.appendChild(docRootNode); 
     1909        } 
     1910    } catch(Exception e) {  
     1911        ex = new FedoraGS3RunException(e); 
     1912        ex.setSpecifics("requested portion of TOC file or trouble with fielded search "); 
     1913    } 
     1914 
     1915    return classifierNode; 
     1916    } 
     1917 
     1918 
     1919    /** Creates all the subclassifiers (CL1.x) for CL1, the classifier to browse by the 
     1920     * starting letter of the alphabet. X is each letter of the alphabet for which there 
     1921     * are matching document titles. 
     1922     * @param collectionName - name of the collection through which we are browsing CL1. 
     1923     * @param classifierNode - the docNodes found will be appended to this node. 
     1924     * @param classifierID - the ID of parent classifier, i.e. CL1, which is used to create 
     1925     * the IDs for the subclassifiers (CL.x). 
     1926     * @param getDescendants - if true, get descendants of any documents found, otherwise 
     1927     * get just the children. 
     1928     * @return the given classifierNode, with the CL.x subclassifiers for the letters of 
     1929     * the alphabet that are represented in the document titles. 
     1930     */ 
     1931    public Element getTitlesByLetterStructure(String collectionName, Element classifierNode, 
     1932                           String classifierID, boolean getDescendants)  
     1933    { 
     1934    Document doc = classifierNode.getOwnerDocument(); 
     1935    FedoraGS3RunException ex = null; // any RemoteException or UnsupportedEncodingException 
     1936 
     1937    // We're going to loop to the end of the alphabet 
     1938    int count = 1; 
     1939    for(char ch = 'A'; ch <= 'Z'; ch++, count++) { 
     1940        // Retrieve the document structure for each subClassifierID:  
     1941        // all the documents that begin with its letter. 
     1942        String letter = String.valueOf(ch); 
     1943        try { 
     1944        String[] docPIDs = this.browseTitlesByLetter(collectionName, letter); 
     1945        if(docPIDs.length == 0) { 
     1946            continue; // skip letters that don't have any kids 
     1947        } 
     1948         
     1949        // <classifierNode nodeID="CL1.x"> 
     1950        Element subClassifier = doc.createElement(GSXML.CLASS_NODE_ELEM); 
    17171951        Attr attribute = doc.createAttribute(GSXML.NODE_ID_ATT); 
    1718         attribute.setValue(classifierIDs[i]); 
    1719         requestedClassifierNode.setAttributeNode(attribute); 
    1720         classifierNodeList.appendChild(requestedClassifierNode); 
    1721          
    1722         // <nodeStructure> 
    1723         Element nodeStructure = doc.createElement(GSXML.NODE_STRUCTURE_ELEM); 
    1724         requestedClassifierNode.appendChild(nodeStructure); 
    1725          
    1726         // And one more time, the top level classifierNode: 
    1727         Element classifierNode = doc.createElement(GSXML.CLASS_NODE_ELEM); 
    1728         attribute = doc.createAttribute(GSXML.NODE_ID_ATT); 
    1729         attribute.setValue(classifierIDs[i]); 
    1730         classifierNode.setAttributeNode(attribute); 
    1731         nodeStructure.appendChild(classifierNode); 
    1732          
    1733         // Work out what we're browsing base on the classifierID's number 
    1734         // classifier CL1 = browse titles by letter; 
    1735         // classifier CL2 = browse by collection; 
    1736         // remove the CL prefix and decimal point to obtain the number from the id: 
    1737         String classifier = classifierIDs[i].replace("CL", ""); 
    1738         int decimal = classifier.indexOf('.'); // look for decimal point 
    1739         if(decimal != -1) { 
    1740             classifier = classifier.substring(0, decimal); 
    1741         } 
    1742         int classifierNum = Integer.parseInt(classifier); 
    1743         switch(classifierNum) { 
    1744             case 1: 
    1745                 // we're going to loop to the end of the alphabet 
    1746                 int num = 1; 
    1747                 for(char ch = 'A'; ch <= 'Z'; ch++, num++) { 
    1748                     // Retrieve the document structure for each subClassifierID:  
    1749                     // all the documents that begin with its letter. 
    1750                     String letter = String.valueOf(ch); 
    1751                     try { 
    1752                     String[] docPIDs = this.browseTitlesByLetter( 
    1753                              collectionName, letter); 
    1754                     if(docPIDs.length == 0) { 
    1755                         continue; // skip letters that don't have any kids 
    1756                     } 
    1757                      
    1758                     // <classifierNode nodeID="CL3.1"> 
    1759                     Element subClassifier = doc.createElement( 
    1760                           GSXML.CLASS_NODE_ELEM); 
    1761                     attribute = doc.createAttribute(GSXML.NODE_ID_ATT); 
    1762                     attribute.setValue(classifierIDs[i]+"."+num); 
    1763                     subClassifier.setAttributeNode(attribute); 
    1764                     classifierNode.appendChild(subClassifier); 
    1765                      
    1766                     // append the <docNodes> for the docPIDs found as children  
    1767                     // of subclassifier  
    1768                     getStructureElement(subClassifier, docPIDs, DESCENDANTS); 
    1769                         //CHILDREN); // for testing 
    1770                     } catch(Exception e) {  
    1771                     ex = new FedoraGS3RunException(e); 
    1772                     ex.setSpecifics("requested portion of TOC file or " 
    1773                             + "trouble with fielded search "); 
    1774                     } 
    1775                 } 
    1776                 // No titles in this collection that start with a letter at all  
    1777                 if(!classifierNode.hasChildNodes()) { 
    1778                     // <classifierNode nodeID="CL1.0"> which we will equate with A-Z 
    1779                     Element subClassifier = doc.createElement( 
    1780                             GSXML.CLASS_NODE_ELEM); 
    1781                     attribute = doc.createAttribute(GSXML.NODE_ID_ATT); 
    1782                     attribute.setValue(classifierIDs[i]+"."+0); // 
    1783                     subClassifier.setAttributeNode(attribute); 
    1784                     classifierNode.appendChild(subClassifier); 
    1785                 } 
    1786                 break; 
    1787             case 2: 
    1788                 break; 
    1789             default: 
    1790                 ex = new FedoraGS3RunException( // cause is regular exception 
    1791                     new Exception("Unknown classifier ID: " + classifierIDs[i])); 
    1792         } 
    1793     } 
    1794         Element responseMsg = createResponseMessage(doc, classifierNodeList, ex, 
    1795                     GSXML.REQUEST_TYPE_DESCRIBE, /*collectionName+*/"/ClassifierBrowse"); 
    1796         try{ 
    1797             return FedoraCommons.elementToFormattedString(responseMsg); 
    1798         }catch(TransformerException e) { 
    1799             return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg 
    1800                 + " " + e; 
    1801         } 
    1802     } 
     1952        attribute.setValue(classifierID+"."+count); 
     1953        subClassifier.setAttributeNode(attribute); 
     1954        classifierNode.appendChild(subClassifier); 
     1955         
     1956        if(getDescendants) { // get the documents 
     1957 
     1958            // append the <docNodes> for the docPIDs found as children  
     1959            // of subclassifier  
     1960 
     1961            for(int i = 0; i < docPIDs.length; i++) { 
     1962            // work out the document's fedora PID and section ID 
     1963            String sectionID = getSectionIDFromDocID(docPIDs[i]); 
     1964            String docPID = getDocPIDFromDocID(docPIDs[i]); 
     1965         
     1966            // get the required section, along with children or descendants 
     1967            Element section = getSectionStructureXML(docPID, sectionID, "descendants", ""); 
     1968 
     1969            // <documentNode nodeID="docID" docType="hierarchy" nodeType="root"> 
     1970            Element rootNode = createDocNodeFromSubsection(doc, section, docPID); 
     1971             
     1972            // fills in the subtree of the rootNode in our nodeStructure element 
     1973            createDocStructure(doc, section, rootNode, docPID); //where section represents the root section 
     1974            subClassifier.appendChild(rootNode); 
     1975            } 
     1976        } 
     1977        } catch(Exception e) {  
     1978        ex = new FedoraGS3RunException(e); 
     1979        ex.setSpecifics("requested portion of TOC file or " 
     1980                + "trouble with fielded search "); 
     1981        }  
     1982    } 
     1983    return classifierNode; 
     1984    } 
     1985 
    18031986     
    18041987    /** This method performs something equivalent to a greenstone3  
    18051988     * ClassifierBrowseMetadataRetrieve on the classifierNodeIDs 
    1806      * @param classNodeIDs array of classifierNode IDs of for which the metadata 
     1989     * @param classNodeIDs array of classifierNode IDs for which the metadata 
    18071990     * needs to be returned. 
     1991     * @param metafields are the classifier metadata fields that are to be returned. 
     1992     * At present this method ignores them/pretends the requested metafields are  
     1993     * "all" and always returns the Title meta for the requested classifier nodes  
     1994     * (because that is all the metadata this Fedora classifier has at present). 
    18081995     * @return a GS3 ClassifierBrowseMetadataRetrieve response message which  
    18091996     * lists the metadata for all the classifierNodes passed as parameter.*/ 
    1810     public String browseMetadataRetrieve(String[] classNodeIDs) 
     1997    public String browseMetadataRetrieve(String[] classNodeIDs, String[] metafields) 
    18111998    { 
    18121999        Document doc = this.builder.newDocument(); 
     
    18602047                "ClassifierBrowseMetadataRetrieve"); 
    18612048        try{ 
    1862             return FedoraCommons.elementToFormattedString(responseMsg); 
     2049            return FedoraCommons.elementToString(responseMsg); 
    18632050        }catch(TransformerException e) { 
    18642051            return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg 
     
    18952082        // now create the displayItem children for classifier: 
    18962083        // <displayItem name="name">#letter</displayItem> 
    1897         // <displayItem name="description"> 
    1898         //Browse titles starting with #letter</displayItem> 
     2084        // <displayItem name="description">Browse titles starting with #letter</displayItem> 
    18992085        Element displayItem = createNameValuePairElement(doc,  
    19002086                GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_NAME, displayNameVal); 
     
    20132199    } 
    20142200     
    2015     /** @return a String representing Greenstone3 XML for a query process 
     2201    /** @return a String representing Greenstone3 XML for a query process 
    20162202     * response returning the results for the query denoted by parameter 
    20172203     * nameValParamsMap. 
     
    20402226        String pids[] = {}; 
    20412227        // (2) for Textquery, we simply search ALL_FIELDS using FedoraGSearch 
    2042         if(service.equals("TextQuery")) { 
     2228        if(service.endsWith("TextQuery")) { 
    20432229            try { 
    20442230                // get the Query field: 
     
    21422328                GSXML.REQUEST_TYPE_PROCESS, service); 
    21432329        try{ 
    2144             return FedoraCommons.elementToFormattedString(responseMsg); 
     2330            return FedoraCommons.elementToString(responseMsg); 
    21452331        }catch(TransformerException e) { 
    21462332            return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg 
     
    21862372            // along with EX of the top-level document: 
    21872373            System.out.println("\nGET META for greenstone:gs2mgdemo-HASH01d667303fe98545f03c14ae:"); 
    2188             System.out.println(con.getDocumentMetadata(new String[]{"greenstone:gs2mgdemo-HASH01d667303fe98545f03c14ae"})); 
     2374            System.out.println(con.getDocumentMetadata(new String[]{"greenstone:gs2mgdemo-HASH01d667303fe98545f03c14ae"}, new String[]{"all"})); 
    21892375             
    21902376                         
     
    21972383            System.out.println("\nGET META:"); 
    21982384            for(int i = 0; i < docIDs.length; i++) { 
    2199                 System.out.println(con.getDocumentMetadata(docIDs[i])); 
     2385                System.out.println(con.getDocumentMetadata(docIDs[i], new String[]{"all"})); 
    22002386            } 
    22012387             
     
    22112397            // their sections 
    22122398            for(int i = 0; i < getTitlesFor.length; i++) { 
    2213                 System.out.println(con.getDocumentMetadata(getTitlesFor[i])); 
     2399                System.out.println(con.getDocumentMetadata(getTitlesFor[i], new String[]{"all"})); 
    22142400            } 
    22152401             
     
    22192405            System.out.println("\nGET STRUCTURE:"); 
    22202406            for(int i = 0; i < docIDs.length; i++) { 
    2221                 System.out.println(con.getChildren(docIDs[i])); 
    2222                 System.out.println(con.getDocumentStructure(docIDs[i])); 
     2407                System.out.println("Descendents and numChildren:\n" 
     2408                           + con.getDocumentStructure(docIDs[i], new String[] {"descendants"}, new String[] {"numChildren"})); 
     2409                System.out.println("Parent and numSiblings:\n" 
     2410                           + con.getDocumentStructure(docIDs[i], new String[] {"parent"}, new String[] {"numSiblings"})); 
    22232411            } 
    22242412             
     
    22292417            "greenstone:demo-pinky" }; 
    22302418            System.out.println(con.getContent(errorCases)); 
    2231             System.out.println(con.getDocumentMetadata(errorCases)); 
    2232             System.out.println(con.getDocumentStructure(errorCases)); 
     2419            System.out.println(con.getDocumentMetadata(errorCases, new String[]{"all"})); 
     2420                           System.out.println(con.getDocumentStructure(errorCases, new String[] {"descendants"}, new String[] {"numChildren"})); 
    22332421             
    22342422            System.out.println("\nCLASSIFIER BROWSE"); 
    22352423            System.out.println(con.browse("gs2mgdemo", //"ClassifierBrowse",  
    2236                               new String[]{"CL1"})); 
     2424                              new String[]{"CL1"}, new String[] {""}, new String[] {""})); 
    22372425             
    22382426            System.out.println("\nCLASSIFIER BROWSE METADATA RETRIEVE"); 
     
    22432431            } 
    22442432            System.out.println(con.browseMetadataRetrieve(//"gs2mgdemo",  
    2245                     classNodeIDs)); 
     2433                                      classNodeIDs, new String[]{"all"})); 
    22462434             
    22472435            System.out.println("Testing query services"); 
  • other-projects/gs3-webservices-java-client/trunk/src/GS3Fedora/org/greenstone/fedora/services/FedoraGS3DL.java

    r15222 r22300  
    331331    /* METHODS FOR GETTING THE STRUCTURE OF DOCUMENTS */ 
    332332 
    333     /** @return the XML content of the TOC of just that portion of the TOC which    
    334      * contains the section denoted by sectionID and its direct child subsections.  
    335      * The children are returned in the order they are encountered, which  
    336      * happens to be in the required order of ascending sectionID.  
    337      * @param docPID is a fedora pid identifying a greenstone document object. 
    338      * @param sectionID identifies the particular section in the 
    339      * document denoted by docPID, may be a section name or number. */ 
    340     public Element getChildrenOfSectionXML(String docPID, String sectionID) 
    341         throws RemoteException, UnsupportedEncodingException,  
    342             SAXException, IOException; 
    343  
    344     /** @return a string representing the XML content of the TOC of just 
    345      * that portion of the TOC which contains the section denoted by sectionID   
    346      * and its direct child subsections.  
    347      * The children are returned in the order they are encountered, which  
    348      * happens to be in the required order of ascending sectionID.  
    349      * @param docPID is a fedora pid identifying a greenstone document object. 
    350      * @param sectionID identifies the particular section in the 
    351      * document denoted by docPID, may be a section name or number. */ 
    352     public String getChildrenOfSection(String docPID, String sectionID) 
    353         throws RemoteException, UnsupportedEncodingException,  
    354             SAXException, IOException, TransformerException; 
    355  
    356333    /** @return the part of the TOC XML file (which outlines doc structure)   
    357334     * relating to the given section. This includes the section denoted by 
    358335     * sectionID as well as all descendent subsections thereof.  
    359      * @param docPID is a fedora pid identifying a greenstone document object. 
    360      * @param sectionID identifies the particular section in the 
    361      * document denoted by docPID, may be a section name or number. */ 
    362     public Element getSubsectionXML(String docPID, String sectionID) 
    363         throws RemoteException, UnsupportedEncodingException,  
    364             SAXException, IOException; 
    365  
    366     /** @return a String representation of the part of the TOC XML file    
    367      * (which outlines doc structure) relating to the given section. This     
    368      * includes the section denoted by sectionID as well as all descendent   
    369      * subsections thereof. 
    370      * @param docPID is a fedora pid identifying a greenstone document object. 
    371      * @param sectionID identifies the particular section in the 
    372      * document denoted by docPID, may be a section name or number. */ 
    373     public String getSubsection(String docPID, String sectionID) 
    374         throws RemoteException, UnsupportedEncodingException, SAXException,   
    375             IOException, TransformerException; 
     336     * @param docPID - a fedora pid identifying a greenstone document object. 
     337     * @param sectionID - identifies the particular section in the 
     338     * document denoted by docPID, may be a section name or number.  
     339     * @param structure can contain any combination of: ancestors, parent,  
     340     * siblings, children, descendants, entire, specifying the portion of  
     341     * the structure to retrieve. 
     342     * @param info can contain any combination of: siblingPosition, numSiblings,  
     343     * numChildren, requesting additional information about the structure. */ 
     344    public Element getSectionStructureXML(String docPID, String sectionID, String structure, String info) 
     345        throws RemoteException, UnsupportedEncodingException, SAXException, IOException; 
    376346 
    377347    /* BROWSING */ 
  • other-projects/gs3-webservices-java-client/trunk/src/GS3Fedora/org/greenstone/fedora/services/FedoraToGS3Interface.java

    r21835 r22300  
    159159     
    160160    /* RETRIEVE SERVICE: DOCUMENT STRUCTURE RETRIEVE */ 
    161      
    162     /** @return the documentStructure of the document or section given by docID.  
    163      * The structure is returned in the XML format of a Greenstone3  
    164      * DocumentStructureRetrieve response message. This method returns the entire 
    165      * subSection of the docID (that is, all descendents included). 
    166      * @param docID the identifier for the document whose structure is required. 
    167      * This is either of the format "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;"  
    168      * OR "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;-" 
    169      * where "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;-1" is the same as  
    170      * "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;" and will return the same response */ 
    171     public String getDocumentStructure(String docID); 
    172      
    173     /** @return a view of the structure of the document or section given by docID 
    174      * which contains only the section and its direct children. This structure is  
    175      * returned in the XML format of a Greenstone3 DocumentStructureRetrieve  
    176      * response message.  
    177      * @param docID the identifier for the document whose structure is required. 
    178      * This is of the format "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;" 
    179      * OR "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;-" 
    180      * where "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;-1" is the same as  
    181      * "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;" and will return the same response */ 
    182     public String getChildren(String docID); 
    183      
    184     /** @return the documentStructure of the documents or sections given by docIDs.  
    185      * The structure is returned in the XML format of a Greenstone3  
    186      * DocumentStructureRetrieve response message. This method returns the entire 
    187      * subSection of each docID (that is, all descendents included). 
    188      * @param docIDs an array of document identifiers whose structures are requested 
    189      * These are of the format "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;" 
    190      * OR "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;-&lt;sectionNumber&gt;" 
    191      * where "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;-1" is the same as  
    192      * "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;" and will return the same response */ 
    193     public String getDocumentStructure(String[] docIDs); 
    194      
    195     /** @return the documentStructure of the documents or sections given by docIDs 
    196      * but only the sections and their children (not any further descendents).  
    197      * The structure is returned in the XML format of a Greenstone3  
    198      * DocumentStructureRetrieve response message. 
    199      * @param docIDs an array of document identifiers whose structures are requested 
    200      * These are of the format "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;" 
    201      * OR "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;-&lt;sectionNumber&gt;"  
    202      * where "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;-1" is the same as  
    203      * "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;" and will return the same response */ 
    204     public String getChildren(String[] docIDs); 
    205      
     161 
     162        /** @return a String representing Greenstone3 DocumentMetadataRetrieve XML 
     163     * containing the requested portion of the document structure of the documents  
     164     * indicated by docIDs:  
     165     * @param collection is the name of the collection. It's already included in the 
     166     * docID for a Fedora DL. 
     167     * @param docID is the document identifier of the document whose hierarchical 
     168     * structure is requested. The collection name is already included in the 
     169     * docID for a Fedora DL. 
     170     * @param structure - strings specifying the required structure of the document.  
     171     * Any combination of: ancestors, parent, siblings, children, descendants, entire. 
     172     * @param info - strings specifying the required structural info of the document.  
     173     * It can be any combination of: siblingPosition, numSiblings, numChildren. 
     174    */ 
     175    public String getDocumentStructure(String docID, String[] structure, String[] info); 
     176 
     177    /** @return a String representing Greenstone3 DocumentMetadataRetrieve XML 
     178     * containing the requested portion of the document structure of the documents  
     179     * indicated by docIDs: 
     180     * @param docIDs is an array of document identifiers of documents whose 
     181     * hierarchical structures are requested. The collection name is already included 
     182     * in the docID for a Fedora DL.  
     183     * @param structure - strings specifying the required structure of each document.  
     184     * Any combination of: ancestors, parent, siblings, children, descendants, entire. 
     185     * @param info - strings specifying the required structural info of each document.  
     186     * It can be any combination of: siblingPosition, numSiblings, numChildren. 
     187    */ 
     188    public String getDocumentStructure(String[] docIDs, String[] structure, String[] info); 
     189 
    206190     
    207191    /* RETRIEVE SERVICE: DOCUMENT METADATA RETRIEVE */ 
     
    221205     * @return a GS3 DocumentMetadataRetrieve response message containing the 
    222206     * EX, DC, DLS metadata for all the requested documents */ 
    223     public String getDocumentMetadata(String[] docIDs); 
     207    public String getDocumentMetadata(String[] docIDs, String[] metadata); 
    224208     
    225209    /** Given a collectionID, returns a GS3 DocumentMetadataRetrieve  
     
    237221     * @return a GS3 DocumentMetadataRetrieve response message containing the 
    238222     * EX, DC, DLS metadata for all the requested document */ 
    239     public String getDocumentMetadata(String docID); 
     223    public String getDocumentMetadata(String docID, String[] metadata); 
    240224 
    241225    /** @return a greenstone DocumentMetadataRetrieve response for the  
     
    245229     * In the last case, the document ID may consist of either 
    246230     * "documentPID-sectionNumber" or may just be just fedora documentPID */ 
    247     public String getMetadata(String[] docIDsOrCollIDs); 
     231    public String getMetadata(String[] docIDsOrCollIDs, String[] metadata); 
    248232     
    249233    /** Given a document identifier, returns a GS3 DocumentMetadataRetrieve  
     
    271255     * @param classNodeIDs are the IDs of the classifierNode for which the metadata 
    272256     * needs to be returned 
     257     * @param metafields are the classifier metadata fields that are to be returned. 
    273258     * @return a GS3 ClassifierBrowseMetadataRetrieve response message which  
    274259     * lists the metadata for all the classifierNodes passed as parameter.*/ 
    275     public String browseMetadataRetrieve(String[] classNodeIDs); 
     260    public String browseMetadataRetrieve(String[] classNodeIDs, String[] metafields); 
    276261         
    277262    /** This method performs the implemented browse operation: allowing the 
     
    283268     * @param collectionName is the name of the collection whose documents  
    284269     * starting with the given letter will be returned. 
     270     * @param structure - the requested browse substructure. Can be any combination 
     271     * of ancestors, parent, siblings, children, descendants. 
     272     * @param info - the requested structural info. Can be numSiblings, siblingPosition, 
     273     * numChildren 
    285274     * @return a GS3 DocumentStructureRetrieve response message which lists all  
    286275     * the documents that start with the letter indicated by parameter classifier. 
    287276    */ 
    288     public String browse(String collectionName, String[] classifierIDs); 
     277    public String browse(String collectionName, String[] classifierIDs, String[] structures, String[] infos); 
    289278     
    290279    /* @returns the document identifiers returned for a search on the titles of