]> git.aero2k.de Git - tmp/jakarta-migration.git/commitdiff
CSPACE-2818, CSPACE-3537 Refactored logic that handles authorityRefs, refObjs, and...
authorPatrick Schmitz <pschmitz@berkeley.edu>
Tue, 22 Nov 2011 20:00:22 +0000 (20:00 +0000)
committerPatrick Schmitz <pschmitz@berkeley.edu>
Tue, 22 Nov 2011 20:00:22 +0000 (20:00 +0000)
16 files changed:
services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/authrefsComplex.xml [new file with mode: 0644]
services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/authrefsSimple.xml [new file with mode: 0644]
services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/intake1.xml [new file with mode: 0644]
services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/organizations_common.xml [new file with mode: 0644]
services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/orgauthorities_common.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/common/src/main/cspace/config/services/tenants/tenant-bindings-proto.xml
services/common/src/main/java/org/collectionspace/services/common/ResourceBase.java
services/common/src/main/java/org/collectionspace/services/common/config/PropertyItemUtils.java
services/common/src/main/java/org/collectionspace/services/common/document/DocumentUtils.java
services/common/src/main/java/org/collectionspace/services/common/vocabulary/RefNameServiceUtils.java [moved from services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/RefNameServiceUtils.java with 55% similarity]
services/common/src/main/java/org/collectionspace/services/common/vocabulary/RefNameUtils.java
services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/DocumentModelHandler.java
services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RemoteDocumentModelHandlerImpl.java
services/organization/client/src/test/java/org/collectionspace/services/client/test/OrgAuthorityAuthRefsTest.java

diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/authrefsComplex.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/authrefsComplex.xml
new file mode 100644 (file)
index 0000000..6100d1f
--- /dev/null
@@ -0,0 +1,24 @@
+<?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="AuthRefsComplex" autoDeletePOSTS="true">\r
+               <test ID="intake1" auth="test">\r
+                       <method>POST</method>\r
+                       <uri>/cspace-services/intakes/</uri>\r
+                       <filename>authrefs/intake1.xml</filename>\r
+               </test>\r
+\r
+               <test ID="getIntakeAuthRefs">\r
+                       <method>GET</method>\r
+                       <uri>/cspace-services/intakes/${intake1.CSID}/authorityrefs</uri>\r
+                       <response>\r
+                               <expected level="ADDOK" />\r
+                               <filename>authrefs/res/intakesAuthRefs.res.xml</filename>\r
+                        </response>\r
+               </test>\r
+\r
+       </testGroup>\r
+</xmlReplay>\r
diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/authrefsSimple.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/authrefsSimple.xml
new file mode 100644 (file)
index 0000000..721c67c
--- /dev/null
@@ -0,0 +1,98 @@
+<?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="AuthRefsSimple" 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="getLoan1AuthRefs">\r
+                       <method>GET</method>\r
+                       <uri>/cspace-services/loansout/${loanout1.CSID}/authorityrefs</uri>\r
+                       <response>\r
+                               <expected level="ADDOK" />\r
+                               <filename>authrefs/res/foo.res.xml</filename>\r
+                        </response>\r
+               </test>\r
+\r
+               <test ID="getPerson1RefObjs">\r
+                       <method>GET</method>\r
+                       <uri>/cspace-services/personauthorities/${PersonAuth1.CSID}/items/${Person1.CSID}/refObjs</uri>\r
+                       <response>\r
+                               <expected level="ADDOK" />\r
+                               <filename>authrefs/res/foo.res.xml</filename>\r
+                        </response>\r
+               </test>\r
+\r
+               <test ID="OrganizationAuth1">\r
+                       <method>POST</method>\r
+                       <uri>/cspace-services/orgauthorities/</uri>\r
+                       <filename>authrefs/orgauthorities_common.xml</filename>\r
+               </test>\r
\r
+               <test ID="Org1">\r
+                       <method>POST</method>\r
+                       <uri>/cspace-services/orgauthorities/${OrganizationAuth1.CSID}/items/</uri>\r
+                       <filename>authrefs/organizations_common.xml</filename>\r
+                       <vars>\r
+                               <var ID="person1">${GetPerson1.got("//refName")}</var>\r
+                               <var ID="person2">${GetPerson2.got("//refName")}</var>\r
+                       </vars>\r
+               </test>\r
+\r
+               <test ID="getOrg1AuthRefs">\r
+                       <method>GET</method>\r
+                       <uri>/cspace-services/orgauthorities/${OrganizationAuth1.CSID}/items/${Org1.CSID}/authorityrefs</uri>\r
+                       <response>\r
+                               <expected level="ADDOK" />\r
+                               <filename>authrefs/res/foo.res.xml</filename>\r
+                        </response>\r
+               </test>\r
+\r
+       </testGroup>\r
+</xmlReplay>\r
diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/intake1.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/intake1.xml
new file mode 100644 (file)
index 0000000..1b61424
--- /dev/null
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document name="intakes">
+    <ns2:intakes_common xmlns:ns2="http://collectionspace.org/services/intake"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+        <entryNumber>CompleteIntake001</entryNumber>
+        <normalLocation>urn:cspace:core.collectionspace.org:locationauthorities:name(location):item:name(MOMA1321979112557)'MOMA'</normalLocation>
+        <insurancePolicyNumber>BH-90210</insurancePolicyNumber>
+        <depositorsRequirements>Must wear suit and tie</depositorsRequirements>
+        <entryReason>commission</entryReason>
+        <insuranceReferenceNumber>1234-5678-90</insuranceReferenceNumber>
+        <returnDate>2010-07-14T04:00:00Z</returnDate>
+        <valuer>urn:cspace:org.collectionspace.demo:orgauthority:name(organization):organization:name(twentiethcentury-foxfilmcorporation)'Twentieth+Century-Fox+Film+Corporation'</valuer>
+        <conditionCheckNote>We got the governator himself to travel back in time, and bring some
+            robot spiders, so the condition can be proper checked</conditionCheckNote>
+        <conditionCheckReferenceNumber>TERM-II</conditionCheckReferenceNumber>
+        <entryMethods>
+            <entryMethod>found-on-doorstep</entryMethod>
+        </entryMethods>
+        <insuranceNote>Dont break it - we cannot afford it</insuranceNote>
+        <valuationReferenceNumber>911-101-404-411</valuationReferenceNumber>
+        <fieldCollectionSources>
+            <fieldCollectionSource/>
+        </fieldCollectionSources>
+        <currentLocationGroupList>
+            <currentLocationGroup>
+                <currentLocationFitness>urn:cspace:core.collectionspace.org:vocabularies:name(conditionfitness):item:name(suitable)'Suitable'</currentLocationFitness>
+                <currentLocationNote>Where is this?</currentLocationNote>
+                <currentLocation>urn:cspace:core.collectionspace.org:locationauthorities:name(location):item:name(TheVault1321979077879)'The Vault'</currentLocation>
+            </currentLocationGroup>
+            <currentLocationGroup>
+                <currentLocationFitness>urn:cspace:core.collectionspace.org:vocabularies:name(conditionfitness):item:name(reasonable)'Reasonable'</currentLocationFitness>
+                <currentLocationNote>Not in plain sight</currentLocationNote>
+                <currentLocation>urn:cspace:core.collectionspace.org:locationauthorities:name(location):item:name(PatricksCube1321979033052)'Patricks Cube'</currentLocation>
+            </currentLocationGroup>
+        </currentLocationGroupList>
+        <fieldCollectors>
+            <fieldCollector/>
+        </fieldCollectors>
+        <insurers>
+            <insurer>urn:cspace:org.collectionspace.demo:personauthority:name(person):person:name(arnoldschwarzenegger)'Arnold Schwarzenegger'</insurer>
+        </insurers>
+        <packingNote>Packed with bubble-wrap and duct-tape - no one will ever be able to open
+            it</packingNote>
+        <conditionCheckersOrAssessors>
+            <conditionCheckerOrAssessor>urn:cspace:org.collectionspace.demo:personauthority:name(person):person:name(tommyjones)'Tommy+Jones'</conditionCheckerOrAssessor>
+        </conditionCheckersOrAssessors>
+        <entryDate>2010-07-16T04:00:00Z</entryDate>
+        <insuranceRenewalDate>2010-07-05T04:00:00Z</insuranceRenewalDate>
+        <currentOwner>urn:cspace:org.collectionspace.demo:personauthority:name(person):person:name(seanbean)'Sean+Bean'</currentOwner>
+        <locationDate>2009-07-15T04:00:00Z</locationDate>
+        <depositor>urn:cspace:org.collectionspace.demo:personauthority:name(person):person:name(tommyjones)'Tommy+Jones'</depositor>
+    </ns2:intakes_common>
+</document>
diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/organizations_common.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/organizations_common.xml
new file mode 100644 (file)
index 0000000..0172a11
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r
+<document name="organizations">\r
+       <ns2:organizations_common xmlns:ns2="http://collectionspace.org/services/organization"\r
+               xmlns:ns3="http://collectionspace.org/services/jaxb">\r
+               <shortIdentifier>1288047801161</shortIdentifier>\r
+               <displayNameComputed>true</displayNameComputed>\r
+               <shortDisplayNameComputed>true</shortDisplayNameComputed>\r
+               <shortName>Test Organization-1288047801161</shortName>\r
+               <longName>Test Organization Name</longName>\r
+               <contactNames>\r
+                       <contactName>${person1}</contactName>\r
+                       <contactName>${person2}</contactName>\r
+               </contactNames>\r
+               <foundingPlace>Anytown, USA</foundingPlace>\r
+               <subBodies>\r
+                       <subBody>urn:cspace:org.collectionspace.demo:orgauthority:name(1288047801161):organization:name(1288047803708)</subBody>\r
+               </subBodies>\r
+               <functions>\r
+                       <function>My new function</function>\r
+                       <function>My second function</function>\r
+               </functions>\r
+               <groups>\r
+                       <group>My new group</group>\r
+                       <group>My second group</group>\r
+                       <group>My third group</group>\r
+               </groups>\r
+               <description>This is a test Authority item</description>\r
+               <source>Some mythical book</source>\r
+               <sourcePage>Let's say page 39</sourcePage>\r
+\r
+       </ns2:organizations_common>\r
+</document>\r
diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/orgauthorities_common.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/authrefs/orgauthorities_common.xml
new file mode 100644 (file)
index 0000000..0fef4cf
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r
+<document name="orgauthorities">\r
+       <ns2:orgauthorities_common xmlns:ns2="http://collectionspace.org/services/organization"\r
+               xmlns:ns3="http://collectionspace.org/services/jaxb">\r
+               <shortIdentifier>1288047801161</shortIdentifier>\r
+               <displayName>TestOrgAuth-1288047801161</displayName>\r
+               <vocabType>OrgAuthority</vocabType>\r
+               <description>This is a test authority</description>\r
+               <source>Some mythical book</source>\r
+       </ns2:orgauthorities_common>\r
+</document>\r
index 686cb68e3f7be8fc2ca30c996122533c1b92ba1f..dd18060bacfae6ab75cb971d6317e3a40d953def 100755 (executable)
@@ -54,6 +54,8 @@
     <run controlFile="report/report.xml" />\r
     <run controlFile="vocabulary/vocabulary.xml" testGroup="TestOrder" />\r
                <run controlFile="authrefs/authrefs.xml" testGroup="AuthRefs" />\r
