]> git.aero2k.de Git - tmp/jakarta-migration.git/commitdiff
CSPACE-1927 Update to displayName for an authority item will update all the reference...
authorPatrick Schmitz <pschmitz@berkeley.edu>
Tue, 15 Nov 2011 00:22:26 +0000 (00:22 +0000)
committerPatrick Schmitz <pschmitz@berkeley.edu>
Tue, 15 Nov 2011 00:22:26 +0000 (00:22 +0000)
12 files changed:
services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/authrefs.xml
services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/res/loanout.res.xml [new file with mode: 0644]
services/IntegrationTests/src/test/resources/test-data/xmlreplay/xml-replay-master.xml
services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/AuthorityResource.java
services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/RefNameServiceUtils.java
services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/nuxeo/AuthorityItemDocumentModelHandler.java
services/common/src/main/cspace/config/services/tenants/tenant-bindings-proto.xml
services/common/src/main/java/org/collectionspace/services/common/config/TenantBindingConfigReaderImpl.java
services/common/src/main/java/org/collectionspace/services/common/context/ServiceBindingUtils.java
services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClientImpl.java
services/person/service/src/main/java/org/collectionspace/services/person/nuxeo/PersonAuthorityValidatorHandler.java
services/person/service/src/main/java/org/collectionspace/services/person/nuxeo/PersonValidatorHandler.java

index c319a4c1ecaca8ed23baa1cb4114b692215003ab..97102274c3eb55fd7e0a0c5c5012fbec60325804 100644 (file)
 <?xml version="1.0" encoding="UTF-8"?>\r
 <xmlReplay>\r
-    <!-- \r
-         testGroup ID="person" is not live.  It works, but may not clean up correctly. \r
-         For now, use ID="updatePerson"\r
-    -->\r
-    <testGroup ID="AuthRefs" autoDeletePOSTS="true">\r
-        <test ID="PersonAuth1" auth="admin@core.collectionspace.org">\r
-            <method>POST</method>\r
-            <uri>/cspace-services/personauthorities/</uri>\r
-            <filename>authrefs/newPersonAuthority.xml</filename>\r
-        </test>\r
-        <test ID="Person1">\r
-            <method>POST</method>\r
-            <uri>/cspace-services/personauthorities/${PersonAuth1.CSID}/items/</uri>\r
-            <filename>authrefs/newPerson1.xml</filename>\r
-        </test>\r
-        <test ID="Person2">\r
-            <method>POST</method>\r
-            <uri>/cspace-services/personauthorities/${PersonAuth1.CSID}/items/</uri>\r
-            <filename>authrefs/newPerson2.xml</filename>\r
-        </test>\r
-\r
-        <test ID="loanout1" auth="test">\r
-            <method>POST</method>\r
-            <uri>/cspace-services/loansout/</uri>\r
-            <filename>authrefs/loanout.xml</filename>\r
-            <vars>\r
-                <var ID="loannum">42</var>\r
-                <var ID="person">${Person1.CSID}</var>\r
-            </vars>\r
-        </test>\r
-\r
-        <test ID="loanout2" auth="test">\r
-            <method>POST</method>\r
-            <uri>/cspace-services/loansout/</uri>\r
-            <filename>authrefs/loanout.xml</filename>\r
-            <vars>\r
-                <var ID="loannum">69</var>\r
-                <var ID="person">${Person2.CSID}</var>\r
-            </vars>\r
-        </test>\r
-\r
-        <test ID="UpdatePerson1">\r
-            <method>PUT</method>\r
-            <uri>/cspace-services/personauthorities/${PersonAuth1.CSID}/items/${Person1.CSID}</uri>\r
-            <filename>authrefs/updatePerson1.xml</filename>\r
-        </test>\r
-\r
-        <test ID="UpdatePerson2">\r
-            <method>PUT</method>\r
-            <uri>/cspace-services/personauthorities/${PersonAuth1.CSID}/items/${Person2.CSID}</uri>\r
-            <filename>authrefs/updatePerson2.xml</filename>\r
-        </test>\r
-    </testGroup>\r
+       <!-- \r
+                        testGroup ID="person" is not live.  It works, but may not clean up correctly. \r
+                        For now, use ID="updatePerson"\r
+       -->\r
+       <testGroup ID="AuthRefs" autoDeletePOSTS="true">\r
+               <test ID="PersonAuth1" auth="admin@core.collectionspace.org">\r
+                       <method>POST</method>\r
+                       <uri>/cspace-services/personauthorities/</uri>\r
+                       <filename>authrefs/newPersonAuthority.xml</filename>\r
+               </test>\r
+               <test ID="Person1">\r
+                       <method>POST</method>\r
+                       <uri>/cspace-services/personauthorities/${PersonAuth1.CSID}/items/</uri>\r
+                       <filename>authrefs/newPerson1.xml</filename>\r
+               </test>\r
+               <test ID="Person2">\r
+                       <method>POST</method>\r
+                       <uri>/cspace-services/personauthorities/${PersonAuth1.CSID}/items/</uri>\r
+                       <filename>authrefs/newPerson2.xml</filename>\r
+               </test>\r
 \r
