]> git.aero2k.de Git - tmp/jakarta-migration.git/commitdiff
CSPACE-5122,CSPACE-5156,CSPACE-3718: Updated Scientific Taxonomy authority service...
authorAron Roberts <aron@socrates.berkeley.edu>
Tue, 8 May 2012 22:11:05 +0000 (15:11 -0700)
committerAron Roberts <aron@socrates.berkeley.edu>
Tue, 8 May 2012 22:11:05 +0000 (15:11 -0700)
services/common/src/main/cspace/config/services/tenants/tenant-bindings-proto.xml
services/taxonomy/3rdparty/nuxeo-platform-cs-taxonomy/src/main/resources/schemas/taxon_common.xsd
services/taxonomy/client/src/main/java/org/collectionspace/services/client/TaxonomyAuthorityClient.java
services/taxonomy/client/src/main/java/org/collectionspace/services/client/TaxonomyAuthorityClientUtils.java
services/taxonomy/client/src/test/java/org/collectionspace/services/client/test/TaxonomyAuthorityServiceTest.java
services/taxonomy/jaxb/src/main/resources/taxon_common.xsd
services/taxonomy/service/src/main/java/org/collectionspace/services/taxonomy/TaxonomyAuthorityResource.java
services/taxonomy/service/src/main/java/org/collectionspace/services/taxonomy/nuxeo/TaxonValidatorHandler.java

index 39e6ff3423fd8ab76a637273ff1eb34f1a2d1f1a..2d275c1c379fe5115fd8c67a24da113746478283 100644 (file)
                         <service:col>inauthority</service:col>
                     </service:field>
                     <service:field>
-                        <service:table>taxon_common</service:table>
-                        <service:col>displayname</service:col>
+                        <service:table>taxontermgroup</service:table>
+                        <service:col>termdisplayname</service:col>
                     </service:field>
                     <service:field>
                         <service:table>taxon_common</service:table>
                         </types:item>
                         <types:item xmlns:types="http://collectionspace.org/services/config/types">
                             <types:key>termRef</types:key>
-                            <types:value>termStatus</types:value>
+                            <types:value>taxonTermGroupList/*/termType</types:value>
+                        </types:item>
+                        <types:item xmlns:types="http://collectionspace.org/services/config/types">
+                            <types:key>termRef</types:key>
+                            <types:value>taxonTermGroupList/*/termLanguage</types:value>
+                        </types:item>
+                        <types:item xmlns:types="http://collectionspace.org/services/config/types">
+                            <types:key>termRef</types:key>
+                            <types:value>taxonTermGroupList/*/termStatus</types:value>
                         </types:item>
                     </service:properties>
                     <service:content contentType="application/xml">
                             <types:key>termRef</types:key>
                             <types:value>recordType</types:value>
                         </types:item>
-                         <types:item xmlns:types="http://collectionspace.org/services/config/types">
+                        <types:item xmlns:types="http://collectionspace.org/services/config/types">
                             <types:key>termRef</types:key>
                             <types:value>conceptTermGroupList/*/termType</types:value>
                         </types:item>
index 6fb5f1bb81f3d81b1e4b75ffb56ad5c0e9baddc9..2f8e427f40309e8d9f5c7a934e914cb105356418 100644 (file)
 -->
 
 <xs:schema 
-  xmlns:xs="http://www.w3.org/2001/XMLSchema"
-  xmlns:ns="http://collectionspace.org/services/taxonomy"
-  xmlns="http://collectionspace.org/services/taxonomy"
-  targetNamespace="http://collectionspace.org/services/taxonomy"
-  version="0.1"
+    xmlns:xs="http://www.w3.org/2001/XMLSchema"
+    xmlns:ns="http://collectionspace.org/services/taxonomy"
+    xmlns="http://collectionspace.org/services/taxonomy"
+    targetNamespace="http://collectionspace.org/services/taxonomy"
+    version="0.1"
 >
 <!-- See http://wiki.collectionspace.org/display/collectionspace/Taxonomy+Service+Home -->    
 
     <xs:element name="inAuthority" type="xs:string" />
     <xs:element name="shortIdentifier" type="xs:string"/>
     <xs:element name="refName" type="xs:string"/>
-    <xs:element name="termStatus" type="xs:string"/>
-    <xs:element name="displayName" type="xs:string"/>
-    <xs:element name="displayNameComputed" type="xs:boolean"/>
-    <xs:element name="shortDisplayName" type="xs:string"/>
-    <xs:element name="shortDisplayNameComputed" type="xs:boolean"/>
-    <xs:element name="source" type="xs:string"/>
-    <xs:element name="sourcePage" type="xs:string"/>
-    <xs:element name="description" type="xs:string"/>
     
+    <!-- Term Information repeatable group -->
+    <xs:element name="taxonTermGroupList" type="taxonTermGroupList"/>
+    
+    <!-- FIXME: See comments on CSPACE-5122 for any additional changes -->
+    <!-- to the set of fields below -->
+    <xs:element name="description" type="xs:string"/>
     <xs:element name="taxonFullName" type="xs:string"/>
     <xs:element name="taxonRank" type="xs:string"/>
     <xs:element name="taxonCurrency" type="xs:string"/>
         </xs:sequence>
     </xs:complexType>
     