+               <run controlFile="authrefs/authrefsSimple.xml" testGroup="AuthRefsSimple" />\r
+               <run controlFile="authrefs/authrefsComplex.xml" testGroup="AuthRefsComplex" />\r
 \r
     \r
 </xmlReplayMaster>\r
index f72d750c52106fbae2508bc99c0fe2a18f6b9db5..61ecbed591b5639fa5d62244539ddbeefe5ca22a 100644 (file)
@@ -51,6 +51,7 @@ 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.repository.RepositoryClient;
+import org.collectionspace.services.common.vocabulary.RefNameServiceUtils;
 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;
@@ -806,10 +807,8 @@ public abstract class AuthorityResource<AuthCommon, AuthItemHandler>
             String itemcsid = lookupItemCSID(itemspecifier, parentcsid, "getAuthorityItemAuthRefs(item)", "GET_ITEM_AUTH_REFS", ctx);
 
             DocumentWrapper<DocumentModel> docWrapper = getRepositoryClient(ctx).getDoc(ctx, itemcsid);
-            List<String> authRefFields =
-                    ((MultipartServiceContextImpl) ctx).getCommonPartPropertyValues(
-                    ServiceBindingUtils.AUTH_REF_PROP, ServiceBindingUtils.QUALIFIED_PROP_NAMES);
-            authRefList = handler.getAuthorityRefs(docWrapper, authRefFields);
+            List<RefNameServiceUtils.AuthRefConfigInfo> authRefsInfo = RefNameServiceUtils.getConfiguredAuthorityRefs(ctx);
+            authRefList = handler.getAuthorityRefs(docWrapper, authRefsInfo);
         } catch (Exception e) {
             throw bigReThrow(e, ServiceMessages.GET_FAILED + " parentspecifier: " + parentspecifier + " itemspecifier:" + itemspecifier);
         }
index 75603635909d5a72d590ebed8f7e6bf07a2df24f..788ab606b5f1973acae7b89d5f89a3bf689397b8 100644 (file)
               <types:key>authRef</types:key>
               <types:value>fieldColEventNames|fieldColEventName</types:value>
             </types:item>
-            <!-- Commented out for now, as searching within a field in a complexType breaks searches. -->
-            <!-- The following fields were placed into complexTypes in group repeatability work in CSPACE-2927: -->
-            <!--
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>contentEventNameGroupList|contentEventName</types:value>
+                                                       <types:value>contentEventNameGroupList/*/contentEventName</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>contentEventNameGroupList|contentEventNameType</types:value>
+                                                       <types:value>contentEventNameGroupList/*/contentEventNameType</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>contentObjectGroupList|contentObjectType</types:value>
+                                                       <types:value>contentObjectGroupList/*/contentObjectType</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>contentOtherGroupList|contentOtherType</types:value>
+                                                       <types:value>contentOtherGroupList/*/contentOtherType</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>materialGroupList|material</types:value>
+                                                       <types:value>materialGroupList/*/material</types:value>
             </types:item>
              <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>materialGroupList|materialComponent</types:value>
+                                                       <types:value>materialGroupList/*/materialComponent</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>materialGroupList|materialSource</types:value>
+                                                       <types:value>materialGroupList/*/materialSource</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>objectComponentGroupList|objectComponentName</types:value>
+                                                       <types:value>objectComponentGroupList/*/objectComponentName</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>objectProductionOrganizationGroupList|objectProductionOrganization</types:value>
+                                                       <types:value>objectProductionOrganizationGroupList/*/objectProductionOrganization</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>objectProductionPeopleGroupList|objectProductionPeople</types:value>
+                                                       <types:value>objectProductionPeopleGroupList/*/objectProductionPeople</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>objectProductionPersonGroupList|objectProductionPerson</types:value>
+                                                       <types:value>objectProductionPersonGroupList/*/objectProductionPerson</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>techniqueGroupList|technique</types:value>
+                                                       <types:value>techniqueGroupList/*/technique</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>techniqueGroupList|techniqueType</types:value>
+                                                       <types:value>techniqueGroupList/*/techniqueType</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>objectProductionPlaceGroupList|objectProductionPlace</types:value>
+                                                       <types:value>objectProductionPlaceGroupList/*/objectProductionPlace</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>assocActivityGroupList|assocActivity</types:value>
+                                                       <types:value>assocActivityGroupList/*/assocActivity</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>assocConceptGroupList|assocConcept</types:value>
+                                                       <types:value>assocConceptGroupList/*/assocConcept</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>assocCulturalContextGroupList|assocCulturalContext</types:value>
+                                                       <types:value>assocCulturalContextGroupList/*/assocCulturalContext</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>assocOrganizationGroupList|assocOrganization</types:value>
+                                                       <types:value>assocOrganizationGroupList/*/assocOrganization</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>assocPeopleGroupList|assocPeople</types:value>
+                                                       <types:value>assocPeopleGroupList/*/assocPeople</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>assocPersonGroupList|assocPerson</types:value>
+                                                       <types:value>assocPersonGroupList/*/assocPerson</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>assocPlaceGroupList|assocPlace</types:value>
+                                                       <types:value>assocPlaceGroupList/*/assocPlace</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>referenceGroupList|reference</types:value>
+                                                       <types:value>referenceGroupList/*/reference</types:value>
             </types:item>
-            -->
             <!-- The following fields will become part of a repeatable group, per CSPACE-4486. -->
             <!-- As a result, they will fall into complexType structures. -->
             <!-- The names of ancestor elements below are anticipated, arbitrary and subject to change. -->
             <!--
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>inscriptionContentGroupList|inscriptionContentInscriber</types:value>
+                                                       <types:value>inscriptionContentGroupList/*/inscriptionContentInscriber</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>inscriptionContentGroupList|inscriptionContentMethod</types:value>
+                                                       <types:value>inscriptionContentGroupList/*/inscriptionContentMethod</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>inscriptionDescriptionGroupList|inscriptionDescriptionInscriber</types:value>
+                                                       <types:value>inscriptionDescriptionGroupList/*/inscriptionDescriptionInscriber</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>inscriptionDescriptionGroupList|inscriptionDescriptionMethod</types:value>
+                                                       <types:value>inscriptionDescriptionGroupList/*/inscriptionDescriptionMethod</types:value>
             </types:item>
             -->
