]> git.aero2k.de Git - tmp/jakarta-migration.git/commitdiff
CSPACE-2418: Groundwork for supporting free-text entry of dates in a variety of forma...
authorAron Roberts <aron@socrates.berkeley.edu>
Tue, 17 Aug 2010 02:31:22 +0000 (02:31 +0000)
committerAron Roberts <aron@socrates.berkeley.edu>
Tue, 17 Aug 2010 02:31:22 +0000 (02:31 +0000)
services/common/src/main/config/services/tenant-bindings.xml
services/common/src/main/java/org/collectionspace/services/common/config/ServiceConfigUtils.java
services/common/src/main/java/org/collectionspace/services/common/config/TenantBindingUtils.java
services/common/src/main/java/org/collectionspace/services/common/datetime/DateTimeFormatUtils.java [new file with mode: 0644]
services/common/src/main/java/org/collectionspace/services/common/datetime/GregorianCalendarDateTimeUtils.java
services/movement/service/src/main/java/org/collectionspace/services/movement/nuxeo/MovementDocumentModelHandler.java
services/movement/service/src/main/java/org/collectionspace/services/movement/nuxeo/MovementValidatorHandler.java

index dfe0b1eb389e793bb1e8eba856cd5ed1ec5bd432..f42e066e7a4b1204270e73680852a1436e83b336 100644 (file)
@@ -1,8 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
     Document   : tenants-bindings.xml
-    Created on : August 31, 2009, 10:52 AM
-    Description: tenant bindings
+    Description: Tenant bindings.
+    $LastChangedRevision$
+    $LastChangedDate$
 -->
 <tenant:TenantBindingConfig
     xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
     xmlns:types='http://collectionspace.org/services/common/types'
     xsi:schemaLocation='http://collectionspace.org/services/common/tenant http://collectionspace.org/services/common/tenant.xsd'
     >
+        
     <!-- begin movingimages.us tenant meta-data -->
     <tenant:tenantBinding
         id="1" name="movingimage.us" displayName="Museum of Moving Images" version="0.1">
+
         <tenant:repositoryDomain name="default-domain" repositoryClient="nuxeo-java"/>
+
+        <tenant:properties>
+            <types:item><types:key>datePattern</types:key><types:value>MM/dd/YYYY</types:value></types:item>
+            <types:item><types:key>datePattern</types:key><types:value>dd.MM.YYYY</types:value></types:item>
+            <!-- <types:item><types:key>datePattern</types:key><types:value>dd/MM/YYYY</types:value></types:item> -->
+            <!-- <types:item><types:key>localeLanguage</types:key><types:value>en</types:value></types:item> -->
+            <!-- <types:item><types:key>localeLanguage</types:key><types:value>da</types:value></types:item> -->
+        </tenant:properties>
+
         <!-- begin idgenerators service meta-data -->
         <tenant:serviceBindings name="idgenerators" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
-
         </tenant:serviceBindings>
         <!-- end idgenerator service meta-data -->
-            <!-- begin id service meta-data -->
+
+        <!-- begin id service meta-data -->
         <tenant:serviceBindings name="id" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
 <!--            <service:uriPath xmlns:service='http://collectionspace.org/services/common/service'>
                 /idgenerators/*/ids
             </service:uriPath> -->
         </tenant:serviceBindings>
+        <!-- end id service meta-data -->
+
+        <!-- begin collectionobject service meta-data -->
         <tenant:serviceBindings name="CollectionObjects" type="object" version="0.1">
-            <!-- begin collectionobject service meta-data -->
             <!-- other URI paths using which this service could be accessed -->
 <!--            <service:uriPath xmlns:service='http://collectionspace.org/services/common/service'>
                 /collectionobjects/*/authorityrefs/
@@ -46,7 +60,6 @@
                 <types:item><types:key>objectNameProperty</types:key><types:value>objectName</types:value></types:item>
                 <types:item><types:key>objectNumberProperty</types:key><types:value>objectNumber</types:value></types:item>
             </service:properties>
-            <!-- end id service meta-data -->
             <service:object name="CollectionObject" version="0.1"
                             xmlns:service='http://collectionspace.org/services/common/service'>
                 <service:part id="0" control_group="Managed"
             </service:object>
         </tenant:serviceBindings>
         <!--end collectionobject service meta-data -->
+
         <!-- begin intake service meta-data -->
         <tenant:serviceBindings name="Intakes" type="procedure" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
             </service:validatorHandler>
             <service:properties xmlns:service='http://collectionspace.org/services/common/service'>
                 <!-- What to use for name???
-                                                        <types:item><types:key>objectNameProperty</types:key><types:value>objectName</types:value></types:item> -->
+                <types:item><types:key>objectNameProperty</types:key><types:value>objectName</types:value></types:item> -->
                 <types:item><types:key>objectNumberProperty</types:key><types:value>entryNumber</types:value></types:item>
             </service:properties>
             <service:object name="Intake" version="0.1"
             </service:object>
         </tenant:serviceBindings>
         <!-- end intake service meta-data -->
+
         <!-- begin loanin service meta-data -->
         <tenant:serviceBindings name="Loansin" type="procedure" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
             </service:validatorHandler>
             <service:properties xmlns:service='http://collectionspace.org/services/common/service'>
                 <!-- What to use for name???
-                                                        <types:item><types:key>objectNameProperty</types:key><types:value>objectName</types:value></types:item> -->
+                <types:item><types:key>objectNameProperty</types:key><types:value>objectName</types:value></types:item> -->
                 <types:item><types:key>objectNumberProperty</types:key><types:value>loanInNumber</types:value></types:item>
             </service:properties>
             <service:object name="Loanin" version="0.1"
             </service:object>
         </tenant:serviceBindings>
         <!-- end loanin service meta-data -->
+
         <!-- begin loanout service meta-data -->
         <tenant:serviceBindings name="Loansout" type="procedure" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
             </service:object>
         </tenant:serviceBindings>
         <!-- end loanout service meta-data -->
+
         <!-- begin movement service meta-data -->
         <tenant:serviceBindings name="Movements" type="procedure" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
             </service:object>
         </tenant:serviceBindings>
         <!-- end movement service meta-data -->