+        <test ID="GetPerson1">\r
+                       <method>GET</method>\r
+                       <uri>/cspace-services/personauthorities/${PersonAuth1.CSID}/items/${Person1.CSID}</uri>\r
+               </test>\r
+\r
+        <test ID="GetPerson2">\r
+                       <method>GET</method>\r
+                       <uri>/cspace-services/personauthorities/${PersonAuth1.CSID}/items/${Person2.CSID}</uri>\r
+               </test>\r
+\r
+               <test ID="loanout1" auth="test">\r
+                       <method>POST</method>\r
+                       <uri>/cspace-services/loansout/</uri>\r
+                       <filename>authrefs/loanout.xml</filename>\r
+                       <vars>\r
+                               <var ID="loannum">42</var>\r
+                               <var ID="person">${GetPerson1.got("//refName")}</var>\r
+                       </vars>\r
+               </test>\r
+\r
+               <test ID="loanout2" auth="test">\r
+                       <method>POST</method>\r
+                       <uri>/cspace-services/loansout/</uri>\r
+                       <filename>authrefs/loanout.xml</filename>\r
+                       <vars>\r
+                               <var ID="loannum">102</var>\r
+                               <var ID="person">${GetPerson2.got("//refName")}</var>\r
+                       </vars>\r
+               </test>\r
+\r
+               <test ID="loanout3" auth="test">\r
+                       <method>POST</method>\r
+                       <uri>/cspace-services/loansout/</uri>\r
+                       <filename>authrefs/loanout.xml</filename>\r
+                       <vars>\r
+                               <var ID="loannum">103</var>\r
+                               <var ID="person">${GetPerson2.got("//refName")}</var>\r
+                       </vars>\r
+               </test>\r
+\r
+               <test ID="loanout4" auth="test">\r
+                       <method>POST</method>\r
+                       <uri>/cspace-services/loansout/</uri>\r
+                       <filename>authrefs/loanout.xml</filename>\r
+                       <vars>\r
+                               <var ID="loannum">104</var>\r
+                               <var ID="person">${GetPerson2.got("//refName")}</var>\r
+                       </vars>\r
+               </test>\r
+\r
+               <test ID="loanout5" auth="test">\r
+                       <method>POST</method>\r
+                       <uri>/cspace-services/loansout/</uri>\r
+                       <filename>authrefs/loanout.xml</filename>\r
+                       <vars>\r
+                               <var ID="loannum">105</var>\r
+                               <var ID="person">${GetPerson2.got("//refName")}</var>\r
+                       </vars>\r
+               </test>\r
+\r
+               <test ID="loanout6" auth="test">\r
+                       <method>POST</method>\r
+                       <uri>/cspace-services/loansout/</uri>\r
+                       <filename>authrefs/loanout.xml</filename>\r
+                       <vars>\r
+                               <var ID="loannum">106</var>\r
+                               <var ID="person">${GetPerson2.got("//refName")}</var>\r
+                       </vars>\r
+               </test>\r
+\r
+               <test ID="loanout7" auth="test">\r
+                       <method>POST</method>\r
+                       <uri>/cspace-services/loansout/</uri>\r
+                       <filename>authrefs/loanout.xml</filename>\r
+                       <vars>\r
+                               <var ID="loannum">107</var>\r
+                               <var ID="person">${GetPerson2.got("//refName")}</var>\r
+                       </vars>\r
+               </test>\r
+\r
+               <test ID="loanout8" auth="test">\r
+                       <method>POST</method>\r
+                       <uri>/cspace-services/loansout/</uri>\r
+                       <filename>authrefs/loanout.xml</filename>\r
+                       <vars>\r
+                               <var ID="loannum">108</var>\r
+                               <var ID="person">${GetPerson2.got("//refName")}</var>\r
+                       </vars>\r
+               </test>\r
+\r
+               <test ID="loanout9" auth="test">\r
+                       <method>POST</method>\r
+                       <uri>/cspace-services/loansout/</uri>\r
+                       <filename>authrefs/loanout.xml</filename>\r
+                       <vars>\r
+                               <var ID="loannum">109</var>\r
+                               <var ID="person">${GetPerson2.got("//refName")}</var>\r
+                       </vars>\r
+               </test>\r
+\r
+               <test ID="loanout10" auth="test">\r
+                       <method>POST</method>\r
+                       <uri>/cspace-services/loansout/</uri>\r
+                       <filename>authrefs/loanout.xml</filename>\r
+                       <vars>\r
+                               <var ID="loannum">110</var>\r
+                               <var ID="person">${GetPerson2.got("//refName")}</var>\r
+                       </vars>\r
+               </test>\r
+\r
+               <test ID="UpdatePerson1">\r
+                       <method>PUT</method>\r
+                       <uri>/cspace-services/personauthorities/${PersonAuth1.CSID}/items/${Person1.CSID}</uri>\r
+                       <filename>authrefs/updatePerson1.xml</filename>\r
+               </test>\r
+\r
+               <test ID="UpdatePerson2">\r
+                       <method>PUT</method>\r
+                       <uri>/cspace-services/personauthorities/${PersonAuth1.CSID}/items/${Person2.CSID}</uri>\r
+                       <filename>authrefs/updatePerson2.xml</filename>\r
+               </test>\r
+\r
+        <test ID="GetFirstUpdatedPerson">\r
+                       <method>GET</method>\r
+                       <uri>/cspace-services/personauthorities/${PersonAuth1.CSID}/items/${Person1.CSID}</uri>\r
+                       <response>\r
+                               <expected level="ADDOK" />\r
+                               <filename>authrefs/updatePerson1.xml</filename>\r
+                       </response>\r
+               </test>\r
+\r
+        <test ID="GetSecondUpdatedPerson">\r
+                       <method>GET</method>\r
+                       <uri>/cspace-services/personauthorities/${PersonAuth1.CSID}/items/${Person2.CSID}</uri>\r
+                       <response>\r
+                               <expected level="ADDOK" />\r
+                               <filename>authrefs/updatePerson2.xml</filename>\r
+                       </response>\r
+               </test>\r
+\r
+               <test ID="afterUpdateGetLoan1">\r
+                       <method>GET</method>\r
+                       <uri>/cspace-services/loansout/${loanout1.CSID}</uri>\r
+                       <response>\r
+                               <expected level="ADDOK" />\r
+                               <label>loansout_common</label>\r
+                               <filename>authrefs/res/loanout.res.xml</filename>\r
+                               <vars>\r
+                                       <var ID="person">${GetFirstUpdatedPerson.got("//refName")}</var>\r
+                               </vars>\r
+                        </response>\r
+               </test>\r
+               \r
+               <test ID="afterUpdateGetLoan2">\r
+                       <method>GET</method>\r
+                       <uri>/cspace-services/loansout/${loanout2.CSID}</uri>\r
+                       <response>\r
+                               <expected level="ADDOK" />\r
+                               <label>loansout_common</label>\r
+                               <filename>authrefs/res/loanout.res.xml</filename>\r
+                               <vars>\r
+                                       <var ID="person">${GetSecondUpdatedPerson.got("//refName")}</var>\r
+                               </vars>\r
+                        </response>\r
+               </test>\r
+               <test ID="afterUpdateGetLoan5">\r
+                       <method>GET</method>\r
+                       <uri>/cspace-services/loansout/${loanout5.CSID}</uri>\r
+                       <response>\r
+                               <expected level="ADDOK" />\r
+                               <label>loansout_common</label>\r
+                               <filename>authrefs/res/loanout.res.xml</filename>\r
+                               <vars>\r
+                                       <var ID="person">${GetSecondUpdatedPerson.got("//refName")}</var>\r
+                               </vars>\r
+                        </response>\r
+               </test>\r
+\r
+               <test ID="afterUpdateGetLoan9">\r
+                       <method>GET</method>\r
+                       <uri>/cspace-services/loansout/${loanout9.CSID}</uri>\r
+                       <response>\r
+                               <expected level="ADDOK" />\r
+                               <label>loansout_common</label>\r
+                               <filename>authrefs/res/loanout.res.xml</filename>\r
+                               <vars>\r
+                                       <var ID="person">${GetSecondUpdatedPerson.got("//refName")}</var>\r
+                               </vars>\r
+                        </response>\r
+               </test>\r
+\r
+\r
+       </testGroup>\r
 </xmlReplay>\r
diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/res/loanout.res.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/res/loanout.res.xml
new file mode 100644 (file)
index 0000000..ee63091
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document name="loansout">
+  <ns2:loansout_common xmlns:ns2="http://collectionspace.org/services/loanout" xmlns:ns3="http://collectionspace.org/services/jaxb">
+    <borrowersContact>${person}</borrowersContact>
+  </ns2:loansout_common>
+</document>
+
index e78cd5c63bda4f0c68d0a37f1296b6b484af6d5b..686cb68e3f7be8fc2ca30c996122533c1b92ba1f 100755 (executable)
@@ -53,6 +53,8 @@
     <run controlFile="batch/batch.xml" />\r
     <run controlFile="report/report.xml" />\r
     <run controlFile="vocabulary/vocabulary.xml" testGroup="TestOrder" />\r
+               <run controlFile="authrefs/authrefs.xml" testGroup="AuthRefs" />\r
+\r
     \r
 </xmlReplayMaster>\r
 \r
index 2764731c50e9fc522305f16ef0ee171079bc0dbd..0ada88dd6c0419b0a22329897f58c96db7f4770c 100644 (file)
@@ -740,9 +740,13 @@ public abstract class AuthorityResource<AuthCommon, AuthItemHandler>
             DocumentModel docModel = docWrapper.getWrappedObject();
             String refName = (String) docModel.getPropertyValue(AuthorityItemJAXBSchema.REF_NAME);
 
+            // Could be smarter about using the list from above, and/or allowing multiple
+            ArrayList<String> serviceTypes = new ArrayList<String>(1);
+            serviceTypes.add(serviceType);
+            
             authRefDocList = RefNameServiceUtils.getAuthorityRefDocs(ctx,
                     repoClient,
-                    serviceType,
+                    serviceTypes,
                     refName,
                     getRefPropName(),
                     myFilter.getPageSize(), myFilter.getStartPage(), true /*computeTotal*/);
index 56fb517791ec1f7a6162b293f369514b3f801393..eedc243c7cc9fd1f4957e85bb72f355ca7fa04bd 100644 (file)
@@ -33,11 +33,15 @@ import java.util.Map;
 import org.nuxeo.ecm.core.api.ClientException;\r
 import org.nuxeo.ecm.core.api.DocumentModel;\r
 import org.nuxeo.ecm.core.api.DocumentModelList;\r