-            <!-- The following field will become part of a repeatable sub-group, per CSPACE-3686. -->
-            <!-- As a result, its parent field/hiearchical paths will change from that shown below. -->
-            <!--
+            <!-- NEEDS ATTENTION - thsi is no longer correct w.r.t. schema
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>dimensionList|measuredBy</types:value>
+                                                       <types:value>dimensionList/*/measuredBy</types:value>
             </types:item>
             -->
             <!-- The following fields may become part of a repeatable sub-group, per JIRA(s) -->
             <!--
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>assocEventGroupList|assocEventOrganization</types:value>
+                                                       <types:value>assocEventGroupList/*/assocEventOrganization</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>assocEventGroupList|assocEventPeople</types:value>
+                                                       <types:value>assocEventGroupList/*/assocEventPeople</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>assocEventGroupList|assocEventPerson</types:value>
+                                                       <types:value>assocEventGroupList/*/assocEventPerson</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>assocEventGroupList|assocEventPlace</types:value>
+                                                       <types:value>assocEventGroupList/*/assocEventPlace</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>ownerGroupList|owner</types:value>
+                                                       <types:value>ownerGroupList/*/owner</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>ownerGroupList|ownershipPlace</types:value>
+                                                       <types:value>ownerGroupList/*/ownershipPlace</types:value>
             </types:item>
             -->
-            <!-- CSPACE-4457: Identification of term list / controlled vocabulary fields -->
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>responsibleDepartment|responsibleDepartments</types:value>
+              <types:value>responsibleDepartments|responsibleDepartment</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
             <!--
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>otherNumberList|numberType</types:value>
+                                                       <types:value>otherNumberList/*/numberType</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>objectNameList|objectNameCurrency</types:value>
+                                                       <types:value>objectNameList/*/objectNameCurrency</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>objectNameList|objectNameLevel</types:value>
+                                                       <types:value>objectNameList/*/objectNameLevel</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>objectNameList|objectNameSystem</types:value>
+                                                       <types:value>objectNameList/*/objectNameSystem</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>objectNameList|objectNameType</types:value>
+                                                       <types:value>objectNameList/*/objectNameType</types:value>
             </types:item>
            <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>objectNameList|objectNameLanguage</types:value>
+                                                       <types:value>objectNameList/*/objectNameLanguage</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>titleGroupList|titleLanguage</types:value>
+                                                       <types:value>titleGroupList/*/titleLanguage</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>contentObjectGroupList|contentObjectType</types:value>
+                                                       <types:value>contentObjectGroupList/*/contentObjectType</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>titleGroupList|titleType</types:value>
+                                                       <types:value>titleGroupList/*/titleType</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>dimensionList|measuredPart</types:value>
+                                                       <types:value>dimensionList/*/measuredPart</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>technicalAttributeGroupList|technicalAttribute</types:value>
+                                                       <types:value>technicalAttributeGroupList/*/technicalAttribute</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>technicalAttributeGroupList|technicalAttributeMeasurement</types:value>
+                                                       <types:value>technicalAttributeGroupList/*/technicalAttributeMeasurement</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>technicalAttributeGroupList|technicalAttributeMeasurementUnit</types:value>
+                                                       <types:value>technicalAttributeGroupList/*/technicalAttributeMeasurementUnit</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>assocObjectGroupList|assocObject</types:value>
+                                                       <types:value>assocObjectGroupList/*/assocObject</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>assocObjectGroupList|assocObjectType</types:value>
+                                                       <types:value>assocObjectGroupList/*/assocObjectType</types:value>
             </types:item>
             -->
             <!-- The following field will become part of a repeatable sub-group, per CSPACE-3627. -->
             <!--
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>titleGroupList|titleTranslationLanguage</types:value>
+                                                       <types:value>titleGroupList/*/titleTranslationLanguage</types:value>
             </types:item>
             -->
             <!-- The following fields will become part of a repeatable sub-group, per CSPACE-3686. -->
             <!--
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>dimensionList|dimension</types:value>
+                                                       <types:value>dimensionList/*/dimension</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>dimensionList|measurementUnit</types:value>
+                                                       <types:value>dimensionList/*/measurementUnit</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>dimensionList|measurementMethod</types:value>
+                                                       <types:value>dimensionList/*/measurementMethod</types:value>
             </types:item>
             -->
             <!-- The following fields will become part of a repeatable group, per CSPACE-4486. -->
             <!--
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>inscriptionContentGroupList|inscriptionContentLanguage</types:value>
+                                                       <types:value>inscriptionContentGroupList/*/inscriptionContentLanguage</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>inscriptionContentGroupList|inscriptionContentPosition</types:value>
+                                                       <types:value>inscriptionContentGroupList/*/inscriptionContentPosition</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>inscriptionContentGroupList|inscriptionContentScript</types:value>
+                                                       <types:value>inscriptionContentGroupList/*/inscriptionContentScript</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>inscriptionContentGroupList|inscriptionContentType</types:value>
+                                                       <types:value>inscriptionContentGroupList/*/inscriptionContentType</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>inscriptionDescriptionGroupList|inscriptionDescriptionLanguage</types:value>
+                                                       <types:value>inscriptionDescriptionGroupList/*/inscriptionDescriptionLanguage</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>inscriptionDescriptionGroupList|inscriptionDescriptionPosition</types:value>
+                                                       <types:value>inscriptionDescriptionGroupList/*/inscriptionDescriptionPosition</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>inscriptionDescriptionGroupList|inscriptionDescriptionType</types:value>
+                                                       <types:value>inscriptionDescriptionGroupList/*/inscriptionDescriptionType</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>usageGroupList|usage</types:value>
+                                                       <types:value>usageGroupList/*/usage</types:value>
             </types:item>
             -->
             <!-- The following fields may become part of a repeatable sub-group, per JIRA(s) -->
             <!--
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>assocEventGroupList|assocEventName</types:value>
+                                                       <types:value>assocEventGroupList/*/assocEventName</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>assocEventGroupList|assocEventNameType</types:value>
+                                                       <types:value>assocEventGroupList/*/assocEventNameType</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>ownerGroupList|ownershipAccess</types:value>
+                                                       <types:value>ownerGroupList/*/ownershipAccess</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>ownerGroupList|ownershipCategory</types:value>
+                                                       <types:value>ownerGroupList/*/ownershipCategory</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>ownerGroupList|ownershipExchangeMethod</types:value>
+                                                       <types:value>ownerGroupList/*/ownershipExchangeMethod</types:value>
             </types:item>
             -->
           </service:properties>
               <types:key>authRef</types:key>
               <types:value>conditionCheckersOrAssessors|conditionCheckerOrAssessor</types:value>
             </types:item>
-            <!-- Commented out for now, as searching within a field in a complexType breaks searches -->
-            <!--
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>currentLocationGroupList|currentLocation</types:value>
+                                                       <types:value>currentLocationGroupList/*/currentLocation</types:value>
             </types:item>
-            -->
             <!-- CSPACE-4457: Identification of term list / controlled vocabulary fields -->
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
             <!--
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>currentLocationGroupList|currentLocationFitness</types:value>
+                                                       <types:value>currentLocationGroupList/*/currentLocationFitness</types:value>
             </types:item>
             -->
           </service:properties>
                <types:key>authRef</types:key>
                <types:value>borrowersContact</types:value>
             </types:item>
-            <!-- Commented out for now, as searching within a field in a complexType breaks searches -->
-            <!--
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>LenderGroupList|lender</types:value>
+                                                       <types:value>LenderGroupList/*/lender</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>LenderGroupList|lendersAuthorizer</types:value>
+                                                       <types:value>LenderGroupList/*/lendersAuthorizer</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
                <types:key>authRef</types:key>
-               <types:value>LenderGroupList|lendersContact</types:value>
-               </types:item>
+                                                        <types:value>LenderGroupList/*/lendersContact</types:value>
             </types:item>
-            -->
-            <!-- To be added to Loan In records per CSPACE-3269 -->
-            <!--
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>loanStatusGroupList|loanStatus</types:value>
+                                                       <types:value>loanStatusGroupList/*/loanStatus</types:value>
             </types:item>
-            -->
           </service:properties>
           <service:content contentType="application/xml">
             <service:xmlContent namespaceURI="http://collectionspace.org/services/loanin" schemaLocation="http://collectionspace.org/services/loanin http://services.collectionspace.org/loanin/loansin_common.xsd" />
             <!--
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>loanedObjectStatusGroupList|loanedObjectStatus</types:value>
+                                                       <types:value>loanedObjectStatusGroupList/*/loanedObjectStatus</types:value>
             </types:item>
             -->
           </service:properties>
             <!-- Subject Authority field -->
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>subjectList|subject</types:value>
+                                                       <types:value>subjectList|subject</types:value>
             </types:item>