+
         <!-- begin report service meta-data -->
         <tenant:serviceBindings name="Reports" type="procedure" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
             </service:object>
         </tenant:serviceBindings>
         <!-- end report service meta-data -->
+
         <!-- begin vocabulary service meta-data -->
         <tenant:serviceBindings name="Vocabularies" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
-
             <service:repositoryDomain xmlns:service='http://collectionspace.org/services/common/service'>
                 default-domain
             </service:repositoryDomain>
             </service:object>
         </tenant:serviceBindings>
         <!-- end vocabulary service meta-data -->
-                <!--
-            begin vocabularyitem service meta-data.
-                        Note there is no Vocabularyitem service, but there is a
-                        Repository workspace so we have to configure that.
+
+        <!-- begin vocabularyitem service meta-data.
+            Note there is no Vocabularyitem service, but there is a
+            Repository workspace so we have to configure that.
         -->
         <tenant:serviceBindings name="Vocabularyitems" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
             </service:object>
         </tenant:serviceBindings>
         <!-- end vocabulary service meta-data -->
+
         <!-- begin orgauthority service meta-data -->
         <tenant:serviceBindings name="Orgauthorities" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
             </service:object>
         </tenant:serviceBindings>
         <!-- end orgauthority service meta-data -->
-                        <!-- begin organization service meta-data.
-                        Note there is no Organization service, but there is a
-                        Repository workspace so we have to configure that.
+
+        <!-- begin organization service meta-data.
+             Note there is no Organization service, but there is a
+             Repository workspace so we have to configure that.
         -->
         <tenant:serviceBindings name="Organizations" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
                         <types:item><types:key>authRef</types:key><types:value>contactNames|contactName</types:value></types:item>
                         <types:item><types:key>authRef</types:key><types:value>subBodies|subBody</types:value></types:item>
                     </service:properties>
-
                     <service:content contentType="application/xml">
                         <service:xmlContent
                             namespaceURI="http://collectionspace.org/services/organization"
             </service:object>
         </tenant:serviceBindings>
         <!-- end organization service meta-data -->
+
         <!-- begin personauthority service meta-data -->
         <tenant:serviceBindings name="Personauthorities" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
             </service:object>
         </tenant:serviceBindings>
         <!-- end personauthority service meta-data -->
-                        <!-- begin person service meta-data.
-                        Note there is no Person service, but there is a
-                        Repository workspace so we have to configure that.
+
+        <!-- begin person service meta-data.
+             Note there is no Person service, but there is a
+             Repository workspace so we have to configure that.
         -->
         <tenant:serviceBindings name="Persons" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
             </service:object>
         </tenant:serviceBindings>
         <!-- end person service meta-data -->
+
         <!-- begin locationauthority service meta-data -->
         <tenant:serviceBindings name="Locationauthorities" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
             </service:object>
         </tenant:serviceBindings>
         <!-- end locationauthority service meta-data -->
-                        <!-- begin location service meta-data.
-                        Note there is no Location service, but there is a
-                        Repository workspace so we have to configure that.
+
+        <!-- begin location service meta-data.
+             Note there is no Location service, but there is a
+             Repository workspace so we have to configure that.
         -->
         <tenant:serviceBindings name="Locations" version="0.1">
             <service:repositoryDomain xmlns:service='http://collectionspace.org/services/common/service'>
             </service:object>
         </tenant:serviceBindings>
         <!-- end location service meta-data -->
+
         <!-- begin acquisition service meta-data -->
         <tenant:serviceBindings name="Acquisitions" type="procedure" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
             </service:validatorHandler>
             <service:properties xmlns:service='http://collectionspace.org/services/common/service'>
                 <!-- What to use for name???
-                                                        <types:item><types:key>objectNameProperty</types:key><types:value>objectName</types:value></types:item> -->
+                <types:item><types:key>objectNameProperty</types:key><types:value>objectName</types:value></types:item> -->
                 <types:item><types:key>objectNumberProperty</types:key><types:value>acquisitionReferenceNumber</types:value></types:item>
             </service:properties>
             <service:object name="Acquisition" version="0.1"
             </service:object>
         </tenant:serviceBindings>
         <!-- end acquisition service meta-data -->
+
         <!-- begin relation service meta-data -->
         <tenant:serviceBindings name="Relations" version="0.1">
             <!-- other URI paths using which this service could be accessed -->'
             </service:object>
         </tenant:serviceBindings>
         <!-- end relation service meta-data -->
+
         <!-- begin account service meta-data -->
         <tenant:serviceBindings name="Accounts" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
-
             <service:documentHandler xmlns:service='http://collectionspace.org/services/common/service'>
                 org.collectionspace.services.account.storage.AccountDocumentHandler
             </service:documentHandler>
             </service:object>
         </tenant:serviceBindings>
         <!-- end account service meta-data -->
+
         <!-- begin dimension service meta-data -->
         <tenant:serviceBindings name="Dimensions" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
-
             <service:repositoryDomain xmlns:service='http://collectionspace.org/services/common/service'>
                 default-domain
             </service:repositoryDomain>
             </service:object>
         </tenant:serviceBindings>
         <!-- end dimension service meta-data -->
+
         <!-- begin contact service meta-data -->
         <tenant:serviceBindings name="Contacts" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
             </service:object>
         </tenant:serviceBindings>
         <!-- end contact service meta-data -->
+
         <!-- begin note service meta-data -->
         <tenant:serviceBindings name="Notes" version="0.1">
             <service:repositoryDomain xmlns:service='http://collectionspace.org/services/common/service'>
             </service:object>
         </tenant:serviceBindings>
         <!-- end note service meta-data -->
+
         <!-- begin role service meta-data -->
         <tenant:serviceBindings name="authorization/roles" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
-
             <service:documentHandler xmlns:service='http://collectionspace.org/services/common/service'>
                 org.collectionspace.services.authorization.storage.RoleDocumentHandler
             </service:documentHandler>
             </service:object>
         </tenant:serviceBindings>
         <!-- end role service meta-data -->
+
         <!-- begin permission service meta-data -->
         <tenant:serviceBindings name="authorization/permissions" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