+import org.nuxeo.ecm.core.api.model.Property;\r
+import org.nuxeo.ecm.core.api.model.PropertyException;\r
+import org.nuxeo.ecm.core.api.model.impl.primitives.StringProperty;\r
 import org.slf4j.Logger;\r
 import org.slf4j.LoggerFactory;\r
 \r
 import org.collectionspace.services.common.ServiceMain;\r
 import org.collectionspace.services.common.context.ServiceContext;\r
+import org.collectionspace.services.common.api.Tools;\r
 import org.collectionspace.services.common.authorityref.AuthorityRefDocList;\r
 import org.collectionspace.services.common.authorityref.AuthorityRefList;\r
 import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;\r
@@ -47,6 +51,7 @@ import org.collectionspace.services.common.document.DocumentNotFoundException;
 import org.collectionspace.services.common.document.DocumentUtils;\r
 import org.collectionspace.services.common.document.DocumentWrapper;\r
 import org.collectionspace.services.common.repository.RepositoryClient;\r
+import org.collectionspace.services.nuxeo.client.java.RepositoryJavaClientImpl;\r
 import org.collectionspace.services.common.service.ServiceBindingType;\r
 import org.collectionspace.services.jaxb.AbstractCommonList;\r
 import org.collectionspace.services.nuxeo.util.NuxeoUtils;\r