-            <!-- Commented out for now, as searching within a field in a complexType breaks searches for referenced objects -->
-            <!--
+            <!-- NEEDS ATTENTION w.r.t. current schema
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>dimensionGroupList|measuredBy</types:value>
+                                                       <types:value>dimensionGroupList/*/measuredBy</types:value>
             </types:item>
             -->
-            <!-- CSPACE-4457: Identification of term list / controlled vocabulary fields -->
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
               <types:value>languageList|language</types:value>
             <!--
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>dimensionGroupList|dimension</types:value>
+                                                       <types:value>dimensionGroupList/*/dimension</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>dimensionGroupList|measurementUnit</types:value>
+                                                       <types:value>dimensionGroupList/*/measurementUnit</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>dimensionGroupList|measurementMethod</types:value>
+                                                       <types:value>dimensionGroupList/*/measurementMethod</types:value>
             </types:item>
             -->
           </service:properties>
             </types:item>
             <!-- To be added per CSPACE-3939. Name is preliminary; please check organizations_common schema before enabling -->
             <!-- Commented out for now, as searching within a field in a complexType breaks searches for referenced objects -->
-            <!--
+            <!-- THIS SHOULD PROBABLY NOT BE DONE THIS WAY (Patrick)
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>affiliatedPersonGroupList|affiliatedPerson</types:value>
+                                                       <types:value>affiliatedPersonGroupList/*/affiliatedPerson</types:value>
             </types:item>
             -->
             <!-- CSPACE-4457: Identification of term list / controlled vocabulary fields -->
             <!--
               <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>affiliatedPersonGroupList|affiliatedPersonType</types:value>
+                                                       <types:value>affiliatedPersonGroupList/*/affiliatedPersonType</types:value>
             </types:item>
             -->
           </service:properties>
             <!-- The following authority reference is commented out for now, as searching within -->
             <!-- a field in a complexType breaks searches for referenced objects -->
             <!-- To be added per CSPACE-3938; field names are preliminary and should be checked before uncommenting -->
-            <!--
+            <!-- NO - this should be implemented with relations.
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>affiliatedOrganizationGroupList|affiliatedOrganization</types:value>
+                                                       <types:value>affiliatedOrganizationGroupList/*/affiliatedOrganization</types:value>
             </types:item>
             -->
             <!-- CSPACE-4457: Identification of term list / controlled vocabulary fields -->
-            <!--
+            <!-- NEEDS ATTENTION - why are these not yet enabled? They look like they should be termRefs.
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
               <types:value>termStatus</types:value>
             </types:item>
             -->
             <!-- The following term reference falls within a nested complexType / multivalued group of fields -->
-            <!--
+            <!-- NO. Do with relations
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>affiliatedOrganizationGroupList|affiliatedOrganizationType</types:value>
+                                                       <types:value>affiliatedOrganizationGroupList/*/affiliatedOrganizationType</types:value>
             </types:item>
             -->
           </service:properties>
         </service:part>
         <service:part id="1" control_group="Managed" versionable="true" auditable="false" label="taxon_common" updated="" order="1">
           <service:properties xmlns:service="http://collectionspace.org/services/common/service">
-            <!-- The following authority reference is commented out for now, as searching within -->
-            <!-- a field in a complexType breaks searches for referenced objects -->
-            <!--
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>taxonAuthorGroupList|taxonAuthor</types:value>
+                                                       <types:value>taxonAuthorGroupList/*/taxonAuthor</types:value>
             </types:item>
-            -->
             <!-- CSPACE-4457: Identification of term list / controlled vocabulary fields -->
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
             <!--
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>taxonAuthorGroupList|taxonAuthorType</types:value>
+                                                       <types:value>taxonAuthorGroupList/*/taxonAuthorType</types:value>
             </types:item>
             -->
           </service:properties>
               <types:key>authRef</types:key>
               <types:value>fieldCollectionEventNames|fieldCollectionEventName</types:value>
             </types:item>
-            <!-- Commented out for now, as searching within a field in a complexType breaks searches for referenced objects -->
-            <!--
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>acquisitionFundingList|acquisitionFundingSource</types:value>
+                                                       <types:value>acquisitionFundingList/*/acquisitionFundingSource</types:value>
             </types:item>
-            -->
             <!-- CSPACE-4457: Identification of term list / controlled vocabulary fields -->
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
             <!--
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>AcquisitionFundingList|acquisitionFundingCurrency</types:value>
+                                                       <types:value>AcquisitionFundingList/*/acquisitionFundingCurrency</types:value>
             </types:item>
             -->
           </service:properties>
           </service:content>
         </service:part>
         <service:part id="1" control_group="Managed" versionable="true" auditable="false" label="contacts_common" updated="" order="1">
-          <!--
           <service:properties>
-          -->
-            <!-- The following authority references are commented out for now, as searching within -->
-            <!-- a field in a complexType breaks searches for referenced objects -->
-            <!--
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>addressGroupList|addressMunicipality</types:value>
+                                                       <types:value>addressGroupList/*/addressMunicipality</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>addressGroupList|addressStateOrProvince</types:value>
+                                                       <types:value>addressGroupList/*/addressStateOrProvince</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>authRef</types:key>
-              <types:value>addressGroupList|addressCountry</types:value>
+                                                       <types:value>addressGroupList/*/addressCountry</types:value>
             </types:item>
-            -->
-            <!-- CSPACE-4457: Identification of term list / controlled vocabulary fields -->
-            <!-- The following term references all fall within a nested complexType / multivalued group of fields -->
-            <!--
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>emailGroupList|emailType</types:value>
+                                                       <types:value>emailGroupList/*/emailType</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>webAddressGroupList|webAddressType</types:value>
+                                                       <types:value>webAddressGroupList/*/webAddressType</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>telephoneNumberGroupList|telephoneNumberType</types:value>
+                                                       <types:value>telephoneNumberGroupList/*/telephoneNumberType</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>faxNumberGroupList|faxNumberType</types:value>
+                                                       <types:value>faxNumberGroupList/*/faxNumberType</types:value>
             </types:item>
             <types:item xmlns:types="http://collectionspace.org/services/common/types">
               <types:key>termRef</types:key>
-              <types:value>addressGroupList|addressType</types:value>
+                                                       <types:value>addressGroupList/*/addressType</types:value>
             </types:item>
-            -->
-          <!--
           </service:properties>
-          -->
           <service:content contentType="application/xml">
             <service:xmlContent namespaceURI="http://collectionspace.org/services/contact" schemaLocation="http://collectionspace.org/services/contact http://services.collectionspace.org/contact/contacts_common.xsd" />
           </service:content>
index 3d348503ac9979b06e82232d1e84c760d8d14ac0..d2c9338101e81a498a40a11090e20927145472b8 100644 (file)
@@ -37,6 +37,8 @@ import org.collectionspace.services.common.document.DocumentNotFoundException;
 import org.collectionspace.services.common.document.DocumentWrapper;\r
 import org.collectionspace.services.common.query.QueryManager;\r
 import org.collectionspace.services.common.security.UnauthorizedException;\r
+import org.collectionspace.services.common.vocabulary.RefNameServiceUtils;\r
+import org.collectionspace.services.common.vocabulary.RefNameServiceUtils.AuthRefConfigInfo;\r
 import org.collectionspace.services.jaxb.AbstractCommonList;\r
 import org.collectionspace.services.nuxeo.client.java.DocumentModelHandler;\r
 import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;\r
@@ -48,6 +50,7 @@ import javax.ws.rs.*;
 import javax.ws.rs.core.*;\r
 \r
 import java.util.List;\r