-
             <service:documentHandler xmlns:service='http://collectionspace.org/services/common/service'>
                 org.collectionspace.services.authorization.storage.PermissionDocumentHandler
             </service:documentHandler>
             </service:object>
         </tenant:serviceBindings>
         <!-- end permission service meta-data -->
+
         <!-- begin permission-role service meta-data -->
         <!-- the following service is same as authorization/roles/permroles service -->
         <!-- except that it is available as a sub resource of the permission service -->
             </service:object>
         </tenant:serviceBindings>
         <!-- end permission-role service meta-data -->
+
         <!-- begin account-role service meta-data -->
         <tenant:serviceBindings name="accounts/accountroles" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
             </service:object>
         </tenant:serviceBindings>
         <!-- end account-role service meta-data -->
+
         <!-- begin role-permission service meta-data -->
         <!-- the following service is same as authorization/permissions/permroles service -->
         <!-- except that it is available as a sub resource of the role service -->
     <!-- end movingimages.us tenant meta-data -->
 
 
-        <!-- begin hearstmuseum.berkeley.edu tenant meta-data -->
+    <!-- ##################################################################### -->
+
+
+    <!-- begin hearstmuseum.berkeley.edu tenant meta-data -->
     <tenant:tenantBinding
         id="2" name="hearstmuseum.berkeley.edu" displayName="Phoebe A. Hearst Museum of Anthropology" version="0.1">
+        
         <tenant:repositoryDomain name="pahma-domain" repositoryClient="nuxeo-java"/>
+
+        <tenant:properties>
+            <types:item><types:key>datePattern</types:key><types:value>MM/dd/YYYY</types:value></types:item>
+            <types:item><types:key>datePattern</types:key><types:value>dd.MM.YYYY</types:value></types:item>
+            <!-- <types:item><types:key>datePattern</types:key><types:value>dd/MM/YYYY</types:value></types:item> -->
+            <!-- <types:item><types:key>localeLanguage</types:key><types:value>en</types:value></types:item> -->
+            <!-- <types:item><types:key>localeLanguage</types:key><types:value>da</types:value></types:item> -->
+        </tenant:properties>
+
         <!-- begin idgenerators service meta-data -->
         <tenant:serviceBindings name="idgenerators" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
-
         </tenant:serviceBindings>
         <!-- end idgenerator service meta-data -->
-            <!-- begin id service meta-data -->
+
+        <!-- begin id service meta-data -->
         <tenant:serviceBindings name="id" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
 <!--            <service:uriPath xmlns:service='http://collectionspace.org/services/common/service'>
                 /idgenerators/*/ids
             </service:uriPath>-->
         </tenant:serviceBindings>
+        <!-- end id service meta-data -->
+
+        <!-- begin collectionobject service meta-data -->
         <tenant:serviceBindings name="CollectionObjects" type="object" version="0.1">
-            <!-- begin collectionobject service meta-data -->
             <!-- other URI paths using which this service could be accessed -->
 <!--            <service:uriPath xmlns:service='http://collectionspace.org/services/common/service'>
                 /collectionobjects/*/authorityrefs/
                 <types:item><types:key>objectNameProperty</types:key><types:value>objectName</types:value></types:item>
                 <types:item><types:key>objectNumberProperty</types:key><types:value>objectNumber</types:value></types:item>
             </service:properties>
-            <!-- end id service meta-data -->
             <service:object name="CollectionObject" version="0.1"
                             xmlns:service='http://collectionspace.org/services/common/service'>
                 <service:part id="0" control_group="Managed"
             </service:object>
         </tenant:serviceBindings>
         <!--end collectionobject service meta-data -->
+
         <!-- begin intake service meta-data -->
         <tenant:serviceBindings name="Intakes" type="procedure" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
             </service:validatorHandler>
             <service:properties xmlns:service='http://collectionspace.org/services/common/service'>
                 <!-- What to use for name???
-                                                        <types:item><types:key>objectNameProperty</types:key><types:value>objectName</types:value></types:item> -->
+                <types:item><types:key>objectNameProperty</types:key><types:value>objectName</types:value></types:item> -->
                 <types:item><types:key>objectNumberProperty</types:key><types:value>entryNumber</types:value></types:item>
             </service:properties>
             <service:object name="Intake" version="0.1"
             </service:object>
         </tenant:serviceBindings>
         <!-- end intake service meta-data -->
+
         <!-- begin loanin service meta-data -->
         <tenant:serviceBindings name="Loansin" type="procedure" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
             </service:validatorHandler>
             <service:properties xmlns:service='http://collectionspace.org/services/common/service'>
                 <!-- What to use for name???
-                                                        <types:item><types:key>objectNameProperty</types:key><types:value>objectName</types:value></types:item> -->
+                <types:item><types:key>objectNameProperty</types:key><types:value>objectName</types:value></types:item> -->
                 <types:item><types:key>objectNumberProperty</types:key><types:value>loanInNumber</types:value></types:item>
             </service:properties>
             <service:object name="Loanin" version="0.1"
             </service:object>
         </tenant:serviceBindings>
         <!-- end loanin service meta-data -->
+
         <!-- begin loanout service meta-data -->
         <tenant:serviceBindings name="Loansout" type="procedure" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
             </service:object>
         </tenant:serviceBindings>
         <!-- end loanout service meta-data -->
+
         <!-- begin movement service meta-data -->
         <tenant:serviceBindings name="Movements" type="procedure" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
             </service:object>
         </tenant:serviceBindings>
         <!-- end movement service meta-data -->
+
         <!-- begin vocabulary service meta-data -->
         <tenant:serviceBindings name="Vocabularies" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
-
             <service:repositoryDomain xmlns:service='http://collectionspace.org/services/common/service'>
                 pahma-domain
             </service:repositoryDomain>
             </service:object>
         </tenant:serviceBindings>
         <!-- end vocabulary service meta-data -->
