Ignore:
Timestamp:
2010-06-24T13:45:34+12:00 (14 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 edited

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