]> git.aero2k.de Git - tmp/jakarta-migration.git/commitdiff
CSPACE-6918: Add material authority and materials profile.
authorRay Lee <rhlee@berkeley.edu>
Thu, 3 Mar 2016 20:54:14 +0000 (12:54 -0800)
committerRay Lee <rhlee@berkeley.edu>
Fri, 18 Mar 2016 22:40:10 +0000 (15:40 -0700)
33 files changed:
services/JaxRsServiceProvider/pom.xml
services/JaxRsServiceProvider/src/main/java/org/collectionspace/services/jaxrs/CollectionSpaceJaxRsApplication.java
services/build.xml
services/common/src/main/cspace/config/services/tenants/materials/materials-tenant-bindings.delta.xml [new file with mode: 0644]
services/material/3rdparty/build.xml [new file with mode: 0644]
services/material/3rdparty/nuxeo-platform-cs-material/build.xml [new file with mode: 0644]
services/material/3rdparty/nuxeo-platform-cs-material/pom.xml [new file with mode: 0644]
services/material/3rdparty/nuxeo-platform-cs-material/src/main/resources/META-INF/README.txt [new file with mode: 0644]
services/material/3rdparty/nuxeo-platform-cs-material/src/main/resources/OSGI-INF/README.txt [new file with mode: 0644]
services/material/3rdparty/nuxeo-platform-cs-material/src/main/resources/schemas/README.txt [new file with mode: 0644]
services/material/3rdparty/pom.xml [new file with mode: 0644]
services/material/build.xml [new file with mode: 0644]
services/material/client/pom.xml [new file with mode: 0644]
services/material/client/src/main/java/org/collectionspace/services/client/MaterialAuthorityClient.java [new file with mode: 0644]
services/material/client/src/main/java/org/collectionspace/services/client/MaterialAuthorityClientUtils.java [new file with mode: 0644]
services/material/client/src/main/java/org/collectionspace/services/client/MaterialAuthorityProxy.java [new file with mode: 0644]
services/material/client/src/main/resources/collectionspace-client.properties [new file with mode: 0644]
services/material/client/src/test/java/org/collectionspace/services/client/test/MaterialAuthorityServiceTest.java [new file with mode: 0644]
services/material/client/src/test/resources/log4j.properties [new file with mode: 0644]
services/material/installer/build.xml [new file with mode: 0644]
services/material/jaxb/pom.xml [new file with mode: 0644]
services/material/jaxb/src/main/java/org/collectionspace/services/MaterialJAXBSchema.java [new file with mode: 0644]
services/material/jaxb/src/main/resources/material_common.xsd [new file with mode: 0644]
services/material/jaxb/src/main/resources/materialauthority_common.xsd [new file with mode: 0644]
services/material/pom.xml [new file with mode: 0644]
services/material/service/pom.xml [new file with mode: 0644]
services/material/service/src/main/java/org/collectionspace/services/material/MaterialAuthorityResource.java [new file with mode: 0644]
services/material/service/src/main/java/org/collectionspace/services/material/nuxeo/MaterialAuthorityConstants.java [new file with mode: 0644]
services/material/service/src/main/java/org/collectionspace/services/material/nuxeo/MaterialAuthorityDocumentModelHandler.java [new file with mode: 0644]
services/material/service/src/main/java/org/collectionspace/services/material/nuxeo/MaterialConstants.java [new file with mode: 0644]
services/material/service/src/main/java/org/collectionspace/services/material/nuxeo/MaterialDocumentModelHandler.java [new file with mode: 0644]
services/material/service/src/main/java/org/collectionspace/services/material/nuxeo/MaterialValidatorHandler.java [new file with mode: 0644]
services/pom.xml

index e91061e9590a9bdf6b89469109ca4fe0cb0dac09..e973871268813289018f7ca461705c3e449f1a91 100644 (file)
             <artifactId>org.collectionspace.services.work.service</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.collectionspace.services</groupId>
+            <artifactId>org.collectionspace.services.material.service</artifactId>
+            <version>${project.version}</version>
+        </dependency>
         <dependency>
             <groupId>org.collectionspace.services</groupId>
             <artifactId>org.collectionspace.services.concept.service</artifactId>
index 23edf527bc01a551d29f36b78e712ae4436208d0..81fa6b8e98426405e55d8a8b574a41bb3aea9fd0 100644 (file)
@@ -39,6 +39,7 @@ import org.collectionspace.services.imports.ImportsResource;
 import org.collectionspace.services.location.LocationAuthorityResource;
 import org.collectionspace.services.place.PlaceAuthorityResource;
 import org.collectionspace.services.work.WorkAuthorityResource;
+import org.collectionspace.services.material.MaterialAuthorityResource;
 import org.collectionspace.services.concept.ConceptAuthorityResource;
 import org.collectionspace.services.taxonomy.TaxonomyAuthorityResource;
 import org.collectionspace.services.movement.MovementResource;
@@ -110,6 +111,7 @@ public class CollectionSpaceJaxRsApplication extends Application
         addResourceToMapAndSingletons(new TaxonomyAuthorityResource());
         addResourceToMapAndSingletons(new PlaceAuthorityResource());
         addResourceToMapAndSingletons(new WorkAuthorityResource());
+        addResourceToMapAndSingletons(new MaterialAuthorityResource());
         addResourceToMapAndSingletons(new AcquisitionResource());
         addResourceToMapAndSingletons(new ContactResource());
         addResourceToMapAndSingletons(new CollectionObjectResource());
index 04b75699e1c29438c78c5112df0053b86e90e279..e44f38413160182a991e944512a19ccf659b9d4d 100644 (file)
         <ant antfile="location/build.xml" target="deploy" inheritAll="false"/>
         <ant antfile="place/build.xml" target="deploy" inheritAll="false"/>
         <ant antfile="work/build.xml" target="deploy" inheritAll="false"/>
+        <ant antfile="material/build.xml" target="deploy" inheritAll="false"/>
         <ant antfile="concept/build.xml" target="deploy" inheritAll="false"/>
         <ant antfile="taxonomy/build.xml" target="deploy" inheritAll="false"/>
         <ant antfile="media/build.xml" target="deploy" inheritAll="false"/>
         <ant antfile="acquisition/build.xml" target="undeploy" inheritAll="false"/>
         <ant antfile="taxonomy/build.xml" target="undeploy" inheritAll="false"/>
         <ant antfile="concept/build.xml" target="undeploy" inheritAll="false"/>
+        <ant antfile="material/build.xml" target="undeploy" inheritAll="false"/>
         <ant antfile="work/build.xml" target="undeploy" inheritAll="false"/>
         <ant antfile="place/build.xml" target="undeploy" inheritAll="false"/>
         <ant antfile="location/build.xml" target="undeploy" inheritAll="false"/>
         <ant antfile="location/build.xml" target="dist" inheritAll="false"/>
         <ant antfile="place/build.xml" target="dist" inheritAll="false"/>
         <ant antfile="work/build.xml" target="dist" inheritAll="false"/>
+        <ant antfile="material/build.xml" target="dist" inheritAll="false"/>
         <ant antfile="concept/build.xml" target="dist" inheritAll="false"/>
         <ant antfile="taxonomy/build.xml" target="dist" inheritAll="false"/>
         <ant antfile="exhibition/build.xml" target="dist" inheritAll="false"/>