-                <!--
-            begin vocabularyitem service meta-data.
-                        Note there is no Vocabularyitem service, but there is a
-                        Repository workspace so we have to configure that.
+
+        <!-- begin vocabularyitem service meta-data.
+             Note there is no Vocabularyitem service, but there is a
+             Repository workspace so we have to configure that.
         -->
         <tenant:serviceBindings name="Vocabularyitems" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
             </service:object>
         </tenant:serviceBindings>
         <!-- end vocabulary service meta-data -->
+
         <!-- begin orgauthority service meta-data -->
         <tenant:serviceBindings name="Orgauthorities" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
             </service:object>
         </tenant:serviceBindings>
         <!-- end orgauthority service meta-data -->
-                        <!-- begin organization service meta-data.
-                        Note there is no Organization service, but there is a
-                        Repository workspace so we have to configure that.
+
+        <!-- begin organization service meta-data.
+             Note there is no Organization service, but there is a
+             Repository workspace so we have to configure that.
         -->
         <tenant:serviceBindings name="Organizations" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
             </service:object>
         </tenant:serviceBindings>
         <!-- end organization service meta-data -->
+
         <!-- begin personauthority service meta-data -->
         <tenant:serviceBindings name="Personauthorities" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
             </service:object>
         </tenant:serviceBindings>
         <!-- end personauthority service meta-data -->
-                        <!-- begin person service meta-data.
-                        Note there is no Person service, but there is a
-                        Repository workspace so we have to configure that.
+
+        <!-- begin person service meta-data.
+             Note there is no Person service, but there is a
+             Repository workspace so we have to configure that.
         -->
         <tenant:serviceBindings name="Persons" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
             </service:object>
         </tenant:serviceBindings>
         <!-- end person service meta-data -->
+
         <!-- begin locationauthority service meta-data -->
         <tenant:serviceBindings name="Locationauthorities" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
             </service:object>
         </tenant:serviceBindings>
         <!-- end locationauthority service meta-data -->
-                        <!-- begin location service meta-data.
-                        Note there is no Location service, but there is a
-                        Repository workspace so we have to configure that.
+
+        <!-- begin location service meta-data.
+             Note there is no Location service, but there is a
+             Repository workspace so we have to configure that.
         -->
         <tenant:serviceBindings name="Locations" version="0.1">
             <service:repositoryDomain xmlns:service='http://collectionspace.org/services/common/service'>
             </service:object>
         </tenant:serviceBindings>
         <!-- end location service meta-data -->
+
         <!-- begin acquisition service meta-data -->
         <tenant:serviceBindings name="Acquisitions" type="procedure" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
             </service:validatorHandler>
             <service:properties xmlns:service='http://collectionspace.org/services/common/service'>
                 <!-- What to use for name???
-                                                        <types:item><types:key>objectNameProperty</types:key><types:value>objectName</types:value></types:item> -->
+                <types:item><types:key>objectNameProperty</types:key><types:value>objectName</types:value></types:item> -->
                 <types:item><types:key>objectNumberProperty</types:key><types:value>acquisitionReferenceNumber</types:value></types:item>
             </service:properties>
             <service:object name="Acquisition" version="0.1"
             </service:object>
         </tenant:serviceBindings>
         <!-- end acquisition service meta-data -->
+
         <!-- begin relation service meta-data -->
         <tenant:serviceBindings name="Relations" version="0.1">
             <!-- other URI paths using which this service could be accessed -->'
             </service:object>
         </tenant:serviceBindings>
         <!-- end relation service meta-data -->
+
         <!-- begin account service meta-data -->
         <tenant:serviceBindings name="Accounts" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
-
             <service:documentHandler xmlns:service='http://collectionspace.org/services/common/service'>
                 org.collectionspace.services.account.storage.AccountDocumentHandler
             </service:documentHandler>
             </service:object>
         </tenant:serviceBindings>
         <!-- end account service meta-data -->
+
         <!-- begin dimension service meta-data -->
         <tenant:serviceBindings name="Dimensions" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
-
             <service:repositoryDomain xmlns:service='http://collectionspace.org/services/common/service'>
                 pahma-domain
             </service:repositoryDomain>
             </service:object>
         </tenant:serviceBindings>
         <!-- end dimension service meta-data -->
+
         <!-- begin contact service meta-data -->
         <tenant:serviceBindings name="Contacts" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
             </service:object>
         </tenant:serviceBindings>
         <!-- end contact service meta-data -->
+
         <!-- begin note service meta-data -->
         <tenant:serviceBindings name="Notes" version="0.1">
             <service:repositoryDomain xmlns:service='http://collectionspace.org/services/common/service'>
             </service:object>
         </tenant:serviceBindings>
         <!-- end note service meta-data -->
+
         <!-- begin role service meta-data -->
         <tenant:serviceBindings name="authorization/roles" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
-
             <service:documentHandler xmlns:service='http://collectionspace.org/services/common/service'>
                 org.collectionspace.services.authorization.storage.RoleDocumentHandler
             </service:documentHandler>
             </service:object>
         </tenant:serviceBindings>
         <!-- end role service meta-data -->
+
         <!-- begin permission service meta-data -->
         <tenant:serviceBindings name="authorization/permissions" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
-
             <service:documentHandler xmlns:service='http://collectionspace.org/services/common/service'>
                 org.collectionspace.services.authorization.storage.PermissionDocumentHandler
             </service:documentHandler>
             </service:object>
         </tenant:serviceBindings>
         <!-- end permission service meta-data -->
+
         <!-- begin permission-role service meta-data -->
         <!-- the following service is same as authorization/roles/permroles service -->
         <!-- except that it is available as a sub resource of the permission service -->
             </service:object>
         </tenant:serviceBindings>
         <!-- end permission-role service meta-data -->
+
         <!-- begin account-role service meta-data -->
         <tenant:serviceBindings name="accounts/accountroles" version="0.1">
             <!-- other URI paths using which this service could be accessed -->
             </service:object>
         </tenant:serviceBindings>
         <!-- end account-role service meta-data -->
+
         <!-- begin role-permission service meta-data -->
         <!-- the following service is same as authorization/permissions/permroles service -->
         <!-- except that it is available as a sub resource of the role service -->