+    <xs:complexType name="taxonTermGroupList">
+        <xs:sequence>
+            <xs:element name="taxonTermGroup" type="taxonTermGroup" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+
+    <xs:complexType name="taxonTermGroup">
+        <xs:sequence>
+            <!-- Common across all authority item terms -->
+            <xs:element name="termDisplayName" type="xs:string"/>
+            <xs:element name="termName" type="xs:string"/>
+            <xs:element name="termType" type="xs:string"/>
+            <xs:element name="termStatus" type="xs:string"/>
+            <xs:element name="termQualifier" type="xs:string"/>
+            <xs:element name="termLanguage" type="xs:string"/>
+            <xs:element name="termPrefForLang" type="xs:boolean"/>
+            <xs:element name="termSource" type="xs:string"/>
+            <xs:element name="termSourceDetail" type="xs:string"/>
+            <xs:element name="termSourceID" type="xs:string"/>
+            <xs:element name="termSourceNote" type="xs:string"/>
+            <!-- Specific to Taxon terms -->
+            <!-- FIXME: See comments on CSPACE-5122 for any additions here -->
+        </xs:sequence>
+    </xs:complexType>
+    
 </xs:schema>
 
index b2f1f239f4fd2bdc3e44d3862e8e785175e6d217..0c3542d8cd3b3e716c28f659f0f2f00263af6bf6 100644 (file)
@@ -37,7 +37,7 @@ public class TaxonomyAuthorityClient extends AuthorityClientImpl<TaxonCommon, Ta
     public static final String SERVICE_PATH_COMPONENT = SERVICE_NAME;
     public static final String SERVICE_PATH = "/" + SERVICE_PATH_COMPONENT;
     public static final String SERVICE_PAYLOAD_NAME = SERVICE_NAME;
-    public static final String TERM_INFO_GROUP_XPATH_BASE = "taxonTermGroup";
+    public static final String TERM_INFO_GROUP_XPATH_BASE = "taxonTermGroupList";
     //
     // Subitem constants
     //
index 774bebbca4918d4ecddb493ea07fcf2c846b3d62..71656e40c4819969dad18700af04c4e13329e7db 100644 (file)
@@ -2,6 +2,8 @@ package org.collectionspace.services.client;
 
 import java.io.File;
 import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
 import java.util.Map;
 
 import javax.ws.rs.core.MediaType;
@@ -11,10 +13,8 @@ import javax.ws.rs.core.Response;
 import org.apache.commons.io.FileUtils;
 import org.collectionspace.services.TaxonJAXBSchema;
 import org.collectionspace.services.client.test.ServiceRequestType;
-import org.collectionspace.services.taxonomy.TaxonAuthorGroupList;
-import org.collectionspace.services.taxonomy.TaxonCitationList;
-import org.collectionspace.services.taxonomy.TaxonCommon;
-import org.collectionspace.services.taxonomy.TaxonomyauthorityCommon;
+import org.collectionspace.services.common.api.Tools;
+import org.collectionspace.services.taxonomy.*;
 import org.dom4j.DocumentException;
 import org.jboss.resteasy.client.ClientResponse;
 import org.slf4j.Logger;