@@ -60,10 +65,12 @@ import org.collectionspace.services.nuxeo.util.NuxeoUtils;
 public class RefNameServiceUtils {\r
 \r
     private static final Logger logger = LoggerFactory.getLogger(RefNameServiceUtils.class);\r
+    \r
+    private static ArrayList<String> refNameServiceTypes = null;\r
 \r
     public static AuthorityRefDocList getAuthorityRefDocs(ServiceContext ctx,\r
             RepositoryClient repoClient,\r
-            String serviceType,\r
+            List<String> serviceTypes,\r
             String refName,\r
             String refPropName,\r
             int pageSize, int pageNum, boolean computeTotal) throws DocumentException, DocumentNotFoundException {\r
@@ -73,11 +80,96 @@ public class RefNameServiceUtils {
         commonList.setPageSize(pageSize);\r
         List<AuthorityRefDocList.AuthorityRefDocItem> list =\r
                 wrapperList.getAuthorityRefDocItem();\r
+        \r
+        Map<String, ServiceBindingType> queriedServiceBindings = new HashMap<String, ServiceBindingType>();\r
+        Map<String, Map<String, String>> authRefFieldsByService = new HashMap<String, Map<String, String>>();\r
+\r
+        DocumentModelList docList = findAuthorityRefDocs(ctx, repoClient, serviceTypes, refName, refPropName,\r
+                       queriedServiceBindings, authRefFieldsByService, pageSize, pageNum, computeTotal);\r
+\r
+        if (docList == null) { // found no authRef fields - nothing to process\r
+            return wrapperList;\r
+        }\r
+        // Set num of items in list. this is useful to our testing framework.\r
+        commonList.setItemsInPage(docList.size());\r
+        // set the total result size\r
+        commonList.setTotalItems(docList.totalSize());\r
+        \r
+        int nRefsFound = processRefObjsDocList(docList, refName, queriedServiceBindings, authRefFieldsByService,\r
+                                                       list, null);\r
+        if(logger.isDebugEnabled()  && (nRefsFound < docList.size())) {\r
+               logger.debug("Internal curiosity: got fewer matches of refs than # docs matched...");\r
+        }\r
+        return wrapperList;\r
+    }\r
+    \r
+    private static ArrayList<String> getRefNameServiceTypes() {\r
+       if(refNameServiceTypes == null) {\r
+               refNameServiceTypes = new ArrayList<String>();\r
+               refNameServiceTypes.add(ServiceBindingUtils.SERVICE_TYPE_AUTHORITY);\r
+               refNameServiceTypes.add(ServiceBindingUtils.SERVICE_TYPE_OBJECT);\r
+               refNameServiceTypes.add(ServiceBindingUtils.SERVICE_TYPE_PROCEDURE);\r
+       }\r
+       return refNameServiceTypes;\r
+    }\r
+    \r
+    public static int updateAuthorityRefDocs(ServiceContext ctx,\r
+            RepositoryClient repoClient,\r
+            String oldRefName,\r
+            String newRefName,\r
+            String refPropName ) {\r
+        Map<String, ServiceBindingType> queriedServiceBindings = new HashMap<String, ServiceBindingType>();\r
+        Map<String, Map<String, String>> authRefFieldsByService = new HashMap<String, Map<String, String>>();\r
+        int nRefsFound = 0;\r
+        if(!(repoClient instanceof RepositoryJavaClientImpl)) {\r
+               throw new InternalError("updateAuthorityRefDocs() called with unknown repoClient type!");\r
+        }\r
+        try {\r
+               final int pageSize = 100;       // Seems like a good value - no real data to set this well.\r
+               int pageNumProcessed = 1;\r
+               while(true) {   // Keep looping until we find all the refs.\r
+                       logger.debug("updateAuthorityRefDocs working on page: "+pageNumProcessed);\r
+                       // Note that we always ask the Repo for the first page, since each page we process\r
+                       // should not be found in successive searches.\r
+                       DocumentModelList docList = findAuthorityRefDocs(ctx, repoClient, getRefNameServiceTypes(), oldRefName, refPropName,\r
+                                       queriedServiceBindings, authRefFieldsByService, pageSize, 0, false);\r
+               \r
+                       if((docList == null)                    // found no authRef fields - nothing to do\r
+                               || (docList.size() == 0)) {     // No more to handle\r
+                               logger.debug("updateAuthorityRefDocs no more results");\r
+                           break;\r
+                       }\r
+                       logger.debug("updateAuthorityRefDocs curr page result list size: "+docList.size());\r
+                       int nRefsFoundThisPage = processRefObjsDocList(docList, oldRefName, queriedServiceBindings, authRefFieldsByService,\r
+                                                                       null, newRefName);\r
+                       if(nRefsFoundThisPage>0) {\r
+                               ((RepositoryJavaClientImpl)repoClient).saveDocListWithoutHandlerProcessing(ctx, docList, true);\r
+                               nRefsFound += nRefsFoundThisPage;\r
+                       }\r
+                       pageNumProcessed++;\r
+               }\r
+        } catch(Exception e) {\r
+               logger.error("Internal error updating the AuthorityRefDocs: " + e.getLocalizedMessage());\r
+               logger.debug(Tools.errorToString(e, true));\r
+        }\r
+               logger.debug("updateAuthorityRefDocs replaced a total of: "+nRefsFound);\r
+        return nRefsFound;\r
+    }\r
+    \r
+    private static DocumentModelList findAuthorityRefDocs(ServiceContext ctx,\r
+            RepositoryClient repoClient,\r
+            List<String> serviceTypes,\r
+            String refName,\r
+            String refPropName,\r
+            Map<String, ServiceBindingType> queriedServiceBindings,\r
+            Map<String, Map<String, String>> authRefFieldsByService,\r
+            int pageSize, int pageNum, boolean computeTotal) throws DocumentException, DocumentNotFoundException {\r
 \r
         // Get the service bindings for this tenant\r
         TenantBindingConfigReaderImpl tReader =\r
                 ServiceMain.getInstance().getTenantBindingConfigReader();\r
-        List<ServiceBindingType> servicebindings = tReader.getServiceBindingsByType(ctx.getTenantId(), serviceType);\r
+        // We need to get all the procedures, authorities, and objects.\r
+        List<ServiceBindingType> servicebindings = tReader.getServiceBindingsByType(ctx.getTenantId(), serviceTypes);\r
         if (servicebindings == null || servicebindings.isEmpty()) {\r
                logger.error("RefNameServiceUtils.getAuthorityRefDocs: No services bindings found, cannot proceed!");\r
             return null;\r
@@ -87,28 +179,18 @@ public class RefNameServiceUtils {
         // TODO What if they are already escaped?\r
         String escapedRefName = refName.replaceAll("'", "\\\\'");\r
         ArrayList<String> docTypes = new ArrayList<String>();\r
-        Map<String, ServiceBindingType> queriedServiceBindings = new HashMap<String, ServiceBindingType>();\r
-        Map<String, Map<String, String>> authRefFieldsByService = new HashMap<String, Map<String, String>>();\r
         \r
         String query = computeWhereClauseForAuthorityRefDocs(escapedRefName, refPropName, docTypes, servicebindings, \r
                                                                                                queriedServiceBindings, authRefFieldsByService );\r
         if (query == null) { // found no authRef fields - nothing to query\r
-            return wrapperList;\r
+            return null;\r
         }\r
         // Now we have to issue the search\r
         DocumentWrapper<DocumentModelList> docListWrapper = repoClient.findDocs(ctx,\r
                 docTypes, query, pageSize, pageNum, computeTotal);\r
         // Now we gather the info for each document into the list and return\r
         DocumentModelList docList = docListWrapper.getWrappedObject();\r
-        // Set num of items in list. this is useful to our testing framework.\r
-        commonList.setItemsInPage(docList.size());\r
-        // set the total result size\r
-        commonList.setTotalItems(docList.totalSize());\r
-        \r
-        processRefObjsDocList(docList, refName, servicebindings,\r
-                                                       queriedServiceBindings, authRefFieldsByService,\r
-                                                       list, null);\r
-        return wrapperList;\r
+        return docList;\r
     }\r
     \r
     private static String computeWhereClauseForAuthorityRefDocs(\r
@@ -173,16 +255,28 @@ public class RefNameServiceUtils {
     /*\r
      * Runs through the list of found docs, processing them. \r
      * If list is non-null, then processing means gather the info for items.\r
-     * If list is null, and newRefName is non-null, then processing means replacing and updating.\r
+     * If list is null, and newRefName is non-null, then processing means replacing and updating. \r
+     *   If processing/updating, this must be called in teh context of an open session, and caller\r
+     *   must release Session after calling this.\r
+     * \r
      */\r
-    private static void processRefObjsDocList(DocumentModelList docList,\r
+    private static int processRefObjsDocList(\r
+               DocumentModelList docList,\r
                String refName,\r
-               List<ServiceBindingType> servicebindings,\r
                Map<String, ServiceBindingType> queriedServiceBindings,\r
                Map<String, Map<String, String>> authRefFieldsByService,\r
                        List<AuthorityRefDocList.AuthorityRefDocItem> list, \r
                        String newAuthorityRefName) {\r
+       if(newAuthorityRefName==null) {\r
+               if(list==null) {\r
+                       throw new InternalError("processRefObjsDocList() called with neither an itemList nor a new RefName!");\r
+               }\r
+       } else if(list!=null) {\r
+               throw new InternalError("processRefObjsDocList() called with both an itemList and a new RefName!");\r
+       }\r
+\r
         Iterator<DocumentModel> iter = docList.iterator();\r
+        int nRefsFoundTotal = 0;\r
         while (iter.hasNext()) {\r
             DocumentModel docModel = iter.next();\r
             AuthorityRefDocList.AuthorityRefDocItem ilistItem;\r
@@ -210,7 +304,7 @@ public class RefNameServiceUtils {
                         ServiceBindingUtils.getMappedFieldInDoc(sb, ServiceBindingUtils.OBJ_NAME_PROP, docModel));\r
             }\r
             // Now, we have to loop over the authRefFieldsByService to figure\r
-            // out which field matched this. Ignore multiple matches.\r
+            // out which field(s) matched this.\r
             Map<String,String> matchingAuthRefFields = authRefFieldsByService.get(docType);\r
             if (matchingAuthRefFields == null || matchingAuthRefFields.isEmpty()) {\r
                 throw new RuntimeException(\r
@@ -219,20 +313,21 @@ public class RefNameServiceUtils {
             String authRefAncestorField = "";\r
             String authRefDescendantField = "";\r
             String sourceField = "";\r
-            boolean fRefFound = false;\r
+            int nRefsFoundInDoc = 0;\r
             // Use this if we go to qualified field names\r
             for (String path : matchingAuthRefFields.keySet()) {\r
                 try {\r
                        // This is the field name we show in the return info\r
+                       // Returned as a schema-qualified property path\r
                     authRefAncestorField = (String) matchingAuthRefFields.get(path);\r
                     // This is the qualified field we have to get from the doc model\r
                     authRefDescendantField = DocumentUtils.getDescendantOrAncestor(path);\r
                     // The ancestor field is part-schema (tablename) qualified\r
-                    String[] strings = authRefAncestorField.split(":");\r
-                    if (strings.length != 2) {\r
-                        throw new RuntimeException(\r
-                                "getAuthorityRefDocs: Bad configuration of path to authority reference field.");\r
-                    }\r
+                    //String[] strings = authRefAncestorField.split(":");\r
+                    //if (strings.length != 2) {\r
+                    //   throw new RuntimeException(\r
+                    //            "getAuthorityRefDocs: Bad configuration of path to authority reference field.");\r
+                    //}\r
                     // strings[0] holds a schema name, such as "intakes_common"\r
                     //\r
                     // strings[1] holds:\r
@@ -243,13 +338,19 @@ public class RefNameServiceUtils {
                     //   field, such as "fieldCollector".\r
                     // TODO - if the value is not simple, or repeating scalar, need a more\r
                     // sophisticated fetch. \r
-                    Object fieldValue = docModel.getProperty(strings[0], strings[1]);\r
-                    // We cannot be sure why we have this doc, so look for matches\r
-                    boolean fRefMatches = refNameFoundInField(refName, fieldValue);\r
-                    if (fRefMatches) {\r
+                    // Change this to an XPath model\r
+                    //Object fieldValue = docModel.getProperty(strings[0], strings[1]);\r
+                    // This will have to handle repeating complex fields by iterating over the possibilities\r
+                    // and finding the one that matches.\r
+                    Property fieldValue = docModel.getProperty(authRefAncestorField);\r
+                    // We know this doc should have a match somewhere, but it may not be in this field\r
+                    // If we are just building up the refItems, then it is enough to know we found a match.\r
+                    // If we are patching refName values, then we have to replace each match.\r
+                    int nRefsMatchedInField = refNameFoundInField(refName, fieldValue, newAuthorityRefName);\r
+                    if (nRefsMatchedInField > 0) {\r
                         sourceField = authRefDescendantField;\r
                         // Handle multiple fields matching in one Doc. See CSPACE-2863.\r
-                       if(fRefFound) {\r
+                       if(nRefsFoundInDoc > 0) {\r
                                // We already added ilistItem, so we need to clone that and add again\r
                                if(ilistItem != null) {\r
                                        ilistItem = cloneAuthRefDocItem(ilistItem, sourceField);\r
@@ -258,11 +359,11 @@ public class RefNameServiceUtils {
                                if(ilistItem != null) {\r
                                        ilistItem.setSourceField(sourceField);\r
                                }\r
-                            fRefFound = true;\r
                        }\r
                                if(ilistItem != null) {\r
                                        list.add(ilistItem);\r
                                }\r
+                               nRefsFoundInDoc += nRefsMatchedInField;\r
                     }\r
 \r
                 } catch (ClientException ce) {\r
@@ -270,13 +371,14 @@ public class RefNameServiceUtils {
                             "getAuthorityRefDocs: Problem fetching: " + sourceField, ce);\r
                 }\r
             }\r
-            if (!fRefFound) {\r
+            if (nRefsFoundInDoc == 0) {\r
                 throw new RuntimeException(\r
                         "getAuthorityRefDocs: Could not find refname in object:"\r
                         + docType + ":" + NuxeoUtils.getCsid(docModel));\r
             }\r
+            nRefsFoundTotal += nRefsFoundInDoc;\r
         }\r
-\r
+        return nRefsFoundTotal;\r
     }\r
     \r
     private static AuthorityRefDocList.AuthorityRefDocItem cloneAuthRefDocItem(\r
@@ -293,6 +395,7 @@ public class RefNameServiceUtils {
 \r
     /*\r
      * Identifies whether the refName was found in the supplied field.\r
+     * If passed a new RefName, will set that into fields in which the old one was found.\r
      *\r
      * Only works for:\r
      * * Scalar fields\r
@@ -302,24 +405,37 @@ public class RefNameServiceUtils {
      * * Structured fields (complexTypes)\r
      * * Repeatable structured fields (repeatable complexTypes)\r
      */\r
-    private static boolean refNameFoundInField(String refName, Object fieldValue) {\r
-\r
-        boolean result = false;\r
-        if (fieldValue instanceof List) {\r
-            List<String> fieldValueList = (List) fieldValue;\r
-            for (String listItemValue : fieldValueList) {\r
-                if (refName.equalsIgnoreCase(listItemValue)) {\r
-                    result = true;\r
-                    break;\r
-                }\r
-\r
-            }\r
-        } else if (fieldValue instanceof String){\r
-            if (refName.equalsIgnoreCase((String)fieldValue)) {\r
-                result = true;\r
-            }\r
-        }\r
-        return result;\r
+    private static int refNameFoundInField(String oldRefName, Property fieldValue, String newRefName) {\r
+       int nFound = 0;\r
+       if (fieldValue instanceof List) {\r
+               List<Property> fieldValueList = (List) fieldValue;\r
+               for (Property listItemValue : fieldValueList) {\r
+                       try {\r
+                               if ((listItemValue instanceof StringProperty)\r
+                                               && oldRefName.equalsIgnoreCase((String)listItemValue.getValue())) {\r
+                                       nFound++;\r
+                                       if(newRefName!=null) {\r
+                                               fieldValue.setValue(newRefName);\r
+                                       } else {\r
+                                               // We cannot quit after the first, if we are replacing values.\r
+                                               // If we are just looking (not replacing), finding one is enough.\r
+                                               break;\r
+                                       }\r
+                               }\r
+                       } catch( PropertyException pe ) {}\r
+               }\r
+       } else {\r
+               try {\r
+                       if ((fieldValue instanceof StringProperty)\r
+                                       && oldRefName.equalsIgnoreCase((String)fieldValue.getValue())) {\r
+                                       nFound++;\r
+                               if(newRefName!=null) {\r
+                                       fieldValue.setValue(newRefName);\r
+                               }\r
+                       }\r
+               } catch( PropertyException pe ) {}\r
+       }\r
+       return nFound;\r
     }\r
 }\r
 \r
index 29dbd50c2b456c145b123a329765e2338e9db435..090e77aa4cb522a6553f79ca3ade80ca456d3c0f 100644 (file)
@@ -33,6 +33,7 @@ import org.collectionspace.services.common.api.CommonAPI;
 import org.collectionspace.services.common.api.RefName;
 import org.collectionspace.services.common.api.Tools;
 import org.collectionspace.services.common.context.MultipartServiceContext;
+import org.collectionspace.services.common.context.ServiceBindingUtils;
 import org.collectionspace.services.common.context.ServiceContext;
 import org.collectionspace.services.common.document.DocumentWrapper;
 import org.collectionspace.services.common.document.DocumentWrapperImpl;
@@ -205,9 +206,23 @@ public abstract class AuthorityItemDocumentModelHandler<AICommon>
     protected void handleItemRefNameReferenceUpdate() {
        if(newRefNameOnUpdate != null && oldRefNameOnUpdate!= null) {
                // We have work to do.
-               logger.debug("Need to find and update references to Item.");
-               logger.debug("Old refName" + oldRefNameOnUpdate);
-               logger.debug("New refName" + newRefNameOnUpdate);
+               if(logger.isDebugEnabled()) {
+                       String eol = System.getProperty("line.separator");
+                       logger.debug("Need to find and update references to Item."+eol
+                                                       +"   Old refName" + oldRefNameOnUpdate + eol
+                                                       +"   New refName" + newRefNameOnUpdate);
+               }
+               ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = getServiceContext();
+               RepositoryClient repoClient = getRepositoryClient(ctx);
+               // HACK - this should be defined for each handler, as with 
+               // AuthorityResource.getRefPropName()
+               String refNameProp = ServiceBindingUtils.AUTH_REF_PROP;
+
+               int nUpdated = RefNameServiceUtils.updateAuthorityRefDocs(ctx, repoClient,
+                                                       oldRefNameOnUpdate, newRefNameOnUpdate, refNameProp );
+               if(logger.isDebugEnabled()) {
+                       logger.debug("Updated "+nUpdated+" instances of oldRefName to newRefName");
+               }
        }
     }
 
@@ -278,7 +293,7 @@ public abstract class AuthorityItemDocumentModelHandler<AICommon>
             throws Exception {
         Map<String, Object> unQObjectProperties = super.extractPart(docModel, schema, partMeta);
 
-        // Add the CSID to the common part
+        // Add the CSID to the common part, since they may have fetched via the shortId.
         if (partMeta.getLabel().equalsIgnoreCase(authorityItemCommonSchemaName)) {
             String csid = getCsid(docModel);//NuxeoUtils.extractId(docModel.getPathAsString());
             unQObjectProperties.put("csid", csid);
index 1dd48b19ab78c62cd13a9af6f61fdee27702ffbd..70f6bd4f37969853c740323b38c4487cd45525cd 100644 (file)
       <!-- <types:item><types:key>localeLanguage</types:key><types:value>da</types:value></types:item> -->
     </tenant:properties>               
     <!-- begin idgenerators service meta-data -->
-    <tenant:serviceBindings id="idgenerators" name="idgenerators" version="0.1">
+    <tenant:serviceBindings id="idgenerators" name="idgenerators" type="utility" version="0.1">
       <!-- other URI paths using which this service could be accessed -->
     </tenant:serviceBindings>
     <!-- end idgenerator service meta-data -->
     <!-- begin id service meta-data -->
-    <tenant:serviceBindings id="id" name="id" version="0.1">
+    <tenant:serviceBindings id="id" name="id" type="utility" version="0.1">
       <!-- other URI paths using which this service could be accessed -->
       <!--            <service:uriPath xmlns:service='http://collectionspace.org/services/common/service'>
                 /idgenerators/*/ids
     </tenant:serviceBindings>
     <!--end collectionobject service meta-data -->
     <!-- begin blob service meta-data -->
+               <!-- This should likely be type="object" -->
     <tenant:serviceBindings id="Blobs" name="Blobs" type="procedure" version="0.1">
       <service:uriPath xmlns:service="http://collectionspace.org/services/common/service">/blobs/*/workflow/</service:uriPath>
       <service:repositoryDomain xmlns:service="http://collectionspace.org/services/common/service">default-domain</service:repositoryDomain>
     </tenant:serviceBindings>
     <!-- end imports service meta-data -->
     <!-- begin media service meta-data -->
-    <tenant:serviceBindings id="Media" name="Media" type="procedure" version="0.1">
+               <!-- This should likely be type="object" -->
+     <tenant:serviceBindings id="Media" name="Media" type="procedure" version="0.1">
       <service:uriPath xmlns:service="http://collectionspace.org/services/common/service">/media/*/workflow/</service:uriPath>
       <service:repositoryDomain xmlns:service="http://collectionspace.org/services/common/service">default-domain</service:repositoryDomain>
       <service:documentHandler xmlns:service="http://collectionspace.org/services/common/service">org.collectionspace.services.media.nuxeo.MediaDocumentModelHandler</service:documentHandler>
     </tenant:serviceBindings>
     <!-- end report service meta-data -->
     <!-- begin vocabulary service meta-data -->
-    <tenant:serviceBindings id="Vocabularies" name="Vocabularies" version="0.1">
+    <tenant:serviceBindings id="Vocabularies" name="Vocabularies" type="utility" version="0.1">
       <service:uriPath xmlns:service="http://collectionspace.org/services/common/service">/vocabularies/*/workflow/</service:uriPath>
       <service:uriPath xmlns:service="http://collectionspace.org/services/common/service">/vocabularies/*/items/*/workflow/</service:uriPath>
       <!-- other URI paths using which this service could be accessed -->
             Note there is no Vocabularyitem service, but there is a
             Repository workspace so we have to configure that.
         -->
-    <tenant:serviceBindings id="Vocabularyitems" name="Vocabularyitems" version="0.1">
+    <tenant:serviceBindings id="Vocabularyitems" name="Vocabularyitems" type="authority" version="0.1">
       <service:uriPath xmlns:service="http://collectionspace.org/services/common/service">/vocabularyitems/*/workflow/</service:uriPath>
       <!-- other URI paths using which this service could be accessed -->
       <!--
     </tenant:serviceBindings>
     <!-- end vocabulary service meta-data -->
     <!-- begin orgauthority service meta-data -->
-    <tenant:serviceBindings id="Orgauthorities" name="Orgauthorities" version="0.1">
+    <tenant:serviceBindings id="Orgauthorities" name="Orgauthorities" type="utility" version="0.1">
       <service:uriPath xmlns:service="http://collectionspace.org/services/common/service">/orgauthorities/*/workflow/</service:uriPath>
       <service:uriPath xmlns:service="http://collectionspace.org/services/common/service">/orgauthorities/*/items/*/workflow/</service:uriPath>
       <!-- other URI paths using which this service could be accessed -->
              Note there is no Organization service, but there is a
              Repository workspace so we have to configure that.
         -->
-    <tenant:serviceBindings id="Organizations" name="Organizations" version="0.1">
+    <tenant:serviceBindings id="Organizations" name="Organizations" type="authority" version="0.1">
       <!-- other URI paths using which this service could be accessed -->
       <!--            <service:uriPath xmlns:service='http://collectionspace.org/services/common/service'>
                 /orgauthorities/*/items/
     </tenant:serviceBindings>
     <!-- end organization service meta-data -->
     <!-- begin personauthority service meta-data -->
-    <tenant:serviceBindings id="Personauthorities" name="Personauthorities" version="0.1">
+    <tenant:serviceBindings id="Personauthorities" name="Personauthorities" type="utility" version="0.1">
       <service:uriPath xmlns:service="http://collectionspace.org/services/common/service">/personauthorities/*/workflow/</service:uriPath>
       <service:uriPath xmlns:service="http://collectionspace.org/services/common/service">/personauthorities/*/items/*/workflow/</service:uriPath>
       <!-- other URI paths using which this service could be accessed -->
              Note there is no Person service, but there is a
              Repository workspace so we have to configure that.
         -->
-    <tenant:serviceBindings id="Persons" name="Persons" version="0.1">
+    <tenant:serviceBindings id="Persons" name="Persons" type="authority" version="0.1">
       <!-- other URI paths using which this service could be accessed -->
       <!--            <service:uriPath xmlns:service='http://collectionspace.org/services/common/service'>
                 /personauthorities/*/items/
       </service:properties>
       <service:object xmlns:service="http://collectionspace.org/services/common/service" id="1" name="Person" version="0.1">
         <service:part id="0" control_group="Managed" versionable="true" auditable="false" label="persons-system" updated="" order="0">
+          <service:content contentType="application/xml">
+            <service:xmlContent namespaceURI="http://collectionspace.org/services/common/system" schemaLocation="http://collectionspace.org/services/common/system http://collectionspace.org/services/common/system/system-response.xsd" />
+          </service:content>
+        </service:part>
+        <service:part id="1" control_group="Managed" versionable="true" auditable="false" label="persons_common" updated="" order="1">
+          <service:content contentType="application/xml">
+            <service:xmlContent namespaceURI="http://collectionspace.org/services/person" schemaLocation="http://collectionspace.org/services/person http://services.collectionspace.org/person/persons_common.xsd" />
+          </service:content>
           <service:properties>
             <!-- Place Authority reference -->
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
             </types:item>
             -->
           </service:properties>
-          <service:content contentType="application/xml">
-            <service:xmlContent namespaceURI="http://collectionspace.org/services/common/system" schemaLocation="http://collectionspace.org/services/common/system http://collectionspace.org/services/common/system/system-response.xsd" />
-          </service:content>
-        </service:part>
-        <service:part id="1" control_group="Managed" versionable="true" auditable="false" label="persons_common" updated="" order="1">
-          <service:content contentType="application/xml">
-            <service:xmlContent namespaceURI="http://collectionspace.org/services/person" schemaLocation="http://collectionspace.org/services/person http://services.collectionspace.org/person/persons_common.xsd" />
-          </service:content>
         </service:part>
         <service:part id="2" control_group="Managed" versionable="true" auditable="false" label="collectionspace_core" updated="" order="2">
           <service:content contentType="application/xml">
     </tenant:serviceBindings>
     <!-- end person service meta-data -->
     <!-- begin locationauthority service meta-data -->
-    <tenant:serviceBindings id="Locationauthorities" name="Locationauthorities" version="0.1">
+    <tenant:serviceBindings id="Locationauthorities" name="Locationauthorities" type="utility" version="0.1">
       <service:uriPath xmlns:service="http://collectionspace.org/services/common/service">/locationauthorities/*/workflow/</service:uriPath>
       <service:uriPath xmlns:service="http://collectionspace.org/services/common/service">/locationauthorities/*/items/*/workflow/</service:uriPath>
       <!-- other URI paths using which this service could be accessed -->
              Note there is no Location service, but there is a
              Repository workspace so we have to configure that.
         -->
-    <tenant:serviceBindings id="Locations" name="Locations" version="0.1">
+    <tenant:serviceBindings id="Locations" name="Locations" type="authority" version="0.1">
       <service:repositoryDomain xmlns:service="http://collectionspace.org/services/common/service">default-domain</service:repositoryDomain>
       <service:documentHandler xmlns:service="http://collectionspace.org/services/common/service">org.collectionspace.services.location.nuxeo.LocationDocumentModelHandler</service:documentHandler>
       <service:DocHandlerParams xmlns:service="http://collectionspace.org/services/common/service">
     </tenant:serviceBindings>
     <!-- end location service meta-data -->
     <!-- begin taxonomyauthority service meta-data -->
-    <tenant:serviceBindings id="Taxonomyauthority" name="Taxonomyauthority" version="0.1">
+    <tenant:serviceBindings id="Taxonomyauthority" name="Taxonomyauthority" type="utility" version="0.1">
       <service:uriPath xmlns:service="http://collectionspace.org/services/common/service">/taxonomyauthority/*/workflow/</service:uriPath>
       <service:uriPath xmlns:service="http://collectionspace.org/services/common/service">/taxonomyauthority/*/items/*/workflow/</service:uriPath>
       <!-- other URI paths using which this service could be accessed -->
              Note there is no Taxon service, but there is a
              Repository workspace so we have to configure that.
         -->
-    <tenant:serviceBindings id="Taxon" name="Taxon" version="0.1">
+    <tenant:serviceBindings id="Taxon" name="Taxon" type="authority" version="0.1">
       <service:repositoryDomain xmlns:service="http://collectionspace.org/services/common/service">default-domain</service:repositoryDomain>
       <service:documentHandler xmlns:service="http://collectionspace.org/services/common/service">org.collectionspace.services.taxonomy.nuxeo.TaxonDocumentModelHandler</service:documentHandler>
       <service:DocHandlerParams xmlns:service="http://collectionspace.org/services/common/service">
     </tenant:serviceBindings>
     <!-- end acquisition service meta-data -->
     <!-- begin relation service meta-data -->
-    <tenant:serviceBindings id="Relations" name="Relations" version="0.1">
+    <tenant:serviceBindings id="Relations" name="Relations" type="utility" version="0.1">
       <service:uriPath xmlns:service="http://collectionspace.org/services/common/service">/relations/*/workflow/</service:uriPath>
       <!-- other URI paths using which this service could be accessed -->
       <service:repositoryDomain xmlns:service="http://collectionspace.org/services/common/service">default-domain</service:repositoryDomain>
     </tenant:serviceBindings>
     <!-- end relation service meta-data -->
     <!-- begin account service meta-data -->
-    <tenant:serviceBindings id="Accounts" name="Accounts" version="0.1">
+    <tenant:serviceBindings id="Accounts" name="Accounts" type="security" version="0.1">
       <!-- other URI paths using which this service could be accessed -->
       <service:documentHandler xmlns:service="http://collectionspace.org/services/common/service">org.collectionspace.services.account.storage.AccountDocumentHandler</service:documentHandler>
       <service:DocHandlerParams xmlns:service="http://collectionspace.org/services/common/service">
     </tenant:serviceBindings>
     <!-- end account service meta-data -->
     <!-- begin dimension service meta-data -->
-    <tenant:serviceBindings id="Dimensions" name="Dimensions" version="0.1">
+    <tenant:serviceBindings id="Dimensions" name="Dimensions" type="utility" version="0.1">
       <!-- other URI paths using which this service could be accessed -->
       <service:uriPath xmlns:service="http://collectionspace.org/services/common/service">/dimensions/*/workflow/</service:uriPath>
       <service:repositoryDomain xmlns:service="http://collectionspace.org/services/common/service">default-domain</service:repositoryDomain>
     </tenant:serviceBindings>
     <!-- end dimension service meta-data -->
     <!-- begin contact service meta-data -->
-    <tenant:serviceBindings id="Contacts" name="Contacts" version="0.1">
+    <tenant:serviceBindings id="Contacts" name="Contacts" type="utility" version="0.1">
       <!-- other URI paths using which this service could be accessed -->
       <!--            <service:uriPath xmlns:service='http://collectionspace.org/services/common/service'>
                 /personauthorities/*/items/*/contacts
     </tenant:serviceBindings>
     <!-- end contact service meta-data -->
     <!-- begin note service meta-data -->
-    <tenant:serviceBindings id="Notes" name="Notes" version="0.1">
+    <tenant:serviceBindings id="Notes" name="Notes" type="utility" version="0.1">
       <service:repositoryDomain xmlns:service="http://collectionspace.org/services/common/service">default-domain</service:repositoryDomain>
       <service:documentHandler xmlns:service="http://collectionspace.org/services/common/service">org.collectionspace.services.note.nuxeo.NoteDocumentModelHandler</service:documentHandler>
       <service:object xmlns:service="http://collectionspace.org/services/common/service" name="CSNote" version="0.1">
     </tenant:serviceBindings>
     <!-- end note service meta-data -->
     <!-- begin role service meta-data -->
-    <tenant:serviceBindings id="authorization/roles" name="authorization/roles" version="0.1">
+    <tenant:serviceBindings id="authorization/roles" name="authorization/roles" type="security" version="0.1">
       <!-- other URI paths using which this service could be accessed -->
       <service:documentHandler xmlns:service="http://collectionspace.org/services/common/service">org.collectionspace.services.authorization.storage.RoleDocumentHandler</service:documentHandler>
       <service:validatorHandler xmlns:service="http://collectionspace.org/services/common/service">org.collectionspace.services.authorization.storage.RoleValidatorHandler</service:validatorHandler>
     </tenant:serviceBindings>
     <!-- end role service meta-data -->
     <!-- begin permission service meta-data -->
-    <tenant:serviceBindings id="authorization/permissions" name="authorization/permissions" version="0.1">
+    <tenant:serviceBindings id="authorization/permissions" name="authorization/permissions" type="security" version="0.1">
       <!-- other URI paths using which this service could be accessed -->
       <service:documentHandler xmlns:service="http://collectionspace.org/services/common/service">org.collectionspace.services.authorization.storage.PermissionDocumentHandler</service:documentHandler>
       <service:validatorHandler xmlns:service="http://collectionspace.org/services/common/service">org.collectionspace.services.authorization.storage.PermissionValidatorHandler</service:validatorHandler>
     <!-- begin permission-role service meta-data -->
     <!-- the following service is same as authorization/roles/permroles service -->
     <!-- except that it is available as a sub resource of the permission service -->
-    <tenant:serviceBindings id="authorization/permissions/permroles" name="authorization/permissions/permroles" version="0.1">
+    <tenant:serviceBindings id="authorization/permissions/permroles" name="authorization/permissions/permroles" type="security" version="0.1">
       <!-- other URI paths using which this service could be accessed -->
       <!--            <service:uriPath xmlns:service='http://collectionspace.org/services/common/service'>
                 /authorization/permissions/*/permroles/
     </tenant:serviceBindings>
     <!-- end permission-role service meta-data -->
     <!-- begin account-role service meta-data -->
-    <tenant:serviceBindings id="accounts/accountroles" name="accounts/accountroles" version="0.1">
+    <tenant:serviceBindings id="accounts/accountroles" name="accounts/accountroles" type="security" version="0.1">
       <!-- other URI paths using which this service could be accessed -->
       <!--            <service:uriPath xmlns:service='http://collectionspace.org/services/common/service'>
                 /accounts/*/accountroles/
     <!-- begin role-permission service meta-data -->
     <!-- the following service is same as authorization/permissions/permroles service -->
     <!-- except that it is available as a sub resource of the role service -->
-    <tenant:serviceBindings id="authorization/roles/permroles" name="authorization/roles/permroles" version="0.1">
+    <tenant:serviceBindings id="authorization/roles/permroles" name="authorization/roles/permroles" type="security" version="0.1">
       <!-- other URI paths using which this service could be accessed -->
       <!--            <service:uriPath xmlns:service='http://collectionspace.org/services/common/service'>
                 /authorization/roles/*/permroles/
     <!-- begin role-account service meta-data -->
     <!-- the following service is same as account/accountroles service -->
     <!-- except that it is available as a sub resource of the role service -->
-    <tenant:serviceBindings id="authorization/roles/accountroles" name="authorization/roles/accountroles" version="0.1">
+    <tenant:serviceBindings id="authorization/roles/accountroles" name="authorization/roles/accountroles" type="security" version="0.1">
       <!-- other URI paths using which this service could be accessed -->
       <!--            <service:uriPath xmlns:service='http://collectionspace.org/services/common/service'>
                 /authorization/roles/*/accountroles/
index 71c93d2c43cf55e346314bc77eee9cc9a12aaf79..59b68ab9efce0e711f8efcd1f828dd63dce35030 100644 (file)
@@ -386,12 +386,12 @@ public class TenantBindingConfigReaderImpl
      * @return
      */
     public List<ServiceBindingType> getServiceBindingsByType(
-            String tenantId, String serviceType) {
+            String tenantId, List<String> serviceTypes) {
         ArrayList<ServiceBindingType> list = null;
         TenantBindingType tenant = tenantBindings.get(tenantId);
         if (tenant != null) {
             for (ServiceBindingType sb : tenant.getServiceBindings()) {
-                if (serviceType.equals(sb.getType())) {
+                if (serviceTypes.contains(sb.getType())) {
                     if (list == null) {
                         list = new ArrayList<ServiceBindingType>();
                     }
index d4b4f0ea2c8702cfec7992436b9d0f97da32c87e..eae2b3da6caae2dda0b8fd565856225d561f0882 100644 (file)
@@ -24,6 +24,9 @@ public class ServiceBindingUtils {
        public static final String SERVICE_TYPE_PROP = "type";\r
        public static final String SERVICE_TYPE_OBJECT = "object";\r
        public static final String SERVICE_TYPE_PROCEDURE = "procedure";\r
+       public static final String SERVICE_TYPE_AUTHORITY = "authority";\r
+       public static final String SERVICE_TYPE_UTILITY = "utility";\r
+       public static final String SERVICE_TYPE_SECURITY = "security";\r
        \r
     public static String getTenantQualifiedDocType(String tenantId, String docType) {\r
        String result = docType + ServiceContext.TENANT_SUFFIX + tenantId;\r
index c80607d16c1b77520d9506d83ed9db0bdf5c0466..46d401d8b66253eaea06394ed2c831dd976190bc 100644 (file)
@@ -708,6 +708,80 @@ public class RepositoryJavaClientImpl implements RepositoryClient<PoxPayloadIn,
             }
         }
     }
+    
+    /**
+     * Save a documentModel to the Nuxeo repository, using the current session,
+     * bypassing the normal document handler processing (validation, etc.)
+     * NOTE: This should be called only in specific circumstances, e.g., to
+     * update known cached values like refNames. DO NOT USE this for any normal
+     * document processing.
+     * NOTE: Does not release session, as it should be called in a wider session context.
+     *  Caller is responsible for releasing the session.
+     * 
+     * @param ctx service context under which this method is invoked
+     * @param docModel the document to save
+     * @param fSaveSession if TRUE, will call CoreSession.save() to save accumulated changes.
+     * @throws DocumentException
+     */
+    public void saveDocWithoutHandlerProcessing(
+            ServiceContext ctx, DocumentModel docModel, boolean fSaveSession)
+            throws ClientException, DocumentException {
+        RepositoryInstance repoSession = null;
+        DocumentWrapper<DocumentModel> wrapDoc = null;
+
+        try {
+            repoSession = getRepositorySession();
+            repoSession.saveDocument(docModel);
+            if(fSaveSession)
+               repoSession.save();
+        } catch (ClientException ce) {
+            throw ce;
+        } catch (Exception e) {
+            if (logger.isDebugEnabled()) {
+                logger.debug("Caught exception ", e);
+            }
+            throw new DocumentException(e);
+        }
+    }
+
+
+    /**
+     * Save a list of documentModels to the Nuxeo repository, using the current session,
+     * bypassing the normal document handler processing (validation, etc.)
+     * NOTE: This should be called only in specific circumstances, e.g., to
+     * update known cached values like refNames. DO NOT USE this for any normal
+     * document processing.
+     * NOTE: Does not release session, as it should be called in a wider session context.
+     *  Caller is responsible for releasing the session.
+     * 
+     * @param ctx service context under which this method is invoked
+     * @param docModel the document to save
+     * @param fSaveSession if TRUE, will call CoreSession.save() to save accumulated changes.
+     * @throws DocumentException
+     */
+    public void saveDocListWithoutHandlerProcessing(
+            ServiceContext ctx, DocumentModelList docList, boolean fSaveSession)
+            throws ClientException, DocumentException {
+        RepositoryInstance repoSession = null;
+        DocumentWrapper<DocumentModel> wrapDoc = null;
+
+        try {
+            repoSession = getRepositorySession();
+            DocumentModel[] docModelArray = new DocumentModel[docList.size()];
+            repoSession.saveDocuments(docList.toArray(docModelArray));
+            if(fSaveSession)
+               repoSession.save();
+        } catch (ClientException ce) {
+            throw ce;
+        } catch (Exception e) {
+            if (logger.isDebugEnabled()) {
+                logger.debug("Caught exception ", e);
+            }
+            throw new DocumentException(e);
+        }
+    }
+
+
 
     /**
      * delete a document from the Nuxeo repository
index 6fb6ac67d0d5603170251a23df943cbb3972fd7b..70e2ceeb161707d52a9a189dd3dfe7fecbd8cf7f 100644 (file)
@@ -61,18 +61,20 @@ public class PersonAuthorityValidatorHandler implements ValidatorHandler {
             String msg = "";
             boolean invalid = false;
 
-            // Validation specific to creates or updates
-            if (action.equals(Action.CREATE)) {
-                String shortId = personAuth.getShortIdentifier();
-                // Per CSPACE-2215, shortIdentifier values that are null (missing)
-                // oe the empty string are now legally accepted in create payloads.
-                // In either of those cases, a short identifier will be synthesized from
-                // a display name or supplied in another manner.
-                if ((shortId != null) && (shortIdBadPattern.matcher(shortId).find())) {
-                    invalid = true;
-                    msg += "shortIdentifier must only contain standard word characters";
-                }
-            } else if (action.equals(Action.UPDATE)) {
+            if(personAuth != null) {   // No guarantee that there is a common part in every post/update.
+                   // Validation specific to creates or updates
+                   if (action.equals(Action.CREATE)) {
+                       String shortId = personAuth.getShortIdentifier();
+                       // Per CSPACE-2215, shortIdentifier values that are null (missing)
+                       // oe the empty string are now legally accepted in create payloads.
+                       // In either of those cases, a short identifier will be synthesized from
+                       // a display name or supplied in another manner.
+                       if ((shortId != null) && (shortIdBadPattern.matcher(shortId).find())) {
+                           invalid = true;
+                           msg += "shortIdentifier must only contain standard word characters";
+                       }
+                   } else if (action.equals(Action.UPDATE)) {
+                   }
             }
 
             if (invalid) {
index cde5cf21b4d8be9f86e97430a9e2a7ee7bacbdc4..f84e6c06e8eb4d299ce12eef6edbfcac2b36118b 100644 (file)
@@ -59,25 +59,27 @@ public class PersonValidatorHandler implements ValidatorHandler {
             String msg = "";
             boolean invalid = false;
             
-            // Validation occurring on both creates and updates
-            String displayName = person.getDisplayName();
-            if (!person.isDisplayNameComputed() && ((displayName == null) || displayName.trim().isEmpty())) {
-                invalid = true;
-                msg += "displayName must be non-null and non-blank if displayNameComputed is false!";
-            }
-            
-            // Validation specific to creates or updates
-            if (action.equals(Action.CREATE)) {
-                String shortId = person.getShortIdentifier();
-                // Per CSPACE-2215, shortIdentifier values that are null (missing)
-                // oe the empty string are now legally accepted in create payloads.
-                // In either of those cases, a short identifier will be synthesized from
-                // a display name or supplied in another manner.
-                if ((shortId != null) && (shortIdBadPattern.matcher(shortId).find())) {
-                    invalid = true;
-                    msg += "shortIdentifier must only contain standard word characters";
-                }
-            } else if (action.equals(Action.UPDATE)) {
+            if(person != null) {       // No guarantee that there is a common part in every post/update.
+                   // Validation occurring on both creates and updates
+                   String displayName = person.getDisplayName();
+                   if (!person.isDisplayNameComputed() && ((displayName == null) || displayName.trim().isEmpty())) {
+                       invalid = true;
+                       msg += "displayName must be non-null and non-blank if displayNameComputed is false!";
+                   }
+                   
+                   // Validation specific to creates or updates
+                   if (action.equals(Action.CREATE)) {
+                       String shortId = person.getShortIdentifier();
+                       // Per CSPACE-2215, shortIdentifier values that are null (missing)
+                       // oe the empty string are now legally accepted in create payloads.
+                       // In either of those cases, a short identifier will be synthesized from
+                       // a display name or supplied in another manner.
+                       if ((shortId != null) && (shortIdBadPattern.matcher(shortId).find())) {
+                           invalid = true;
+                           msg += "shortIdentifier must only contain standard word characters";
+                       }
+                   } else if (action.equals(Action.UPDATE)) {
+                   }
             }
 
             if (invalid) {