index dc52cabce0374af03b5d37ecfcbf13a452e825d4..51426de5e1f224e473675b69318909b258733459 100644 (file)
@@ -40,9 +40,11 @@ public class ServiceConfigUtils {
 \r
 \r
     /**\r
-     * @param serviceConfig\r
-     * @param propName the property to fetch (allows multiple property values)\r
-     * @return\r
+     * Gets the values of a configured property for a service.\r
+     *\r
+     * @param serviceConfiga tenant binding\r
+     * @param propName the property to fetch (can return multiple values for this property).\r
+     * @return a list of values for the supplied property.\r
      */\r
     public static List<String> getPropertyValues(ServiceConfig serviceConfig,\r
                String propName) {\r
index de64c3e371c62bd4ccfc88788c0133e71683434d..05ee63bde20c8585e38fc70b6ebd44beccf28ccb 100644 (file)
@@ -10,24 +10,52 @@ import org.collectionspace.services.common.types.PropertyItemType;
 import org.collectionspace.services.common.types.PropertyType;\r
 \r
 public class TenantBindingUtils {\r
-       \r
-       public static final boolean SET_PROP_IF_MISSING = true;\r
-       public static final boolean SET_PROP_ALWAYS = false;\r
-       \r
+\r
+    public static final boolean SET_PROP_IF_MISSING = true;\r
+    public static final boolean SET_PROP_ALWAYS = false;\r
+\r
     /**\r
      * @param tenantBinding\r
      * @param propName the property to fetch\r
      * @return the String value of the named property\r
      */\r
     public static String getPropertyValue(TenantBindingType tenantBinding,\r
-               String propName) {\r
-       if(propName==null) {\r
-               throw new IllegalArgumentException("TenantBindingUtils.getPropertyValues: null property name!");\r
-       }\r
-               List<PropertyType> tenantPropList = tenantBinding.getProperties();\r
-               return PropertyItemUtils.getPropertyValueByNameFromNodeList(tenantPropList, propName );\r
+            String propName) {\r
+        if (propName == null) {\r
+            throw new IllegalArgumentException("TenantBindingUtils.getPropertyValue: null property name!");\r
+        }\r
+        List<PropertyType> tenantPropList = tenantBinding.getProperties();\r
+        return PropertyItemUtils.getPropertyValueByNameFromNodeList(tenantPropList, propName);\r
+    }\r
+\r
+    /**\r
+     * Gets the values of a configured property for a tenant.\r
+     *\r
+     * @param tenantBinding a tenant binding\r
+     * @param propName the property to fetch (can return multiple values for this property).\r
+     * @return a list of values for the supplied property.\r
+     */\r
+    public static List<String> getPropertyValues(TenantBindingType tenantBinding,\r
+            String propName) {\r
+        List<String> propValues = null;\r
+        List<PropertyType> propList = tenantBinding.getProperties();\r
+        if (propList != null && propList.size() > 0) {\r
+            List<PropertyItemType> propItems = propList.get(0).getItem();\r
+            for (PropertyItemType propItem : propItems) {\r
+                if (propName.equals(propItem.getKey())) {\r
+                    String value = propItem.getValue();\r
+                    if (value != null) {\r
+                        if (propValues == null) {\r
+                            propValues = new ArrayList<String>();\r
+                        }\r
+                        propValues.add(value);\r
+                    }\r
+                }\r
+            }\r
+        }\r
+        return propValues;\r
     }\r
-    \r
+\r
     /**\r
      * @param service\r
      * @param propName the property to fetch\r
@@ -36,15 +64,15 @@ public class TenantBindingUtils {
      * @return true if set, false if an existing value was left as is.\r
      */\r
     public static boolean setPropertyValue(TenantBindingType tenantBinding,\r
-               PropertyItemType prop, boolean onlyIfNotSet) {\r
-       if(prop==null) {\r
-               throw new IllegalArgumentException(\r
-                               "TenantBindingUtils.setPropertyValue: null property!");\r
-       }\r
-       return setPropertyValue(tenantBinding, prop.getKey(), prop.getValue(),\r
-                                                               onlyIfNotSet);\r
+            PropertyItemType prop, boolean onlyIfNotSet) {\r
+        if (prop == null) {\r
+            throw new IllegalArgumentException(\r
+                    "TenantBindingUtils.setPropertyValue: null property!");\r
+        }\r
+        return setPropertyValue(tenantBinding, prop.getKey(), prop.getValue(),\r
+                onlyIfNotSet);\r
     }\r
-    \r
+\r
     /**\r
      * @param tenantBinding\r
      * @param propName the property to fetch\r
@@ -53,18 +81,17 @@ public class TenantBindingUtils {
      * @return true if set, false if an existing value was left as is.\r
      */\r
     public static boolean setPropertyValue(TenantBindingType tenantBinding,\r
-               String propName, String value,\r
-               boolean onlyIfNotSet) {\r
-       boolean valueFound = false;\r
-       boolean valueSet = false;\r
-       if(propName==null) {\r
-               throw new IllegalArgumentException("TenantBindingUtils.setPropertyValue: null property name!");\r
-       }\r
-               List<PropertyType> tenantPropertiesNode = tenantBinding.getProperties();\r
-               return PropertyItemUtils.setPropertyValueInNodeList(tenantPropertiesNode,\r
-                               propName, value, onlyIfNotSet);\r
+            String propName, String value,\r
+            boolean onlyIfNotSet) {\r
+        boolean valueFound = false;\r
+        boolean valueSet = false;\r
+        if (propName == null) {\r
+            throw new IllegalArgumentException("TenantBindingUtils.setPropertyValue: null property name!");\r
+        }\r
+        List<PropertyType> tenantPropertiesNode = tenantBinding.getProperties();\r
+        return PropertyItemUtils.setPropertyValueInNodeList(tenantPropertiesNode,\r
+                propName, value, onlyIfNotSet);\r
     }\r
-    \r
 \r
     /**\r
      * @param tenantBinding\r
@@ -74,15 +101,14 @@ public class TenantBindingUtils {
      * @return true if set, false if an existing value was left as is.\r
      */\r
     public static void propagatePropertiesToServices(\r
-               TenantBindingType tenantBinding, boolean onlyIfNotSet) {\r
-               List<PropertyItemType> tenantPropList =  \r
-                       tenantBinding.getProperties().get(0).getItem();\r
-       for(PropertyItemType tenantPropItem:tenantPropList) {\r
-               for(ServiceBindingType service:tenantBinding.getServiceBindings()) {\r
-                       ServiceBindingUtils.setPropertyValue(service, \r
-                                                               tenantPropItem, onlyIfNotSet);\r
-               }\r
-       }\r
+            TenantBindingType tenantBinding, boolean onlyIfNotSet) {\r
+        List<PropertyItemType> tenantPropList =\r
+                tenantBinding.getProperties().get(0).getItem();\r
+        for (PropertyItemType tenantPropItem : tenantPropList) {\r
+            for (ServiceBindingType service : tenantBinding.getServiceBindings()) {\r
+                ServiceBindingUtils.setPropertyValue(service,\r
+                        tenantPropItem, onlyIfNotSet);\r
+            }\r
+        }\r
     }\r
-    \r
 }\r
diff --git a/services/common/src/main/java/org/collectionspace/services/common/datetime/DateTimeFormatUtils.java b/services/common/src/main/java/org/collectionspace/services/common/datetime/DateTimeFormatUtils.java
new file mode 100644 (file)
index 0000000..b01e5b8
--- /dev/null
@@ -0,0 +1,226 @@
+/**
+ *  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
+ */
+package org.collectionspace.services.common.datetime;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.TimeZone;
+
+import org.collectionspace.services.common.ServiceMain;
+import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
+import org.collectionspace.services.common.config.TenantBindingUtils;
+import org.collectionspace.services.common.context.ServiceContext;
+import org.collectionspace.services.common.tenant.TenantBindingType;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ * DateTimeFormatUtils.java
+ *
+ * $LastChangedRevision$
+ * $LastChangedDate$
+ *
+ */
+public class DateTimeFormatUtils {
+
+    private static final Logger logger = LoggerFactory.getLogger(DateTimeFormatUtils.class);
+    final static String DATE_FORMAT_PATTERN_PROPERTY_NAME = "datePattern";
+    final static String ISO_8601_UTC_TIMESTAMP_PATTERN = "yyyy-MM-dd'T'HH:mm:ss'Z'";
+
+    // FIXME:
+    // - Add a method to return the default set of ISO 8601-based date patterns,
+    //   irrespective of per-tenant configuration.
+    // - Consider cacheing the lists of per-tenant date format patterns
+    //   and refresh the cached copies whenever tenant bindings are read.
+    // - Methods below related to per-tenant configuration of date formats might
+    //   be moved to their own class.
+
+    /**
+     * Returns a list of the date format patterns permitted in a service context.
+     * These patterns must conform to the format for date and time pattern strings
+     * specified in the Javadocs for the Java language class, java.text.SimpleDateFormat.
+     *
+     * @param ctx a service context.
+     *
+     * @return    a list of date format patterns permitted in the service context.
+     *            Returns an empty list of patterns if the service context is null.
+     */
+    public static List<String> getDateFormatPatternsForTenant(ServiceContext ctx) {
+        if (ctx == null) {
+            return new ArrayList<String>();
+        }
+        return getDateFormatPatternsForTenant(ctx.getTenantId());
+    }
+
+    /**
+     * Returns a list of the date format patterns permitted for a tenant, specified
+     * by tenant ID.
+     *
+     * These patterns must conform to the format for date and time pattern strings
+     * specified in the Javadocs for the Java language class, java.text.SimpleDateFormat.
+     *
+     * @param tenantId  a tenant ID.
+     *
+     * @return          a list of date format patterns permitted for the tenant.
+     */
+    public static List<String> getDateFormatPatternsForTenant(String tenantId) {
+        List<String> patterns = new ArrayList<String>();
+        if (tenantId == null || tenantId.trim().isEmpty()) {
+            return patterns;
+        }
+        TenantBindingConfigReaderImpl tReader =
+                ServiceMain.getInstance().getTenantBindingConfigReader();
+        TenantBindingType tenantBinding = tReader.getTenantBinding(tenantId);
+        patterns = TenantBindingUtils.getPropertyValues(tenantBinding,
+                DATE_FORMAT_PATTERN_PROPERTY_NAME);
+        return validatePatterns(patterns);
+    }
+
+    public static List<String> validatePatterns(List<String> patterns) {
+        if (patterns == null) {
+            return new ArrayList<String>();
+        }
+        List<String> validPatterns = new ArrayList<String>();
+        for (String pattern : patterns) {
+            try {
+                DateFormat df = getDateFormatter(pattern);
+                validPatterns.add(pattern);
+            } catch (IllegalArgumentException iae) {
+                logger.warn("Invalid " + DATE_FORMAT_PATTERN_PROPERTY_NAME + " property: " + pattern);
+            }
+        }
+        return validPatterns;
+    }
+
+    /**
+     * Returns a representation of a calendar date and time instance,
+     * as an ISO 8601-formatted timestamp in the UTC time zone.
+     *
+     * @param cal a calendar date and time instance.
+     *
+     * @return    a representation of that calendar date and time instance,
+     *            as an ISO 8601-formatted timestamp in the UTC time zone.
+     */
+    public static String formatAsISO8601Timestamp(GregorianCalendar cal) {
+        return formatGregorianCalendarDate(cal, GregorianCalendarDateTimeUtils.UTCTimeZone(),
+                getDateFormatter(ISO_8601_UTC_TIMESTAMP_PATTERN));
+    }
+
+    /**
+     * Formats a provided calendar date using a provided date formatter,
+     * in the default system time zone.
+     *
+     * @param date  A calendar date to format.
+     * @param df    A date formatter to apply.
+     *
+     * @return      A formatted date string, or the empty string
+     *              if one or more of the parameter values were invalid.
+     */
+    public static String formatGregorianCalendarDate(GregorianCalendar gcal, DateFormat df) {
+        return formatGregorianCalendarDate(gcal, TimeZone.getDefault(), df);
+    }
+
+    /**
+     * Formats a provided calendar date using a provided date formatter,
+     * in a provided time zone.
+     *
+     * @param date  A calendar date to format.
+     * @param tz    The time zone qualifier for the calendar date to format.
+     * @param df    A date formatter to apply.
+     *
+     * @return      A formatted date string, or the empty string
+     *              if one or more of the parameter values were invalid.
+     */
+    public static String formatGregorianCalendarDate(GregorianCalendar gcal, TimeZone tz, DateFormat df) {
+        String formattedDate = "";
+        if (gcal == null) {
+            logger.warn("Null calendar date was provided when a non-null calendar date was required.");
+            return formattedDate;
+        }
+        if (tz == null) {
+            logger.warn("Null time zone was provided when a non-null time zone was required.");
+            return formattedDate;
+        }
+        if (df == null) {
+            logger.warn("Null date formatter was provided when a non-null date formatter was required.");
+            return formattedDate;
+        }
+        gcal.setTimeZone(tz);
+        Date date = gcal.getTime();
+        df.setTimeZone(tz);
+        formattedDate = df.format(date);
+        return formattedDate;
+    }
+
+    /**
+     * Identifies whether a presumptive date or date/time can be parsed
+     * by a date parser, using a specified format pattern.
+     *
+     * @param str      a String, possibly a date or date/time String.
+     *
+     * @param pattern  A date or date/time pattern.
+     *
+     * @return         true, if the String can be parsed, using the pattern;
+     *                 false if the String cannot be parsed by the pattern,
+     *                 or if the String or pattern are null.
+     */
+    public static boolean isParseableByDatePattern(String str, String pattern) {
+        if (pattern == null || pattern.trim().isEmpty()) {
+            return false;
+        }
+        DateFormat df = null;
+        try {
+            df = new SimpleDateFormat(pattern);
+            df.parse(str);
+        } catch (ParseException pe) {
+            return false;
+        } catch (IllegalArgumentException iae) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Returns a date formatter for a provided date or date/time pattern.
+     *
+     * @param pattern  A date or date/time pattern.
+     *
+     * @return         A date formatter using that pattern, or null
+     *                 if the pattern was null, empty, or invalid.
+     */
+    public static DateFormat getDateFormatter(String pattern) {
+        DateFormat df = null;
+        if (pattern == null || pattern.trim().isEmpty()) {
+            logger.warn("Null or empty date pattern string was provided when getting date formatter.");
+            return df;
+        }
+        try {
+            df = new SimpleDateFormat(pattern);
+        } catch (IllegalArgumentException iae) {
+            logger.warn("Invalid date pattern string '" + pattern + "': " + iae.getMessage());
+        }
+        return df;
+    }
+}
index afc6f0acca17b51d75c8db3561de11ad2598a14a..0aab30641f19d9cad82ff3a77d92a0828ea5f3b3 100644 (file)
@@ -17,8 +17,6 @@
  */
 package org.collectionspace.services.common.datetime;
 
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.GregorianCalendar;
 import java.util.TimeZone;
@@ -86,99 +84,7 @@ public class GregorianCalendarDateTimeUtils {
     * @return A String representing the current date and time instance.
     */
     public static String timestampUTC() {
-        return formatAsISO8601Timestamp(currentDateAndTime(UTCTimeZone()));
-    }
-
-   /**
-    * Returns a representation of a calendar date and time instance,
-    * as an ISO 8601-formatted timestamp in the UTC time zone.
-    *
-    * @param cal A calendar date and time instance
-    *
-    * @return    A representation of that calendar date and time instance,
-    *            as an ISO 8601-formatted timestamp in the UTC time zone.
-    */
-    public static String formatAsISO8601Timestamp(GregorianCalendar cal) {
-        return formatCalendarDate(cal, UTCTimeZone(), ISO8601TimestampFormatter());
-    }
-
-   /**
-    * Formats a provided calendar date using a provided date formatter,
-    * in the default system time zone.
-    *
-    * @param date  A calendar date to format.
-    * @param df    A date formatter to apply.
-    *
-    * @return      A formatted date string, or the empty string
-    *              if one or more of the parameter values were invalid.
-    */
-    public static String formatCalendarDate(GregorianCalendar gcal, DateFormat df) {
-        return formatCalendarDate(gcal, TimeZone.getDefault(), df);
-    }
-
-   /**
-    * Formats a provided calendar date using a provided date formatter,
-    * in a provided time zone.
-    *
-    * @param date  A calendar date to format.
-    * @param tz    The time zone qualifier for the calendar date to format.
-    * @param df    A date formatter to apply.
-    *
-    * @return      A formatted date string, or the empty string
-    *              if one or more of the parameter values were invalid.
-    */
-    public static String formatCalendarDate(GregorianCalendar gcal, TimeZone tz, DateFormat df) {
-        String formattedDate = "";
-        if (gcal == null) {
-            logger.warn("Null calendar date was provided when a non-null calendar date was required.");
-            return formattedDate;
-        }
-        if (tz == null) {
-            logger.warn("Null time zone was provided when a non-null time zone was required.");
-            return formattedDate;
-        }
-        if (df == null) {
-            logger.warn("Null date formatter was provided when a non-null date formatter was required.");
-            return formattedDate;
-        }
-        gcal.setTimeZone(tz);
-        Date date = gcal.getTime();
-        df.setTimeZone(tz);
-        formattedDate = df.format(date);
-        return formattedDate;
-    }
-
-   /**
-    * Returns a date formatter for an ISO 8601 timestamp pattern.
-    *
-    * @return  A date formatter for an ISO 8601 timestamp pattern.
-    *          This pattern is specified as a class constant above.
-    */
-    public static DateFormat ISO8601TimestampFormatter() {
-        return getDateFormatter(ISO_8601_UTC_TIMESTAMP_PATTERN);
-    }
-
-   /**
-    * Returns a date formatter for a provided date or date/time pattern.
-    *
-    * @param pattern  A date or date/time pattern.
-    *
-    * @return         A date formatter using that pattern, or null
-    *                 if the pattern was null, empty, or invalid.
-    */
-    public static DateFormat getDateFormatter(String pattern) {
-        DateFormat df = null;
-        if (pattern == null || pattern.trim().isEmpty()) {
-            logger.warn("Null or empty date pattern string was provided " +
-                "when a non-null, non-empty date pattern string was required.");
-            return df;
-        }
-        try {
-            df = new SimpleDateFormat(pattern);
-        } catch (IllegalArgumentException iae) {
-            logger.warn("Invalid date pattern string: " + pattern);
-        }
-        return df;
+        return DateTimeFormatUtils.formatAsISO8601Timestamp(currentDateAndTime(UTCTimeZone()));
     }
 
 }
index f606909c1f9fabc46fa2085f6c075018829847b2..808b28ebcf6ecdb9cda449fdc15556ab4ff69193 100644 (file)
  */
 package org.collectionspace.services.movement.nuxeo;
 
-import java.util.Calendar;
 import java.util.GregorianCalendar;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
 
 import org.collectionspace.services.MovementJAXBSchema;
-import org.collectionspace.services.common.datetime.GregorianCalendarDateTimeUtils;
+import org.collectionspace.services.common.datetime.DateTimeFormatUtils;
 import org.collectionspace.services.common.document.DocumentWrapper;
-import org.collectionspace.services.common.service.ObjectPartType;
 import org.collectionspace.services.movement.MovementsCommon;
 import org.collectionspace.services.movement.MovementsCommonList;
 import org.collectionspace.services.movement.MovementsCommonList.MovementListItem;
@@ -46,14 +42,15 @@ import org.slf4j.LoggerFactory;
 
 /**
  * The Class MovementDocumentModelHandler.
+ *
+ * $LastChangedRevision$
+ * $LastChangedDate$
  */
 public class MovementDocumentModelHandler
         extends RemoteDocumentModelHandlerImpl<MovementsCommon, MovementsCommonList> {
 
     /** The logger. */
     private final Logger logger = LoggerFactory.getLogger(MovementDocumentModelHandler.class);
-
-    private static final String COMMON_PART_LABEL = "movements_common";
     
     /** The Movement. */
     private MovementsCommon Movement;
@@ -145,7 +142,7 @@ public class MovementDocumentModelHandler
                     MovementJAXBSchema.MOVEMENT_REFERENCE_NUMBER));
             GregorianCalendar gcal = (GregorianCalendar) docModel.getProperty(getServiceContext().getCommonPartLabel(),
                     MovementJAXBSchema.LOCATION_DATE);
-            ilistItem.setLocationDate(GregorianCalendarDateTimeUtils.formatAsISO8601Timestamp(gcal));
+            ilistItem.setLocationDate(DateTimeFormatUtils.formatAsISO8601Timestamp(gcal));
             String id = NuxeoUtils.extractId(docModel.getPathAsString());
             ilistItem.setUri(getServiceContextPath() + id);
             ilistItem.setCsid(id);
@@ -166,15 +163,5 @@ public class MovementDocumentModelHandler
         return MovementConstants.NUXEO_SCHEMA_NAME + ":" + prop;
     }
 
-    private boolean isDateTimeType(Object obj) {
-        boolean isDateTimeType = false;
-
-        if (obj != null && obj instanceof Calendar) {
-            isDateTimeType = true;
-        }
-
-        return isDateTimeType;
-    }
-
 }
 
