]> git.aero2k.de Git - tmp/jakarta-migration.git/commitdiff
CSPACE-573 Added *order* field to schema for Vocabularies and list result. Developed...
authorLaramie Crocker <laramie@berkeley.edu>
Fri, 27 May 2011 22:19:48 +0000 (22:19 +0000)
committerLaramie Crocker <laramie@berkeley.edu>
Fri, 27 May 2011 22:19:48 +0000 (22:19 +0000)
18 files changed:
services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlReplay.java
services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlReplayReport.java
services/IntegrationTests/src/main/java/org/collectionspace/services/IntegrationTests/xmlreplay/XmlReplayTest.java
services/IntegrationTests/src/test/resources/test-data/xmlreplay/_includes/reports-include.css [moved from services/IntegrationTests/src/test/resources/test-data/xmlreplay/TEST-REPORTS/reports-include.css with 100% similarity]
services/IntegrationTests/src/test/resources/test-data/xmlreplay/_includes/reports-include.js [moved from services/IntegrationTests/src/test/resources/test-data/xmlreplay/TEST-REPORTS/reports-include.js with 100% similarity]
services/IntegrationTests/src/test/resources/test-data/xmlreplay/location/hierarchy/0-note.xml [new file with mode: 0644]
services/IntegrationTests/src/test/resources/test-data/xmlreplay/location/hierarchy/3-locations_w_relations.xml
services/IntegrationTests/src/test/resources/test-data/xmlreplay/location/hierarchy/4-locations_w_relations_mixed.xml [new file with mode: 0755]
services/IntegrationTests/src/test/resources/test-data/xmlreplay/location/location-hierarchy-dual-parents.xml [new file with mode: 0644]
services/IntegrationTests/src/test/resources/test-data/xmlreplay/location/location-mixed-hierarchy.xml [new file with mode: 0644]
services/authority/src/main/java/org/collectionspace/services/common/vocabulary/AuthorityItemJAXBSchema.java
services/authority/src/main/java/org/collectionspace/services/common/vocabulary/AuthorityResource.java
services/authority/src/main/java/org/collectionspace/services/common/vocabulary/Hierarchy.java [new file with mode: 0644]
services/common/src/main/java/org/collectionspace/services/common/XmlTools.java
services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RemoteDocumentModelHandlerImpl.java
services/vocabulary/3rdparty/nuxeo-platform-cs-vocabulary/src/main/resources/schemas/vocabularyitems_common.xsd
services/vocabulary/jaxb/src/main/resources/vocabularyitem_common.xsd
services/vocabulary/service/src/main/java/org/collectionspace/services/vocabulary/nuxeo/VocabularyItemDocumentModelHandler.java

index 5b80c7595860009e202d17e406b829181754f09e..ebf19c30e36e457a736b8f2602aa9c05f321d6a4 100755 (executable)
@@ -20,16 +20,21 @@ import java.util.*;
  */\r
 public class XmlReplay {\r
 \r
-    public XmlReplay(String basedir){\r
+    public XmlReplay(String basedir, String reportsDir){\r
         this.basedir = basedir;\r
         this.serviceResultsMap = createResultsMap();\r
         this.reportsList = new ArrayList<String>();\r
+        this.reportsDir = reportsDir;\r
     }\r
 \r
     public static final String DEFAULT_CONTROL = "xml-replay-control.xml";\r
     public static final String DEFAULT_MASTER_CONTROL = "xml-replay-master.xml";\r
     public static final String DEFAULT_DEV_MASTER_CONTROL = "dev-master.xml";\r
 \r
+    private String reportsDir = "";\r
+    public String getReportsDir(){\r
+        return reportsDir;\r
+    }\r
     private String basedir = ".";  //set from constructor.\r
     public String getBaseDir(){\r
         return basedir;\r
@@ -89,7 +94,7 @@ public class XmlReplay {
     }\r
 \r
     public String toString(){\r
-        return "XmlReplay{"+this.basedir+", "+this.defaultAuthsMap+", "+this.dump+'}';\r
+        return "XmlReplay{"+this.basedir+", "+this.defaultAuthsMap+", "+this.dump+", "+this.reportsDir+'}';\r
     }\r
 \r
     // ============== METHODS ===========================================================\r
@@ -166,7 +171,7 @@ public class XmlReplay {
             test = runNode.valueOf("@test"); //may be empty\r
 \r
             //Create a new instance and clone only config values, not any results maps.\r
-            XmlReplay replay = new XmlReplay(basedir);\r
+            XmlReplay replay = new XmlReplay(basedir, this.reportsDir);\r
             replay.setControlFileName(controlFile);\r
             replay.setProtoHostPort(protoHostPort);\r
             replay.setAutoDeletePOSTS(isAutoDeletePOSTS());\r
@@ -178,7 +183,7 @@ public class XmlReplay {
             list.add(results);\r
             this.reportsList.addAll(replay.getReportsList());   //Add all the reports from the inner replay, to our master replay's reportsList, to generate the index.html file.\r
         }\r
-        XmlReplayReport.saveIndexForMaster(basedir, masterFilename, this.reportsList);\r
+        XmlReplayReport.saveIndexForMaster(basedir, reportsDir, masterFilename, this.reportsList);\r
         return list;\r
     }\r
 \r
@@ -193,7 +198,8 @@ public class XmlReplay {
                                 dump,\r
                                 this.protoHostPort,\r
                                 this.defaultAuthsMap,\r
-                                this.reportsList);\r
+                                this.reportsList,\r
+                                this.reportsDir);\r
         return result;\r
     }\r
 \r
@@ -208,7 +214,8 @@ public class XmlReplay {
                                 dump,\r
                                 this.protoHostPort,\r
                                 this.defaultAuthsMap,\r
-                                this.reportsList);\r
+                                this.reportsList,\r
+                                this.reportsDir);\r
         if (result.size()>1){\r
             throw new IndexOutOfBoundsException("Multiple ("+result.size()+") tests with ID='"+testID+"' were found within test group '"+testGroupID+"', but there should only be one test per ID attribute.");\r
         }\r