@@ -61,23 +61,28 @@ public class TaxonomyAuthorityClientUtils {
      * @return The PoxPayloadOut payload for the create call
      */
     public static PoxPayloadOut createTaxonInstance(
-            String taxonomyAuthRefName, Map<String, String> taxonInfo,
+            String taxonomyAuthRefName, Map<String, String> taxonInfo, List<TaxonTermGroup> terms,
             TaxonAuthorGroupList taxonAuthorGroupList, TaxonCitationList taxonCitationList,
             String headerLabel) {
         TaxonCommon taxon = new TaxonCommon();
         String shortId = taxonInfo.get(TaxonJAXBSchema.SHORT_IDENTIFIER);
-        String displayName = taxonInfo.get(TaxonJAXBSchema.DISPLAY_NAME);
         taxon.setShortIdentifier(shortId);
-        // String taxonomyRefName = createTaxonomyRefName(taxonomyAuthRefName, shortId, displayName);
-        // taxon.setRefName(taxonomyRefName);
-        String value = null;
-        value = taxonInfo.get(TaxonJAXBSchema.DISPLAY_NAME_COMPUTED);
-        boolean displayNameComputed = (value == null) || value.equalsIgnoreCase("true");
-        taxon.setDisplayNameComputed(displayNameComputed);
-        if ((value = (String) taxonInfo.get(TaxonJAXBSchema.TERM_STATUS)) != null) {
-            taxon.setTermStatus(value);
-        }
 
+        // Set values in the Term Information Group
+        String displayName = taxonInfo.get(TaxonJAXBSchema.DISPLAY_NAME);
+        TaxonTermGroupList termList = new TaxonTermGroupList();
+        if (terms == null || terms.isEmpty()) {
+            if (Tools.notBlank(displayName)) {
+                terms = getTermGroupInstance(displayName);
+            } else {
+                terms = getTermGroupInstance(getGeneratedIdentifier());
+            }
+        }
+        terms.get(0).setTermStatus(taxonInfo.get(TaxonJAXBSchema.TERM_STATUS));
+        termList.getTaxonTermGroup().addAll(terms); 
+        taxon.setTaxonTermGroupList(termList);        
+        
+        String value = null;
         // Fields specific to this authority record type.
         if ((value = (String) taxonInfo.get(TaxonJAXBSchema.NAME)) != null) {
             taxon.setTaxonFullName(value);
@@ -128,7 +133,7 @@ public class TaxonomyAuthorityClientUtils {
      */
     public static String createItemInAuthority(String vcsid,
             String TaxonomyauthorityRefName, Map<String, String> taxonMap,
-            TaxonAuthorGroupList taxonAuthorGroupList,
+            List<TaxonTermGroup> terms, TaxonAuthorGroupList taxonAuthorGroupList,
             TaxonCitationList taxonCitationList, TaxonomyAuthorityClient client) {
         // Expected status code: 201 Created
         int EXPECTED_STATUS_CODE = Response.Status.CREATED.getStatusCode();
@@ -154,7 +159,7 @@ public class TaxonomyAuthorityClientUtils {
         }
         PoxPayloadOut multipart =
                 createTaxonInstance(TaxonomyauthorityRefName,
-                taxonMap, taxonAuthorGroupList, taxonCitationList, client.getItemCommonPartName());
+                taxonMap, terms, taxonAuthorGroupList, taxonCitationList, client.getItemCommonPartName());
         String newID = null;
         ClientResponse<Response> res = client.createItem(vcsid, multipart);
         try {
@@ -317,4 +322,20 @@ public class TaxonomyAuthorityClientUtils {
         newStr.append(name);
         return newStr.toString();
     }
+    
+    public static List<TaxonTermGroup> getTermGroupInstance(String identifier) {
+        if (Tools.isBlank(identifier)) {
+            identifier = getGeneratedIdentifier();
+        }
+        List<TaxonTermGroup> terms = new ArrayList<TaxonTermGroup>();
+        TaxonTermGroup term = new TaxonTermGroup();
+        term.setTermDisplayName(identifier);
+        term.setTermName(identifier);
+        terms.add(term);
+        return terms;
+    }
+    
+    private static String getGeneratedIdentifier() {
+        return "id" + new Date().getTime(); 
+   }
 }
index 8650b4c54607c042accbafdd1a72092539617568..45fb4eac1abc19c7f137a1df34f1c160e7625e66 100644 (file)
@@ -44,6 +44,7 @@ import org.collectionspace.services.taxonomy.TaxonomyauthorityCommon;
 import org.collectionspace.services.taxonomy.TaxonCommon;
 
 import javax.ws.rs.core.Response;
+import org.collectionspace.services.taxonomy.*;
 import org.jboss.resteasy.client.ClientResponse;
 
 import org.slf4j.Logger;
@@ -65,24 +66,23 @@ public class TaxonomyAuthorityServiceTest extends AbstractAuthorityServiceTest<T
     /** The logger. */
     private final String CLASS_NAME = TaxonomyAuthorityServiceTest.class.getName();
     private final Logger logger = LoggerFactory.getLogger(TaxonomyAuthorityServiceTest.class);
-    private final String REFNAME = "refName";
-    private final String DISPLAYNAME = "displayName";
 
-    final String TEST_SHORTID = "CentauruspleurexanthemusGreen1832";
-    final String TEST_TERM_STATUS = "accepted";
-    final String TEST_TAXON_FULL_NAME = "Centaurus pleurexanthemus Green 1832";
+    private final String TEST_SHORTID = "CentauruspleurexanthemusGreen1832";
+    private final String TEST_TERM_STATUS = "accepted";
+    private final String TEST_TAXON_FULL_NAME = "Centaurus pleurexanthemus Green 1832";
     // TODO Re-implement the Taxon Rank field so as to provide an orderable
     // ranking value, as well as a display name.
-    final String TEST_TAXON_RANK = "species";
-    final String TEST_TAXON_AUTHOR = "J. Green";
-    final String TEST_TAXON_AUTHOR_TYPE = "ascribed";
-    final String TEST_TAXON_CITATION = "A Monograph of the Trilobites of North America";
-    final String TEST_TAXON_CURRENCY = "current";
-    final String TEST_TAXON_YEAR = "1832";
-    final String TEST_TAXONOMIC_STATUS = "valid";
-    final String TEST_TAXON_IS_NAMED_HYBRID = "false";
-    final TaxonAuthorGroupList NULL_TAXON_AUTHOR_GROUP_LIST = null;
-    final TaxonCitationList NULL_TAXON_CITATION_LIST = null;
+    private final String TEST_TAXON_RANK = "species";
+    private final String TEST_TAXON_AUTHOR = "J. Green";
+    private final String TEST_TAXON_AUTHOR_TYPE = "ascribed";
+    private final String TEST_TAXON_CITATION = "A Monograph of the Trilobites of North America";
+    private final String TEST_TAXON_CURRENCY = "current";
+    private final String TEST_TAXON_YEAR = "1832";
+    private final String TEST_TAXONOMIC_STATUS = "valid";
+    private final String TEST_TAXON_IS_NAMED_HYBRID = "false";
+    private final List<TaxonTermGroup> NULL_TAXON_TERMS_LIST = null;
+    private final TaxonAuthorGroupList NULL_TAXON_AUTHOR_GROUP_LIST = null;
+    private final TaxonCitationList NULL_TAXON_CITATION_LIST = null;
     
     private String knownResourceShortIdentifer = null;
     private String knownTaxonomyTypeRefName = null;
@@ -157,7 +157,7 @@ public class TaxonomyAuthorityServiceTest extends AbstractAuthorityServiceTest<T
         // * an authref field (when implemented)
 
         String newID = TaxonomyAuthorityClientUtils.createItemInAuthority(vcsid,
-                authRefName, taxonMap, taxonAuthorGroupList, taxonCitationList, client);
+                authRefName, taxonMap, NULL_TAXON_TERMS_LIST, taxonAuthorGroupList, taxonCitationList, client);
 
         // Store the ID returned from the first item resource created
         // for additional tests below.
@@ -176,117 +176,13 @@ public class TaxonomyAuthorityServiceTest extends AbstractAuthorityServiceTest<T
         return newID;
     }
 
-    /**
-     * Verify item display name.
-     *
-     * @param testName the test name
-     * @throws Exception the exception
-     */
-    @Test(dataProvider = "testName",
-               dependsOnMethods = {"readItem", "updateItem"})
-    public void verifyItemDisplayName(String testName) throws Exception {
-        //
-       // First read in our known resource
-       //
-       setupRead();
-        TaxonomyAuthorityClient client = new TaxonomyAuthorityClient();
-        ClientResponse<String> res = client.readItem(knownResourceId, knownItemResourceId);
-        TaxonCommon taxon = null;
-        try {
-               assertStatusCode(res, testName);
-            // Check whether taxon has expected displayName.
-            PoxPayloadIn input = new PoxPayloadIn(res.getEntity());
-            taxon = (TaxonCommon) extractPart(input,
-                    client.getItemCommonPartName(), TaxonCommon.class);
-            Assert.assertNotNull(taxon);
-        } finally {
-               if (res != null) {
-                res.releaseConnection();
-            }
-        }
-        //
-        // Now setup for an update
-        //
-        String displayName = taxon.getDisplayName();
-        // Make sure displayName matches computed form
-        String expectedDisplayName =
-                TaxonomyAuthorityClientUtils.prepareDefaultDisplayName(TEST_TAXON_FULL_NAME);
-        Assert.assertNotNull(displayName, "Display name was null.  Expected it to be: " + expectedDisplayName);
-        // Update the shortName and verify the computed name is updated.
-        taxon.setCsid(null);
-        taxon.setDisplayNameComputed(true);
-        taxon.setTaxonFullName("updated-" + TEST_TAXON_FULL_NAME);
-        expectedDisplayName =
-                TaxonomyAuthorityClientUtils.prepareDefaultDisplayName("updated-" + TEST_TAXON_FULL_NAME);
-
-        // Create the update payload.
-        PoxPayloadOut output = new PoxPayloadOut(TaxonomyAuthorityClient.SERVICE_ITEM_PAYLOAD_NAME);
-        PayloadOutputPart commonPart = output.addPart(client.getItemCommonPartName(), taxon);
-
-        setupUpdate();
-        res = client.updateItem(knownResourceId, knownItemResourceId, output);
-        TaxonCommon updatedTaxon = null;
-        try {
-               assertStatusCode(res, testName);
-            // Retrieve the updated resource and verify that its contents exist.
-               PoxPayloadIn input = new PoxPayloadIn(res.getEntity());
-            updatedTaxon =
-                    (TaxonCommon) extractPart(input,
-                    client.getItemCommonPartName(), TaxonCommon.class);
-            Assert.assertNotNull(updatedTaxon);
-        } finally {
-               if (res != null) {
-                res.releaseConnection();
-            }
-        }
-        // Verify that the updated resource received the correct data.
-        Assert.assertEquals(updatedTaxon.getTaxonFullName(), taxon.getTaxonFullName(),
-                "Updated ForeName in Taxonomy did not match submitted data.");
-        // Verify that the updated resource computes the right displayName.
-        Assert.assertEquals(updatedTaxon.getDisplayName(), expectedDisplayName,
-                "Updated ForeName in Taxonomy not reflected in computed DisplayName.");
-        //
-        // Now Update the displayName, not computed and verify the computed name is overriden.
-        //
-        taxon.setDisplayNameComputed(false);
-        expectedDisplayName = "TestName";
-        taxon.setDisplayName(expectedDisplayName);
-
-        // Submit the updated resource to the service and store the response.
-        output = new PoxPayloadOut(TaxonomyAuthorityClient.SERVICE_ITEM_PAYLOAD_NAME);
-        commonPart = output.addPart(client.getItemCommonPartName(), taxon);
-        setupUpdate(); // setup expected status code for result
-        res = client.updateItem(knownResourceId, knownItemResourceId, output);
-        try {
-               assertStatusCode(res, testName);
-            // Retrieve the updated resource and verify that its contents exist.
-               PoxPayloadIn input = new PoxPayloadIn(res.getEntity());
-            updatedTaxon =
-                    (TaxonCommon) extractPart(input,
-                    client.getItemCommonPartName(), TaxonCommon.class);
-            Assert.assertNotNull(updatedTaxon);
-        } finally {
-               if (res != null) {
-                res.releaseConnection();
-            }
-        }
-        // Verify that the updated resource received the correct data.
-        Assert.assertEquals(updatedTaxon.isDisplayNameComputed(), false,
-                "Updated displayNameComputed in Taxonomy did not match submitted data.");
-        // Verify that the updated resource computes the right displayName.
-        Assert.assertEquals(updatedTaxon.getDisplayName(),
-                expectedDisplayName,
-                "Updated DisplayName (not computed) in Taxonomy not stored.");
-    }
-
     /**
      * Verify illegal item display name.
      *
      * @param testName the test name
      * @throws Exception the exception
      */
-    @Test(dataProvider = "testName",
-               dependsOnMethods = {"verifyItemDisplayName"})
+    @Test(dataProvider = "testName")
     public void verifyIllegalItemDisplayName(String testName) throws Exception {
         //
        // First read in our known resource.
@@ -308,10 +204,15 @@ public class TaxonomyAuthorityServiceTest extends AbstractAuthorityServiceTest<T
             }
         }
         //
-        // Try to Update with computed false and no displayName
+        // Make an invalid UPDATE request, without a display name
         //
-        taxon.setDisplayNameComputed(false);
-        taxon.setDisplayName(null);
+        TaxonTermGroupList termList = taxon.getTaxonTermGroupList();
+        Assert.assertNotNull(termList);
+        List<TaxonTermGroup> terms = termList.getTaxonTermGroup();
+        Assert.assertNotNull(terms);
+        Assert.assertTrue(terms.size() > 0);
+        terms.get(0).setTermDisplayName(null);
+        terms.get(0).setTermName(null);
         
         PoxPayloadOut output = new PoxPayloadOut(TaxonomyAuthorityClient.SERVICE_ITEM_PAYLOAD_NAME);
         PayloadOutputPart commonPart = output.addPart(client.getItemCommonPartName(), taxon);
@@ -393,10 +294,10 @@ public class TaxonomyAuthorityServiceTest extends AbstractAuthorityServiceTest<T
 
             for (AbstractCommonList.ListItem item : items) {
                String value = 
-                       AbstractCommonListUtils.ListItemGetElementValue(item, REFNAME);
+                       AbstractCommonListUtils.ListItemGetElementValue(item, TaxonJAXBSchema.REF_NAME);
                 Assert.assertTrue((null != value), "Item refName is null!");
                value = 
-                       AbstractCommonListUtils.ListItemGetElementValue(item, DISPLAYNAME);
+                       AbstractCommonListUtils.ListItemGetElementValue(item, TaxonJAXBSchema.DISPLAY_NAME);
                 Assert.assertTrue((null != value), "Item displayName is null!");
             }
             if(logger.isTraceEnabled()){
@@ -574,20 +475,38 @@ public class TaxonomyAuthorityServiceTest extends AbstractAuthorityServiceTest<T
        }
        
        @Override
-       protected TaxonCommon updateItemInstance(TaxonCommon authorityItem) {
-               TaxonCommon result = new TaxonCommon();
-               
-        result.setDisplayName("updated-" + authorityItem.getTaxonFullName());
-        result.setTaxonFullName("updated-" + authorityItem.getTaxonFullName());
-               
-               return result;
+       protected TaxonCommon updateItemInstance(TaxonCommon taxonCommon) {
+            TaxonCommon result = taxonCommon;
+            TaxonTermGroupList termList = taxonCommon.getTaxonTermGroupList();
+            Assert.assertNotNull(termList);
+            List<TaxonTermGroup> terms = termList.getTaxonTermGroup();
+            Assert.assertNotNull(terms);
+            Assert.assertTrue(terms.size() > 0);
+            terms.get(0).setTermDisplayName("updated-" + terms.get(0).getTermDisplayName());
+            terms.get(0).setTermName("updated-" + terms.get(0).getTermName());
+           result.setTaxonTermGroupList(termList);
+            return result;
        }
 
        @Override
        protected void compareUpdatedItemInstances(TaxonCommon original,
                        TaxonCommon updated) throws Exception {
-        Assert.assertEquals(updated.getTaxonFullName(), original.getTaxonFullName(),
-                "Taxon full name in updated Taxon did not match submitted data.");
+
+            TaxonTermGroupList originalTermList = original.getTaxonTermGroupList();
+            Assert.assertNotNull(originalTermList);
+            List<TaxonTermGroup> originalTerms = originalTermList.getTaxonTermGroup();
+            Assert.assertNotNull(originalTerms);
+            Assert.assertTrue(originalTerms.size() > 0);
+            
+            TaxonTermGroupList updatedTermList = updated.getTaxonTermGroupList();
+            Assert.assertNotNull(updatedTermList);
+            List<TaxonTermGroup> updatedTerms = updatedTermList.getTaxonTermGroup();
+            Assert.assertNotNull(updatedTerms);
+            Assert.assertTrue(updatedTerms.size() > 0);
+            
+            Assert.assertEquals(updatedTerms.get(0).getTermDisplayName(),
+                originalTerms.get(0).getTermDisplayName(),
+                "Value in updated record did not match submitted data.");
        }
 
        @Override
@@ -605,15 +524,10 @@ public class TaxonomyAuthorityServiceTest extends AbstractAuthorityServiceTest<T
         nonexMap.put(TaxonJAXBSchema.NAME, TEST_TAXON_FULL_NAME);
         nonexMap.put(TaxonJAXBSchema.SHORT_IDENTIFIER, "nonEx");
         nonexMap.put(TaxonJAXBSchema.TERM_STATUS, TEST_TERM_STATUS);
-        // PoxPayloadOut multipart =
-        //        TaxonomyAuthorityClientUtils.createTaxonInstance(
-        //        TaxonomyAuthorityClientUtils.createTaxonomyRefName(knownResourceRefName, "nonEx", "Non Existent"),
-        //        nonexMap, NULL_TAXON_AUTHOR_GROUP_LIST, NULL_TAXON_CITATION_LIST,
-        //        client.getItemCommonPartName());
         final String EMPTY_REFNAME = "";
         PoxPayloadOut result =
                 TaxonomyAuthorityClientUtils.createTaxonInstance(EMPTY_REFNAME,
-                nonexMap, NULL_TAXON_AUTHOR_GROUP_LIST, NULL_TAXON_CITATION_LIST,
+                nonexMap, NULL_TAXON_TERMS_LIST, NULL_TAXON_AUTHOR_GROUP_LIST, NULL_TAXON_CITATION_LIST,
                 commonPartName);
                return result;
        }
index 126d94a1a8aab8eb93d7c51d418e2db03d2eff5c..c39632fc5cd3f2556f2c4df3ed168acc51edea54 100644 (file)
@@ -7,7 +7,7 @@
     xmlns="http://collectionspace.org/services/taxonomy"
     targetNamespace="http://collectionspace.org/services/taxonomy"
     version="0.1"
-    >
+>
     
     <!-- avoid XmlRootElement nightnmare, see http://weblogs.java.net/blog/kohsuke/archive/2006/03/why_does_jaxb_p.html-->
     <!-- See http://wiki.collectionspace.org/display/collectionspace/Taxonomy+Service+Home -->    
                 <xs:element name="inAuthority" type="xs:string" />
                 <xs:element name="shortIdentifier" type="xs:string"/>
                 <xs:element name="refName" type="xs:string"/>
-                <xs:element name="termStatus" type="xs:string"/>
-                <xs:element name="displayName" type="xs:string"/>
-                <xs:element name="displayNameComputed" type="xs:boolean"/>
-                <xs:element name="shortDisplayName" type="xs:string"/>
-                <xs:element name="shortDisplayNameComputed" type="xs:boolean"/>
-                <xs:element name="source" type="xs:string"/>
-                <xs:element name="sourcePage" type="xs:string"/>
+                
+                <!-- Term Information repeatable group -->
+                <xs:element name="taxonTermGroupList" type="taxonTermGroupList"/>
+    
+                <!-- FIXME: See comments on CSPACE-5122 for any additional changes -->
+                <!-- to the set of fields below -->
                 <xs:element name="description" type="xs:string"/>
                 <xs:element name="taxonFullName" type="xs:string"/>
                 <xs:element name="taxonRank" type="xs:string"/>
             <xs:element name="taxonCitation" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
         </xs:sequence>
     </xs:complexType>
+    
+    <xs:complexType name="taxonTermGroupList">
+        <xs:sequence>
+            <xs:element name="taxonTermGroup" type="taxonTermGroup" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+
+    <xs:complexType name="taxonTermGroup">
+        <xs:sequence>
+            <!-- Common across all authority item terms -->
+            <xs:element name="termDisplayName" type="xs:string"/>
+            <xs:element name="termName" type="xs:string"/>
+            <xs:element name="termType" type="xs:string"/>
+            <xs:element name="termStatus" type="xs:string"/>
+            <xs:element name="termQualifier" type="xs:string"/>
+            <xs:element name="termLanguage" type="xs:string"/>
+            <xs:element name="termPrefForLang" type="xs:boolean"/>
+            <xs:element name="termSource" type="xs:string"/>
+            <xs:element name="termSourceDetail" type="xs:string"/>
+            <xs:element name="termSourceID" type="xs:string"/>
+            <xs:element name="termSourceNote" type="xs:string"/>
+            <!-- Specific to Taxon terms -->
+            <!-- FIXME: See comments on CSPACE-5122 for any additions here -->
+        </xs:sequence>
+    </xs:complexType>
 
 </xs:schema>
 
index 7aaa10d37f51a3bf4bef44e44b35e2e6ea98dfde..72cdb3465e88c1d7c43c62adfa05f90865102a1a 100644 (file)
@@ -1,73 +1,66 @@
 /**
- *  This document is a part of the source code and related artifacts
- *  for CollectionSpace, an open source collections management system
- *  for museums and related institutions:
-
- *  http://www.collectionspace.org
- *  http://wiki.collectionspace.org
-
- *  Copyright 2009 University of California at Berkeley
-
- *  Licensed under the Educational Community License (ECL), Version 2.0.
- *  You may not use this file except in compliance with this License.
-
- *  You may obtain a copy of the ECL 2.0 License at
-
- *  https://source.collectionspace.org/collection-space/LICENSE.txt
-
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ * This document is a part of the source code and related artifacts for
+ * CollectionSpace, an open source collections management system for museums and
+ * related institutions:
+ *
+ * http://www.collectionspace.org http://wiki.collectionspace.org
+ *
+ * Copyright 2009 University of California at Berkeley
+ *
+ * Licensed under the Educational Community License (ECL), Version 2.0. You may
+ * not use this file except in compliance with this License.
+ *
+ * You may obtain a copy of the ECL 2.0 License at
+ *
+ * https://source.collectionspace.org/collection-space/LICENSE.txt
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
  */
 package org.collectionspace.services.taxonomy;
 
+import javax.ws.rs.Consumes;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
 import org.collectionspace.services.client.TaxonomyAuthorityClient;
 import org.collectionspace.services.common.vocabulary.AuthorityResource;
 import org.collectionspace.services.taxonomy.nuxeo.TaxonDocumentModelHandler;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.ws.rs.Consumes;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-
+/**
+ * TaxonomyAuthorityResource
+ *
+ * Handles, dispatches, and returns responses to RESTful requests related to
+ * Taxonomy authority-related resources.
+ */
 @Path(TaxonomyAuthorityClient.SERVICE_PATH)
 @Consumes("application/xml")
 @Produces("application/xml")
-public class TaxonomyAuthorityResource
-        extends AuthorityResource<TaxonomyauthorityCommon, TaxonDocumentModelHandler> {
-
-    private final static String taxonomyAuthorityServiceName = "taxonomyauthority";
-    private final static String TAXONOMYAUTHORITY_COMMON = "taxonomyauthority_common";
-    private final static String taxonomyItemServiceName = "taxon";
-    private final static String TAXONOMYITEM_COMMON = "taxon_common";
+public class TaxonomyAuthorityResource extends AuthorityResource<TaxonomyauthorityCommon, TaxonDocumentModelHandler> {
 
     final Logger logger = LoggerFactory.getLogger(TaxonomyAuthorityResource.class);
 
     public TaxonomyAuthorityResource() {
         super(TaxonomyauthorityCommon.class, TaxonomyAuthorityResource.class,
-                TAXONOMYAUTHORITY_COMMON, TAXONOMYITEM_COMMON);
+                TaxonomyAuthorityClient.SERVICE_COMMON_PART_NAME, TaxonomyAuthorityClient.SERVICE_ITEM_COMMON_PART_NAME);
     }
 
     @Override
     public String getServiceName() {
-        return taxonomyAuthorityServiceName;
+        return TaxonomyAuthorityClient.SERVICE_NAME;
     }
 
     @Override
     public String getItemServiceName() {
-        return taxonomyItemServiceName;
+        return TaxonomyAuthorityClient.SERVICE_ITEM_NAME;
     }
 
     @Override
-    public Class<TaxonomyauthorityCommon> getCommonPartClass() {
-        return TaxonomyauthorityCommon.class;
-    }
-
-       @Override
-       public String getItemTermInfoGroupXPathBase() {
+    public String getItemTermInfoGroupXPathBase() {
         return TaxonomyAuthorityClient.TERM_INFO_GROUP_XPATH_BASE;
-       }
-}
+    }
+}
\ No newline at end of file
index abc758b339af456f54a044f1814ffb789613fd82..51b85ff947f8e3e50e41776ab8baf82970d6aa70 100644 (file)
  */
 package org.collectionspace.services.taxonomy.nuxeo;
 