index 5b29958e43ea9f16b799ad342dfcae372dcbfffe..0bd4dd9345a3100eee565718d24d742dc09aa69d 100644 (file)
@@ -1,17 +1,76 @@
 package org.collectionspace.services.movement.nuxeo;
 
+import java.util.List;
+
 import org.collectionspace.services.common.context.ServiceContext;
+import org.collectionspace.services.common.context.MultipartServiceContext;
+import org.collectionspace.services.common.datetime.DateTimeFormatUtils;
 import org.collectionspace.services.common.document.InvalidDocumentException;
 import org.collectionspace.services.common.document.ValidatorHandler;
 import org.collectionspace.services.common.document.DocumentHandler.Action;
+import org.collectionspace.services.movement.MovementsCommon;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class MovementValidatorHandler implements ValidatorHandler {
 
+        final Logger logger = LoggerFactory.getLogger(MovementValidatorHandler.class);
+
        @Override
        public void validate(Action action, ServiceContext ctx)
                        throws InvalidDocumentException {
-               // TODO Auto-generated method stub
-               System.out.println("movementValidatorHandler executed.");
+
+                if(logger.isDebugEnabled()) {
+                    logger.debug("validate() action=" + action.name());
+                }
+                try {
+                    MultipartServiceContext mctx = (MultipartServiceContext) ctx;
+                    MovementsCommon mc = (MovementsCommon) mctx.getInputPart(mctx.getCommonPartLabel(),
+                            MovementsCommon.class);
+                    StringBuilder msgBldr = new StringBuilder("validate()");
+                    boolean invalid = false;
+
+                    List<String> patterns = DateTimeFormatUtils.getDateFormatPatternsForTenant(ctx);
+
+                    // FIXME: This is an early proof-of-concept.
+                    //
+                    // We need a better way of determining which fields
+                    // in the incoming payload are date fields whose values we
+                    // might wish to validate, and of extracting their values,
+                    // than hard-coding them here.
+
+                    /*
+                    boolean validDateFormat = false;
+                    String locDate = mc.getLocationDate();
+                    for (String pattern : patterns) {
+                        if (DateTimeFormatUtils.isParseableByDatePattern(locDate, pattern)) {
+                            validDateFormat = true;
+                        }
+                    }
+                    if (! validDateFormat) {
+                        invalid = true;
+                        msgBldr.append("\nlocationDate : unrecognized date format '" + locDate + "'");
+                    }
+                    *
+                    */
+
+                    if(action.equals(Action.CREATE)) {
+                        //create specific validation here
+                    } else if(action.equals(Action.UPDATE)) {
+                        //update specific validation here
+                    }
+
+                    if (invalid) {
+                        String msg = msgBldr.toString();
+                        logger.error(msg);
+                        throw new InvalidDocumentException(msg);
+                    }
+                } catch (InvalidDocumentException ide) {
+                    throw ide;
+                } catch (Exception e) {
+                    throw new InvalidDocumentException(e);
+                }
 
        }