@@ -457,14 +464,15 @@ public class XmlReplay {
                                           Dump dump,\r
                                           String protoHostPortParam,\r
                                           AuthsMap defaultAuths,\r
-                                          List<String> reportsList)\r
+                                          List<String> reportsList,\r
+                                          String reportsDir)\r
                                           throws Exception {\r
         //Internally, we maintain two collections of ServiceResult:\r
         //  the first is the return value of this method.\r
         //  the second is the serviceResultsMap, which is used for keeping track of CSIDs created by POSTs, for later reference by DELETE, etc.\r
         List<ServiceResult> results = new ArrayList<ServiceResult>();\r
 \r
-        XmlReplayReport report = new XmlReplayReport();\r
+        XmlReplayReport report = new XmlReplayReport(reportsDir);\r
 \r
         String controlFile = Tools.glue(xmlReplayBaseDir, "/", controlFileName);\r
         org.dom4j.Document document;\r
@@ -719,7 +727,7 @@ public class XmlReplay {
         String localName = m.getName();//don't instantiate, just use File to extract file name without directory.\r
         String reportName = localName+'-'+testGroupID+".html";\r
 \r
-        File resultFile = report.saveReport(xmlReplayBaseDir, reportName);\r
+        File resultFile = report.saveReport(xmlReplayBaseDir, reportsDir, reportName);\r
         if (resultFile!=null) {\r
             String toc = report.getTOC(reportName);\r
             reportsList.add(toc);\r
@@ -778,6 +786,7 @@ public class XmlReplay {
             CommandLine line = parser.parse(options, args);\r
 \r
             String xmlReplayBaseDir = opt(line, "xmlReplayBaseDir");\r
+            String reportsDir = opt(line, "reportsDir");\r
             String testGroupID      = opt(line, "testGroupID");\r
             String testID           = opt(line, "testID");\r
             String autoDeletePOSTS  = opt(line, "autoDeletePOSTS");\r
@@ -785,6 +794,10 @@ public class XmlReplay {
             String controlFilename   = opt(line, "controlFilename");\r
             String xmlReplayMaster  = opt(line, "xmlReplayMaster");\r
 \r
+            if (Tools.isBlank(reportsDir)){\r
+                reportsDir = xmlReplayBaseDir + XmlReplayTest.REPORTS_DIRNAME;\r
+            }\r
+            reportsDir = Tools.fixFilename(reportsDir);\r
             xmlReplayBaseDir = Tools.fixFilename(xmlReplayBaseDir);\r
             controlFilename = Tools.fixFilename(controlFilename);\r
 \r
@@ -829,7 +842,7 @@ public class XmlReplay {
                 if (Tools.notEmpty(controlFilename)){\r
                     System.out.println("WARN: controlFilename: "+controlFilename+" will not be used because master was specified.  Running master: "+xmlReplayMaster);\r
                 }\r
-                XmlReplay replay = new XmlReplay(xmlReplayBaseDirResolved);\r
+                XmlReplay replay = new XmlReplay(xmlReplayBaseDirResolved, reportsDir);\r
                 replay.readOptionsFromMasterConfigFile(xmlReplayMaster);\r
                 replay.setAutoDeletePOSTS(bAutoDeletePOSTS);\r
                 Dump dumpFromMaster = replay.getDump();\r
@@ -840,7 +853,7 @@ public class XmlReplay {
                 Dump dump = getDumpConfig();\r
                 dump.payloads = Tools.isTrue(dumpResults);\r
                 List<String> reportsList = new ArrayList<String>();\r
-                runXmlReplayFile(xmlReplayBaseDirResolved, controlFilename, testGroupID, testID, createResultsMap(), bAutoDeletePOSTS, dump, "", null, reportsList);\r
+                runXmlReplayFile(xmlReplayBaseDirResolved, controlFilename, testGroupID, testID, createResultsMap(), bAutoDeletePOSTS, dump, "", null, reportsList, reportsDir);\r
                 System.out.println("DEPRECATED: reportsList is generated, but not dumped: "+reportsList.toString());\r
             }\r
         } catch (ParseException exp) {\r
index d46c07926e65dd3beaa920a61c9724490a2d62b9..14485619666a1c0d6a42aa554847b78dcdcf5f44 100644 (file)
@@ -15,6 +15,8 @@ import java.util.List;
  * @author  laramie
  */
 public class XmlReplayReport {
+    public static final String INCLUDES_DIR =  "_includes";
+
     protected static final String HTML_PAGE_END = "</body></html>";
     protected static final String TOPLINKS = "<a class='TOPLINKS' href='javascript:openAll();'>Show All Payloads</a>" + "<a class='TOPLINKS' href='javascript:closeAll();'>Hide All Payloads</a>";
 
@@ -40,6 +42,14 @@ public class XmlReplayReport {
 
     private static final String SP = "&nbsp;&nbsp;&nbsp;";
 
+    public XmlReplayReport(String reportsDir){
+        this.reportsDir = reportsDir;
+    }
+
+    private String reportsDir = "";
+    public String getReportsDir(){
+        return reportsDir;
+    }
 
     protected static String formatCollapse(String myDivID, String linkText){
         return  "<a href='javascript:;' onmousedown=\"toggleDiv('"+myDivID+"');\">"+linkText+"</a>"
@@ -115,8 +125,8 @@ public class XmlReplayReport {
     private List<TOC> tocList = new ArrayList<TOC>();
 
     public static String formatPageStart(String xmlReplayBaseDir){
-            String script = FileTools.readFile(xmlReplayBaseDir, "TEST-REPORTS/reports-include.js");
-            String style =  FileTools.readFile(xmlReplayBaseDir, "TEST-REPORTS/reports-include.css");
+            String script = FileTools.readFile(xmlReplayBaseDir, INCLUDES_DIR+"/reports-include.js");
+            String style =  FileTools.readFile(xmlReplayBaseDir, INCLUDES_DIR+"/reports-include.css");
             return "<html><head><script type='text/javascript'>\r\n"
                      +script
                      +"\r\n</script>\r\n<style>\r\n"
@@ -124,9 +134,9 @@ public class XmlReplayReport {
                      +"\r\n</style></head><body>";
     }
 
-    public File saveReport(String xmlReplayBaseDir, String reportName)  {
+    public File saveReport(String xmlReplayBaseDir, String reportsDir, String reportName)  {
         try {
-            File resultFile = FileTools.saveFile(getReportsDir(xmlReplayBaseDir), reportName, this.getPage(xmlReplayBaseDir), true);
+            File resultFile = FileTools.saveFile(reportsDir, reportName, this.getPage(xmlReplayBaseDir), true);
             if (resultFile!=null) {
                 String resultFileName =  resultFile.getCanonicalPath();
                 //System.out.println("XmlReplay summary reports saved to directory: "+resultFile.getParent());
@@ -134,21 +144,21 @@ public class XmlReplayReport {
                 return resultFile;
             }
         } catch (Exception e){
-            System.out.println("ERROR saving XmlReplay report in basedir: "+xmlReplayBaseDir+" reportName: "+reportName+" error: "+e);
+            System.out.println("ERROR saving XmlReplay report in basedir: "+reportsDir+" reportName: "+reportName+" error: "+e);
         }
         return null;
     }
 
-    public static String getReportsDir(String basename){
-        return Tools.glue(basename,"/","TEST-REPORTS");
-    }
+    //public static String getReportsDir(String basename){
+    //    return Tools.glue(basename,"/","TEST-REPORTS");
+    //}
 
     /** @param localMasterFilename should be a local filename for the index of each xmlReplay master control file, e.g. objectexit.xml
      *               so what gets written to disk will be something like index.objectexit.xml.html . The actual filename will be available from
      *               the returned File object if successful.
      *   @return File if successful, else returns null.
      */
-    public static File saveIndexForMaster(String xmlReplayBaseDir, String localMasterFilename, List<String> reportsList){
+    public static File saveIndexForMaster(String xmlReplayBaseDir, String reportsDir, String localMasterFilename, List<String> reportsList){
         String masterFilename =  "index."+localMasterFilename+".html";
         try{
             StringBuffer sb = new StringBuffer(formatPageStart(xmlReplayBaseDir));
@@ -160,9 +170,9 @@ public class XmlReplayReport {
             }
             sb.append(HTML_PAGE_END);
 
-            return FileTools.saveFile(getReportsDir(xmlReplayBaseDir),masterFilename, sb.toString(), false);
+            return FileTools.saveFile(reportsDir,masterFilename, sb.toString(), false);
         } catch (Exception e){
-            System.out.println("ERROR saving XmlReplay report index: in  xmlReplayBaseDir: "+xmlReplayBaseDir+"localMasterFilename: "+localMasterFilename+" masterFilename: "+masterFilename+" list: "+reportsList+" error: "+e);
+            System.out.println("ERROR saving XmlReplay report index: in  xmlReplayBaseDir: "+reportsDir+"localMasterFilename: "+localMasterFilename+" masterFilename: "+masterFilename+" list: "+reportsList+" error: "+e);
             return null;
         }
     }
index 641e2cbd79e044c17ca4f6da68d42a51a9e99231..27d0fce30e94a24587cffefab5e53b46c402f416 100755 (executable)
@@ -38,6 +38,8 @@ import java.util.List;
 public class XmlReplayTest {\r
 \r
     public static final String XMLREPLAY_REL_DIR_TO_MODULE = "/src/test/resources/test-data/xmlreplay";\r
+    public static final String REPORTS_DIRNAME = "xml-replay-reports";\r
+    public static final String XMLREPLAY_REL_DIR_REPORTS_TO_MODULE= "/target/"+REPORTS_DIRNAME;\r
 \r
     /** To use this method, you should have a test repository of xml files in the path\r
      *  defined by XMLREPLAY_REL_DIR_TO_MODULE, relative to your pom.xml file, but normally\r
@@ -47,7 +49,8 @@ public class XmlReplayTest {
     public static XmlReplay createXmlReplayForModule() throws Exception {\r
         String pwd = (new File(".")).getCanonicalPath();\r
         System.out.println("createXmlReplayForModule.pwd: "+pwd);\r
-        XmlReplay replay = new XmlReplay(pwd+XMLREPLAY_REL_DIR_TO_MODULE);\r
+        XmlReplay replay = new XmlReplay(pwd+XMLREPLAY_REL_DIR_TO_MODULE,\r
+                                                              pwd+XMLREPLAY_REL_DIR_REPORTS_TO_MODULE);\r
         System.out.println("XmlReplay: "+replay);\r
         return replay;\r
     }\r
@@ -70,7 +73,8 @@ public class XmlReplayTest {
         String thisDir = Tools.glue(relToServicesRoot, "/", "IntegrationTests");\r
         String pwd = (new File(thisDir)).getCanonicalPath();\r
         //System.out.println("createXmlReplayUsingIntegrationTestsModule.pwd: "+pwd);\r
-        XmlReplay replay = new XmlReplay(pwd+XMLREPLAY_REL_DIR_TO_MODULE);\r
+        XmlReplay replay = new XmlReplay(pwd+XMLREPLAY_REL_DIR_TO_MODULE,\r
+                                                             pwd+XMLREPLAY_REL_DIR_REPORTS_TO_MODULE);\r
         //System.out.println("XmlReplay: "+replay);\r
         return replay;\r
     }\r
diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/location/hierarchy/0-note.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/location/hierarchy/0-note.xml
new file mode 100644 (file)
index 0000000..8ac9951
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document name="dimensions">
+  <ns2:dimensions_common xmlns:ns2="http://collectionspace.org/services/dimension" xmlns:ns3="http://collectionspace.org/services/jaxb">
+    <dimension>XmlReplay NOTE</dimension>
+    <value>${content}</value>
+    <valueDate>entryDate-1306297181479</valueDate>
+  </ns2:dimensions_common>
+</document>
+
index aecbeaa4acf3c49526b5114a11540f246366ab35..0477ff25720960dc476fb6bd8678a745df63cf1d 100755 (executable)
                <subject>\r
                  <csid>${itemCSID}</csid>\r
                  <documentType>Locationitem</documentType>\r
-                 <name>Item</name>\r
-                 <number>1111</number>\r
                </subject>\r
                <object>\r
                  <csid>${parentCSID}</csid>\r
                  <uri>${parentUri}</uri>\r
                  <documentType>Locationitem</documentType>\r
-                 <number>0000-setting-error</number>\r
-                 <name>Parent</name>\r
                </object>\r
        </relation-list-item>\r
        <relation-list-item>\r
diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/location/hierarchy/4-locations_w_relations_mixed.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/location/hierarchy/4-locations_w_relations_mixed.xml
new file mode 100755 (executable)
index 0000000..3c79b2b
--- /dev/null
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<document name="locations">\r
+  <ns2:locations_common xmlns:ns2="http://collectionspace.org/services/location" xmlns:ns3="http://collectionspace.org/services/jaxb">\r
+    <inAuthority>${inAuthority}</inAuthority>\r
+    <shortIdentifier>${shortIdentifier}</shortIdentifier>\r
+    <refName>urn:cspace:org.collectionspace.demo:locationauthority:name(${authShortIdentifier}):location:name(${shortIdentifier})'${name}'</refName>\r
+    <displayName>${name}</displayName>\r
+    <displayNameComputed>false</displayNameComputed>\r
+    <shortDisplayNameComputed>true</shortDisplayNameComputed>\r
+  </ns2:locations_common>\r
+  <ns3:relations-common-list xmlns:ns3="http://collectionspace.org/services/relation" xmlns:ns2="http://collectionspace.org/services/jaxb">\r
+    <relation-list-item>\r
+               <predicate>hasBroader</predicate>\r
+               <subject>\r
+                 <csid>${childCSID}</csid>\r
+                 <documentType>Locationitem</documentType>\r
+               </subject>\r
+               <object>\r
+                 <csid>${itemCSID}</csid>\r
+                 <documentType>Locationitem</documentType>\r
+               </object>\r
+       </relation-list-item>\r
+       <relation-list-item>\r
+               <predicate>hasBroader</predicate>\r
+               <subject>\r
+                 <csid>${child2CSID}</csid>\r
+                 <documentType>Locationitem</documentType>\r
+               </subject>\r
+               <object>\r
+                 <csid>${itemCSID}</csid>\r
+                 <documentType>Locationitem</documentType>\r
+               </object>\r
+       </relation-list-item>\r
+  </ns3:relations-common-list>\r
+</document>\r
+\r
+\r
diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/location/location-hierarchy-dual-parents.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/location/location-hierarchy-dual-parents.xml
new file mode 100644 (file)
index 0000000..6ebd343
--- /dev/null
@@ -0,0 +1,219 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xmlReplay>
+       <testGroup ID="HierarchicLocationTooManyParents" autoDeletePOSTS="true">
+       
+           <test ID="LocationAuth1" auth="admin@collectionspace.org">
+            <method>POST</method>
+            <uri>/cspace-services/locationauthorities/</uri>
+            <filename>location/hierarchy/1-authority.xml</filename>
+            <vars>
+               <var ID="shortIdentifier">CSPACE3739LocationAuthority</var>
+               <var ID="displayName">LocationAuth1-displayName</var>
+            </vars>
+        </test>
+        <test ID="LocationChild1">
+            <method>POST</method>
+            <uri>/cspace-services/locationauthorities/${LocationAuth1.CSID}/items/</uri>
+            <filename>location/hierarchy/2-item.xml</filename>
+            <vars>
+               <var ID="inAuthority">${LocationAuth1.CSID}</var>
+               <var ID="authShortIdentifier">CSPACE3739LocationAuthority</var>
+               <var ID="shortIdentifier">Shelf1</var>
+               <var ID="name">Shelf 1</var>
+            </vars>
+        </test>
+        <test ID="LocationChild2">
+            <method>POST</method>
+            <uri>/cspace-services/locationauthorities/${LocationAuth1.CSID}/items/</uri>
+            <filename>location/hierarchy/2-item.xml</filename>
+            <vars>
+               <var ID="inAuthority">${LocationAuth1.CSID}</var>
+               <var ID="authShortIdentifier">CSPACE3739LocationAuthority</var>
+               <var ID="shortIdentifier">Shelf2</var>
+               <var ID="name">Shelf 2</var>
+            </vars>
+        </test>
+        <test ID="LocationChild3">
+            <method>POST</method>
+            <uri>/cspace-services/locationauthorities/${LocationAuth1.CSID}/items/</uri>
+            <filename>location/hierarchy/2-item.xml</filename>
+            <vars>
+               <var ID="inAuthority">${LocationAuth1.CSID}</var>
+               <var ID="authShortIdentifier">CSPACE3739LocationAuthority</var>
+               <var ID="shortIdentifier">Shelf3</var>
+               <var ID="name">Shelf 3</var>
+            </vars>
+        </test>
+        
+        <test ID="LocationParent">
+            <method>POST</method>
+            <uri>/cspace-services/locationauthorities/urn:cspace:name(CSPACE3739LocationAuthority)/items/</uri>
+            <filename>location/hierarchy/2-item.xml</filename>
+            <vars>
+               <var ID="inAuthority">${LocationAuth1.CSID}</var>
+               <var ID="authShortIdentifier">CSPACE3739LocationAuthority</var>
+               <var ID="shortIdentifier">Aisle3</var>
+               <var ID="name">Aisle 3</var>
+            </vars>
+        </test>
+        
+        <test ID="Location1">
+            <method>POST</method>
+            <uri>/cspace-services/locationauthorities/urn:cspace:name(CSPACE3739LocationAuthority)/items/</uri>
+            <filename>location/hierarchy/3-locations_w_relations.xml</filename>
+            <vars>
+               <var ID="inAuthority">${LocationAuth1.CSID}</var>
+               <var ID="authShortIdentifier">CSPACE3739LocationAuthority</var>
+               <var ID="shortIdentifier">Cabinet1</var>
+               <var ID="name">Cabinet 1</var>
+               <var ID="parentCSID">${LocationParent.CSID}</var>
+               <var ID="parentUri">/cspace-services/locationauthorities/urn:cspace:name(CSPACE3739LocationAuthority)/items/${LocationParent.CSID}</var>
+               <var ID="childCSID">${LocationChild1.CSID}</var>
+               <var ID="childUri">/cspace-services/locationauthorities/urn:cspace:name(CSPACE3739LocationAuthority)/items/${LocationChild1.CSID}</var>
+               <var ID="child2CSID">${LocationChild2.CSID}</var>
+               <var ID="child2Uri">/cspace-services/locationauthorities/urn:cspace:name(CSPACE3739LocationAuthority)/items/${LocationChild2.CSID}</var>
+               <var ID="child3CSID">${LocationChild3.CSID}</var>
+               <var ID="child3Uri">/cspace-services/locationauthorities/urn:cspace:name(CSPACE3739LocationAuthority)/items/${LocationChild3.CSID}</var>
+            </vars>
+        </test>
+        <!--
+        <test ID="Location2">
+            <method>POST</method>
+            <uri>/cspace-services/locationauthorities/urn:cspace:name(CSPACE3739LocationAuthority)/items/</uri>
+            <filename>location/hierarchy/3-locations_w_relations.xml</filename>
+            <vars>
+               <var ID="inAuthority">${LocationAuth1.CSID}</var>
+               <var ID="authShortIdentifier">CSPACE3739LocationAuthority</var>
+               <var ID="shortIdentifier">Cabinet1SecondParent</var>
+               <var ID="name">Cabinet 1 Second Parent</var>
+               <var ID="parentCSID">${LocationParent.CSID}</var>
+               <var ID="parentUri">/cspace-services/locationauthorities/urn:cspace:name(CSPACE3739LocationAuthority)/items/${LocationParent.CSID}</var>
+               <var ID="childCSID">${LocationChild1.CSID}</var>
+               <var ID="childUri">/cspace-services/locationauthorities/urn:cspace:name(CSPACE3739LocationAuthority)/items/${LocationChild1.CSID}</var>
+               <var ID="child2CSID">${LocationChild2.CSID}</var>
+               <var ID="child2Uri">/cspace-services/locationauthorities/urn:cspace:name(CSPACE3739LocationAuthority)/items/${LocationChild2.CSID}</var>
+               <var ID="child3CSID">${LocationChild3.CSID}</var>
+               <var ID="child3Uri">/cspace-services/locationauthorities/urn:cspace:name(CSPACE3739LocationAuthority)/items/${LocationChild3.CSID}</var>
+            </vars>
+        </test>
+        -->
+        <test ID="EchoNotes">
+            <method>POST</method>
+            <uri>/cspace-services/dimensions/</uri>
+            <filename>location/hierarchy/0-note.xml</filename>
+            <vars>
+               <var ID="content">
+               LocationAuth1: ${LocationAuth1.CSID}
+               | Location: ${Location1.CSID}
+               | Parent: ${LocationParent.CSID}
+               | Children:
+               | 1: ${LocationChild1.CSID}
+               | 2: ${LocationChild2.CSID}
+               | 3: ${LocationChild3.CSID}
+               | Location2: ${Location2.CSID}
+               
+               </var>
+            </vars>
+        </test>
+        
+        <test ID="GetLocation">
+            <method>GET</method>
+            <uri>/cspace-services/locationauthorities/${LocationAuth1.CSID}/items/${Location1.CSID}?showRelations=true</uri>
+        </test>
+        
+        <test ID="GetParent">
+            <method>GET</method>
+            <uri>/cspace-services/locationauthorities/${LocationAuth1.CSID}/items/${LocationParent.CSID}?showRelations=true</uri>
+        </test>
+        
+        <test ID="Get_siblings">
+            <method>GET</method>
+            <uri>/cspace-services/locationauthorities/${LocationAuth1.CSID}/items/${LocationChild1.CSID}?showSiblings=true</uri>
+               </test>
+        
+        <test ID="Get_allRelations">
+            <method>GET</method>
+            <uri>/cspace-services/locationauthorities/${LocationAuth1.CSID}/items/${Location1.CSID}?showAllRelations=true</uri>
+               </test>
+        
+        <test ID="relationsGET">
+             <method>GET</method>
+             <uri>/cspace-services/relations/</uri>
+         </test>
+         
+         
+        <test ID="GetHierarchyL1">
+            <method>GET</method>
+            <uri>/cspace-services/locationauthorities/${LocationAuth1.CSID}/items/${Location1.CSID}/hierarchy</uri>
+        </test>
+        
+        <test ID="GetHierarchyLP">
+            <method>GET</method>
+            <uri>/cspace-services/locationauthorities/${LocationAuth1.CSID}/items/${LocationParent.CSID}/hierarchy</uri>
+        </test>
+        
+        <test ID="GetHierarchyLP_Parents">
+            <method>GET</method>
+            <uri>/cspace-services/locationauthorities/${LocationAuth1.CSID}/items/${LocationChild1.CSID}/hierarchy?direction=parents</uri>
+        </test>
+        
+        <!--
+           <test ID="GetLocation">
+            <method>GET</method>
+            <uri>/cspace-services/locationauthorities/${LocationAuth1.CSID}/items/${Location1.CSID}?showRelations=true</uri>
+        </test>
+        
+        <test ID="Get_siblings">
+            <method>GET</method>
+            <uri>/cspace-services/locationauthorities/${LocationAuth1.CSID}/items/${LocationChild1.CSID}?showSiblings=true</uri>
+            <response>
+                               <expected level="ADDOK" />
+                               <filename>location/hierarchy/res/Get_siblings.res.xml</filename>
+                               <vars>
+                                       <var ID="locationCSID">${Location1.CSID}</var>
+                                       <var ID="child1CSID">${LocationChild1.CSID}</var>
+                                       <var ID="child2CSID">${LocationChild2.CSID}</var>
+                               </vars>
+                               <startElement>/document/*[local-name()='relations-common-list']</startElement>
+                </response>
+               </test>
+        
+        <test ID="Get_allRelations">
+            <method>GET</method>
+            <uri>/cspace-services/locationauthorities/${LocationAuth1.CSID}/items/${Location1.CSID}?showAllRelations=true</uri>
+            <response>
+                               <expected level="ADDOK" />
+                               <filename>location/hierarchy/res/Get_allRelations.res.xml</filename>
+                               <startElement>/document/*[local-name()='relations-common-list']</startElement>
+                        </response>
+                        
+               </test>
+               
+         <test ID="relationsGET">
+             <method>GET</method>
+             <uri>/cspace-services/relations/</uri>
+         </test>
+         
+         <test ID="relations_sbj">
+             <method>GET</method>
+             <uri>/cspace-services/relations?sbj=${Location1.CSID}</uri>
+         </test>
+         
+         <test ID="relations_obj">
+             <method>GET</method>
+             <uri>/cspace-services/relations?obj=${Location1.CSID}</uri>
+         </test>
+        -->
+       </testGroup>
+       <!-- NOTE: item  on url is .../items/${LocationChild1.CSID} so this looks for
+                   siblings of Child1, which would be child2 and child3.
+    -->
+       <!-- NOTE: vars are referenced in showAllRelations.res.xml
+                from tests in this test group, e.g. 
+                LocationParent.CSID :: ${LocationParent.CSID} 
+                These vars are all in the expression context while this group is active,
+                because we hang onto all ServiceResult objects for the duration of the group,
+                and ServiceObjects keep their vars.
+       -->
+
+</xmlReplay>
diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/location/location-mixed-hierarchy.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/location/location-mixed-hierarchy.xml
new file mode 100644 (file)
index 0000000..058ab5b
--- /dev/null
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xmlReplay>
+       <testGroup ID="HierarchicLocation" autoDeletePOSTS="true">
+       
+           <test ID="LocationAuth1" auth="admin@collectionspace.org">
+            <method>POST</method>
+            <uri>/cspace-services/locationauthorities/</uri>
+            <filename>location/hierarchy/1-authority.xml</filename>
+            <vars>
+               <var ID="shortIdentifier">CSPACE4042LocationAuthority</var>
+               <var ID="displayName">LocationAuth1-displayName</var>
+            </vars>
+        </test>
+        
+        <test ID="LocationAuth2" auth="admin@collectionspace.org">
+            <method>POST</method>
+            <uri>/cspace-services/locationauthorities/</uri>
+            <filename>location/hierarchy/1-authority.xml</filename>
+            <vars>
+               <var ID="shortIdentifier">CSPACE4042LocationAuthoritySecond</var>
+               <var ID="displayName">LocationAuth1-Second-Instance</var>
+            </vars>
+        </test>
+        
+        <test ID="GETLocationAuth1" auth="admin@collectionspace.org">
+            <method>GET</method>
+            <uri>/cspace-services/locationauthorities/${LocationAuth1.CSID}</uri>
+        </test>
+        
+        <test ID="GETLocationAuth2" auth="admin@collectionspace.org">
+            <method>GET</method>
+            <uri>/cspace-services/locationauthorities/${LocationAuth2.CSID}</uri>
+        </test>
+        
+        <test ID="LocationChild1">
+            <method>POST</method>
+            <uri>/cspace-services/locationauthorities/${LocationAuth1.CSID}/items/</uri>
+            <filename>location/hierarchy/2-item.xml</filename>
+            <vars>
+               <var ID="inAuthority">${LocationAuth1.CSID}</var>
+               <var ID="authShortIdentifier">CSPACE4042LocationAuthority</var>
+               <var ID="shortIdentifier">Shelf1</var>
+               <var ID="name">Shelf 1 in LocationAuth1</var>
+            </vars>
+        </test>
+        
+        <!-- Dig this test: 
+                  LocationChild1 is in LocationAuth1
+                  LocationChild2 is in LocationAuth2
+             This should be illegal per CSPACE-4042
+             
+             TODO: This fails with a 500, (that's good) but we don't get the right error message.
+             
+        -->          
+                  
+        <test ID="LocationChild2">
+            <method>POST</method>
+            <uri>/cspace-services/locationauthorities/${LocationAuth2.CSID}/items/</uri>
+            <filename>location/hierarchy/2-item.xml</filename>
+            <vars>
+               <var ID="inAuthority">${LocationAuth2.CSID}</var>
+               <var ID="authShortIdentifier">CSPACE4042LocationAuthoritySecond</var>
+               <var ID="shortIdentifier">Shelf2</var>
+               <var ID="name">Shelf 2 in LocationAuth2</var>
+            </vars>
+        </test>
+        
+        <test ID="Location1">
+            <method>POST</method>
+            <uri>/cspace-services/locationauthorities/urn:cspace:name(CSPACE4042LocationAuthority)/items/</uri>
+            <filename>location/hierarchy/4-locations_w_relations_mixed.xml</filename>
+            <vars>
+               <var ID="inAuthority">${LocationAuth1.CSID}</var>
+               <var ID="authShortIdentifier">CSPACE4042LocationAuthority</var>
+               <var ID="shortIdentifier">Cabinet1</var>
+               <var ID="name">Cabinet 1</var>
+               <var ID="childCSID">${LocationChild1.CSID}</var>
+               <var ID="child2CSID">${LocationChild2.CSID}</var>
+            </vars>
+        </test>
+        
+           <test ID="GetLocation">
+            <method>GET</method>
+            <uri>/cspace-services/locationauthorities/${LocationAuth1.CSID}/items/${Location1.CSID}?showRelations=true</uri>
+        </test>
+        
+               </testGroup>
+</xmlReplay>
index b6be3b3bfcab6a697753aa9a868219e5e352b5de..05689825d6709c0d3286aee53a714a7bd497ebf6 100644 (file)
@@ -34,6 +34,7 @@ public interface AuthorityItemJAXBSchema {
        final static String SHORT_DISPLAY_NAME_COMPUTED = "shortDisplayNameComputed";\r
        final static String IN_AUTHORITY = "inAuthority";\r
        final static String REF_NAME = "refName";\r
+       final static String ORDER = "order";\r
        final static String SHORT_IDENTIFIER = "shortIdentifier";\r
        final static String TERM_STATUS = "termStatus";\r
        final static String CSID = "csid";\r
index e97d2a646a43674c3681e91f26280352d878eb48..2c293c42cdf0916695dbdbe9c0129d9112e2fc52 100644 (file)
  */
 package org.collectionspace.services.common.vocabulary;
 
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.util.List;
-
-import javax.management.relation.Relation;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.Encoded;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.Request;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriBuilder;
-import javax.ws.rs.core.UriInfo;
-
 import org.collectionspace.services.client.IQueryManager;
-import org.collectionspace.services.client.PayloadInputPart;
-import org.collectionspace.services.client.PayloadOutputPart;
 import org.collectionspace.services.client.PoxPayloadIn;
 import org.collectionspace.services.client.PoxPayloadOut;
-import org.collectionspace.services.client.RelationClient;
 import org.collectionspace.services.client.workflow.WorkflowClient;
-import org.collectionspace.services.common.document.JaxbUtils;
-import org.collectionspace.services.common.relation.IRelationsManager;
-import org.collectionspace.services.common.vocabulary.AuthorityJAXBSchema;
-import org.collectionspace.services.common.vocabulary.AuthorityItemJAXBSchema;
-import org.collectionspace.services.common.vocabulary.nuxeo.AuthorityDocumentModelHandler;
-import org.collectionspace.services.common.vocabulary.nuxeo.AuthorityItemDocumentModelHandler;
-import org.collectionspace.services.common.workflow.service.nuxeo.WorkflowDocumentModelHandler;
 import org.collectionspace.services.common.AbstractMultiPartCollectionSpaceResourceImpl;
 import org.collectionspace.services.common.ClientType;
+import org.collectionspace.services.common.ResourceBase;
 import org.collectionspace.services.common.ServiceMain;
 import org.collectionspace.services.common.ServiceMessages;
+import org.collectionspace.services.common.XmlTools;
 import org.collectionspace.services.common.api.RefName;
+import org.collectionspace.services.common.api.Tools;
 import org.collectionspace.services.common.authorityref.AuthorityRefDocList;
 import org.collectionspace.services.common.authorityref.AuthorityRefList;
 import org.collectionspace.services.common.context.JaxRsContext;
@@ -73,19 +43,20 @@ import org.collectionspace.services.common.context.MultipartServiceContextImpl;
 import org.collectionspace.services.common.context.RemoteServiceContext;
 import org.collectionspace.services.common.context.ServiceBindingUtils;
 import org.collectionspace.services.common.context.ServiceContext;
-import org.collectionspace.services.common.document.BadRequestException;
 import org.collectionspace.services.common.document.DocumentException;
 import org.collectionspace.services.common.document.DocumentFilter;
 import org.collectionspace.services.common.document.DocumentHandler;
 import org.collectionspace.services.common.document.DocumentNotFoundException;
 import org.collectionspace.services.common.document.DocumentWrapper;
+import org.collectionspace.services.common.query.QueryManager;
+import org.collectionspace.services.common.relation.IRelationsManager;
 import org.collectionspace.services.common.repository.RepositoryClient;
 import org.collectionspace.services.common.security.UnauthorizedException;
-import org.collectionspace.services.common.query.QueryManager;
+import org.collectionspace.services.common.vocabulary.nuxeo.AuthorityDocumentModelHandler;
+import org.collectionspace.services.common.vocabulary.nuxeo.AuthorityItemDocumentModelHandler;
+import org.collectionspace.services.common.workflow.service.nuxeo.WorkflowDocumentModelHandler;
 import org.collectionspace.services.nuxeo.client.java.RemoteDocumentModelHandlerImpl;
-import org.collectionspace.services.nuxeo.util.NuxeoUtils;
 import org.collectionspace.services.relation.RelationResource;
-import org.collectionspace.services.relation.RelationsCommon;
 import org.collectionspace.services.relation.RelationsCommonList;
 import org.collectionspace.services.relation.RelationshipType;
 import org.jboss.resteasy.util.HttpResponseCodes;
@@ -93,13 +64,32 @@ import org.nuxeo.ecm.core.api.DocumentModel;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+import java.util.List;
+
 /**
  * The Class AuthorityResource.
  */
 @Consumes("application/xml")
 @Produces("application/xml")
-public abstract class AuthorityResource<AuthCommon, AuthCommonList, AuthItemCommonList, AuthItemHandler> extends
-       AbstractMultiPartCollectionSpaceResourceImpl {
+public abstract class AuthorityResource<AuthCommon, AuthCommonList, AuthItemCommonList, AuthItemHandler>
+        //extends ResourceBase {
+        extends AbstractMultiPartCollectionSpaceResourceImpl {
 
        protected Class<AuthCommon> authCommonClass;
        protected Class<?> resourceClass;
@@ -923,5 +913,31 @@ public abstract class AuthorityResource<AuthCommon, AuthCommonList, AuthItemComm
                        throw bigReThrow(e, ServiceMessages.DELETE_FAILED + "  itemcsid: " + itemcsid+ " parentcsid:" + parentcsid);
                }
        }
+
+    public final static String hierarchy = "hierarchy";
+    @GET
+    @Path("{csid}/items/{itemcsid}/"+hierarchy)
+    @Produces("application/xml")
+    public String getHierarchy(@PathParam("csid") String csid,
+                                           @PathParam("itemcsid") String itemcsid,
+                                           @Context UriInfo ui) throws Exception {
+        try {
+            // All items in dive can look at their child uri's to get uri.  So we calculate the very first one.  We could also do a GET and look at the common part uri field, but why...?
+            String calledUri = ui.getPath();
+            String uri = "/"+calledUri.substring(0, (calledUri.length()-("/"+hierarchy).length()));
+            ServiceContext ctx = createServiceContext(getItemServiceName());
+            ctx.setUriInfo(ui);
+            String direction = ui.getQueryParameters().getFirst(Hierarchy.directionQP);
+            if (Tools.notBlank(direction) && Hierarchy.direction_parents.equals(direction)){
+                return Hierarchy.surface(ctx, itemcsid, uri);
+            } else {
+                return Hierarchy.dive(ctx, itemcsid, uri);
+            }
+        } catch (Exception e){
+            throw bigReThrow(e, "Error showing hierarchy", itemcsid);
+        }
+    }
+
+
     
 }
diff --git a/services/authority/src/main/java/org/collectionspace/services/common/vocabulary/Hierarchy.java b/services/authority/src/main/java/org/collectionspace/services/common/vocabulary/Hierarchy.java
new file mode 100644 (file)
index 0000000..641e02f
--- /dev/null
@@ -0,0 +1,192 @@
+/**
+ *  This document is a part of the source code and related artifacts
+ *  for CollectionSpace, an open source collections management system
+ *  for museums and related institutions:
+
+ *  http://www.collectionspace.org
+ *  http://wiki.collectionspace.org
+
+ *  Copyright 2011 University of California at Berkeley
+
+ *  Licensed under the Educational Community License (ECL), Version 2.0.
+ *  You may not use this file except in compliance with this License.
+
+ *  You may obtain a copy of the ECL 2.0 License at
+
+ *  https://source.collectionspace.org/collection-space/LICENSE.txt
+
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.collectionspace.services.common.vocabulary;
+
+import org.collectionspace.services.common.XmlTools;
+import org.collectionspace.services.common.api.Tools;
+import org.collectionspace.services.common.context.ServiceContext;
+import org.collectionspace.services.common.relation.IRelationsManager;
+import org.collectionspace.services.relation.RelationResource;
+import org.collectionspace.services.relation.RelationsCommonList;
+import org.collectionspace.services.relation.RelationsDocListItem;
+import org.collectionspace.services.relation.RelationshipType;
+
+import javax.ws.rs.core.MultivaluedMap;
+import java.util.List;
+
+/**
+ * @author Laramie Crocker
+ */
+public class Hierarchy {
+
+    public static final String directionQP = "direction";
+    public static final String direction_parents = "parents";
+
+
+    /**Call with the URI and CSID of the root element of the tree you wish to inspect.  The uri can be a blank string.
+     * @param uri informational, optional - if not known, pass an empty String.
+     * @return String of XML document, including xml processing instruction, root node is "&lt;hierarchy&gt;".
+     */
+    public static String dive(ServiceContext ctx, String itemcsid, String uri) {
+        String result = dive(ctx, itemcsid, uri, true);
+        result =  "<?xml version='1.0' ?><hierarchy>"+result+"</hierarchy>";
+        try {
+            result = XmlTools.prettyPrint(result);
+        } catch (Exception e){
+        }
+        return result;
+    }
+
+    private static String dive(ServiceContext ctx, String itemcsid, String uri, boolean lookupFirstName) {
+        MultivaluedMap queryParams = ctx.getUriInfo().getQueryParameters();
+        //Run getList() once as sent to get childListOuter:
+        queryParams.putSingle(IRelationsManager.PREDICATE_QP, RelationshipType.HAS_BROADER.value());
+        queryParams.putSingle(IRelationsManager.SUBJECT_QP, null);
+        queryParams.putSingle(IRelationsManager.SUBJECT_TYPE_QP, null);
+        queryParams.putSingle(IRelationsManager.OBJECT_QP, itemcsid);
+        queryParams.putSingle(IRelationsManager.OBJECT_TYPE_QP, null);
+        RelationsCommonList childListOuter = (new RelationResource()).getList(ctx.getUriInfo());    //magically knows all query params because they are in the context.
+        List<RelationsCommonList.RelationListItem> childList = childListOuter.getRelationListItem();
+
+        StringBuffer sb = new StringBuffer();
+
+        if (lookupFirstName && childList.size() > 0) {
+            RelationsCommonList.RelationListItem firstItem = childList.get(0);
+            sb.append("<uri>" + firstItem.getObject().getUri() + "</uri>\r\n");
+            sb.append("<uri-called>" + uri + "</uri-called>\r\n");
+            sb.append("<name>" + firstItem.getObject().getName() + "</name><number>" + firstItem.getObject().getNumber() + "</number>\r\n");
+        } else {
+            sb.append("<uri>" + uri + "</uri>\r\n");
+        }
+        sb.append("<csid>" + itemcsid + "</csid>\r\n");
+        sb.append("<children>\r\n");
+        for (RelationsCommonList.RelationListItem item : childList) {
+            RelationsDocListItem parent = item.getObject();
+            RelationsDocListItem child = item.getSubject();
+            String childCSID = child.getCsid();
+            String childURI = child.getUri();
+            sb.append("<child>\r\n");
+            sb.append("<parent-uri>" +parent.getUri() + "</parent-uri>\r\n");
+            sb.append("  <name>" + child.getName() + "</name><number>" + child.getNumber() + "</number>\r\n");
+            String s = dive(ctx, childCSID, childURI, false);
+            sb.append(s);
+            sb.append("</child>\r\n");
+        }
+        sb.append("</children>\r\n");
+        return sb.toString();
+    }
+
+    public static String surface(ServiceContext ctx, String itemcsid, String uri) {
+        String result = surface(ctx, itemcsid, uri, true).resultBuffer.toString();
+        result =  "<?xml version='1.0' ?><hierarchy direction='"+direction_parents+"'>"+result+"</hierarchy>";
+        try {
+            result = XmlTools.prettyPrint(result);
+        } catch (Exception e){
+        }
+        return result;
+    }
+    private static class SurfaceResultStruct {
+        public StringBuffer resultBuffer;
+        public boolean noParents = false;
+    }
+    private static SurfaceResultStruct surface(ServiceContext ctx, String itemcsid, String uri, boolean first) {
+        MultivaluedMap queryParams = ctx.getUriInfo().getQueryParameters();
+        //Run getList() once as sent to get parentListOuter:
+        queryParams.putSingle(IRelationsManager.PREDICATE_QP, RelationshipType.HAS_BROADER.value());
+        queryParams.putSingle(IRelationsManager.SUBJECT_QP, itemcsid);
+        queryParams.putSingle(IRelationsManager.SUBJECT_TYPE_QP, null);
+        queryParams.putSingle(IRelationsManager.OBJECT_QP, null);
+        queryParams.putSingle(IRelationsManager.OBJECT_TYPE_QP, null);
+        RelationsCommonList parentListOuter = (new RelationResource()).getList(ctx.getUriInfo());    //magically knows all query params because they are in the context.
+        List<RelationsCommonList.RelationListItem> parentList = parentListOuter.getRelationListItem();
+
+        StringBuffer sbOuter = new StringBuffer();
+        SurfaceResultStruct resultStruct = new SurfaceResultStruct();
+        resultStruct.resultBuffer = sbOuter;
+
+
+        sbOuter.append("<uri>" + uri + "</uri>\r\n");
+        sbOuter.append("<csid>" + itemcsid + "</csid>\r\n");
+
+        StringBuffer sb = new StringBuffer();
+
+        String name = "";
+        String otherNames="";
+        String number = "";
+        String otherNumbers = "";
+
+        sb.append("<parents>\r\n");
+        if (parentList.size()==0){
+            resultStruct.noParents = true;
+        }
+        for (RelationsCommonList.RelationListItem item : parentList) {
+            resultStruct.noParents = false;
+            RelationsDocListItem parent = item.getObject();
+            RelationsDocListItem child = item.getSubject();
+            String parentCSID =parent.getCsid();
+            String parentURI = parent.getUri();
+
+            String aName = child.getName();
+            String aNumber = child.getNumber();
+            if (name.length()>0 && (!name.equals(aName))){
+                otherNames = otherNames+";"+aName;
+            } else {
+                name = aName;
+            }
+            if (number.length()>0 && (!number.equals(aNumber))){
+                otherNumbers = otherNumbers+";"+aNumber;
+            } else {
+                number = aName;
+            }
+
+            sb.append("<parent>\r\n");
+            //sb.append("<parent-uri>" +parentURI + "</parent-uri>\r\n");
+
+            SurfaceResultStruct struct = surface(ctx, parentCSID, parentURI, false);
+            StringBuffer surfaceResult = struct.resultBuffer;
+
+            if (struct.noParents){
+                //when there are no more parents, there is no way to look up the name and number, so use this trick:
+                sb.append("<name>" + parent.getName() + "</name><number>" + parent.getNumber() + "</number>\r\n");
+            }
+
+            sb.append(surfaceResult);
+            sb.append("</parent>\r\n");
+        }
+        sb.append("</parents>\r\n");
+
+
+        if (name.length()>0)sbOuter.append("  <name>" +name + "</name>\r\n");
+        if (otherNames.length()>0)    sbOuter.append("  <name-mismatches-by-parents>" +otherNames + "</name-mismatches-by-parents>\r\n");
+
+        if (number.length()>0) sbOuter.append("<number>" +number + "</number>\r\n");
+        if (otherNumbers.length()>0) sbOuter.append("  <number-mismatches-by-parents>" +otherNumbers + "</number-mismatches-by-parents>\r\n");
+
+        sbOuter.append(sb);
+
+        return resultStruct;
+    }
+
+}
index e97ff9d96d2fe9ca884bbcd0ea16dc3f8ace341e..6a344e80ffc4a6d65318aa3d333f46bdc6e8c59e 100644 (file)
@@ -101,9 +101,14 @@ public class XmlTools {
         return doc;
     }
 
+    public static String prettyPrint(String xml) throws Exception {
+        Document doc = textToXMLDocument(xml);
+        return prettyPrint(doc,  "    ");
+    }
+
     public static String prettyPrint(Document document) {
-            return prettyPrint(document, null);
-        }
+        return prettyPrint(document, null);
+    }
 
     public static String prettyPrint(Document document, String indentString) {
         String prettyHTML;
index 743c4b4b5aa346a0cf48a7437b1bfbdc07fc9d3c..d4fb4359663113f4c8c5702e09efb1238acc43bf 100644 (file)
@@ -121,7 +121,11 @@ public abstract class   RemoteDocumentModelHandlerImpl<T, TL>
                     Map<String, Object> unQObjectProperties = extractPart(docModel, partLabel, partMeta);
                     addOutputPart(unQObjectProperties, partLabel, partMeta);
                 } catch (Throwable t){
-                    System.out.println("===============================\r\nUnable to addOutputPart: "+partLabel+" error: "+t);
+
+                    System.out.println("===============================\r\nUnable to addOutputPart: "+partLabel
+                                               +" in serviceContextPath: "+this.getServiceContextPath()
+                                               +" with URI: "+this.getServiceContext().getUriInfo().getPath()
+                                               +" error: "+t);
                 }
                }
         } else {
index 7202c731e877c467c2eb226c529b9f33035177ab..a38f369e94b3259c39a331bce30dd90d02f16045 100644 (file)
@@ -27,6 +27,6 @@
                <xs:element name="shortIdentifier" type="xs:string"/>
                <xs:element name="termStatus" type="xs:string"/>
                <xs:element name="displayName" type="xs:string"/>
-
+               <xs:element name="order" type="xs:string"/>
 </xs:schema>
 
index add19438f709f328a32655812d5280971722d758..dca9978f27956967b8b91e20703718b52fe07adc 100644 (file)
@@ -1,35 +1,36 @@
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<xs:schema 
-  xmlns:xs="http://www.w3.org/2001/XMLSchema"
-  xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
-  jaxb:version="1.0" elementFormDefault="unqualified"  
-  xmlns:ns="http://collectionspace.org/services/vocabulary"
-  xmlns="http://collectionspace.org/services/vocabulary"
-  targetNamespace="http://collectionspace.org/services/vocabulary"
-  version="0.1"
->
+<xs:schema
+        xmlns:xs="http://www.w3.org/2001/XMLSchema"
+        xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
+        jaxb:version="1.0" elementFormDefault="unqualified"
+        xmlns:ns="http://collectionspace.org/services/vocabulary"
+        xmlns="http://collectionspace.org/services/vocabulary"
+        targetNamespace="http://collectionspace.org/services/vocabulary"
+        version="0.1"
+        >
 
 
-<!-- avoid XmlRootElement nightnmare, see http://weblogs.java.net/blog/kohsuke/archive/2006/03/why_does_jaxb_p.html-->
-<!-- See http://wiki.collectionspace.org/display/collectionspace/Vocabulary+Schema -->    
-    
+    <!-- avoid XmlRootElement nightnmare, see http://weblogs.java.net/blog/kohsuke/archive/2006/03/why_does_jaxb_p.html-->
+    <!-- See http://wiki.collectionspace.org/display/collectionspace/Vocabulary+Schema -->
+
     <!-- Vocabularyitem -->
-       <xs:element name="vocabularyitems_common">
-               <xs:complexType>
-                       <xs:sequence>
-                               <!--  Common identifier -->
-                               <xs:element name="csid" type="xs:string" />
+    <xs:element name="vocabularyitems_common">
+        <xs:complexType>
+            <xs:sequence>
+                <!--  Common identifier -->
+                <xs:element name="csid" type="xs:string"/>
+
+                <!--  Vocabularyitem Information Group -->
+                <xs:element name="inAuthority" type="xs:string"/>
+                <xs:element name="displayName" type="xs:string"/>
+                <xs:element name="shortIdentifier" type="xs:string"/>
+                <xs:element name="refName" type="xs:string"/>
+                <xs:element name="termStatus" type="xs:string"/>
+                <xs:element name="order" type="xs:string"/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
 
-                               <!--  Vocabularyitem Information Group -->
-                               <xs:element name="inAuthority" type="xs:string" />
-                               <xs:element name="displayName" type="xs:string" />
-                               <xs:element name="shortIdentifier" type="xs:string" />
-                               <xs:element name="refName" type="xs:string" />
-                               <xs:element name="termStatus" type="xs:string" />
-                       </xs:sequence>
-               </xs:complexType>
-       </xs:element>
-    
     <!-- This is the base class for paginated lists -->
     <xs:complexType name="abstractCommonListItem">
         <xs:annotation>
     <xs:element name="vocabularyitems-common-list">
         <xs:complexType>
             <xs:complexContent>
-                <xs:extension base="abstractCommonListItem">                                        
+                <xs:extension base="abstractCommonListItem">
                     <xs:sequence>
                         <xs:element name="vocabularyitem_list_item" maxOccurs="unbounded">
                             <xs:complexType>
                                 <xs:sequence>
                                     <xs:element name="displayName" type="xs:string"
-                                        minOccurs="1" />
-                                                                       <xs:element name="shortIdentifier" type="xs:string"
-                                        minOccurs="1" />
+                                                minOccurs="1"/>
+                                    <xs:element name="shortIdentifier" type="xs:string"
+                                                minOccurs="1"/>
+                                    <xs:element name="order" type="xs:string"
+                                                minOccurs="0"/>
                                     <!-- uri to retrieve vocabularyitem details -->
                                     <xs:element name="uri" type="xs:anyURI"
-                                        minOccurs="1" />
+                                                minOccurs="1"/>
                                     <xs:element name="refName" type="xs:string"
-                                        minOccurs="1" />
+                                                minOccurs="1"/>
                                     <xs:element name="csid" type="xs:string"
-                                        minOccurs="1" />
+                                                minOccurs="1"/>
                                 </xs:sequence>
                             </xs:complexType>
                         </xs:element>
                     </xs:sequence>
                 </xs:extension>
-            </xs:complexContent>                    
+            </xs:complexContent>
         </xs:complexType>
     </xs:element>
-    
+
 </xs:schema>
 
index 0d751ac674569e1f2142e5275a0400ecfe7935d0..54683b20886c8135e1cee924d7cbc43e19e820f9 100644 (file)
@@ -68,7 +68,7 @@ public class VocabularyItemDocumentModelHandler
                        DocumentWrapper<DocumentModelList> wrapDoc) throws Exception {
                VocabularyitemsCommonList coList = extractPagingInfo(new VocabularyitemsCommonList(), wrapDoc);
         AbstractCommonList commonList = (AbstractCommonList) coList;
-        commonList.setFieldsReturned("displayName|refName|shortIdentifier|uri|csid");
+        commonList.setFieldsReturned("displayName|refName|shortIdentifier|order|uri|csid");
                
                List<VocabularyitemsCommonList.VocabularyitemListItem> list = coList.getVocabularyitemListItem();
                Iterator<DocumentModel> iter = wrapDoc.getWrappedObject().iterator();
@@ -80,8 +80,10 @@ public class VocabularyItemDocumentModelHandler
                                        AuthorityItemJAXBSchema.DISPLAY_NAME));
                        ilistItem.setShortIdentifier((String) docModel.getProperty(commonPartLabel,
                                        AuthorityItemJAXBSchema.SHORT_IDENTIFIER));
-                       ilistItem.setRefName((String) docModel.getProperty(commonPartLabel, 
-                                       AuthorityItemJAXBSchema.REF_NAME));
+            ilistItem.setRefName((String) docModel.getProperty(commonPartLabel,
+                                AuthorityItemJAXBSchema.REF_NAME));
+            ilistItem.setOrder((String) docModel.getProperty(commonPartLabel,
+                              AuthorityItemJAXBSchema.ORDER));
                        String id = getCsid(docModel);//NuxeoUtils.extractId(docModel.getPathAsString());
                        ilistItem.setUri("/vocabularies/" + inAuthority + "/items/" + id);
                        ilistItem.setCsid(id);