diff --git a/services/common/src/main/cspace/config/services/tenants/materials/materials-tenant-bindings.delta.xml b/services/common/src/main/cspace/config/services/tenants/materials/materials-tenant-bindings.delta.xml
new file mode 100644 (file)
index 0000000..ad75d53
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<tenant:TenantBindingConfig
+        xmlns:merge='http://xmlmerge.el4j.elca.ch'
+        xmlns:tenant='http://collectionspace.org/services/config/tenant'>
+
+    <!-- Add your changes, if any, within the following tag pair. -->
+    <!-- The value of the 'id' attribute, below, should match the corresponding -->
+    <!-- value in cspace/config/services/tenants/materials-tenant-bindings-proto.xml -->
+
+    <tenant:tenantBinding id="2000">
+    </tenant:tenantBinding>
+
+</tenant:TenantBindingConfig>
diff --git a/services/material/3rdparty/build.xml b/services/material/3rdparty/build.xml
new file mode 100644 (file)
index 0000000..abe0abc
--- /dev/null
@@ -0,0 +1,135 @@
+
+<project name="material.3rdparty" default="package" basedir=".">
+    <description>
+        material service 3rdparty
+    </description>
+  <!-- set global properties for this build -->
+    <property name="services.trunk" value="../../.."/>
+    <!-- enviornment should be declared before reading build.properties -->
+    <property environment="env" />
+    <property file="${services.trunk}/build.properties" />
+    <property name="mvn.opts" value="-V" />
+    <property name="src" location="src"/>
+
+    <condition property="osfamily-unix">
+        <os family="unix" />
+    </condition>
+    <condition property="osfamily-windows">
+        <os family="windows" />
+    </condition>
+
+    <target name="init" >
+    <!-- Create the time stamp -->
+        <tstamp/>
+    </target>
+
+    <target name="package" depends="package-unix,package-windows"
+  description="Package CollectionSpace Services" />
+    <target name="package-unix" if="osfamily-unix">
+        <exec executable="mvn" failonerror="true">
+            <arg value="package" />
+            <arg value="-Dmaven.test.skip=true" />
+            <arg value="-f" />
+            <arg value="${basedir}/pom.xml" />
+            <arg value="-N" />
+            <arg value="${mvn.opts}" />
+        </exec>
+    </target>
+    <target name="package-windows" if="osfamily-windows">
+        <exec executable="cmd" failonerror="true">
+            <arg value="/c" />
+            <arg value="mvn.bat" />
+            <arg value="package" />
+            <arg value="-Dmaven.test.skip=true" />
+            <arg value="-f" />
+            <arg value="${basedir}/pom.xml" />
+            <arg value="-N" />
+            <arg value="${mvn.opts}" />
+        </exec>
+    </target>
+
+    <target name="install" depends="install-unix,install-windows"
+  description="Install" />
+    <target name="install-unix" if="osfamily-unix">
+        <exec executable="mvn" failonerror="true">
+            <arg value="install" />
+            <arg value="-Dmaven.test.skip=true" />
+            <arg value="-f" />
+            <arg value="${basedir}/pom.xml" />
+            <arg value="-N" />
+            <arg value="${mvn.opts}" />
+        </exec>
+    </target>
+    <target name="install-windows" if="osfamily-windows">
+        <exec executable="cmd" failonerror="true">
+            <arg value="/c" />
+            <arg value="mvn.bat" />
+            <arg value="install" />
+            <arg value="-Dmaven.test.skip=true" />
+            <arg value="-f" />
+            <arg value="${basedir}/pom.xml" />
+            <arg value="-N" />
+            <arg value="${mvn.opts}" />
+        </exec>
+    </target>
+    
+    <target name="clean" depends="clean-unix,clean-windows"
+  description="Delete target directories" >
+        <delete dir="${build}"/>
+    </target>
+    <target name="clean-unix" if="osfamily-unix">
+        <exec executable="mvn" failonerror="true">
+            <arg value="clean" />
+            <arg value="${mvn.opts}" />
+        </exec>
+    </target>
+    <target name="clean-windows" if="osfamily-windows">
+        <exec executable="cmd" failonerror="true">
+            <arg value="/c" />
+            <arg value="mvn.bat" />
+            <arg value="clean" />
+            <arg value="${mvn.opts}" />
+        </exec>
+    </target>
+
+    <target name="test" depends="test-unix,test-windows" description="Run tests" />
+    <target name="test-unix" if="osfamily-unix">
+        <exec executable="mvn" failonerror="true">
+            <arg value="test" />
+            <arg value="${mvn.opts}" />
+        </exec>
+    </target>
+    <target name="test-windows" if="osfamily-windows">
+        <exec executable="cmd" failonerror="true">
+            <arg value="/c" />
+            <arg value="mvn.bat" />
+            <arg value="test" />
+            <arg value="${mvn.opts}" />
+        </exec>
+    </target>
+
+    <target name="deploy" depends="install"
+    description="deploy material in ${jee.server.nuxeo}">
+        <!-- This target is obsolete.  The Nuxeo artifacts are now created and deployed using the "csmake" tool 
+            <ant antfile="nuxeo-platform-cs-material/build.xml" target="deploy" inheritall="false"/>
+        -->
+    </target>
+
+    <target name="undeploy"
+    description="undeploy material from ${jee.server.nuxeo}">
+        <!-- This target is obsolete.  The Nuxeo artifacts are now created and deployed using the "csmake" tool
++      leaving this only for backwards compatibility reasons. --> 
+        <ant antfile="nuxeo-platform-cs-material/build.xml" target="undeploy" inheritall="false"/>
+    </target>
+
+    <target name="dist"
+    description="generate distribution for material" depends="package">
+        <ant antfile="nuxeo-platform-cs-material/build.xml" target="dist" inheritall="false"/>
+    </target>
+    
+    <target name="dist_installer"
+    description="generate distribution for material" depends="package">
+        <ant antfile="nuxeo-platform-cs-material/build.xml" target="dist_installer" inheritall="false"/>
+    </target>
+
+</project>
diff --git a/services/material/3rdparty/nuxeo-platform-cs-material/build.xml b/services/material/3rdparty/nuxeo-platform-cs-material/build.xml
new file mode 100644 (file)
index 0000000..ac8bbf5
--- /dev/null
@@ -0,0 +1,167 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="nuxeo-platform-cs-material" default="package" basedir=".">
+    <description>
+        material nuxeo document type
+    </description>
+    <!-- set global properties for this build -->
+    <property name="services.trunk" value="../../../.."/>
+    <!-- environment should be declared before reading build.properties -->
+    <property environment="env" />
+    <property file="${services.trunk}/build.properties" />
+    <property name="mvn.opts" value="-V" />
+    <property name="src" location="src"/>
+    <!-- JAR files used by CollectionSpace 4.0 and later -->
+    <property name="nuxeo.material.doctype.jars.all"
+        value="collectionspace.material.doctype.*.jar"/>
+    <property name="nuxeo.material.schema.jars.all"
+        value="collectionspace.material.schema.*.jar"/>
+    <!-- Legacy JAR files used by CollectionSpace 3.3 and earlier --> 
+    <property name="nuxeo.material.legacy.jars.all"
+        value="org.collectionspace.services.material.3rdparty.nuxeo-*.jar"/>
+    <property name="nuxeo.material.legacy.jar"
+        value="org.collectionspace.services.material.3rdparty.nuxeo-${cspace.release}.jar"/>
+
+    <condition property="osfamily-unix">
+        <os family="unix" />
+    </condition>
+    <condition property="osfamily-windows">
+        <os family="windows" />
+    </condition>
+
+    <target name="init" >
+        <!-- Create the time stamp -->
+        <tstamp/>
+    </target>
+
+    <target name="package" depends="package-unix,package-windows"
+        description="Package CollectionSpace Services" />
+    <target name="package-unix" if="osfamily-unix">
+        <exec executable="mvn" failonerror="true">
+            <arg value="package" />
+            <arg value="-Dmaven.test.skip=true" />
+            <arg value="-f" />
+            <arg value="${basedir}/pom.xml" />
+            <arg value="-N" />
+            <arg value="${mvn.opts}" />
+        </exec>
+    </target>
+    <target name="package-windows" if="osfamily-windows">
+        <exec executable="cmd" failonerror="true">
+            <arg value="/c" />
+            <arg value="mvn.bat" />
+            <arg value="package" />
+            <arg value="-Dmaven.test.skip=true" />
+            <arg value="-f" />
+            <arg value="${basedir}/pom.xml" />
+            <arg value="-N" />
+            <arg value="${mvn.opts}" />
+        </exec>
+    </target>
+
+    <target name="install" depends="install-unix,install-windows"
+        description="Install" />
+    <target name="install-unix" if="osfamily-unix">
+        <exec executable="mvn" failonerror="true">
+            <arg value="install" />
+            <arg value="-Dmaven.test.skip=true" />
+            <arg value="-f" />
+            <arg value="${basedir}/pom.xml" />
+            <arg value="-N" />
+            <arg value="${mvn.opts}" />
+        </exec>
+    </target>
+    <target name="install-windows" if="osfamily-windows">
+        <exec executable="cmd" failonerror="true">
+            <arg value="/c" />
+            <arg value="mvn.bat" />
+            <arg value="install" />
+            <arg value="-Dmaven.test.skip=true" />
+            <arg value="-f" />
+            <arg value="${basedir}/pom.xml" />
+            <arg value="-N" />
+            <arg value="${mvn.opts}" />
+        </exec>
+    </target>
+
+    <target name="clean" depends="clean-unix,clean-windows"
+        description="Delete target directories" >
+        <delete dir="${build}"/>
+    </target>
+    <target name="clean-unix" if="osfamily-unix">
+        <exec executable="mvn" failonerror="true">
+            <arg value="clean" />
+            <arg value="${mvn.opts}" />
+        </exec>
+    </target>
+    <target name="clean-windows" if="osfamily-windows">
+        <exec executable="cmd" failonerror="true">
+            <arg value="/c" />
+            <arg value="mvn.bat" />
+            <arg value="clean" />
+            <arg value="${mvn.opts}" />
+        </exec>
+    </target>
+
+    <target name="test" depends="test-unix,test-windows" description="Run tests" />
+    <target name="test-unix" if="osfamily-unix">
+        <exec executable="mvn" failonerror="true">
+            <arg value="test" />
+            <arg value="${mvn.opts}" />
+        </exec>
+    </target>
+    <target name="test-windows" if="osfamily-windows">
+        <exec executable="cmd" failonerror="true">
+            <arg value="/c" />
+            <arg value="mvn.bat" />
+            <arg value="test" />
+            <arg value="${mvn.opts}" />
+        </exec>
+    </target>
+
+    <target name="deploy" depends="install"
+        description="deploy material doctype in ${jee.server.nuxeo}">
+        <!-- This target is obsolete.  The Nuxeo artifacts are now created and deployed using the "csmake" tool
+        leaving this only for backwards compatibility reasons. -->  
+        <copy file="${basedir}/target/${nuxeo.material.legacy.jar}"
+            todir="${jee.deploy.nuxeo.plugins}"/>
+    </target>
+
+    <target name="undeploy"
+        description="undeploy material doctype from ${jee.server.nuxeo}">
+        <delete>
+            <!-- Undeploy doctype and schema artifacts -->
+            <fileset dir="${jee.deploy.nuxeo.plugins}">
+                <include name="${nuxeo.material.doctype.jars.all}"/>
+            </fileset>
+            <fileset dir="${jee.deploy.nuxeo.plugins}">
+                <include name="${nuxeo.material.schema.jars.all}"/>
+            </fileset>
+            <!-- Undeploy legacy artifacts -->
+            <fileset dir="${jee.deploy.nuxeo.plugins}">
+                <include name="${nuxeo.material.legacy.jars.all}"/>
+            </fileset>
+        </delete>
+        <!-- Undeploy legacy artifacts from old deployment location through release 0.6 -->
+        <delete quiet="true">
+            <fileset dir="${jee.deploy.nuxeo.system}">
+                <include name="${nuxeo.material.legacy.jars.all}"/>
+            </fileset>
+        </delete>
+    </target>
+
+    <target name="dist"
+        description="generate distribution for material doctype" depends="package">
+        <copy todir="${services.trunk}/${dist.deploy.nuxeo.plugins}">
+            <fileset file="${basedir}/target/${nuxeo.material.legacy.jar}"/>
+        </copy>
+    </target>
+
+    <target name="dist_installer"
+        description="Creates an installer distribution for material doctype" depends="package">
+        <copy todir="${services.trunk}/${dist.installer.services}/material/nuxeo">
+            <fileset file="${basedir}/target/${nuxeo.material.legacy.jar}"/>
+        </copy>
+    </target>
+
+</project>
+
diff --git a/services/material/3rdparty/nuxeo-platform-cs-material/pom.xml b/services/material/3rdparty/nuxeo-platform-cs-material/pom.xml
new file mode 100644 (file)
index 0000000..08bbc10
--- /dev/null
@@ -0,0 +1,42 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <groupId>org.collectionspace.services</groupId>
+        <artifactId>org.collectionspace.services.material.3rdparty</artifactId>
+        <version>4.4-SNAPSHOT</version>
+    </parent>
+    
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>org.collectionspace.services.material.3rdparty.nuxeo</artifactId>
+    <name>services.material.3rdparty.nuxeo</name>
+    <packaging>jar</packaging>
+    <description>
+        Material Nuxeo Document Type
+    </description>
+    
+    <build>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>true</filtering>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <manifestFile> src/main/resources/META-INF/MANIFEST.MF </manifestFile>
+                        <manifestEntries>
+                            <Bundle-Version>${eclipseVersion}</Bundle-Version>
+                            <Bundle-ManifestVersion>2</Bundle-ManifestVersion>
+                        </manifestEntries>
+                    </archive>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+    
+</project>
diff --git a/services/material/3rdparty/nuxeo-platform-cs-material/src/main/resources/META-INF/README.txt b/services/material/3rdparty/nuxeo-platform-cs-material/src/main/resources/META-INF/README.txt
new file mode 100644 (file)
index 0000000..5f8c5a6
--- /dev/null
@@ -0,0 +1,16 @@
+Files formerly located in this directory are no longer needed
+-------------------------------------------------------------
+
+In CollectionSpace versions 4.0 and higher, changes were introduced
+which streamline and simplify the process through which you configure
+fields in CollectionSpace's main record types.
+
+In most cases now, you will typically change the behavior of existing fields,
+or create extension schemas to add new fields specific to your museum and/or
+community of practice, merely by editing simpler XML-based configuration
+files within CollectionSpace's Application layer.
+
+Services layer files that were formerly located in this directory and
+other, similar directories - which you previously needed to manually
+create or edit - are now generated automatically from your configuration
+in the Application layer.
\ No newline at end of file
diff --git a/services/material/3rdparty/nuxeo-platform-cs-material/src/main/resources/OSGI-INF/README.txt b/services/material/3rdparty/nuxeo-platform-cs-material/src/main/resources/OSGI-INF/README.txt
new file mode 100644 (file)
index 0000000..5f8c5a6
--- /dev/null
@@ -0,0 +1,16 @@
+Files formerly located in this directory are no longer needed
+-------------------------------------------------------------
+
+In CollectionSpace versions 4.0 and higher, changes were introduced
+which streamline and simplify the process through which you configure
+fields in CollectionSpace's main record types.
+
+In most cases now, you will typically change the behavior of existing fields,
+or create extension schemas to add new fields specific to your museum and/or
+community of practice, merely by editing simpler XML-based configuration
+files within CollectionSpace's Application layer.
+
+Services layer files that were formerly located in this directory and
+other, similar directories - which you previously needed to manually
+create or edit - are now generated automatically from your configuration
+in the Application layer.
\ No newline at end of file
diff --git a/services/material/3rdparty/nuxeo-platform-cs-material/src/main/resources/schemas/README.txt b/services/material/3rdparty/nuxeo-platform-cs-material/src/main/resources/schemas/README.txt
new file mode 100644 (file)
index 0000000..5f8c5a6
--- /dev/null
@@ -0,0 +1,16 @@
+Files formerly located in this directory are no longer needed
+-------------------------------------------------------------
+
+In CollectionSpace versions 4.0 and higher, changes were introduced
+which streamline and simplify the process through which you configure
+fields in CollectionSpace's main record types.
+
+In most cases now, you will typically change the behavior of existing fields,
+or create extension schemas to add new fields specific to your museum and/or
+community of practice, merely by editing simpler XML-based configuration
+files within CollectionSpace's Application layer.
+
+Services layer files that were formerly located in this directory and
+other, similar directories - which you previously needed to manually
+create or edit - are now generated automatically from your configuration
+in the Application layer.
\ No newline at end of file
diff --git a/services/material/3rdparty/pom.xml b/services/material/3rdparty/pom.xml
new file mode 100644 (file)
index 0000000..5cdbd87
--- /dev/null
@@ -0,0 +1,24 @@
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <groupId>org.collectionspace.services</groupId>
+        <artifactId>org.collectionspace.services.material</artifactId>
+        <version>4.4-SNAPSHOT</version>
+    </parent>
+    
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>org.collectionspace.services.material.3rdparty</artifactId>
+    <name>services.material.3rdparty</name>
+    <packaging>pom</packaging>
+    <description>
+        3rd party build for material service
+    </description>
+
+    <modules>
+        <!-- This module is obsolete.  The Nuxeo artifacts are now created and deployed using the "csmake" tool
+            <module>nuxeo-platform-cs-material</module>
+        -->
+    </modules>
+</project>
diff --git a/services/material/build.xml b/services/material/build.xml
new file mode 100644 (file)
index 0000000..5a4ad7c
--- /dev/null
@@ -0,0 +1,131 @@
+<project name="material" default="package" basedir=".">
+    <description>
+        Material Authority service
+    </description>
+  <!-- set global properties for this build -->
+    <property name="services.trunk" value="../.."/>
+        <!-- enviornment should be declared before reading build.properties -->
+    <property environment="env" />
+    <property file="${services.trunk}/build.properties" />
+    <property name="mvn.opts" value="-V" />
+    <property name="src" location="src"/>
+
+    <condition property="osfamily-unix">
+        <os family="unix" />
+    </condition>
+    <condition property="osfamily-windows">
+        <os family="windows" />
+    </condition>
+
+    <target name="package" depends="package-unix,package-windows"
+  description="Package CollectionSpace Services" />
+  
+    <target name="package-unix" if="osfamily-unix">
+        <exec executable="mvn" failonerror="true">
+            <arg value="package" />
+            <arg value="-Dmaven.test.skip=true" />
+            <arg value="-f" />
+            <arg value="${basedir}/pom.xml" />
+            <arg value="-N" />
+            <arg value="${mvn.opts}" />
+        </exec>
+    </target>
+    
+    <target name="package-windows" if="osfamily-windows">
+        <exec executable="cmd" failonerror="true">
+            <arg value="/c" />
+            <arg value="mvn.bat" />
+            <arg value="package" />
+            <arg value="-Dmaven.test.skip=true" />
+            <arg value="-f" />
+            <arg value="${basedir}/pom.xml" />
+            <arg value="-N" />
+            <arg value="${mvn.opts}" />
+        </exec>
+    </target>
+
+    <target name="install" depends="install-unix,install-windows"
+  description="Install" />
+    <target name="install-unix" if="osfamily-unix">
+        <exec executable="mvn" failonerror="true">
+            <arg value="install" />
+            <arg value="-Dmaven.test.skip=true" />
+            <arg value="-f" />
+            <arg value="${basedir}/pom.xml" />
+            <arg value="-N" />
+            <arg value="${mvn.opts}" />
+        </exec>
+    </target>
+    <target name="install-windows" if="osfamily-windows">
+        <exec executable="cmd" failonerror="true">
+            <arg value="/c" />
+            <arg value="mvn.bat" />
+            <arg value="install" />
+            <arg value="-Dmaven.test.skip=true" />
+            <arg value="-f" />
+            <arg value="${basedir}/pom.xml" />
+            <arg value="-N" />
+            <arg value="${mvn.opts}" />
+        </exec>
+    </target>
+
+    <target name="clean" depends="clean-unix,clean-windows"
+  description="Delete target directories" >
+        <delete dir="${build}"/>
+    </target>
+    <target name="clean-unix" if="osfamily-unix">
+        <exec executable="mvn" failonerror="true">
+            <arg value="clean" />
+            <arg value="${mvn.opts}" />
+        </exec>
+    </target>
+    <target name="clean-windows" if="osfamily-windows">
+        <exec executable="cmd" failonerror="true">
+            <arg value="/c" />
+            <arg value="mvn.bat" />
+            <arg value="clean" />
+            <arg value="${mvn.opts}" />
+        </exec>
+    </target>
+
+    <target name="test" depends="test-unix,test-windows" description="Run tests" />
+    <target name="test-unix" if="osfamily-unix">
+        <exec executable="mvn" failonerror="true">
+            <arg value="test" />
+            <arg value="${mvn.opts}" />
+        </exec>
+    </target>
+    <target name="test-windows" if="osfamily-windows">
+        <exec executable="cmd" failonerror="true">
+            <arg value="/c" />
+            <arg value="mvn.bat" />
+            <arg value="test" />
+            <arg value="${mvn.opts}" />
+        </exec>
+    </target>
+
+    <target name="deploy" depends="install"
+        description="deploy material service">
+        <ant antfile="3rdparty/build.xml" target="deploy" inheritall="false"/>
+    </target>
+
+    <target name="undeploy"
+        description="undeploy material service">
+        <ant antfile="3rdparty/build.xml" target="undeploy" inheritall="false"/>
+    </target>
+
+    <target name="dist" depends="package"
+        description="distribute material service">
+        <ant antfile="3rdparty/build.xml" target="dist" inheritall="false"/>
+    </target>
+
+    <target name="dist_installer" depends="package"
+        description="distribute material service">        
+        <!-- copy install scripts, etc. -->
+        <copy todir="${services.trunk}/${dist.installer.services}/material">
+            <fileset dir="${basedir}/installer/"/>
+        </copy>
+        <ant antfile="3rdparty/build.xml" target="dist_installer" inheritall="false"/>
+    </target>
+
+</project>
diff --git a/services/material/client/pom.xml b/services/material/client/pom.xml
new file mode 100644 (file)
index 0000000..b370576
--- /dev/null
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <groupId>org.collectionspace.services</groupId>
+        <artifactId>org.collectionspace.services.material</artifactId>
+        <version>4.4-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>org.collectionspace.services.material.client</artifactId>
+    <name>services.material.client</name>
+    
+    <dependencies>
+        <!-- keep slf4j dependencies on the top -->
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-log4j12</artifactId>
+        </dependency>
+        <!-- CollectionSpace dependencies -->
+        <dependency>
+            <groupId>org.collectionspace.services</groupId>
+            <artifactId>org.collectionspace.services.jaxb</artifactId>
+            <version>${project.version}</version>
+        </dependency>        
+        <dependency>
+            <groupId>org.collectionspace.services</groupId>
+            <artifactId>org.collectionspace.services.common</artifactId>
+            <optional>true</optional>
+        </dependency>        
+        <dependency>
+            <groupId>org.collectionspace.services</groupId>
+            <artifactId>org.collectionspace.services.material.jaxb</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.collectionspace.services</groupId>
+            <artifactId>org.collectionspace.services.client</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.collectionspace.services</groupId>
+            <artifactId>org.collectionspace.services.authority.jaxb</artifactId>
+            <optional>true</optional>
+            <version>${project.version}</version>
+        </dependency>   
+        <!-- External dependencies -->
+        <dependency>
+            <groupId>org.testng</groupId>
+            <artifactId>testng</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jaxrs</artifactId>
+            <!-- filter out unwanted jars -->
+            <exclusions>
+                <exclusion>
+                    <groupId>tjws</groupId>
+                    <artifactId>webserver</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jaxb-provider</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-multipart-provider</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-httpclient</groupId>
+            <artifactId>commons-httpclient</artifactId>
+        </dependency>
+    </dependencies>
+    
+    <build>
+        <finalName>collectionspace-services-material-client</finalName>
+        <plugins>
+        </plugins>
+    </build>
+</project>
+
diff --git a/services/material/client/src/main/java/org/collectionspace/services/client/MaterialAuthorityClient.java b/services/material/client/src/main/java/org/collectionspace/services/client/MaterialAuthorityClient.java
new file mode 100644 (file)
index 0000000..38dae0e
--- /dev/null
@@ -0,0 +1,72 @@
+/**
+ * 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 The Regents of the University of California
+ *
+ * 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.client;
+
+import org.collectionspace.services.material.MaterialsCommon;
+
+/**
+ * The Class MaterialAuthorityClient.
+ */
+public class MaterialAuthorityClient extends AuthorityClientImpl<MaterialsCommon, MaterialAuthorityProxy> {
+
+    public static final String SERVICE_NAME = "materialauthorities";
+    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 = "materialTermGroupList";
+    //
+    // Subitem constants
+    //
+    public static final String SERVICE_ITEM_NAME = "materials";
+    public static final String SERVICE_ITEM_PAYLOAD_NAME = SERVICE_ITEM_NAME;
+    //
+    // Payload Part/Schema part names
+    //
+    public static final String SERVICE_COMMON_PART_NAME = SERVICE_NAME
+            + PART_LABEL_SEPARATOR + PART_COMMON_LABEL;
+    public static final String SERVICE_ITEM_COMMON_PART_NAME = SERVICE_ITEM_NAME
+            + PART_LABEL_SEPARATOR + PART_COMMON_LABEL;
+
+    @Override
+    public String getServiceName() {
+        return SERVICE_NAME;
+    }
+
+    @Override
+    public String getServicePathComponent() {
+        return SERVICE_PATH_COMPONENT;
+    }
+
+    @Override
+    public String getItemCommonPartName() {
+        return getCommonPartName(SERVICE_ITEM_NAME);
+    }
+
+    @Override
+    public Class<MaterialAuthorityProxy> getProxyClass() {
+        return MaterialAuthorityProxy.class;
+    }
+
+    @Override
+    public String getInAuthority(MaterialsCommon item) {
+        return item.getInAuthority();
+    }
+
+    @Override
+    public void setInAuthority(MaterialsCommon item, String inAuthorityCsid) {
+        item.setInAuthority(inAuthorityCsid);
+    }
+}
diff --git a/services/material/client/src/main/java/org/collectionspace/services/client/MaterialAuthorityClientUtils.java b/services/material/client/src/main/java/org/collectionspace/services/client/MaterialAuthorityClientUtils.java
new file mode 100644 (file)
index 0000000..399e6b3
--- /dev/null
@@ -0,0 +1,294 @@
+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;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import org.apache.commons.io.FileUtils;
+import org.collectionspace.services.MaterialJAXBSchema;
+import org.collectionspace.services.client.test.ServiceRequestType;
+import org.collectionspace.services.common.api.Tools;
+import org.collectionspace.services.material.MaterialTermGroup;
+import org.collectionspace.services.material.MaterialTermGroupList;
+import org.collectionspace.services.material.MaterialauthoritiesCommon;
+import org.collectionspace.services.material.MaterialsCommon;
+import org.dom4j.DocumentException;
+import org.jboss.resteasy.client.ClientResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MaterialAuthorityClientUtils {
+    private static final Logger logger =
+        LoggerFactory.getLogger(MaterialAuthorityClientUtils.class);
+
+    /**
+     * Creates a new Material Authority
+     * @param displayName   The displayName used in UI, etc.
+     * @param refName       The proper refName for this authority
+     * @param headerLabel   The common part label
+     * @return  The PoxPayloadOut payload for the create call
+     */
+    public static PoxPayloadOut createMaterialAuthorityInstance(
+            String displayName, String shortIdentifier, String headerLabel ) {
+        MaterialauthoritiesCommon materialAuthority = new MaterialauthoritiesCommon();
+        materialAuthority.setDisplayName(displayName);
+        materialAuthority.setShortIdentifier(shortIdentifier);
+        String refName = createMaterialAuthRefName(shortIdentifier, displayName);
+        materialAuthority.setRefName(refName);
+        materialAuthority.setVocabType("MaterialAuthority"); //FIXME: REM - Should this really be hard-coded?
+        PoxPayloadOut multipart = new PoxPayloadOut(MaterialAuthorityClient.SERVICE_PAYLOAD_NAME);
+        PayloadOutputPart commonPart = multipart.addPart(materialAuthority, MediaType.APPLICATION_XML_TYPE);
+        commonPart.setLabel(headerLabel);
+
+        if(logger.isDebugEnabled()){
+            logger.debug("to be created, materialAuthority common ", 
+                        materialAuthority, MaterialauthoritiesCommon.class);
+        }
+
+        return multipart;
+    }
+
+    /**
+     * @param materialRefName  The proper refName for this authority
+     * @param materialInfo the properties for the new Material. Can pass in one condition
+     *                      note and date string.
+     * @param headerLabel   The common part label
+     * @return  The PoxPayloadOut payload for the create call
+     */
+    public static PoxPayloadOut createMaterialInstance( 
+            String materialAuthRefName, Map<String, String> materialInfo, 
+        List<MaterialTermGroup> terms, String headerLabel){
+        MaterialsCommon material = new MaterialsCommon();
+        String shortId = materialInfo.get(MaterialJAXBSchema.SHORT_IDENTIFIER);
+        material.setShortIdentifier(shortId);
+
+        // Set values in the Term Information Group
+        MaterialTermGroupList termList = new MaterialTermGroupList();
+        if (terms == null || terms.isEmpty()) {
+            terms = getTermGroupInstance(getGeneratedIdentifier());
+        }
+        termList.getMaterialTermGroup().addAll(terms); 
+        material.setMaterialTermGroupList(termList);
+        
+        PoxPayloadOut multipart = new PoxPayloadOut(MaterialAuthorityClient.SERVICE_ITEM_PAYLOAD_NAME);
+        PayloadOutputPart commonPart = multipart.addPart(material,
+            MediaType.APPLICATION_XML_TYPE);
+        commonPart.setLabel(headerLabel);
+
+        if(logger.isDebugEnabled()){
+            logger.debug("to be created, material common ", material, MaterialsCommon.class);
+        }
+
+        return multipart;
+    }
+    
+    /**
+     * @param vcsid CSID of the authority to create a new material
+     * @param materialAuthorityRefName The refName for the authority
+     * @param materialMap the properties for the new Material
+     * @param client the service client
+     * @return the CSID of the new item
+     */
+    public static String createItemInAuthority(String vcsid, 
+            String materialAuthorityRefName, Map<String,String> materialMap,
+            List<MaterialTermGroup> terms, MaterialAuthorityClient client ) {
+        // Expected status code: 201 Created
+        int EXPECTED_STATUS_CODE = Response.Status.CREATED.getStatusCode();
+        // Type of service request being tested
+        ServiceRequestType REQUEST_TYPE = ServiceRequestType.CREATE;
+        
+        String displayName = "";
+        if ((terms !=null) && (! terms.isEmpty())) {
+            displayName = terms.get(0).getTermDisplayName();
+        }
+        if(logger.isDebugEnabled()){
+            logger.debug("Creating item with display name: \"" + displayName
+                    +"\" in locationAuthority: \"" + vcsid +"\"");
+        }
+        PoxPayloadOut multipart = 
+            createMaterialInstance( materialAuthorityRefName,
+                materialMap, terms, client.getItemCommonPartName() );
+        String newID = null;
+        Response res = client.createItem(vcsid, multipart);
+        try {
+            int statusCode = res.getStatus();
+    
+            if(!REQUEST_TYPE.isValidStatusCode(statusCode)) {
+                throw new RuntimeException("Could not create Item: \""
+                        +materialMap.get(MaterialJAXBSchema.SHORT_IDENTIFIER)
+                        +"\" in materialAuthority: \"" + materialAuthorityRefName
+                        +"\" "+ invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+            }
+            if(statusCode != EXPECTED_STATUS_CODE) {
+                throw new RuntimeException("Unexpected Status when creating Item: \""
+                        +materialMap.get(MaterialJAXBSchema.SHORT_IDENTIFIER)
+                        +"\" in materialAuthority: \"" + materialAuthorityRefName +"\", Status:"+ statusCode);
+            }
+            newID = extractId(res);
+        } finally {
+            res.close();
+        }
+
+        return newID;
+    }
+
+    public static PoxPayloadOut createMaterialInstance(
+            String commonPartXML, String headerLabel)  throws DocumentException {
+        PoxPayloadOut multipart = new PoxPayloadOut(MaterialAuthorityClient.SERVICE_ITEM_PAYLOAD_NAME);
+        PayloadOutputPart commonPart = multipart.addPart(commonPartXML,
+            MediaType.APPLICATION_XML_TYPE);
+        commonPart.setLabel(headerLabel);
+
+        if(logger.isDebugEnabled()){
+            logger.debug("to be created, material common ", commonPartXML);
+        }
+
+        return multipart;
+    }
+    
+    public static String createItemInAuthority(String vcsid,
+            String commonPartXML,
+            MaterialAuthorityClient client ) throws DocumentException {
+        // Expected status code: 201 Created
+        int EXPECTED_STATUS_CODE = Response.Status.CREATED.getStatusCode();
+        // Type of service request being tested
+        ServiceRequestType REQUEST_TYPE = ServiceRequestType.CREATE;
+        
+        PoxPayloadOut multipart = 
+            createMaterialInstance(commonPartXML, client.getItemCommonPartName());
+        String newID = null;
+        Response res = client.createItem(vcsid, multipart);
+        try {
+            int statusCode = res.getStatus();
+    
+            if(!REQUEST_TYPE.isValidStatusCode(statusCode)) {
+                throw new RuntimeException("Could not create Item: \""+commonPartXML
+                        +"\" in materialAuthority: \"" + vcsid
+                        +"\" "+ invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+            }
+            if(statusCode != EXPECTED_STATUS_CODE) {
+                throw new RuntimeException("Unexpected Status when creating Item: \""+commonPartXML
+                        +"\" in materialAuthority: \"" + vcsid +"\", Status:"+ statusCode);
+            }
+            newID = extractId(res);
+        } finally {
+            res.close();
+        }
+
+        return newID;
+    }
+    
+    /**
+     * Creates the from xml file.
+     *
+     * @param fileName the file name
+     * @return new CSID as string
+     * @throws Exception the exception
+     */
+    private String createItemInAuthorityFromXmlFile(String vcsid, String commonPartFileName, 
+            MaterialAuthorityClient client) throws Exception {
+        byte[] b = FileUtils.readFileToByteArray(new File(commonPartFileName));
+        String commonPartXML = new String(b);
+        return createItemInAuthority(vcsid, commonPartXML, client );
+    }    
+
+    /**
+     * Creates the materialAuthority ref name.
+     *
+     * @param shortId the materialAuthority shortIdentifier
+     * @param displaySuffix displayName to be appended, if non-null
+     * @return the string
+     */
+    public static String createMaterialAuthRefName(String shortId, String displaySuffix) {
+        String refName = "urn:cspace:org.collectionspace.demo:materialauthority:name("
+            +shortId+")";
+        if(displaySuffix!=null&&!displaySuffix.isEmpty())
+            refName += "'"+displaySuffix+"'";
+        return refName;
+    }
+
+    /**
+     * Creates the material ref name.
+     *
+     * @param materialAuthRefName the materialAuthority ref name
+     * @param shortId the material shortIdentifier
+     * @param displaySuffix displayName to be appended, if non-null
+     * @return the string
+     */
+    public static String createMaterialRefName(
+                            String materialAuthRefName, String shortId, String displaySuffix) {
+        String refName = materialAuthRefName+":material:name("+shortId+")";
+        if(displaySuffix!=null&&!displaySuffix.isEmpty())
+            refName += "'"+displaySuffix+"'";
+        return refName;
+    }
+
+    public static String extractId(Response res) {
+        MultivaluedMap<String, Object> mvm = res.getMetadata();
+        String uri = (String) ((ArrayList<Object>) mvm.get("Location")).get(0);
+        if(logger.isDebugEnabled()){
+            logger.debug("extractId:uri=" + uri);
+        }
+        String[] segments = uri.split("/");
+        String id = segments[segments.length - 1];
+        if(logger.isDebugEnabled()){
+            logger.debug("id=" + id);
+        }
+        return id;
+    }
+    
+    /**
+     * Returns an error message indicating that the status code returned by a
+     * specific call to a service does not fall within a set of valid status
+     * codes for that service.
+     *
+     * @param serviceRequestType  A type of service request (e.g. CREATE, DELETE).
+     *
+     * @param statusCode  The invalid status code that was returned in the response,
+     *                    from submitting that type of request to the service.
+     *
+     * @return An error message.
+     */
+    public static String invalidStatusCodeMessage(ServiceRequestType requestType, int statusCode) {
+        return "Status code '" + statusCode + "' in response is NOT within the expected set: " +
+                requestType.validStatusCodesAsString();
+    }
+
+
+    
+    /**
+     * Produces a default displayName from one or more supplied field(s).
+     * @see MaterialAuthorityDocumentModelHandler.prepareDefaultDisplayName() which
+     * duplicates this logic, until we define a service-general utils package
+     * that is neither client nor service specific.
+     * @param materialName  
+     * @return a display name
+     */
+    public static String prepareDefaultDisplayName(
+            String materialName ) {
+        StringBuilder newStr = new StringBuilder();
+            newStr.append(materialName);
+        return newStr.toString();
+    }
+    
+    public static List<MaterialTermGroup> getTermGroupInstance(String identifier) {
+        if (Tools.isBlank(identifier)) {
+            identifier = getGeneratedIdentifier();
+        }
+        List<MaterialTermGroup> terms = new ArrayList<MaterialTermGroup>();
+        MaterialTermGroup term = new MaterialTermGroup();
+        term.setTermDisplayName(identifier);
+        term.setTermName(identifier);
+        terms.add(term);
+        return terms;
+    }
+    
+    private static String getGeneratedIdentifier() {
+        return "id" + new Date().getTime(); 
+   }
+    
+}
diff --git a/services/material/client/src/main/java/org/collectionspace/services/client/MaterialAuthorityProxy.java b/services/material/client/src/main/java/org/collectionspace/services/client/MaterialAuthorityProxy.java
new file mode 100644 (file)
index 0000000..a74b039
--- /dev/null
@@ -0,0 +1,11 @@
+package org.collectionspace.services.client;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+@Path(MaterialAuthorityClient.SERVICE_PATH + "/")
+@Produces("application/xml")
+@Consumes("application/xml")
+public interface MaterialAuthorityProxy extends AuthorityProxy {
+}
diff --git a/services/material/client/src/main/resources/collectionspace-client.properties b/services/material/client/src/main/resources/collectionspace-client.properties
new file mode 100644 (file)
index 0000000..de4600e
--- /dev/null
@@ -0,0 +1,6 @@
+#url of the collectionspace server
+cspace.url=http://localhost:8180/cspace-services/
+cspace.ssl=false
+cspace.auth=true
+cspace.user=admin@materials.collectionspace.org
+cspace.password=Administrator
diff --git a/services/material/client/src/test/java/org/collectionspace/services/client/test/MaterialAuthorityServiceTest.java b/services/material/client/src/test/java/org/collectionspace/services/client/test/MaterialAuthorityServiceTest.java
new file mode 100644 (file)
index 0000000..dac1a84
--- /dev/null
@@ -0,0 +1,513 @@
+/**
+ * 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 (c)) 2009 Regents of the University of California
+ *
+ * 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.client.test;
+
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.ws.rs.core.Response;
+
+import org.collectionspace.services.MaterialJAXBSchema;
+import org.collectionspace.services.client.AbstractCommonListUtils;
+import org.collectionspace.services.client.AuthorityClient;
+import org.collectionspace.services.client.CollectionSpaceClient;
+import org.collectionspace.services.client.PayloadOutputPart;
+import org.collectionspace.services.client.PoxPayloadIn;
+import org.collectionspace.services.client.PoxPayloadOut;
+import org.collectionspace.services.client.MaterialAuthorityClient;
+import org.collectionspace.services.client.MaterialAuthorityClientUtils;
+import org.collectionspace.services.jaxb.AbstractCommonList;
+import org.collectionspace.services.material.MaterialTermGroup;
+import org.collectionspace.services.material.MaterialTermGroupList;
+import org.collectionspace.services.material.MaterialauthoritiesCommon;
+import org.collectionspace.services.material.MaterialsCommon;
+import org.jboss.resteasy.client.ClientResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.Test;
+
+/**
+ * MaterialAuthorityServiceTest, carries out tests against a
+ * deployed and running MaterialAuthority Service.
+ *
+ */
+public class MaterialAuthorityServiceTest extends AbstractAuthorityServiceTest<MaterialauthoritiesCommon, MaterialsCommon> {
+
+    /** The logger. */
+    private final String CLASS_NAME = MaterialAuthorityServiceTest.class.getName();
+    private final Logger logger = LoggerFactory.getLogger(MaterialAuthorityServiceTest.class);
+
+    @Override
+    public String getServicePathComponent() {
+        return MaterialAuthorityClient.SERVICE_PATH_COMPONENT;
+    }
+
+    @Override
+    protected String getServiceName() {
+        return MaterialAuthorityClient.SERVICE_NAME;
+    }
+    
+    public String getItemServicePathComponent() {
+        return AuthorityClient.ITEMS;
+    }   
+    
+    // Instance variables specific to this test.
+    
+//    /** The SERVICE path component. */
+//    final String SERVICE_PATH_COMPONENT = "materialauthorities";
+//    
+//    /** The ITEM service path component. */
+//    final String ITEM_SERVICE_PATH_COMPONENT = "items";
+//    
+
+    final String TEST_MATERIAL_TERM_DISPLAY_NAME = "SuperGlass 2";
+    final String TEST_MATERIAL_TERM_NAME = "SuperGlass";
+    final String TEST_MATERIAL_TERM_STATUS = "accepted";
+    final String TEST_MATERIAL_TERM_SOURCE = "source";
+    final String TEST_MATERIAL_TERM_SOURCE_DETAIL = "internal";
+    final String TEST_MATERIAL_DESCRIPTION = "Really strong glass";
+    final String TEST_MATERIAL_SHORT_IDENTIFIER = "superglass";
+    
+    /* (non-Javadoc)
+     * @see org.collectionspace.services.client.test.BaseServiceTest#getClientInstance()
+     */
+    @Override
+    protected CollectionSpaceClient getClientInstance() {
+        return new MaterialAuthorityClient();
+    }
+
+    /**
+     * Creates the item in authority.
+     *
+     * @param vcsid the vcsid
+     * @param authRefName the auth ref name
+     * @return the string
+     */
+    private String createItemInAuthority(String vcsid, String authRefName) {
+        final String testName = "createItemInAuthority("+vcsid+","+authRefName+")"; 
+    
+        // Submit the request to the service and store the response.
+        MaterialAuthorityClient client = new MaterialAuthorityClient();
+        Map<String, String> materialMap = new HashMap<String,String>();
+        // TODO Make material type and status be controlled vocabs.
+        materialMap.put(MaterialJAXBSchema.SHORT_IDENTIFIER, TEST_MATERIAL_SHORT_IDENTIFIER);
+        materialMap.put(MaterialJAXBSchema.MATERIAL_DESCRIPTION, TEST_MATERIAL_DESCRIPTION);
+        
+        List<MaterialTermGroup> terms = new ArrayList<MaterialTermGroup>();
+        MaterialTermGroup term = new MaterialTermGroup();
+        term.setTermDisplayName(TEST_MATERIAL_TERM_DISPLAY_NAME);
+        term.setTermName(TEST_MATERIAL_TERM_NAME);
+        term.setTermSource(TEST_MATERIAL_TERM_SOURCE);
+        term.setTermSourceDetail(TEST_MATERIAL_TERM_SOURCE_DETAIL);
+        term.setTermStatus(TEST_MATERIAL_TERM_STATUS);
+        terms.add(term);
+        
+        String newID = MaterialAuthorityClientUtils.createItemInAuthority(vcsid,
+                authRefName, materialMap, terms, client );    
+
+        // Store the ID returned from the first item resource created
+        // for additional tests below.
+        if (knownItemResourceId == null){
+            setKnownItemResource(newID, TEST_MATERIAL_SHORT_IDENTIFIER);
+            if (logger.isDebugEnabled()) {
+                logger.debug(testName + ": knownItemResourceId=" + newID);
+            }
+        }
+        
+        // Store the IDs from any item resources created
+        // by tests, along with the IDs of their parents, so these items
+        // can be deleted after all tests have been run.
+        allResourceItemIdsCreated.put(newID, vcsid);
+
+        return newID;
+    }
+
+    /**
+     * Verify illegal item display name.
+     *
+     * @param testName the test name
+     * @throws Exception the exception
+     */
+    @Test(dataProvider="testName")
+       public void verifyIllegalItemDisplayName(String testName) throws Exception {
+               // Perform setup for read.
+               setupRead();
+
+               // Submit the request to the service and store the response.
+               MaterialAuthorityClient client = new MaterialAuthorityClient();
+               Response res = client.readItem(knownResourceId, knownItemResourceId);
+               MaterialsCommon material = null;
+               try {
+                       assertStatusCode(res, testName);
+                       PoxPayloadIn input = new PoxPayloadIn(res.readEntity(String.class));
+                       material = (MaterialsCommon) extractPart(input,
+                                       client.getItemCommonPartName(), MaterialsCommon.class);
+                       Assert.assertNotNull(material);
+               } finally {
+                       if (res != null) {
+                               res.close();
+                       }
+               }
+
+               //
+               // Make an invalid UPDATE request, without a display name
+               //
+               MaterialTermGroupList termList = material.getMaterialTermGroupList();
+               Assert.assertNotNull(termList);
+               List<MaterialTermGroup> terms = termList.getMaterialTermGroup();
+               Assert.assertNotNull(terms);
+               Assert.assertTrue(terms.size() > 0);
+               terms.get(0).setTermDisplayName(null);
+               terms.get(0).setTermName(null);
+
+               setupUpdateWithInvalidBody(); // we expect a failure
+
+               // Submit the updated resource to the service and store the response.
+               PoxPayloadOut output = new PoxPayloadOut(
+                               MaterialAuthorityClient.SERVICE_ITEM_PAYLOAD_NAME);
+               PayloadOutputPart commonPart = output.addPart(
+                               client.getItemCommonPartName(), material);
+               setupUpdateWithInvalidBody(); // we expected a failure here.
+               res = client.updateItem(knownResourceId, knownItemResourceId, output);
+               try {
+                       assertStatusCode(res, testName);
+               } finally {
+                       if (res != null) {
+                               res.close();
+                       }
+               }
+       }
+
+    /**
+     * Read item list.
+     */
+    @Test(dataProvider = "testName", groups = {"readList"},
+               dependsOnMethods = {"readList"})
+    public void readItemList(String testName) {
+        readItemList(knownAuthorityWithItems, null);
+    }
+
+    /**
+     * Read item list by authority name.
+     */
+    @Test(dataProvider = "testName", groups = {"readList"},
+            dependsOnMethods = {"readItemList"})
+    public void readItemListByAuthorityName(String testName) {
+        readItemList(null, READITEMS_SHORT_IDENTIFIER);
+    }
+    
+    /**
+     * Read item list.
+     * 
+     * @param vcsid
+     *            the vcsid
+     * @param name
+     *            the name
+     */
+    private void readItemList(String vcsid, String shortId) {
+        String testName = "readItemList";
+
+        // Perform setup.
+        setupReadList();
+
+        // Submit the request to the service and store the response.
+        MaterialAuthorityClient client = new MaterialAuthorityClient();
+        Response res = null;
+        if (vcsid != null) {
+            res = client.readItemList(vcsid, null, null);
+        } else if (shortId != null) {
+            res = client.readItemListForNamedAuthority(shortId, null, null);
+        } else {
+            Assert.fail("readItemList passed null csid and name!");
+        }
+        
+        AbstractCommonList list = null;
+        try {
+            assertStatusCode(res, testName);
+            list = res.readEntity(AbstractCommonList.class);
+        } finally {
+            if (res != null) {
+                res.close();
+            }
+        }
+        
+        List<AbstractCommonList.ListItem> items = list.getListItem();
+        int nItemsReturned = items.size();
+        // There will be 'nItemsToCreateInList'
+        // items created by the createItemList test,
+        // all associated with the same parent resource.
+        int nExpectedItems = nItemsToCreateInList;
+        if (logger.isDebugEnabled()) {
+            logger.debug(testName + ": Expected " + nExpectedItems
+                    + " items; got: " + nItemsReturned);
+        }
+        Assert.assertEquals(nItemsReturned, nExpectedItems);
+
+        for (AbstractCommonList.ListItem item : items) {
+            String value = AbstractCommonListUtils.ListItemGetElementValue(
+                    item, MaterialJAXBSchema.REF_NAME);
+            Assert.assertTrue((null != value), "Item refName is null!");
+            value = AbstractCommonListUtils.ListItemGetElementValue(item,
+                    MaterialJAXBSchema.MATERIAL_TERM_DISPLAY_NAME);
+            Assert.assertTrue((null != value), "Item termDisplayName is null!");
+        }
+        if (logger.isTraceEnabled()) {
+            AbstractCommonListUtils.ListItemsInAbstractCommonList(list, logger,
+                    testName);
+        }
+    }
+
+    @Override
+    public void delete(String testName) throws Exception {
+        // Do nothing.  See localDelete().  This ensure proper test order.
+    }
+    
+    @Test(dataProvider = "testName", dependsOnMethods = {"localDeleteItem"})    
+    public void localDelete(String testName) throws Exception {
+        super.delete(testName);
+    }
+
+    @Override
+    public void deleteItem(String testName) throws Exception {
+        // Do nothing.  We need to wait until after the test "localDelete" gets run.  When it does,
+        // its dependencies will get run first and then we can call the base class' delete method.
+    }
+    
+    @Test(dataProvider = "testName", groups = {"delete"},
+        dependsOnMethods = {"verifyIllegalItemDisplayName"})
+    public void localDeleteItem(String testName) throws Exception {
+        super.deleteItem(testName);
+    }
+    
+    // ---------------------------------------------------------------
+    // Cleanup of resources created during testing
+    // ---------------------------------------------------------------
+    
+    /**
+     * Deletes all resources created by tests, after all tests have been run.
+     *
+     * This cleanup method will always be run, even if one or more tests fail.
+     * For this reason, it attempts to remove all resources created
+     * at any point during testing, even if some of those resources
+     * may be expected to be deleted by certain tests.
+     */
+
+    @AfterClass(alwaysRun=true)
+    public void cleanUp() {
+        String noTest = System.getProperty("noTestCleanup");
+        if(Boolean.TRUE.toString().equalsIgnoreCase(noTest)) {
+            if (logger.isDebugEnabled()) {
+                logger.debug("Skipping Cleanup phase ...");
+            }
+            return;
+        }
+        if (logger.isDebugEnabled()) {
+            logger.debug("Cleaning up temporary resources created for testing ...");
+        }
+        String parentResourceId;
+        String itemResourceId;
+        // Clean up contact resources.
+        MaterialAuthorityClient client = new MaterialAuthorityClient();
+        parentResourceId = knownResourceId;
+        // Clean up item resources.
+        for (Map.Entry<String, String> entry : allResourceItemIdsCreated.entrySet()) {
+            itemResourceId = entry.getKey();
+            parentResourceId = entry.getValue();
+            // Note: Any non-success responses from the delete operation
+            // below are ignored and not reported.
+            client.deleteItem(parentResourceId, itemResourceId).close();
+        }
+        // Clean up parent resources.
+        for (String resourceId : allResourceIdsCreated) {
+            // Note: Any non-success responses from the delete operation
+            // below are ignored and not reported.
+        client.delete(resourceId).close();
+        }
+    }
+
+    // ---------------------------------------------------------------
+    // Utility methods used by tests above
+    // ---------------------------------------------------------------
+    /* (non-Javadoc)
+     * @see org.collectionspace.services.client.test.BaseServiceTest#getServicePathComponent()
+     */
+
+    /**
+     * Returns the root URL for the item service.
+     *
+     * This URL consists of a base URL for all services, followed by
+     * a path component for the owning parent, followed by the
+     * path component for the items.
+     *
+     * @param  parentResourceIdentifier  An identifier (such as a UUID) for the
+     * parent authority resource of the relevant item resource.
+     *
+     * @return The root URL for the item service.
+     */
+    protected String getItemServiceRootURL(String parentResourceIdentifier) {
+        return getResourceURL(parentResourceIdentifier) + "/" + getItemServicePathComponent();
+    }
+
+    /**
+     * Returns the URL of a specific item resource managed by a service, and
+     * designated by an identifier (such as a universally unique ID, or UUID).
+     *
+     * @param  parentResourceIdentifier  An identifier (such as a UUID) for the
+     * parent authority resource of the relevant item resource.
+     *
+     * @param  itemResourceIdentifier  An identifier (such as a UUID) for an
+     * item resource.
+     *
+     * @return The URL of a specific item resource managed by a service.
+     */
+    protected String getItemResourceURL(String parentResourceIdentifier, String itemResourceIdentifier) {
+        return getItemServiceRootURL(parentResourceIdentifier) + "/" + itemResourceIdentifier;
+    }
+
+        @Override
+    public void authorityTests(String testName) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    //
+    // Material specific overrides
+    //
+    
+    @Override
+    protected PoxPayloadOut createInstance(String commonPartName,
+            String identifier) {
+        // Submit the request to the service and store the response.
+        String shortId = identifier;
+        String displayName = "displayName-" + shortId;
+        // String baseRefName = MaterialAuthorityClientUtils.createMaterialAuthRefName(shortId, null);      
+        PoxPayloadOut result = 
+            MaterialAuthorityClientUtils.createMaterialAuthorityInstance(
+            displayName, shortId, commonPartName);
+        return result;
+    }
+    
+    @Override
+    protected PoxPayloadOut createNonExistenceInstance(String commonPartName, String identifier) {
+        String displayName = "displayName-NON_EXISTENT_ID";
+        PoxPayloadOut result = MaterialAuthorityClientUtils.createMaterialAuthorityInstance(
+                    displayName, "nonEx", commonPartName);
+        return result;
+    }
+
+    @Override
+    protected MaterialauthoritiesCommon updateInstance(MaterialauthoritiesCommon materialauthoritiesCommon) {
+        MaterialauthoritiesCommon result = new MaterialauthoritiesCommon();
+        
+        result.setDisplayName("updated-" + materialauthoritiesCommon.getDisplayName());
+        result.setVocabType("updated-" + materialauthoritiesCommon.getVocabType());
+        
+        return result;
+    }
+
+    @Override
+    protected void compareUpdatedInstances(MaterialauthoritiesCommon original,
+            MaterialauthoritiesCommon updated) throws Exception {
+        Assert.assertEquals(updated.getDisplayName(),
+                original.getDisplayName(),
+                "Display name in updated object did not match submitted data.");
+    }
+
+    protected void compareReadInstances(MaterialauthoritiesCommon original,
+            MaterialauthoritiesCommon fromRead) throws Exception {
+        Assert.assertNotNull(fromRead.getDisplayName());
+        Assert.assertNotNull(fromRead.getShortIdentifier());
+        Assert.assertNotNull(fromRead.getRefName());
+    }
+    
+    //
+    // Authority item specific overrides
+    //
+    
+    @Override
+    protected String createItemInAuthority(String authorityId) {
+        return createItemInAuthority(authorityId, null /*refname*/);
+    }
+
+    @Override
+    protected MaterialsCommon updateItemInstance(MaterialsCommon materialsCommon) {
+                            
+            MaterialTermGroupList termList = materialsCommon.getMaterialTermGroupList();
+            Assert.assertNotNull(termList);
+            List<MaterialTermGroup> terms = termList.getMaterialTermGroup();
+            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());
+            materialsCommon.setMaterialTermGroupList(termList);
+
+            return materialsCommon;
+    }
+
+    @Override
+    protected void compareUpdatedItemInstances(MaterialsCommon original,
+            MaterialsCommon updated) throws Exception {
+            
+            MaterialTermGroupList originalTermList = original.getMaterialTermGroupList();
+            Assert.assertNotNull(originalTermList);
+            List<MaterialTermGroup> originalTerms = originalTermList.getMaterialTermGroup();
+            Assert.assertNotNull(originalTerms);
+            Assert.assertTrue(originalTerms.size() > 0);
+            
+            MaterialTermGroupList updatedTermList = updated.getMaterialTermGroupList();
+            Assert.assertNotNull(updatedTermList);
+            List<MaterialTermGroup> updatedTerms = updatedTermList.getMaterialTermGroup();
+            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
+    protected void verifyReadItemInstance(MaterialsCommon item)
+            throws Exception {
+        // TODO Auto-generated method stub
+        
+    }
+
+    @Override
+    protected PoxPayloadOut createNonExistenceItemInstance(
+            String commonPartName, String identifier) {
+        Map<String, String> nonexMap = new HashMap<String,String>();
+        nonexMap.put(MaterialJAXBSchema.MATERIAL_TERM_DISPLAY_NAME, TEST_MATERIAL_TERM_DISPLAY_NAME);
+        nonexMap.put(MaterialJAXBSchema.SHORT_IDENTIFIER, "nonEx");
+        nonexMap.put(MaterialJAXBSchema.MATERIAL_TERM_STATUS, TEST_MATERIAL_TERM_STATUS);
+        final String EMPTY_REFNAME = "";
+        PoxPayloadOut result = 
+                MaterialAuthorityClientUtils.createMaterialInstance(EMPTY_REFNAME, nonexMap,
+                MaterialAuthorityClientUtils.getTermGroupInstance(TEST_MATERIAL_TERM_DISPLAY_NAME), commonPartName);
+        return result;
+    }
+}
diff --git a/services/material/client/src/test/resources/log4j.properties b/services/material/client/src/test/resources/log4j.properties
new file mode 100644 (file)
index 0000000..148a3e8
--- /dev/null
@@ -0,0 +1,23 @@
+log4j.rootLogger=debug, stdout, R
+
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+
+# Pattern to output the caller's file name and line number.
+log4j.appender.stdout.layout.ConversionPattern=%d %-5p [%t] [%c:%L] %m%n
+
+log4j.appender.R=org.apache.log4j.RollingFileAppender
+log4j.appender.R.File=target/test-client.log
+
+log4j.appender.R.MaxFileSize=100KB
+# Keep one backup file
+log4j.appender.R.MaxBackupIndex=1
+
+log4j.appender.R.layout=org.apache.log4j.PatternLayout
+log4j.appender.R.layout.ConversionPattern=%d %-5p [%t] [%c:%L] %m%n
+
+#packages
+log4j.logger.org.collectionspace=DEBUG
+log4j.logger.org.apache=INFO
+log4j.logger.httpclient=INFO
+log4j.logger.org.jboss.resteasy=INFO
diff --git a/services/material/installer/build.xml b/services/material/installer/build.xml
new file mode 100644 (file)
index 0000000..369c653
--- /dev/null
@@ -0,0 +1,61 @@
+
+<project name="material" default="package" basedir=".">
+    <description>
+        material service
+    </description>
+  <!-- set global properties for this build -->
+    <property name="services.trunk" value="../.."/>
+    <property file="${services.trunk}/build.properties" />
+    <property name="mvn.opts" value="-V" />
+    <property name="src" location="src"/>
+
+    <condition property="osfamily-unix">
+        <os family="unix" />
+    </condition>
+    <condition property="osfamily-windows">
+        <os family="windows" />
+    </condition>
+    
+    <target name="install" description="">
+        <exec executable="echo">
+                <arg value="Installer: Executing material Service's &apos;install&apos; target." />
+                </exec>
+                <!-- Copy the Nuxeo DocType jar files to the Nuxeo app server domain -->
+        <copy todir="${jee.deploy.nuxeo.plugins}">
+            <fileset file="nuxeo/*.jar"/>
+        </copy>             
+    </target>    
+
+    <target name="config" description="" depends="install">
+        <exec executable="echo">
+                <arg value="Installer: Executing Material Service's &apos;config&apos; target." />
+                </exec>
+    </target>
+    
+    <target name="predeploy" description="" depends="config">
+        <exec executable="echo">
+                <arg value="Installer: Executing Material Service's &apos;predeploy&apos; target." />
+                </exec>
+    </target>    
+    
+    <target name="deploy" description="">
+        <exec executable="echo">
+                <arg value="Installer: Executing Material Service's &apos;deploy&apos; target." />
+                </exec>
+    </target>
+    
+    <target name="postdeploy">
+        <exec executable="echo">
+                <arg value="Installer: Executing installer's &apos;postdeploy&apos; target for the Material Service." />
+                </exec>     
+        <exec executable="echo">
+                <arg value="Importing necessary materialauthorities." />
+                </exec>             
+        <java jar="./postdeploy/collectionspace-services-material-importer-jar-with-dependencies.jar"
+            fork="true"
+            failonerror="true">
+                </java> 
+    </target>
+    
+
+</project>
diff --git a/services/material/jaxb/pom.xml b/services/material/jaxb/pom.xml
new file mode 100644 (file)
index 0000000..f6904ea
--- /dev/null
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <groupId>org.collectionspace.services</groupId>
+        <artifactId>org.collectionspace.services.material</artifactId>
+        <version>4.4-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>org.collectionspace.services.material.jaxb</artifactId>
+    <name>services.material.jaxb</name>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.collectionspace.services</groupId>
+            <artifactId>org.collectionspace.services.common</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.sun.xml.bind</groupId>
+            <artifactId>jaxb-impl</artifactId>
+        </dependency>
+                <!--
+        <dependency>
+            <groupId>org.jvnet.jaxb2-commons</groupId>
+            <artifactId>property-listener-injector</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jvnet.jaxb2_commons</groupId>
+            <artifactId>runtime</artifactId>
+                </dependency>
+                -->
+        <dependency>
+            <groupId>org.collectionspace.services</groupId>
+            <artifactId>org.collectionspace.services.jaxb</artifactId>
+            <version>${project.version}</version>
+        </dependency>  
+        <dependency>
+            <groupId>org.collectionspace.services</groupId>
+            <artifactId>org.collectionspace.services.authority.jaxb</artifactId>
+            <optional>true</optional>
+            <version>${project.version}</version>
+        </dependency>   
+    </dependencies>
+
+    <build>
+        <finalName>collectionspace-services-material-jaxb</finalName>
+        <defaultGoal>install</defaultGoal>
+        <plugins>
+            <plugin>
+                <groupId>org.jvnet.jaxb2.maven2</groupId>
+                <artifactId>maven-jaxb2-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+</project>
+
diff --git a/services/material/jaxb/src/main/java/org/collectionspace/services/MaterialJAXBSchema.java b/services/material/jaxb/src/main/java/org/collectionspace/services/MaterialJAXBSchema.java
new file mode 100644 (file)
index 0000000..3790f9d
--- /dev/null
@@ -0,0 +1,29 @@
+/**
+ * 
+ */
+package org.collectionspace.services;
+import org.collectionspace.services.common.vocabulary.AuthorityItemJAXBSchema;
+
+public interface MaterialJAXBSchema extends AuthorityItemJAXBSchema {
+    final static String MATERIALS_COMMON = "materials_common";
+
+    final static String MATERIAL_DESCRIPTION = "description";
+
+    final static String MATERIAL_TERM_GROUP_LIST = "materialTermGroupList";
+    final static String MATERIAL_TERM_DISPLAY_NAME = "termDisplayName";
+    final static String MATERIAL_TERM_NAME = "termName";
+    final static String MATERIAL_TERM_TYPE = "termType";
+    final static String MATERIAL_TERM_STATUS = "termStatus";
+    final static String MATERIAL_TERM_QUALIFIER = "termQualifier";
+    final static String MATERIAL_TERM_LANGUAGE = "termLanguage";
+    final static String MATERIAL_TERM_PREFFORLANGUAGE = "termPrefForLang";
+    final static String MATERIAL_TERM_SOURCE = "termSource";
+    final static String MATERIAL_TERM_SOURCE_DETAIL = "termSourceDetail";
+    final static String MATERIAL_TERM_SOURCE_ID = "termSourceID";
+    final static String MATERIAL_TERM_SOURCE_NOTE = "termSourceNote";
+
+    final static String MATERIAL_SHORT_IDENTIFIER = "shortIdentifier";
+    final static String MATERIAL_REFNAME = "refName";
+    final static String MATERIAL_INAUTHORITY = "inAuthority";
+}
+
diff --git a/services/material/jaxb/src/main/resources/material_common.xsd b/services/material/jaxb/src/main/resources/material_common.xsd
new file mode 100644 (file)
index 0000000..c462941
--- /dev/null
@@ -0,0 +1,471 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<xs:schema 
+    xmlns:xs="http://www.w3.org/2001/XMLSchema"
+    xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
+    jaxb:version="1.0" elementFormDefault="unqualified"
+    xmlns:ns="http://collectionspace.org/services/material"
+    xmlns="http://collectionspace.org/services/material"
+    targetNamespace="http://collectionspace.org/services/material"
+    version="0.1"
+    >
+
+    <!-- avoid XmlRootElement nightmare, see http://weblogs.java.net/blog/kohsuke/archive/2006/03/why_does_jaxb_p.html-->
+
+    <!-- Material -->
+    <xs:element name="materials_common">
+        <xs:complexType>
+            <xs:sequence>
+                <!--  Common identifier -->
+                <xs:element name="csid" type="xs:string" />
+
+                <!--  Common Authority Information Group -->
+                <!--  inAuthority is the csid of the owning MaterialAuthority -->
+                <xs:element name="inAuthority" type="xs:string"/>
+                <xs:element name="shortIdentifier" type="xs:string"/>
+                <xs:element name="refName" type="xs:string"/>
+
+                <!-- List of materialTerms -->
+                <xs:element name="materialTermGroupList" type="materialTermGroupList"/>
+
+                <xs:element name="familyName" type="xs:string"/>
+                <xs:element name="className" type="xs:string"/>
+                <xs:element name="genericName" type="xs:string"/>
+
+                <xs:element name="description" type="xs:string"/>
+                
+                <xs:element name="typicalUses" type="typicalUseList"/>
+                
+                <xs:element name="materialProductionOrganizationGroupList" type="materialProductionOrganizationGroupList"/>
+                <xs:element name="materialProductionPersonGroupList" type="materialProductionPersonGroupList"/>
+                <xs:element name="materialProductionPlaceGroupList" type="materialProductionPlaceGroupList"/>
+                <xs:element name="featuredApplicationGroupList" type="featuredApplicationGroupList"/>
+                <xs:element name="materialCitationGroupList" type="materialCitationGroupList"/>
+                <xs:element name="externalUrlGroupList" type="externalUrlGroupList"/>
+                <xs:element name="additionalResourceGroupList" type="additionalResourceGroupList"/>
+                
+                <xs:element name="commonForm" type="xs:string"/>
+                <xs:element name="formTypeGroupList" type="formTypeGroupList"/>
+                <xs:element name="typicalSizeGroupList" type="typicalSizeGroupList"/>
+                <xs:element name="formNote" type="xs:string"/>
+                <xs:element name="acousticalPropertyGroupList" type="acousticalPropertyGroupList"/>
+                <xs:element name="durabilityPropertyGroupList" type="durabilityPropertyGroupList"/>
+                <xs:element name="electricalPropertyGroupList" type="electricalPropertyGroupList"/>
+                <xs:element name="mechanicalPropertyGroupList" type="mechanicalPropertyGroupList"/>
+                <xs:element name="hygrothermalPropertyGroupList" type="hygrothermalPropertyGroupList"/>
+                <xs:element name="opticalPropertyGroupList" type="opticalPropertyGroupList"/>
+                <xs:element name="sensorialPropertyGroupList" type="sensorialPropertyGroupList"/>
+                <xs:element name="smartMaterialPropertyGroupList" type="smartMaterialPropertyGroupList"/>
+                <xs:element name="additionalPropertyGroupList" type="additionalPropertyGroupList"/>
+                <xs:element name="propertyNote" type="xs:string"/>
+                
+                <xs:element name="recycledContentGroupList" type="recycledContentGroupList"/>
+                <xs:element name="lifecycleComponentGroupList" type="lifecycleComponentGroupList"/>
+                <xs:element name="embodiedEnergyGroupList" type="embodiedEnergyGroupList"/>
+                <xs:element name="certificationCreditGroupList" type="certificationCreditGroupList"/>
+                <xs:element name="ecologyNote" type="xs:string"/>
+
+                <xs:element name="castingProcesses" type="castingProcessList"/>
+                <xs:element name="deformingProcesses" type="deformingProcessList"/>
+                <xs:element name="joiningProcesses" type="joiningProcessList"/>
+                <xs:element name="machiningProcesses" type="machiningProcessList"/>
+                <xs:element name="moldingProcesses" type="moldingProcessList"/>
+                <xs:element name="rapidPrototypingProcesses" type="rapidPrototypingProcessList"/>
+                <xs:element name="surfacingProcesses" type="surfacingProcessList"/>
+                <xs:element name="additionalProcessGroupList" type="additionalProcessGroupList"/>
+                <xs:element name="processNote" type="xs:string"/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:complexType name="materialTermGroupList">
+        <xs:sequence>
+            <xs:element name="materialTermGroup" type="materialTermGroup" minOccurs="0"
+                        maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+
+    <xs:complexType name="materialTermGroup">
+        <xs:sequence>
+            <xs:element name="termDisplayName" type="xs:string"/>
+            <xs:element name="termFormattedDisplayName" 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"/>
+            <xs:element name="historicalStatus" type="xs:string"/>
+        </xs:sequence>
+    </xs:complexType>
+
+    <xs:complexType name="typicalUseList">
+        <xs:sequence>
+            <xs:element name="typicalUse" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="materialProductionOrganizationGroupList">
+        <xs:sequence>
+            <xs:element name="materialProductionOrganizationGroup" type="materialProductionOrganizationGroup" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="materialProductionOrganizationGroup">
+        <xs:sequence>
+            <xs:element name="materialProductionOrganization" type="xs:string"/>
+            <xs:element name="materialProductionOrganizationRole" type="xs:string"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="materialProductionPersonGroupList">
+        <xs:sequence>
+            <xs:element name="materialProductionPersonGroup" type="materialProductionPersonGroup" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="materialProductionPersonGroup">
+        <xs:sequence>
+            <xs:element name="materialProductionPerson" type="xs:string"/>
+            <xs:element name="materialProductionPersonRole" type="xs:string"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="materialProductionPlaceGroupList">
+        <xs:sequence>
+            <xs:element name="materialProductionPlaceGroup" type="materialProductionPlaceGroup" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="materialProductionPlaceGroup">
+        <xs:sequence>
+            <xs:element name="materialProductionPlace" type="xs:string"/>
+            <xs:element name="materialProductionPlaceRole" type="xs:string"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="featuredApplicationGroupList">
+        <xs:sequence>
+            <xs:element name="featuredApplicationGroup" type="featuredApplicationGroup" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="featuredApplicationGroup">
+        <xs:sequence>
+            <xs:element name="featuredApplication" type="xs:string"/>
+            <xs:element name="featuredApplicationNote" type="xs:string"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="materialCitationGroupList">
+        <xs:sequence>
+            <xs:element name="materialCitationGroup" type="materialCitationGroup" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="materialCitationGroup">
+        <xs:sequence>
+            <xs:element name="materialCitationSource" type="xs:string"/>
+            <xs:element name="materialCitationSourceDetail" type="xs:string"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="externalUrlGroupList">
+        <xs:sequence>
+            <xs:element name="externalUrlGroup" type="externalUrlGroup" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="externalUrlGroup">
+        <xs:sequence>
+            <xs:element name="externalUrl" type="xs:string"/>
+            <xs:element name="externalUrlNote" type="xs:string"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="additionalResourceGroupList">
+        <xs:sequence>
+            <xs:element name="additionalResourceGroup" type="additionalResourceGroup" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="additionalResourceGroup">
+        <xs:sequence>
+            <xs:element name="additionalResource" type="xs:string"/>
+            <xs:element name="additionalResourceNote" type="xs:string"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="formTypeGroupList">
+        <xs:sequence>
+            <xs:element name="formTypeGroup" type="formTypeGroup" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="formTypeGroup">
+        <xs:sequence>
+            <xs:element name="formType" type="xs:string"/>
+            <xs:element name="formSubtype" type="xs:string"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="typicalSizeGroupList">
+        <xs:sequence>
+            <xs:element name="typicalSizeGroup" type="typicalSizeGroup" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="typicalSizeGroup">
+        <xs:sequence>
+            <xs:element name="typicalSize" type="xs:string"/>
+            <xs:element name="typicalSizeDimensionGroupList" type="typicalSizeDimensionGroupList"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="typicalSizeDimensionGroupList">
+        <xs:sequence>
+            <xs:element name="typicalSizeDimensionGroup" type="typicalSizeDimensionGroup" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="typicalSizeDimensionGroup">
+        <xs:sequence>
+            <xs:element name="dimension" type="xs:string"/>
+            <xs:element name="measurementUnit" type="xs:string"/>
+            <xs:element name="value" type="xs:decimal"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="acousticalPropertyGroupList">
+        <xs:sequence>
+            <xs:element name="acousticalPropertyGroup" type="acousticalPropertyGroup" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="acousticalPropertyGroup">
+        <xs:sequence>
+            <xs:element name="acousticalPropertyType" type="xs:string"/>
+            <xs:element name="acousticalPropertyNote" type="xs:string"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="durabilityPropertyGroupList">
+        <xs:sequence>
+            <xs:element name="durabilityPropertyGroup" type="durabilityPropertyGroup" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="durabilityPropertyGroup">
+        <xs:sequence>
+            <xs:element name="durabilityPropertyType" type="xs:string"/>
+            <xs:element name="durabilityPropertyNote" type="xs:string"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="electricalPropertyGroupList">
+        <xs:sequence>
+            <xs:element name="electricalPropertyGroup" type="electricalPropertyGroup" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="electricalPropertyGroup">
+        <xs:sequence>
+            <xs:element name="electricalPropertyType" type="xs:string"/>
+            <xs:element name="electricalPropertyNote" type="xs:string"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="mechanicalPropertyGroupList">
+        <xs:sequence>
+            <xs:element name="mechanicalPropertyGroup" type="mechanicalPropertyGroup" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="mechanicalPropertyGroup">
+        <xs:sequence>
+            <xs:element name="mechanicalPropertyType" type="xs:string"/>
+            <xs:element name="mechanicalPropertyUnit" type="xs:string"/>
+            <xs:element name="mechanicalPropertyValue" type="xs:decimal"/>
+            <xs:element name="mechanicalPropertyNote" type="xs:string"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="hygrothermalPropertyGroupList">
+        <xs:sequence>
+            <xs:element name="hygrothermalPropertyGroup" type="hygrothermalPropertyGroup" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="hygrothermalPropertyGroup">
+        <xs:sequence>
+            <xs:element name="hygrothermalPropertyType" type="xs:string"/>
+            <xs:element name="hygrothermalPropertyUnit" type="xs:string"/>
+            <xs:element name="hygrothermalPropertyValue" type="xs:decimal"/>
+            <xs:element name="hygrothermalPropertyNote" type="xs:string"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="opticalPropertyGroupList">
+        <xs:sequence>
+            <xs:element name="opticalPropertyGroup" type="opticalPropertyGroup" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="opticalPropertyGroup">
+        <xs:sequence>
+            <xs:element name="opticalPropertyType" type="xs:string"/>
+            <xs:element name="opticalPropertyNote" type="xs:string"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="sensorialPropertyGroupList">
+        <xs:sequence>
+            <xs:element name="sensorialPropertyGroup" type="sensorialPropertyGroup" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="sensorialPropertyGroup">
+        <xs:sequence>
+            <xs:element name="sensorialPropertyType" type="xs:string"/>
+            <xs:element name="sensorialPropertyNote" type="xs:string"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="smartMaterialPropertyGroupList">
+        <xs:sequence>
+            <xs:element name="smartMaterialPropertyGroup" type="smartMaterialPropertyGroup" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="smartMaterialPropertyGroup">
+        <xs:sequence>
+            <xs:element name="smartMaterialPropertyType" type="xs:string"/>
+            <xs:element name="smartMaterialPropertyNote" type="xs:string"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="additionalPropertyGroupList">
+        <xs:sequence>
+            <xs:element name="additionalPropertyGroup" type="additionalPropertyGroup" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="additionalPropertyGroup">
+        <xs:sequence>
+            <xs:element name="additionalPropertyType" type="xs:string"/>
+            <xs:element name="additionalPropertyNote" type="xs:string"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="recycledContentGroupList">
+        <xs:sequence>
+            <xs:element name="recycledContentGroup" type="recycledContentGroup" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="recycledContentGroup">
+        <xs:sequence>
+            <xs:element name="recycledContent" type="xs:decimal"/>
+            <xs:element name="recycledContentQualifier" type="xs:string"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="lifecycleComponentGroupList">
+        <xs:sequence>
+            <xs:element name="lifecycleComponentGroup" type="lifecycleComponentGroup" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="lifecycleComponentGroup">
+        <xs:sequence>
+            <xs:element name="lifecycleComponent" type="xs:string"/>
+            <xs:element name="lifecycleComponentNote" type="xs:string"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="embodiedEnergyGroupList">
+        <xs:sequence>
+            <xs:element name="embodiedEnergyGroup" type="embodiedEnergyGroup" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="embodiedEnergyGroup">
+        <xs:sequence>
+            <xs:element name="embodiedEnergyValue" type="xs:decimal"/>
+            <xs:element name="embodiedEnergyUnit" type="xs:string"/>
+            <xs:element name="embodiedEnergyNote" type="xs:string"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="certificationCreditGroupList">
+        <xs:sequence>
+            <xs:element name="certificationCreditGroup" type="certificationCreditGroup" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="certificationCreditGroup">
+        <xs:sequence>
+            <xs:element name="certificationProgram" type="xs:string"/>
+            <xs:element name="certificationCreditNote" type="xs:string"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="castingProcessList">
+        <xs:sequence>
+            <xs:element name="castingProcess" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="deformingProcessList">
+        <xs:sequence>
+            <xs:element name="deformingProcess" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="joiningProcessList">
+        <xs:sequence>
+            <xs:element name="joiningProcess" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="machiningProcessList">
+        <xs:sequence>
+            <xs:element name="machiningProcess" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="moldingProcessList">
+        <xs:sequence>
+            <xs:element name="moldingProcess" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="rapidPrototypingProcessList">
+        <xs:sequence>
+            <xs:element name="rapidPrototypingProcess" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="surfacingProcessList">
+        <xs:sequence>
+            <xs:element name="surfacingProcess" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="additionalProcessGroupList">
+        <xs:sequence>
+            <xs:element name="additionalProcessGroup" type="additionalProcessGroup" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+    <xs:complexType name="additionalProcessGroup">
+        <xs:sequence>
+            <xs:element name="additionalProcess" type="xs:string"/>
+            <xs:element name="additionalProcessNote" type="xs:string"/>
+        </xs:sequence>
+    </xs:complexType>
+    
+</xs:schema>
\ No newline at end of file
diff --git a/services/material/jaxb/src/main/resources/materialauthority_common.xsd b/services/material/jaxb/src/main/resources/materialauthority_common.xsd
new file mode 100644 (file)
index 0000000..3746b5c
--- /dev/null
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+
+<!--
+    MaterialAuthority schema (XSD)
+    
+    Entity  : MaterialAuthority
+    Part    : Common
+    Used for: JAXB binding between XML and Java objects
+    
+-->
+
+<xs:schema 
+    xmlns:xs="http://www.w3.org/2001/XMLSchema"
+    xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
+    jaxb:version="1.0" elementFormDefault="unqualified"
+    xmlns:ns="http://collectionspace.org/services/material"
+    xmlns="http://collectionspace.org/services/material"
+    targetNamespace="http://collectionspace.org/services/material"
+    version="0.1"
+    >
+    
+    <!--
+        Avoid XmlRootElement nightmare:
+        See http://weblogs.java.net/blog/kohsuke/archive/2006/03/why_does_jaxb_p.html
+    -->
+    <!-- See http://wiki.collectionspace.org/display/collectionspace/Material+Service+Home -->    
+    
+    <!-- MaterialAuthority  -->
+    <xs:element name="materialauthorities_common">
+        <xs:complexType>
+            <xs:sequence>
+                <!--  Common identifier -->
+                <xs:element name="csid" type="xs:string" />
+                
+                <!--  MaterialAuthority Information Group -->
+                <xs:element name="displayName" type="xs:string"/>
+                <xs:element name="shortIdentifier" type="xs:string"/>
+                <xs:element name="refName" type="xs:string"/>
+                <xs:element name="vocabType" type="xs:string"/>
+                <xs:element name="source" type="xs:string"/>
+                <xs:element name="description" type="xs:string"/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+    
+</xs:schema>
+
diff --git a/services/material/pom.xml b/services/material/pom.xml
new file mode 100644 (file)
index 0000000..bac43bb
--- /dev/null
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <groupId>org.collectionspace.services</groupId>
+        <artifactId>org.collectionspace.services.main</artifactId>
+        <version>4.4-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.collectionspace.services</groupId>
+    <artifactId>org.collectionspace.services.material</artifactId>
+    <name>services.material</name>
+    <packaging>pom</packaging>
+
+    <dependencies>
+      <!--  <dependency>
+            <groupId>org.collectionspace.services</groupId>
+            <artifactId>org.collectionspace.services.authority.service</artifactId>
+            <optional>true</optional>
+            <version>${project.version}</version>
+        </dependency>-->
+    </dependencies>
+
+    <modules>
+        <module>jaxb</module>
+        <module>service</module>
+        <module>3rdparty</module>
+        <module>client</module>
+    </modules>
+    
+    <profiles>
+        <profile>
+            <id>samples</id>
+        <modules>
+            <!-- <module>sample</module> -->
+        </modules>
+        </profile>
+    </profiles>
+    
+</project>
+
diff --git a/services/material/service/pom.xml b/services/material/service/pom.xml
new file mode 100644 (file)
index 0000000..8ac3536
--- /dev/null
@@ -0,0 +1,142 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <groupId>org.collectionspace.services</groupId>
+        <artifactId>org.collectionspace.services.material</artifactId>
+        <version>4.4-SNAPSHOT</version>
+    </parent>
+    
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>org.collectionspace.services.material.service</artifactId>
+    <name>services.material.service</name>
+    <packaging>jar</packaging>
+    
+    <dependencies>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-log4j12</artifactId>
+        </dependency>
+<!-- CollectionSpace dependencies -->        
+        <dependency>
+            <groupId>org.collectionspace.services</groupId>
+            <artifactId>org.collectionspace.services.common</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.collectionspace.services</groupId>
+            <artifactId>org.collectionspace.services.material.jaxb</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.collectionspace.services</groupId>
+            <artifactId>org.collectionspace.services.material.client</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.collectionspace.services</groupId>
+            <artifactId>org.collectionspace.services.authority.service</artifactId>
+            <optional>true</optional>
+            <version>${project.version}</version>
+        </dependency>
+        <!-- External dependencies -->        
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.testng</groupId>
+            <artifactId>testng</artifactId>
+        </dependency>
+        
+        <!-- apache -->
+        <dependency>
+            <groupId>commons-beanutils</groupId>
+            <artifactId>commons-beanutils</artifactId>
+            <version>1.6.1</version>
+        </dependency>
+        <!-- use explict 1.1 version to prevent errors coming from Nuxeo client -->
+        <dependency>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+            <version>1.1</version>
+        </dependency>
+      <!-- javax -->
+
+
+        <dependency>
+            <groupId>javax.security</groupId>
+            <artifactId>jaas</artifactId>
+            <version>1.0.01</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>dom4j</groupId>
+            <artifactId>dom4j</artifactId>
+            <version>1.6.1</version>
+            <scope>provided</scope>
+        </dependency>
+        
+        <!-- jboss -->
+
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jaxrs</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>tjws</groupId>
+                    <artifactId>webserver</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jaxb-provider</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-multipart-provider</artifactId>
+        </dependency>
+        
+        <!-- nuxeo -->
+
+        <dependency>
+            <groupId>org.nuxeo.ecm.core</groupId>
+            <artifactId>nuxeo-core-api</artifactId>
+            <exclusions>
+                <exclusion>
+                    <artifactId>jboss-remoting</artifactId>
+                    <groupId>jboss</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>org.restlet</groupId>
+            <artifactId>org.restlet</artifactId>
+            <version>1.0.7</version>
+        </dependency>
+        <dependency>
+            <groupId>com.noelios.restlet</groupId>
+            <artifactId>com.noelios.restlet.ext.httpclient</artifactId>
+            <version>1.0.7</version>
+        </dependency>
+        <dependency>
+            <groupId>com.noelios.restlet</groupId>
+            <artifactId>com.noelios.restlet</artifactId>
+            <version>1.0.7</version>
+        </dependency>
+
+    </dependencies>
+    
+    <build>
+        <finalName>collectionspace-services-material</finalName>
+        <plugins>
+        </plugins>
+    </build>
+</project>
+
diff --git a/services/material/service/src/main/java/org/collectionspace/services/material/MaterialAuthorityResource.java b/services/material/service/src/main/java/org/collectionspace/services/material/MaterialAuthorityResource.java
new file mode 100644 (file)
index 0000000..4b05fea
--- /dev/null
@@ -0,0 +1,69 @@
+/**
+ * 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.material;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import org.collectionspace.services.client.MaterialAuthorityClient;
+import org.collectionspace.services.common.vocabulary.AuthorityResource;
+import org.collectionspace.services.material.nuxeo.MaterialDocumentModelHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * MaterialAuthorityResource
+ * 
+ * Handles, dispatches, and returns responses to RESTful requests
+ * related to Material authority-related resources.
+ */
+
+@Path(MaterialAuthorityClient.SERVICE_PATH)
+@Consumes("application/xml")
+@Produces("application/xml")
+public class MaterialAuthorityResource
+        extends AuthorityResource<MaterialauthoritiesCommon, MaterialDocumentModelHandler> {
+
+    final Logger logger = LoggerFactory.getLogger(MaterialAuthorityResource.class);
+
+    public MaterialAuthorityResource() {
+        super(MaterialauthoritiesCommon.class, MaterialAuthorityResource.class,
+                MaterialAuthorityClient.SERVICE_COMMON_PART_NAME, MaterialAuthorityClient.SERVICE_ITEM_COMMON_PART_NAME);
+    }
+
+    @Override
+    public String getServiceName() {
+        return MaterialAuthorityClient.SERVICE_NAME;
+    }
+
+    @Override
+    public String getItemServiceName() {
+        return MaterialAuthorityClient.SERVICE_ITEM_NAME;
+    }
+
+    @Override
+    public String getItemTermInfoGroupXPathBase() {
+        return MaterialAuthorityClient.TERM_INFO_GROUP_XPATH_BASE;
+    }
+
+}
diff --git a/services/material/service/src/main/java/org/collectionspace/services/material/nuxeo/MaterialAuthorityConstants.java b/services/material/service/src/main/java/org/collectionspace/services/material/nuxeo/MaterialAuthorityConstants.java
new file mode 100644 (file)
index 0000000..17c5e68
--- /dev/null
@@ -0,0 +1,35 @@
+/**
+ *  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.material.nuxeo;
+
+/**
+ * Constants for the Material Authority service
+ *
+ */
+public class MaterialAuthorityConstants {
+
+    public final static String NUXEO_DOCTYPE = "MaterialAuthority";
+    public final static String NUXEO_SCHEMA_NAME = "materialauthority";
+    public final static String NUXEO_DC_TITLE = "CollectionSpace-MaterialAuthority";
+}
diff --git a/services/material/service/src/main/java/org/collectionspace/services/material/nuxeo/MaterialAuthorityDocumentModelHandler.java b/services/material/service/src/main/java/org/collectionspace/services/material/nuxeo/MaterialAuthorityDocumentModelHandler.java
new file mode 100644 (file)
index 0000000..dd50b22
--- /dev/null
@@ -0,0 +1,55 @@
+/**
+ *  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.material.nuxeo;
+
+import org.collectionspace.services.common.vocabulary.nuxeo.AuthorityDocumentModelHandler;
+import org.collectionspace.services.material.MaterialauthoritiesCommon;
+
+/**
+ * MaterialAuthorityDocumentModelHandler
+ *
+ */
+public class MaterialAuthorityDocumentModelHandler
+        extends AuthorityDocumentModelHandler<MaterialauthoritiesCommon> {
+
+    /**
+     * Common part schema label
+     */
+    private static final String COMMON_PART_LABEL = "materialauthorities_common";   
+    
+    public MaterialAuthorityDocumentModelHandler() {
+        super(COMMON_PART_LABEL);
+    }
+    
+    /**
+     * getQProperty converts the given property to qualified schema property
+     * @param prop
+     * @return
+     */
+    @Override
+    public String getQProperty(String prop) {
+        return MaterialAuthorityConstants.NUXEO_SCHEMA_NAME + ":" + prop;
+    }
+}
+
diff --git a/services/material/service/src/main/java/org/collectionspace/services/material/nuxeo/MaterialConstants.java b/services/material/service/src/main/java/org/collectionspace/services/material/nuxeo/MaterialConstants.java
new file mode 100644 (file)
index 0000000..691b546
--- /dev/null
@@ -0,0 +1,35 @@
+ /**
+ *  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.material.nuxeo;
+
+/**
+ * Constants for the Material service
+ *
+ */
+public class MaterialConstants {
+
+    public final static String NUXEO_DOCTYPE = "Material";
+    public final static String NUXEO_SCHEMA_NAME = "material";
+    public final static String NUXEO_DC_TITLE = "CollectionSpace-Material";
+}
diff --git a/services/material/service/src/main/java/org/collectionspace/services/material/nuxeo/MaterialDocumentModelHandler.java b/services/material/service/src/main/java/org/collectionspace/services/material/nuxeo/MaterialDocumentModelHandler.java
new file mode 100644 (file)
index 0000000..de97409
--- /dev/null
@@ -0,0 +1,114 @@
+/**
+ *  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.material.nuxeo;
+
+import org.collectionspace.services.MaterialJAXBSchema;
+import org.collectionspace.services.client.MaterialAuthorityClient;
+import org.collectionspace.services.common.document.DocumentWrapper;
+import org.collectionspace.services.common.vocabulary.nuxeo.AuthorityItemDocumentModelHandler;
+import org.collectionspace.services.material.MaterialsCommon;
+import org.nuxeo.ecm.core.api.DocumentModel;
+
+/**
+ * MaterialDocumentModelHandler
+ *
+ */
+public class MaterialDocumentModelHandler
+        extends AuthorityItemDocumentModelHandler<MaterialsCommon> {
+
+    /**
+     * Common part schema label
+     */
+    private static final String COMMON_PART_LABEL = "materials_common";
+    
+    public MaterialDocumentModelHandler() {
+        super(COMMON_PART_LABEL);
+    }
+
+    @Override
+    public String getAuthorityServicePath(){
+        return MaterialAuthorityClient.SERVICE_PATH_COMPONENT;    //  CSPACE-3932
+    }
+
+        /**
+     * Handle display name.
+     *
+     * @param docModel the doc model
+     * @throws Exception the exception
+     */
+//    @Override
+//    protected void handleComputedDisplayNames(DocumentModel docModel) throws Exception {
+//        String commonPartLabel = getServiceContext().getCommonPartLabel("materials");
+//      Boolean displayNameComputed = (Boolean) docModel.getProperty(commonPartLabel,
+//              MaterialJAXBSchema.DISPLAY_NAME_COMPUTED);
+//      Boolean shortDisplayNameComputed = (Boolean) docModel.getProperty(commonPartLabel,
+//              MaterialJAXBSchema.SHORT_DISPLAY_NAME_COMPUTED);
+//      if(displayNameComputed==null)
+//          displayNameComputed = true;
+//      if(shortDisplayNameComputed==null)
+//          shortDisplayNameComputed = true;
+//      if (displayNameComputed || shortDisplayNameComputed) {
+//                // Obtain the primary material name from the list of material names, for computing the display name.
+//          String xpathToMaterialName = MaterialJAXBSchema.MATERIAL_TERM_NAME_GROUP_LIST 
+//                        + "/[0]/" + MaterialeJAXBSchema.MATERIAL_TERM_NAME;
+//          String materialName = getXPathStringValue(docModel, COMMON_PART_LABEL, xpathToMaterialName);
+//          String displayName = prepareDefaultDisplayName(materialName);
+//          if (displayNameComputed) {
+//              docModel.setProperty(commonPartLabel, MaterialJAXBSchema.DISPLAY_NAME,
+//                      displayName);
+//          }
+//          if (shortDisplayNameComputed) {
+//              docModel.setProperty(commonPartLabel, MaterialJAXBSchema.SHORT_DISPLAY_NAME,
+//                      displayName);
+//          }
+//      }
+//    }
+    
+    /**
+     * Produces a default displayName from one or more supplied fields.
+     * @see MaterialAuthorityClientUtils.prepareDefaultDisplayName() which
+     * duplicates this logic, until we define a service-general utils package
+     * that is neither client nor service specific.
+     * @param materialName
+     * @return the default display name
+     * @throws Exception
+     */
+    private static String prepareDefaultDisplayName(
+            String materialName ) throws Exception {
+        StringBuilder newStr = new StringBuilder();
+            newStr.append(materialName);
+            return newStr.toString();
+    }
+    
+    /**
+     * getQProperty converts the given property to qualified schema property
+     * @param prop
+     * @return
+     */
+    @Override
+    public String getQProperty(String prop) {
+        return MaterialConstants.NUXEO_SCHEMA_NAME + ":" + prop;
+    }
+}
+
diff --git a/services/material/service/src/main/java/org/collectionspace/services/material/nuxeo/MaterialValidatorHandler.java b/services/material/service/src/main/java/org/collectionspace/services/material/nuxeo/MaterialValidatorHandler.java
new file mode 100644 (file)
index 0000000..71f0f3a
--- /dev/null
@@ -0,0 +1,148 @@
+/**
+ *  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, 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.material.nuxeo;
+
+import java.util.List;
+import java.util.regex.Pattern;
+import org.collectionspace.services.common.api.Tools;
+import org.collectionspace.services.common.document.InvalidDocumentException;
+import org.collectionspace.services.common.document.ValidatorHandlerImpl;
+import org.collectionspace.services.material.MaterialTermGroup;
+import org.collectionspace.services.material.MaterialTermGroupList;
+import org.collectionspace.services.material.MaterialsCommon;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * MaterialValidatorHandler
+ * 
+ * Performs validation when making requests related to Material 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 MaterialValidatorHandler extends ValidatorHandlerImpl {
+
+    final Logger logger = LoggerFactory.getLogger(MaterialValidatorHandler.class);
+    // 'Bad pattern' for shortIdentifiers matches any non-word characters
+    private static final Pattern SHORT_ID_BAD_PATTERN = Pattern.compile("[\\W]");
+    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 TERM_HAS_EMPTY_DISPLAYNAME_ERROR =
+            "Each term group in an authority item must contain "
+            + "a non-empty display name.";
+
+    @Override
+    protected Class getCommonPartClass() {
+        return MaterialsCommon.class;
+    }
+
+    @Override
+    protected void handleCreate() throws InvalidDocumentException {
+        MaterialsCommon material = (MaterialsCommon) getCommonPart();
+        // No guarantee that there is a common part in every post/update.
+        if (material != null) {
+            try {
+                String shortId = material.getShortIdentifier();
+                if (shortId != null) {
+                    CS_ASSERT(shortIdentifierContainsOnlyValidChars(shortId), SHORT_ID_BAD_CHARS_ERROR);
+                }
+                CS_ASSERT(containsAtLeastOneTerm(material), HAS_NO_TERMS_ERROR);
+                CS_ASSERT(allTermsContainDisplayName(material), TERM_HAS_EMPTY_DISPLAYNAME_ERROR);
+            } catch (AssertionError e) {
+                if (logger.isErrorEnabled()) {
+                    logger.error(e.getMessage(), e);
+                }
+                throw new InvalidDocumentException(e.getMessage(), e);
+            }
+        }
+    }
+
+    @Override
+    protected void handleGet() throws InvalidDocumentException {
+    }
+
+    @Override
+    protected void handleGetAll() throws InvalidDocumentException {
+    }
+
+    @Override
+    protected void handleUpdate() throws InvalidDocumentException {
+        MaterialsCommon material = (MaterialsCommon) getCommonPart();
+        // No guarantee that there is a common part in every post/update.
+        if (material != 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(material), HAS_NO_TERMS_ERROR);
+                CS_ASSERT(allTermsContainDisplayName(material), TERM_HAS_EMPTY_DISPLAYNAME_ERROR);
+            } catch (AssertionError e) {
+                if (logger.isErrorEnabled()) {
+                    logger.error(e.getMessage(), e);
+                }
+                throw new InvalidDocumentException(e.getMessage(), 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(MaterialsCommon material) {
+        MaterialTermGroupList termGroupList = material.getMaterialTermGroupList();
+        if (termGroupList == null) {
+            return false;
+        }
+        List<MaterialTermGroup> termGroups = termGroupList.getMaterialTermGroup();
+        if ((termGroups == null) || (termGroups.isEmpty())){ 
+            return false;
+        }
+        return true;
+    }
+
+    private boolean allTermsContainDisplayName(MaterialsCommon material) {
+        MaterialTermGroupList termGroupList = material.getMaterialTermGroupList();
+        List<MaterialTermGroup> termGroups = termGroupList.getMaterialTermGroup();
+        for (MaterialTermGroup termGroup : termGroups) {
+            if (Tools.isBlank(termGroup.getTermDisplayName())) {
+                return false;
+            }
+        }
+        return true;
+    }
+}
+
index 6d921f513ec7ebd054e7ff977c487bf070a50f43..50d13d1b768acd010d385cdcd49f934d537e5167 100644 (file)
@@ -72,6 +72,7 @@
         <module>location</module>
         <module>place</module>
         <module>work</module>
+        <module>material</module>
         <module>concept</module>
         <module>taxonomy</module>
         <module>movement</module>