+import java.util.List;
 import java.util.regex.Pattern;
-import org.collectionspace.services.taxonomy.TaxonCommon;
-import org.collectionspace.services.common.context.MultipartServiceContext;
-import org.collectionspace.services.common.context.ServiceContext;
-import org.collectionspace.services.common.document.DocumentHandler.Action;
+import org.collectionspace.services.common.api.Tools;
 import org.collectionspace.services.common.document.InvalidDocumentException;
-import org.collectionspace.services.common.document.ValidatorHandler;
+import org.collectionspace.services.common.document.ValidatorHandlerImpl;
+import org.collectionspace.services.taxonomy.TaxonCommon;
+import org.collectionspace.services.taxonomy.TaxonTermGroup;
+import org.collectionspace.services.taxonomy.TaxonTermGroupList;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
  * TaxonValidatorHandler
  * 
- * Validates data supplied when attempting to create and/or update Taxon records.
- * 
- * $LastChangedRevision$
- * $LastChangedDate$
+ * Performs validation when making requests related to Taxon records.
+ * As an example, you can modify this class to customize validation of
+ * payloads supplied in requests to create and/or update records.
  */
-public class TaxonValidatorHandler implements ValidatorHandler {
+public class TaxonValidatorHandler extends ValidatorHandlerImpl {
 
     final Logger logger = LoggerFactory.getLogger(TaxonValidatorHandler.class);
-    private static final Pattern shortIdBadPattern = Pattern.compile("[\\W]"); //.matcher(input).matches()
+    // 'Bad pattern' for shortIdentifiers matches any non-word characters
+    private static final Pattern SHORT_ID_BAD_PATTERN = Pattern.compile("[\\W]"); //.matcher(input).matches()
+    private static final String VALIDATION_ERROR = "The record payload was invalid. See log file for more details.";
+    private static final String SHORT_ID_BAD_CHARS_ERROR =
+            "shortIdentifier must only contain standard word characters";
+    private static final String HAS_NO_TERMS_ERROR =
+            "Authority items must contain at least one term.";
+    private static final String HAS_AN_EMPTY_TERM_ERROR =
+            "Each term group in an authority item must contain "
+            + "a non-empty term name or "
+            + "a non-empty term display name.";
 
     @Override
-    public void validate(Action action, ServiceContext ctx)
-            throws InvalidDocumentException {
-        if (logger.isDebugEnabled()) {
-            logger.debug("validate() action=" + action.name());
-        }
-        
-        // Bail out if the validation action is for delete.
-        if (action.equals(Action.DELETE)) {
-               return;
-        }
-        
-        try {
-            MultipartServiceContext mctx = (MultipartServiceContext) ctx;
-            TaxonCommon taxon = (TaxonCommon) mctx.getInputPart(mctx.getCommonPartLabel(),
-                    TaxonCommon.class);
-            String msg = "";
-            boolean invalid = false;
-
-            // Validation occurring on both creates and updates
-            String displayName = taxon.getDisplayName();
-            if (!taxon.isDisplayNameComputed() && ((displayName == null) || displayName.trim().isEmpty())) {
-                invalid = true;
-                msg += "displayName must be non-null and non-blank if displayNameComputed is false";
+    protected Class getCommonPartClass() {
+        return TaxonCommon.class;
+    }
+
+    @Override
+    protected void handleCreate() throws InvalidDocumentException {
+        TaxonCommon organization = (TaxonCommon) getCommonPart();
+        // No guarantee that there is a common part in every post/update.
+        if (organization != null) {
+            try {
+                String shortId = organization.getShortIdentifier();
+                if (shortId != null) {
+                    CS_ASSERT(shortIdentifierContainsOnlyValidChars(shortId), SHORT_ID_BAD_CHARS_ERROR);
+                }
+                CS_ASSERT(containsAtLeastOneTerm(organization), HAS_NO_TERMS_ERROR);
+                CS_ASSERT(allTermsContainNameOrDisplayName(organization), HAS_AN_EMPTY_TERM_ERROR);
+            } catch (AssertionError e) {
+                if (logger.isErrorEnabled()) {
+                    logger.error(e.getMessage(), e);
+                }
+                throw new InvalidDocumentException(VALIDATION_ERROR, e);
             }
+        }
+    }
 
-            // Validation specific to creates or updates
-            if (action.equals(Action.CREATE)) {
-                String shortId = taxon.getShortIdentifier();
-                // Per CSPACE-2215, shortIdentifier values that are null (missing)
-                // oe the empty string are now legally accepted in create payloads.
-                // In either of those cases, a short identifier will be synthesized from
-                // a display name or supplied in another manner.
-                if ((shortId != null) && (shortIdBadPattern.matcher(shortId).find())) {
-                    invalid = true;
-                    msg += "shortIdentifier must only contain standard word characters";
+    @Override
+    protected void handleGet() throws InvalidDocumentException {
+    }
+
+    @Override
+    protected void handleGetAll() throws InvalidDocumentException {
+    }
+
+    @Override
+    protected void handleUpdate() throws InvalidDocumentException {
+        TaxonCommon organization = (TaxonCommon) getCommonPart();
+        // No guarantee that there is a common part in every post/update.
+        if (organization != null) {
+            try {
+                // shortIdentifier is among a set of fields that are
+                // prevented from being changed on an update, and thus
+                // we don't need to check its value here.
+                CS_ASSERT(containsAtLeastOneTerm(organization), HAS_NO_TERMS_ERROR);
+                CS_ASSERT(allTermsContainNameOrDisplayName(organization), HAS_AN_EMPTY_TERM_ERROR);
+            } catch (AssertionError e) {
+                if (logger.isErrorEnabled()) {
+                    logger.error(e.getMessage(), e);
                 }
-            } else if (action.equals(Action.UPDATE)) {
+                throw new InvalidDocumentException(VALIDATION_ERROR, e);
             }
+        }
+    }
+
+    @Override
+    protected void handleDelete() throws InvalidDocumentException {
+    }
+
+    private boolean shortIdentifierContainsOnlyValidChars(String shortId) {
+        // Check whether any characters match the 'bad' pattern
+        if (SHORT_ID_BAD_PATTERN.matcher(shortId).find()) {
+            return false;
+        }
+        return true;
+    }
+
+    private boolean containsAtLeastOneTerm(TaxonCommon organization) {
+        TaxonTermGroupList termGroupList = organization.getTaxonTermGroupList();
+        if (termGroupList == null) {
+            return false;
+        }
+        List<TaxonTermGroup> termGroups = termGroupList.getTaxonTermGroup();
+        if ((termGroups == null) || (termGroups.isEmpty())){ 
+            return false;
+        }
+        return true;
+    }
 
-            if (invalid) {
-                logger.error(msg);
-                throw new InvalidDocumentException(msg);
+    private boolean allTermsContainNameOrDisplayName(TaxonCommon organization) {
+        TaxonTermGroupList termGroupList = organization.getTaxonTermGroupList();
+        List<TaxonTermGroup> termGroups = termGroupList.getTaxonTermGroup();
+        for (TaxonTermGroup termGroup : termGroups) {
+            if (Tools.isBlank(termGroup.getTermName()) || Tools.isBlank(termGroup.getTermDisplayName())) {
+                return false;
             }
-        } catch (InvalidDocumentException ide) {
-            throw ide;
-        } catch (Exception e) {
-            throw new InvalidDocumentException(e);
         }
+        return true;
     }
 }