+import java.util.Map;\r
 \r
 /**\r
  * $LastChangedRevision:  $\r
@@ -331,10 +334,8 @@ public abstract class ResourceBase
             ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(queryParams);\r
             DocumentWrapper<DocumentModel> docWrapper = getRepositoryClient(ctx).getDoc(ctx, csid);\r
             DocumentModelHandler<PoxPayloadIn, PoxPayloadOut> handler = (DocumentModelHandler<PoxPayloadIn, PoxPayloadOut>) createDocumentHandler(ctx);\r
-            List<String> authRefFields =\r
-                    ((MultipartServiceContextImpl) ctx).getCommonPartPropertyValues(\r
-                    ServiceBindingUtils.AUTH_REF_PROP, ServiceBindingUtils.QUALIFIED_PROP_NAMES);\r
-            authRefList = handler.getAuthorityRefs(docWrapper, authRefFields);\r
+            List<AuthRefConfigInfo> authRefsInfo = RefNameServiceUtils.getConfiguredAuthorityRefs(ctx);\r
+            authRefList = handler.getAuthorityRefs(docWrapper, authRefsInfo);\r
         } catch (Exception e) {\r
             throw bigReThrow(e, ServiceMessages.AUTH_REFS_FAILED, csid);\r
         }\r
index 892b3103e8fd169e08506d966a9936fba3b14d8e..dd15f33c8f1603832f370495517ce0605644aa1f 100644 (file)
@@ -95,6 +95,7 @@ public class PropertyItemUtils {
                values = new ArrayList<String>();\r
        for(PropertyItemType propItem:propItems) {\r
                if(propName.equals(propItem.getKey())) {\r
+                       // TODO - the trim() belongs here, not down a few lines.\r
                        String value = propItem.getValue();\r
                        if(value!=null) {\r
                                values.add((qualPrefix!=null)?(qualPrefix+value):value.trim());\r
index 00e0ce46e3efbc893a8c491568693ea4328e82fb..a1c5cc54bb71f588a0b3f31e61c227a96b97f987 100644 (file)
@@ -817,6 +817,7 @@ public class DocumentUtils {
         * @return true, if is list type
         */
        public static boolean isListType(Property prop) {
+               // TODO simplify this to return (prop!=null && prop.getType().isListType());
                boolean isList = false;
                if (prop == null) {
                        return isList;
@@ -834,6 +835,7 @@ public class DocumentUtils {
         * @return true, if is complex type
         */
        public static boolean isComplexType(Property prop) {
+               // TODO simplify this to return (prop!=null && prop.getType().isComplexType());
                boolean isComplex = false;
                if (prop == null) {
                        return isComplex;
@@ -853,6 +855,7 @@ public class DocumentUtils {
          *               false, if it is not a date type.
          */
         private static boolean isDateType(Type type) {
+               // TODO simplify this to return ((SimpleType)type).getPrimitiveType() instanceof DateType;
             SimpleType st = (SimpleType) type;
             if (st.getPrimitiveType() instanceof DateType) {
                 return true;
similarity index 55%
rename from services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/RefNameServiceUtils.java
rename to services/common/src/main/java/org/collectionspace/services/common/vocabulary/RefNameServiceUtils.java
index 5e22beb2aec4b6c8c7b41ea84452044ea317a9f8..781f43e060f52c9b3825e9bf33ad9c58801fefa8 100644 (file)
@@ -35,12 +35,14 @@ import org.nuxeo.ecm.core.api.DocumentModel;
 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.PropertyNotFoundException;\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.context.AbstractServiceContextImpl;\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
@@ -57,6 +59,8 @@ import org.collectionspace.services.common.service.ServiceBindingType;
 import org.collectionspace.services.jaxb.AbstractCommonList;\r
 import org.collectionspace.services.nuxeo.util.NuxeoUtils;\r
 \r
+import com.sun.xml.bind.v2.runtime.unmarshaller.XsiNilLoader.Array;\r
+\r
 /**\r
  * RefNameServiceUtils is a collection of services utilities related to refName usage.\r
  *\r
@@ -65,9 +69,137 @@ import org.collectionspace.services.nuxeo.util.NuxeoUtils;
  */\r
 public class RefNameServiceUtils {\r
 \r
+       public static class AuthRefConfigInfo {\r
+               public String getQualifiedDisplayName() {\r
+               return(Tools.isBlank(schema))?\r
+                               displayName:DocumentUtils.appendSchemaName(schema, displayName);\r
+               }\r
+               public String getDisplayName() {\r
+                       return displayName;\r
+               }\r
+               public void setDisplayName(String displayName) {\r
+                       this.displayName = displayName;\r
+               }\r
+               String displayName;\r
+               String schema;\r
+               public String getSchema() {\r
+                       return schema;\r
+               }\r
+               public void setSchema(String schema) {\r
+                       this.schema = schema;\r
+               }\r
+               public String getFullPath() {\r
+                       return fullPath;\r
+               }\r
+               public void setFullPath(String fullPath) {\r
+                       this.fullPath = fullPath;\r
+               }\r
+               String fullPath;\r
+               protected String[] pathEls;\r
+               public AuthRefConfigInfo(AuthRefConfigInfo arci) {\r
+                       this.displayName = arci.displayName;\r
+                       this.schema = arci.schema;\r
+                       this.fullPath = arci.fullPath;\r
+                       this.pathEls = arci.pathEls;\r
+                       // Skip the pathElse check, since we are creatign from another (presumably valid) arci.\r
+               }\r
+               \r
+               public AuthRefConfigInfo(String displayName, String schema, String fullPath, String[] pathEls) {\r
+                       this.displayName = displayName;\r
+                       this.schema = schema;\r
+                       this.fullPath = fullPath;\r
+                       this.pathEls = pathEls;\r
+                       checkPathEls();\r
+               }\r
+\r
+               // Split a config value string like "intakes_common:collector", or\r
+               // "collectionobjects_common:contentPeoples|contentPeople"\r
+               // "collectionobjects_common:assocEventGroupList/*/assocEventPlace"\r
+               // If has a pipe ('|') second part is a displayLabel, and first is path\r
+               // Otherwise, entry is a path, and can use the last pathElement as displayName\r
+               // Should be schema qualified.\r
+               public AuthRefConfigInfo(String configString) {\r
+               String[] pair = configString.split("\\|", 2);\r
+               String[] pathEls;\r
+               String displayName, fullPath;\r
+               if(pair.length == 1) {\r
+                       // no label specifier, so we'll defer getting label\r
+                       fullPath = pair[0];\r
+                       pathEls = pair[0].split("/");\r
+                       displayName = pathEls[pathEls.length-1];\r
+               } else {\r
+                       fullPath = pair[0];\r
+                       pathEls = pair[0].split("/");\r
+                       displayName = pair[1];\r
+               }\r
+               String[] schemaSplit = pathEls[0].split(":",2);\r
+               String schema; \r
+               if(schemaSplit.length==1) {     // schema not specified\r
+                       schema = null;\r
+               } else {\r
+                       schema = schemaSplit[0];\r
+                       if(pair.length == 1 && pathEls.length == 1) {   // simplest case of field in top level schema, no labelll\r
+                               displayName = schemaSplit[1];   // Have to fix up displayName to have no schema\r
+                       }\r
+               }\r
+                       this.displayName = displayName;\r
+                       this.schema = schema;\r
+                       this.fullPath = fullPath;\r
+                       this.pathEls = pathEls;\r
+                       checkPathEls();\r
+               }\r
+               \r
+               protected void checkPathEls() {\r
+               int len = pathEls.length;\r
+               if(len<1)\r
+                       throw new InternalError("Bad values in authRef info - caller screwed up:"+fullPath);\r
+               // Handle case of them putting a leading slash on the path\r
+               if(len>1 && pathEls[0].endsWith(":")) {\r
+                       len--;\r
+                       String[] newArray = new String[len];\r
+                       newArray[0] = pathEls[0]+pathEls[1];\r
+                       if(len>=2) {\r
+                               System.arraycopy(pathEls, 2, newArray, 1, len-1);\r
+                       }\r
+                       pathEls = newArray;\r
+               }\r
+               }\r
+       }\r
+\r
+       public static class AuthRefInfo extends AuthRefConfigInfo {\r
+               public Property getProperty() {\r
+                       return property;\r
+               }\r
+               public void setProperty(Property property) {\r
+                       this.property = property;\r
+               }\r
+               Property property;\r
+               public AuthRefInfo(String displayName, String schema, String fullPath, String[] pathEls, Property prop) {\r
+                       super(displayName, schema, fullPath, pathEls);\r
+                       this.property = prop;\r
+               }\r
+               public AuthRefInfo(AuthRefConfigInfo arci, Property prop) {\r
+                       super(arci);\r
+                       this.property = prop;\r
+               }\r
+       }\r
+\r
     private static final Logger logger = LoggerFactory.getLogger(RefNameServiceUtils.class);\r
     \r
     private static ArrayList<String> refNameServiceTypes = null;\r
+    \r
+    public static List<AuthRefConfigInfo> getConfiguredAuthorityRefs(ServiceContext ctx) {\r
+       List<String> authRefFields =\r
+                ((AbstractServiceContextImpl) ctx).getAllPartsPropertyValues(\r
+                ServiceBindingUtils.AUTH_REF_PROP, ServiceBindingUtils.QUALIFIED_PROP_NAMES);\r
+       ArrayList<AuthRefConfigInfo> authRefsInfo = new ArrayList<AuthRefConfigInfo>(authRefFields.size()); \r
+       for(String spec:authRefFields) {\r
+               AuthRefConfigInfo arci = new AuthRefConfigInfo(spec);\r
+               authRefsInfo.add(arci);\r
+       }\r
+       return authRefsInfo;\r
+    }\r
+\r
 \r
     public static AuthorityRefDocList getAuthorityRefDocs(ServiceContext ctx,\r
             RepositoryClient repoClient,\r
@@ -83,7 +215,7 @@ public class RefNameServiceUtils {
                 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
+        Map<String, List<AuthRefConfigInfo>> authRefFieldsByService = new HashMap<String, List<AuthRefConfigInfo>>();\r
 \r
         DocumentModelList docList = findAuthorityRefDocs(ctx, repoClient, serviceTypes, refName, refPropName,\r
                        queriedServiceBindings, authRefFieldsByService, pageSize, pageNum, computeTotal);\r
@@ -114,24 +246,28 @@ public class RefNameServiceUtils {
        return refNameServiceTypes;\r
     }\r
     \r
+    // Seems like a good value - no real data to set this well.\r
+    private static final int N_OBJS_TO_UPDATE_PER_LOOP = 100;\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
+        Map<String, List<AuthRefConfigInfo>> authRefFieldsByService = new HashMap<String, List<AuthRefConfigInfo>>();\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
+               final int pageSize = N_OBJS_TO_UPDATE_PER_LOOP; \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
+                       // should not be found in successive searches. Slightly inefficient, but more\r
+                       // reliable (stateless).\r
                        DocumentModelList docList = findAuthorityRefDocs(ctx, repoClient, getRefNameServiceTypes(), oldRefName, refPropName,\r
                                        queriedServiceBindings, authRefFieldsByService, pageSize, 0, false);\r
                \r
@@ -163,7 +299,7 @@ public class RefNameServiceUtils {
             String refName,\r
             String refPropName,\r
             Map<String, ServiceBindingType> queriedServiceBindings,\r
-            Map<String, Map<String, String>> authRefFieldsByService,\r
+            Map<String, List<AuthRefConfigInfo>> authRefFieldsByService,\r
             int pageSize, int pageNum, boolean computeTotal) throws DocumentException, DocumentNotFoundException {\r
 \r
         // Get the service bindings for this tenant\r
@@ -194,16 +330,18 @@ public class RefNameServiceUtils {
         return docList;\r
     }\r
     \r
+    private static final boolean READY_FOR_COMPLEX_QUERY = false;\r
+    \r
     private static String computeWhereClauseForAuthorityRefDocs(\r
                String escapedRefName,\r
                String refPropName,\r
                ArrayList<String> docTypes,\r
                List<ServiceBindingType> servicebindings,\r
                Map<String, ServiceBindingType> queriedServiceBindings,\r
-               Map<String, Map<String, String>> authRefFieldsByService ) {\r
+               Map<String, List<AuthRefConfigInfo>> authRefFieldsByService ) {\r
         StringBuilder whereClause = new StringBuilder();\r
         boolean fFirst = true;\r
-        List<String> authRefFieldPaths = new ArrayList<String>();\r
+        List<String> authRefFieldPaths;\r
         for (ServiceBindingType sb : servicebindings) {\r
                // Gets the property names for each part, qualified with the part label (which\r
                // is also the table name, the way that the repository works).\r
@@ -213,33 +351,29 @@ public class RefNameServiceUtils {
             if (authRefFieldPaths.isEmpty()) {\r
                 continue;\r
             }\r
-            String authRefPath = "";\r
-            String ancestorAuthRefFieldName = "";\r
-            Map<String, String> authRefFields = new HashMap<String, String>();\r
-            for (int i = 0; i < authRefFieldPaths.size(); i++) {\r
-                // fieldName = DocumentUtils.getDescendantOrAncestor(authRefFields.get(i));\r
-               // For simple field values, we just search on the item.\r
-               // For simple repeating scalars, we just search the group field \r
-               // For repeating complex types, we will need to do more.\r
-                authRefPath = authRefFieldPaths.get(i);\r
-                ancestorAuthRefFieldName = DocumentUtils.getAncestorAuthRefFieldName(authRefFieldPaths.get(i));\r
-                authRefFields.put(authRefPath, ancestorAuthRefFieldName);\r
-            }\r
+            ArrayList<AuthRefConfigInfo> authRefsInfo = new ArrayList<AuthRefConfigInfo>();\r
+               for(String spec:authRefFieldPaths) {\r
+                       AuthRefConfigInfo arci = new AuthRefConfigInfo(spec);\r
+                       authRefsInfo.add(arci);\r
+               }\r
 \r
             String docType = sb.getObject().getName();\r
             queriedServiceBindings.put(docType, sb);\r
-            authRefFieldsByService.put(docType, authRefFields);\r
+            authRefFieldsByService.put(docType, authRefsInfo);\r
             docTypes.add(docType);\r
-            Collection<String> fields = authRefFields.values();\r
-            for (String field : fields) {\r
+            for (AuthRefConfigInfo arci : authRefsInfo) {\r
                 // Build up the where clause for each authRef field\r
+               if(!READY_FOR_COMPLEX_QUERY) {  // filter complex field references\r
+                       if(arci.pathEls.length>1)\r
+                               continue;                               // skip this one\r
+               }\r
                 if (fFirst) {\r
                     fFirst = false;\r
                 } else {\r
                     whereClause.append(" OR ");\r
                 }\r
                 //whereClause.append(prefix);\r
-                whereClause.append(field);\r
+                whereClause.append(arci.getFullPath());\r
                 whereClause.append("='");\r
                 whereClause.append(escapedRefName);\r
                 whereClause.append("'");\r
@@ -265,17 +399,9 @@ public class RefNameServiceUtils {
                DocumentModelList docList,\r
                String refName,\r
                Map<String, ServiceBindingType> queriedServiceBindings,\r
-               Map<String, Map<String, String>> authRefFieldsByService,\r
+               Map<String, List<AuthRefConfigInfo>> 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
@@ -290,9 +416,15 @@ public class RefNameServiceUtils {
             }\r
             String serviceContextPath = "/" + sb.getName().toLowerCase() + "/";\r
             \r
-            if(list == null) {\r
+            if(list == null) { // no list - should be update refName case.\r
+               if(newAuthorityRefName==null) {\r
+                       throw new InternalError("processRefObjsDocList() called with neither an itemList nor a new RefName!");\r
+                       }\r
                ilistItem = null;\r
-            } else {\r
+            } else {   // Have a list - refObjs case\r
+               if(newAuthorityRefName!=null) {\r
+                       throw new InternalError("processRefObjsDocList() called with both an itemList and a new RefName!");\r
+               }\r
                ilistItem = new AuthorityRefDocList.AuthorityRefDocItem();\r
                 String csid = NuxeoUtils.getCsid(docModel);//NuxeoUtils.extractId(docModel.getPathAsString());\r
                 ilistItem.setDocId(csid);\r
@@ -311,71 +443,37 @@ public class RefNameServiceUtils {
             }\r
             // Now, we have to loop over the authRefFieldsByService to figure\r
             // out which field(s) matched this.\r
-            Map<String,String> matchingAuthRefFields = authRefFieldsByService.get(docType);\r
+            List<AuthRefConfigInfo> matchingAuthRefFields = authRefFieldsByService.get(docType);\r
             if (matchingAuthRefFields == null || matchingAuthRefFields.isEmpty()) {\r
                 throw new RuntimeException(\r
                         "getAuthorityRefDocs: internal logic error: can't fetch authRefFields for DocType.");\r
             }\r
-            String authRefAncestorField = "";\r
-            String authRefDescendantField = "";\r
-            String sourceField = "";\r
+            //String authRefAncestorField = "";\r
+            //String authRefDescendantField = "";\r
+            //String sourceField = "";\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
-                    // strings[0] holds a schema name, such as "intakes_common"\r
-                    //\r
-                    // strings[1] holds:\r
-                    // * The name of an authority reference field, such as "depositor";\r
-                    //   or\r
-                    // * The name of an ancestor (e.g. parent, grandparent ...) field,\r
-                    //   such as "fieldCollectors", of a repeatable authority reference\r
-                    //   field, such as "fieldCollector".\r
-                    // TODO - if the value is not simple, or repeating scalar, need a more\r
-                    // sophisticated fetch. \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(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
-                               }\r
-                       } else {\r
-                               if(ilistItem != null) {\r
-                                       ilistItem.setSourceField(sourceField);\r
-                               }\r
-                       }\r
-                               if(ilistItem != null) {\r
-                                       list.add(ilistItem);\r
-                               }\r
-                               nRefsFoundInDoc += nRefsMatchedInField;\r
-                    }\r
-\r
-                } catch (ClientException ce) {\r
-                    throw new RuntimeException(\r
-                            "getAuthorityRefDocs: Problem fetching: " + sourceField, ce);\r
-                }\r
+            \r
+            ArrayList<RefNameServiceUtils.AuthRefInfo> foundProps \r
+                                               = new ArrayList<RefNameServiceUtils.AuthRefInfo>();\r
+            try {\r
+                   findAuthRefPropertiesInDoc(docModel, matchingAuthRefFields, refName, foundProps);\r
+                   for(RefNameServiceUtils.AuthRefInfo ari:foundProps) {\r
+                               if(ilistItem != null) {\r
+                               if(nRefsFoundInDoc == 0) {      // First one?\r
+                                       ilistItem.setSourceField(ari.getQualifiedDisplayName());\r
+                               } else {        // duplicates from one object\r
+                                       ilistItem = cloneAuthRefDocItem(ilistItem, ari.getQualifiedDisplayName());\r
+                               }\r
+                                       list.add(ilistItem);\r
+                               } else {        // update refName case\r
+                                       Property propToUpdate = ari.getProperty();\r
+                                       propToUpdate.setValue(newAuthorityRefName);\r
+                               }\r
+                               nRefsFoundInDoc++;\r
+                   }\r
+            } catch (ClientException ce) {\r
+                throw new RuntimeException(\r
+                        "getAuthorityRefDocs: Problem fetching values from repo: " + ce.getLocalizedMessage());\r
             }\r
             if (nRefsFoundInDoc == 0) {\r
                 throw new RuntimeException(\r
@@ -398,6 +496,119 @@ public class RefNameServiceUtils {
        newlistItem.setSourceField(sourceField);\r
        return newlistItem;\r
     }\r
+    \r
+    public static List<AuthRefInfo> findAuthRefPropertiesInDoc( \r
+               DocumentModel docModel, \r
+               List<AuthRefConfigInfo> authRefFieldInfo,\r
+               String refNameToMatch,\r
+               List<AuthRefInfo> foundProps\r
+               ) {\r
+       // Assume that authRefFieldInfo is keyed by the field name (possibly mapped for UI)\r
+       // and the values are elPaths to the field, where intervening group structures in\r
+       // lists of complex structures are replaced with "*". Thus, valid paths include\r
+       // the following (note that the ServiceBindingUtils prepend schema names to configured values):\r
+       // "schemaname:fieldname"\r
+       // "schemaname:scalarlistname"\r
+       // "schemaname:complexfieldname/fieldname"\r
+       // "schemaname:complexlistname/*/fieldname"\r
+       // "schemaname:complexlistname/*/scalarlistname"\r
+       // "schemaname:complexlistname/*/complexfieldname/fieldname"\r
+       // "schemaname:complexlistname/*/complexlistname/*/fieldname"\r
+       // etc.\r
+        for (AuthRefConfigInfo arci : authRefFieldInfo) {\r
+            try {\r
+               // Get first property and work down as needed.\r
+                       Property prop = docModel.getProperty(arci.pathEls[0]);\r
+                       findAuthRefPropertiesInProperty(foundProps, prop, arci, 0, refNameToMatch);\r
+            } catch(Exception e) {\r
+               logger.error("Problem fetching property: "+arci.pathEls[0]);\r
+            }\r
+        }\r
+        return foundProps;\r
+    }\r
+\r
+    public static List<AuthRefInfo> findAuthRefPropertiesInProperty(\r
+               List<AuthRefInfo> foundProps,\r
+               Property prop, \r
+               AuthRefConfigInfo arci,\r
+               int pathStartIndex,             // Supports recursion and we work down the path\r
+               String refNameToMatch\r
+               ) {\r
+       if(pathStartIndex >= arci.pathEls.length) {\r
+               throw new ArrayIndexOutOfBoundsException("Index = "+pathStartIndex+" for path: "\r
+                                                                                               +arci.pathEls.toString());\r
+       }\r
+               AuthRefInfo ari = null;\r
+               if(prop == null)\r
+                       return foundProps;\r
+               if(prop instanceof StringProperty) {    // scalar string\r
+                       addARIifMatches(refNameToMatch, arci, prop, foundProps);\r
+               } else if(prop instanceof List) {\r
+                       List<Property> propList = (List)prop;\r
+                       // run through list. Must either be list of Strings, or Complex\r
+                       for (Property listItemProp : propList) {\r
+                               if(listItemProp instanceof StringProperty) {\r
+                                       if(arci.pathEls.length-pathStartIndex != 1) {\r
+                                               logger.error("Configuration for authRefs does not match schema structure: "\r
+                                                               +arci.pathEls.toString());\r
+                                               break;\r
+                                       } else {\r
+                                               addARIifMatches(refNameToMatch, arci, listItemProp, foundProps);\r
+                                       }\r
+                               } else if(listItemProp.isComplex()) {   \r
+                                       // Just recurse to handle this. Note that since this is a list of complex, \r
+                                       // which should look like listName/*/... we add 2 to the path start index \r
+                                       findAuthRefPropertiesInProperty(foundProps, listItemProp, arci,\r
+                                                       pathStartIndex+2, refNameToMatch);\r
+                               } else {\r
+                                       logger.error("Configuration for authRefs does not match schema structure: "\r
+                                                       +arci.pathEls.toString());\r
+                                       break;\r
+                               }\r
+                       }\r
+               } else if(prop.isComplex()) {\r
+                       String localPropName = arci.pathEls[pathStartIndex];\r
+                       try {\r
+                               Property localProp = prop.get(localPropName);\r
+                               // Now just recurse, pushing down the path 1 step\r
+                               findAuthRefPropertiesInProperty(foundProps, localProp, arci, \r
+                                                                                               pathStartIndex, refNameToMatch);\r
+                       } catch(PropertyNotFoundException pnfe) {\r
+                               logger.error("Could not find property: ["+localPropName+"] in path: "+\r
+                                                               arci.getFullPath());\r
+                               // Fall through - ari will be null and we will continue...\r
+                       }\r
+               } else {\r
+                               logger.error("Configuration for authRefs does not match schema structure: "\r
+                                               +arci.pathEls.toString());\r
+               }\r
+\r
+       if(ari != null) {\r
+               foundProps.add(ari);\r
+       }\r
+       return foundProps;\r
+    }\r
+    \r
+    private static void addARIifMatches(\r
+               String refNameToMatch, \r
+               AuthRefConfigInfo arci, \r
+               Property prop, \r
+               List<AuthRefInfo> foundProps) {\r
+               // Need to either match a passed refName \r
+               // OR have no refName to match but be non-empty\r
+       try {\r
+               String value = (String)prop.getValue();\r
+                       if(((refNameToMatch!=null) && refNameToMatch.equals(value))\r
+                                       || ((refNameToMatch==null) && Tools.notBlank(value))) {\r
+                               // Found a match\r
+                               logger.debug("Found a match on property: "+prop.getPath()+" with value: ["+value+"]");\r
+                               AuthRefInfo ari = new AuthRefInfo(arci, prop);\r
+                               foundProps.add(ari);\r
+                       }\r
+       } catch(PropertyException pe) {\r
+                       logger.debug("PropertyException on: "+prop.getPath()+pe.getLocalizedMessage());\r
+       }\r
+    }\r
 \r
     /*\r
      * Identifies whether the refName was found in the supplied field.\r
@@ -410,7 +621,6 @@ public class RefNameServiceUtils {
      * Does not work for:\r
      * * Structured fields (complexTypes)\r
      * * Repeatable structured fields (repeatable complexTypes)\r
-     */\r
     private static int refNameFoundInField(String oldRefName, Property fieldValue, String newRefName) {\r
        int nFound = 0;\r
        if (fieldValue instanceof List) {\r
@@ -443,5 +653,6 @@ public class RefNameServiceUtils {
        }\r
        return nFound;\r
     }\r
+     */\r
 }\r
 \r
index ae255a0544ce4aebe45cedc044b40b782f2f70a2..981acd8482e51dfe64ac70e4a7f0a25bfa8fbef8 100644 (file)
@@ -113,7 +113,14 @@ public class RefNameUtils {
                } else if(resource.equals("orgauthority")) {\r
                        uri.append("/orgauthorities/");\r
                } else {\r
-                       throw new RuntimeException("Illegal Authority Type: " + resource);\r
+                       if(!(resource.equals("orgauthorities")\r
+                               || resource.equals("personauthorities")\r
+                               || resource.equals("locationauthorities")\r
+                               || resource.equals("placeauthorities")\r
+                               || resource.equals("vocabularies"))) {  \r
+                               logger.error("Unrecognized Authority Type: " + resource);\r
+                       }\r
+                       uri.append("/"+resource+"/");\r
                }\r
                if(csid!=null) {\r
                        uri.append(csid);\r
index 91c7a2f0c290a42f1211630b79e460c34ae30d42..02e3e9a0610616ff26a5c2162f21bbc2026e5072 100644 (file)
@@ -24,6 +24,7 @@
 package org.collectionspace.services.nuxeo.client.java;
 
 import java.util.List;
+import java.util.Map;
 
 import org.collectionspace.services.client.PoxPayloadIn;
 import org.collectionspace.services.client.PoxPayloadOut;
@@ -39,6 +40,7 @@ import org.collectionspace.services.nuxeo.util.NuxeoUtils;
 import org.collectionspace.services.common.profile.Profiler;
 import org.collectionspace.services.common.repository.RepositoryClient;
 import org.collectionspace.services.common.repository.RepositoryClientFactory;
+import org.collectionspace.services.common.vocabulary.RefNameServiceUtils.AuthRefConfigInfo;
 
 import org.nuxeo.ecm.core.api.ClientException;
 import org.nuxeo.ecm.core.api.DocumentModel;
@@ -184,7 +186,7 @@ public abstract class DocumentModelHandler<T, TL>
      */
     abstract public AuthorityRefList getAuthorityRefs(
             DocumentWrapper<DocumentModel> docWrapper,
-               List<String> authRefFields) throws PropertyException;    
+            List<AuthRefConfigInfo> authRefsInfo) throws PropertyException;    
 
     private void handleCoreValues(DocumentWrapper<DocumentModel> docWrapper, 
                Action action)  throws ClientException {
index 5c365d0566f57b98026e8fbcc74c9d9962783b71..60d96f3d15441c5e1a0178f790265c9367436bee 100644 (file)
@@ -23,6 +23,7 @@
  */
 package org.collectionspace.services.nuxeo.client.java;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.GregorianCalendar;
 import java.util.HashMap;
@@ -42,6 +43,7 @@ import org.collectionspace.services.client.PayloadOutputPart;
 import org.collectionspace.services.client.PoxPayloadIn;
 import org.collectionspace.services.client.PoxPayloadOut;
 import org.collectionspace.services.client.workflow.WorkflowClient;
+import org.collectionspace.services.common.api.Tools;
 import org.collectionspace.services.common.authorityref.AuthorityRefList;
 import org.collectionspace.services.common.context.JaxRsContext;
 import org.collectionspace.services.common.context.MultipartServiceContext;
@@ -56,6 +58,8 @@ import org.collectionspace.services.common.security.SecurityUtils;
 import org.collectionspace.services.common.service.ObjectPartType;
 import org.collectionspace.services.common.storage.jpa.JpaStorageUtils;
 import org.collectionspace.services.common.vocabulary.RefNameUtils;
+import org.collectionspace.services.common.vocabulary.RefNameServiceUtils;
+import org.collectionspace.services.common.vocabulary.RefNameServiceUtils.AuthRefConfigInfo;
 import org.dom4j.Element;
 
 import org.nuxeo.ecm.core.api.DocumentModel;
@@ -381,7 +385,7 @@ public abstract class   RemoteDocumentModelHandlerImpl<T, TL>
     @Override
     public AuthorityRefList getAuthorityRefs(
             DocumentWrapper<DocumentModel> docWrapper,
-            List<String> authRefFieldNames) throws PropertyException {
+            List<AuthRefConfigInfo> authRefsInfo) throws PropertyException {
 
         AuthorityRefList authRefList = new AuthorityRefList();
         AbstractCommonList commonList = (AbstractCommonList) authRefList;
@@ -400,101 +404,22 @@ public abstract class   RemoteDocumentModelHandlerImpl<T, TL>
                int iFirstToUse = (int)(pageSize*pageNum);
                int nFoundInPage = 0;
                int nFoundTotal = 0;
-            for (String authRefFieldName : authRefFieldNames) {
-
-                // FIXME: Can use the schema to validate field existence,
-                // to help avoid encountering PropertyExceptions.
-                String schemaName = DocumentUtils.getSchemaNamePart(authRefFieldName);
-                Schema schema = DocumentUtils.getSchemaFromName(schemaName);
-
-                String descendantAuthRefFieldName = DocumentUtils.getDescendantAuthRefFieldName(authRefFieldName);
-                if (descendantAuthRefFieldName != null && !descendantAuthRefFieldName.trim().isEmpty()) {
-                    authRefFieldName = DocumentUtils.getAncestorAuthRefFieldName(authRefFieldName);
-                }
-
-                String xpath = "//" + authRefFieldName;
-                Property prop = docModel.getProperty(xpath);
-                if (prop == null) {
-                    continue;
-                }
-
-                // If this is a single scalar field, with no children,
-                // add an item with its values to the authRefs list.
-                if (DocumentUtils.isSimpleType(prop)) {
-                       String refName = prop.getValue(String.class);
-                    if (refName == null) {
-                        continue;
-                    }
-                    refName = refName.trim();
-                    if (refName.isEmpty()) {
-                        continue;
-                    }
-                       if((nFoundTotal < iFirstToUse)
-                               || (nFoundInPage >= pageSize)) {
-                               nFoundTotal++;
-                               continue;
-                       }
-                       nFoundTotal++;
-                       nFoundInPage++;
-                       appendToAuthRefsList(refName, schemaName, authRefFieldName, list);
-
-                    // Otherwise, if this field has children, cycle through each child.
-                    //
-                    // Whenever we find instances of the descendant field among
-                    // these children, add an item with its values to the authRefs list.
-                    //
-                    // FIXME: When we increase maximum repeatability depth, that is, the depth
-                    // between ancestor and descendant, we'll need to use recursion here,
-                    // rather than making fixed assumptions about hierarchical depth.
-                } else if ((DocumentUtils.isListType(prop) || DocumentUtils.isComplexType(prop))
-                        && prop.size() > 0) {
-                    
-                    Collection<Property> childProp = prop.getChildren();
-                    for (Property cProp : childProp) {
-                        if (DocumentUtils.isSimpleType(cProp) && cProp.getName().equals(descendantAuthRefFieldName)) {
-                               String refName = cProp.getValue(String.class);
-                            if (refName == null) {
-                                continue;
-                            }
-                            refName = refName.trim();
-                            if (refName.isEmpty()) {
-                                continue;
-                            }
-                               if((nFoundTotal < iFirstToUse)
-                                       || (nFoundInPage >= pageSize)) {
-                                       nFoundTotal++;
-                                       continue;
-                               }
-                               nFoundTotal++;
-                               nFoundInPage++;
-                            appendToAuthRefsList(refName, schemaName, descendantAuthRefFieldName, list);
-                        } else if ((DocumentUtils.isListType(cProp) || DocumentUtils.isComplexType(cProp))
-                            && prop.size() > 0) {
-                            Collection<Property> grandChildProp = cProp.getChildren();
-                            for (Property gProp : grandChildProp) {
-                                if (DocumentUtils.isSimpleType(gProp) && gProp.getName().equals(descendantAuthRefFieldName)) {
-                                       String refName = gProp.getValue(String.class);
-                                    if (refName == null) {
-                                        continue;
-                                    }
-                                    refName = refName.trim();
-                                    if (refName.isEmpty()) {
-                                        continue;
-                                    }
-                                       if((nFoundTotal < iFirstToUse)
-                                               || (nFoundInPage >= pageSize)) {
-                                               nFoundTotal++;
-                                               continue;
-                                       }
-                                       nFoundTotal++;
-                                       nFoundInPage++;
-                                    appendToAuthRefsList(refName, schemaName, descendantAuthRefFieldName, list);
-                                }
-                            }
-                        }
-                    }
-                }
-            }
+               
+               ArrayList<RefNameServiceUtils.AuthRefInfo> foundProps 
+                       = new ArrayList<RefNameServiceUtils.AuthRefInfo>();
+               RefNameServiceUtils.findAuthRefPropertiesInDoc(docModel, authRefsInfo, null, foundProps);
+               // Slightly goofy pagination support - how many refs do we expect from one object?
+               for(RefNameServiceUtils.AuthRefInfo ari:foundProps) {
+                               if((nFoundTotal >= iFirstToUse) && (nFoundInPage < pageSize)) {
+                                       if(appendToAuthRefsList(ari, list)) {
+                                       nFoundInPage++;
+                                       nFoundTotal++;
+                                       }
+                               } else {
+                                       nFoundTotal++;
+                               }
+               }
+               
             // Set num of items in list. this is useful to our testing framework.
             commonList.setItemsInPage(nFoundInPage);
             // set the total result size
@@ -519,13 +444,21 @@ public abstract class   RemoteDocumentModelHandlerImpl<T, TL>
         return authRefList;
     }
 
-    private void appendToAuthRefsList(String refName, String schemaName,
-            String fieldName, List<AuthorityRefList.AuthorityRefItem> list)
+    private boolean appendToAuthRefsList(RefNameServiceUtils.AuthRefInfo ari, 
+                                               List<AuthorityRefList.AuthorityRefItem> list)
             throws Exception {
-        if (DocumentUtils.getSchemaNamePart(fieldName).isEmpty()) {
-            fieldName = DocumentUtils.appendSchemaName(schemaName, fieldName);
-        }
-        list.add(authorityRefListItem(fieldName, refName));
+       String fieldName = ari.getQualifiedDisplayName();
+       try {
+                       String refNameValue = (String)ari.getProperty().getValue();
+                       AuthorityRefList.AuthorityRefItem item = authorityRefListItem(fieldName, refNameValue);
+                       if(item!=null) {        // ignore garbage values.
+                               list.add(item);
+                               return true;
+                       }
+       } catch(PropertyException pe) {
+                       logger.debug("PropertyException on: "+ari.getProperty().getPath()+pe.getLocalizedMessage());
+       }
+       return false;
     }
 
     private AuthorityRefList.AuthorityRefItem authorityRefListItem(String authRefFieldName, String refName) {
@@ -539,7 +472,8 @@ public abstract class   RemoteDocumentModelHandlerImpl<T, TL>
             ilistItem.setSourceField(authRefFieldName);
             ilistItem.setUri(termInfo.getRelativeUri());
         } catch (Exception e) {
-            // Do nothing upon encountering an Exception here.
+               logger.error("Trouble parsing refName from value: "+refName+" in field: "+authRefFieldName+e.getLocalizedMessage());
+               ilistItem = null;
         }
         return ilistItem;
     }
index ef155886bbe84abbfcf0ddd5944e7d6a25a27c2a..776498d24a776b17f87ba966ca9186845da13e80 100644 (file)
@@ -109,7 +109,7 @@ public class OrgAuthorityAuthRefsTest extends BaseServiceTest {
     private String subBodyRefName = null;
     
     /** The number of authorityreferences expected. */
-    private final int NUM_AUTH_REFS_EXPECTED = 3;
+    private final int NUM_AUTH_REFS_EXPECTED = 2;      // Place authRef not legal, should not be returned.
 
     protected void setKnownResource( String id, String refName ) {
        knownResourceId = id;