<dependency>
<groupId>org.collectionspace.services</groupId>
<artifactId>org.collectionspace.services.imports.service</artifactId>
- <version>${project.version}</version>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.export.service</artifactId>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.collectionspace.services</groupId>
import org.collectionspace.services.objectexit.ObjectExitResource;
import org.collectionspace.services.batch.BatchResource;
import org.collectionspace.services.imports.ImportsResource;
+import org.collectionspace.services.export.ExportResource;
import org.collectionspace.services.location.LocationAuthorityResource;
import org.collectionspace.services.place.PlaceAuthorityResource;
import org.collectionspace.services.work.WorkAuthorityResource;
singletons.add(new PermissionResource());
singletons.add(new ServiceGroupResource());
singletons.add(new ImportsResource());
+ singletons.add(new ExportResource());
singletons.add(new StructuredDateResource());
singletons.add(new SystemInfoResource());
singletons.add(new IndexResource());
import org.collectionspace.services.client.PoxPayloadOut;
import org.collectionspace.services.client.XmlTools;
import org.collectionspace.services.client.workflow.WorkflowClient;
+import org.collectionspace.services.common.CollectionSpaceResource;
import org.collectionspace.services.common.CSWebApplicationException;
import org.collectionspace.services.common.NuxeoBasedResource;
import org.collectionspace.services.common.ResourceMap;
) throws Exception {
return updateAuthorityItem(null, itemServiceCtx, resourceMap, uriInfo, parentspecifier, itemspecifier, theUpdate, shouldUpdateRevNumber, isProposed, isSASItem);
}
-
+
public PoxPayloadOut updateAuthorityItem(
ServiceContext<PoxPayloadIn, PoxPayloadOut> parentCtx,
ServiceContext<PoxPayloadIn, PoxPayloadOut> itemServiceCtx, // Ok to be null. Will be null on PUT calls, but not on sync calls
uriInfo = new UriInfoWrapper(uriInfo);
return updateItemWorkflowWithTransition(null, uriInfo, parentIdentifier, itemIdentifier, transition);
}
-
+
public byte[] updateItemWorkflowWithTransition(
ServiceContext<PoxPayloadIn, PoxPayloadOut> existingContext,
UriInfo uriInfo,
}
result = (PoxPayloadOut) ctx.getOutput();
- if (result != null) {
+ if (result != null && !parentcsid.equals(PARENT_WILDCARD)) {
String inAuthority = XmlTools.getElementValue(result.getDOMDocument(), "//" + AuthorityItemJAXBSchema.IN_AUTHORITY);
if (inAuthority.equalsIgnoreCase(parentcsid) == false) {
throw new Exception(String.format("Looked up item = '%s' and found with inAuthority = '%s', but expected inAuthority = '%s'.",
String xmlPayload) {
return updateAuthorityItem(null, resourceMap, uriInfo, parentSpecifier, itemSpecifier, xmlPayload);
}
-
+
public byte[] updateAuthorityItem(
ServiceContext<PoxPayloadIn, PoxPayloadOut> parentCtx,
ResourceMap resourceMap,
return csid;
}
+ public static AuthorityResource<?, ?> getResourceForItem(ResourceMap resourceMap, String tenantId, String itemDocType) {
+ for (String serviceName : resourceMap.keySet()) {
+ CollectionSpaceResource<?, ?> resource = (CollectionSpaceResource<?, ?>) resourceMap.get(serviceName);
+
+ if (resource instanceof AuthorityResource) {
+ AuthorityResource<?, ?> authorityResource = (AuthorityResource<?, ?>) resource;
+ String docType = authorityResource.getItemDocType(tenantId);
+
+ if (docType.equals(itemDocType)) {
+ return authorityResource;
+ }
+ }
+ }
+
+ return null;
+ }
}
</tenant:serviceBindings>
<!-- end imports service meta-data -->
+ <!-- begin export service meta-data -->
+ <tenant:serviceBindings id="Exports" merge:matcher="id" name="Exports" type="utility" version="1.0">
+ <service:repositoryDomain xmlns:service="http://collectionspace.org/services/config/service">default-domain</service:repositoryDomain>
+ <service:documentHandler xmlns:service="http://collectionspace.org/services/config/service">org.collectionspace.services.export.nuxeo.ExportDocumentModelHandler
+ </service:documentHandler>
+ <service:DocHandlerParams xmlns:service="http://collectionspace.org/services/config/service">
+ <service:params>
+ <service:ListResultsFields>
+ </service:ListResultsFields>
+ </service:params>
+ </service:DocHandlerParams>
+ <service:object xmlns:service="http://collectionspace.org/services/config/service" name="Export"
+ version="1.0">
+ <service:part id="0" control_group="Managed" versionable="true" auditable="false" label="exports-system"
+ updated="" order="0">
+ <service:content contentType="application/xml">
+ <service:xmlContent namespaceURI="http://collectionspace.org/services/config/system"
+ schemaLocation="http://collectionspace.org/services/config/system http://collectionspace.org/services/config/system/system-response.xsd" />
+ </service:content>
+ </service:part>
+ <service:part id="1" control_group="Managed" versionable="true" auditable="false" label="exports_common"
+ updated="" order="1">
+ <service:content contentType="application/xml">
+ <service:xmlContent namespaceURI="http://collectionspace.org/services/export"
+ schemaLocation="http://collectionspace.org/services/export http://services.collectionspace.org/export/exports_common.xsd" />
+ </service:content>
+ </service:part>
+ <service:part id="2" control_group="Managed" versionable="true" auditable="false" label="collectionspace_core"
+ updated="" order="2">
+ <service:content contentType="application/xml">
+ <service:xmlContent namespaceURI="http://collectionspace.org/collectionspace_core/"
+ schemaLocation="http://collectionspace.org/collectionspace_core/ http://services.collectionspace.org/collectionspace_core.xsd" />
+ </service:content>
+ </service:part>
+ </service:object>
+ </tenant:serviceBindings>
+ <!-- end export service meta-data -->
+
<!-- begin Workflow service meta-data -->
<tenant:serviceBindings id="Workflow" merge:matcher="id" name="Workflow" type="utility"
version="1.0">
*/
package org.collectionspace.services.common.invocable;
-import org.collectionspace.services.common.invocable.InvocationContext;
import java.util.List;
import org.collectionspace.services.client.PoxPayloadIn;
@Override
public String toString() {
- return (Tools.notBlank(message)) ? message : "No error message provided";
+ return (Tools.notBlank(message)) ? message : "No error message provided";
}
}
-
- public String INVOCATION_MODE_SINGLE = "single";
- public String INVOCATION_MODE_LIST = "list";
- public String INVOCATION_MODE_GROUP = "group";
- public String INVOCATION_MODE_NO_CONTEXT = "nocontext";
- //public String INVOCATION_MODE_QUERY = "query"; NYI
-
+
+ public final String INVOCATION_MODE_SINGLE = "single";
+ public final String INVOCATION_MODE_LIST = "list";
+ public final String INVOCATION_MODE_GROUP = "group";
+ public final String INVOCATION_MODE_NO_CONTEXT = "nocontext";
+ public final String INVOCATION_MODE_QUERY = "query";
+
public final int STATUS_ERROR = -1;
public final int STATUS_UNSTARTED = 0;
public final int STATUS_MIN_PROGRESS = 1;
--- /dev/null
+
+<project name="export" default="package" basedir=".">
+ <description>
+ export 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" />
+ <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" />
+ <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" />
+ <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" />
+ <arg value="test" />
+ <arg value="${mvn.opts}" />
+ </exec>
+ </target>
+</project>
--- /dev/null
+<?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.export</artifactId>
+ <version>${revision}</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>org.collectionspace.services.export.client</artifactId>
+ <name>services.export.client</name>
+
+ <dependencies>
+<!-- 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.export.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.person.client</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.acquisition.client</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.acquisition.jaxb</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.organization.client</artifactId>
+ <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>
+ </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-export-client</finalName>
+ </build>
+</project>
--- /dev/null
+/**
+ * ExportClient.java
+ *
+ * {Purpose of This Class}
+ *
+ * {Other Notes Relating to This Class (Optional)}
+ *
+ * $LastChangedBy: $
+ * $LastChangedRevision: $
+ * $LastChangedDate: $
+ *
+ * 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 {Contributing Institution}
+ *
+ * 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 javax.ws.rs.core.Response;
+
+import org.collectionspace.services.common.invocable.InvocationContext;
+import org.collectionspace.services.export.ExportsCommon;
+
+/**
+ * An Export client.
+
+ * @version $Revision:$
+ */
+public class ExportClient extends AbstractCommonListPoxServiceClientImpl<ExportProxy, ExportsCommon> {
+ public static final String SERVICE_NAME = "exports";
+ public static final String SERVICE_PATH_COMPONENT = SERVICE_NAME;
+ public static final String SERVICE_PATH = "/" + SERVICE_PATH_COMPONENT;
+ public static final String SERVICE_COMMON_PART_NAME = SERVICE_NAME + PART_LABEL_SEPARATOR + PART_COMMON_LABEL;
+
+ public ExportClient() throws Exception {
+ super();
+ }
+
+ public ExportClient(String clientPropertiesFilename) throws Exception {
+ super(clientPropertiesFilename);
+ }
+
+ @Override
+ public String getServiceName() {
+ return SERVICE_NAME;
+ }
+
+ @Override
+ public String getServicePathComponent() {
+ return SERVICE_PATH_COMPONENT;
+ }
+
+ @Override
+ public Class<ExportProxy> getProxyClass() {
+ return ExportProxy.class;
+ }
+}
--- /dev/null
+/**
+ * ExportProxy.java
+ *
+ * {Purpose of This Class}
+ *
+ * {Other Notes Relating to This Class (Optional)}
+ *
+ * $LastChangedBy: $
+ * $LastChangedRevision: $
+ * $LastChangedDate: $
+ *
+ * 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 {Contributing Institution}
+ *
+ * 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 javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Response;
+
+import org.collectionspace.services.common.invocable.InvocationContext;
+
+/**
+ * @version $Revision:$
+ * FIXME: http://issues.collectionspace.org/browse/CSPACE-1684
+ */
+@Path("/exports/")
+@Produces({"application/xml;charset=UTF-8"})
+@Consumes({"application/xml"})
+public interface ExportProxy extends CollectionSpaceCommonListPoxProxy {
+}
--- /dev/null
+/target/
+/target/
+/target/
--- /dev/null
+<?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>
+ <artifactId>org.collectionspace.services.export</artifactId>
+ <groupId>org.collectionspace.services</groupId>
+ <version>${revision}</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>org.collectionspace.services.export.jaxb</artifactId>
+ <name>services.export.jaxb</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.jaxb</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <finalName>collectionspace-services-export-jaxb</finalName>
+ <defaultGoal>install</defaultGoal>
+ <plugins>
+ <plugin>
+ <groupId>org.jvnet.jaxb2.maven2</groupId>
+ <artifactId>maven-jaxb2-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
--- /dev/null
+/**
+ *
+ */
+package org.collectionspace.services;
+
+import org.collectionspace.services.jaxb.InvocableJAXBSchema;
+
+public interface ExportJAXBSchema extends InvocableJAXBSchema {
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+
+<!--
+ Export schema (XSD)
+
+ Entity : Export
+ Part : Common
+ Used for: JAXB binding between XML and Java objects
+
+ $LastChangedRevision: 2498 $
+ $LastChangedDate: 2010-06-16 14:47:45 -0700 (Wed, 16 Jun 2010) $
+-->
+
+<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/export"
+ xmlns="http://collectionspace.org/services/export"
+ targetNamespace="http://collectionspace.org/services/export"
+ version="0.1"
+>
+
+ <!--
+ Avoid XmlRootElement nightmare:
+ See http://weblogs.java.net/blog/kohsuke/archive/2006/03/why_does_jaxb_p.html
+ -->
+ <xs:element name="exports_common">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="csid" type="xs:string" />
+ <xs:element name="name" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- A comment. -->
+<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>${revision}</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.export</artifactId>
+ <name>services.export</name>
+ <packaging>pom</packaging>
+
+ <dependencies>
+ </dependencies>
+
+ <modules>
+ <module>jaxb</module>
+ <module>service</module>
+ <module>client</module>
+ </modules>
+</project>
--- /dev/null
+<?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.export</artifactId>
+ <version>${revision}</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>org.collectionspace.services.export.service</artifactId>
+ <name>services.export.service</name>
+ <packaging>jar</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.authentication.service</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.account.service</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.authority.service</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.config</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>
+ <dependency>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.common</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.export.jaxb</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.export.client</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.collectionobject.jaxb</artifactId>
+ <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>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-csv</artifactId>
+ <version>1.8</version>
+ </dependency>
+
+ <!-- javax -->
+
+ <dependency>
+ <groupId>javax.security</groupId>
+ <artifactId>jaas</artifactId>
+ <version>1.0.01</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <!-- jboss -->
+
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-jaxrs</artifactId>
+ </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>
+
+ </dependencies>
+
+ <build>
+ <finalName>collectionspace-services-export</finalName>
+ </build>
+</project>
--- /dev/null
+package org.collectionspace.services.export;
+
+import java.math.BigInteger;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+import javax.ws.rs.core.PathSegment;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.http.client.utils.URIBuilder;
+import org.collectionspace.services.client.PoxPayloadIn;
+import org.collectionspace.services.client.PoxPayloadOut;
+import org.collectionspace.services.common.NuxeoBasedResource;
+import org.collectionspace.services.common.ServiceMain;
+import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
+import org.collectionspace.services.common.context.ServiceBindingUtils;
+import org.collectionspace.services.common.context.ServiceContext;
+import org.collectionspace.services.common.invocable.InvocationContext;
+import org.collectionspace.services.common.query.UriInfoImpl;
+import org.collectionspace.services.common.vocabulary.AuthorityResource;
+import org.collectionspace.services.config.service.ServiceBindingType;
+import org.collectionspace.services.jaxb.AbstractCommonList;
+import org.jboss.resteasy.specimpl.PathSegmentImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class AbstractDocumentsByQueryIterator<ListItemType> implements Iterator<PoxPayloadOut> {
+ private final Logger logger = LoggerFactory.getLogger(AbstractDocumentsByQueryIterator.class);
+
+ private NuxeoBasedResource resource;
+ private String vocabulary;
+ private boolean isAuthorityItem = false;
+ private AbstractCommonList resultList;
+ private Iterator<ListItemType> resultItemIterator;
+ private InvocationContext.Query query;
+
+ protected ServiceContext<PoxPayloadIn, PoxPayloadOut> serviceContext;
+
+ AbstractDocumentsByQueryIterator(
+ ServiceContext<PoxPayloadIn, PoxPayloadOut> serviceContext,
+ String docType,
+ String vocabulary,
+ InvocationContext.Query query) throws Exception {
+
+ TenantBindingConfigReaderImpl tenantBindingConfigReader = ServiceMain.getInstance().getTenantBindingConfigReader();
+ ServiceBindingType serviceBinding = tenantBindingConfigReader.getServiceBindingForDocType(serviceContext.getTenantId(), docType);
+ String serviceType = serviceBinding.getType();
+ String serviceName = serviceBinding.getName();
+
+ this.serviceContext = serviceContext;
+ this.isAuthorityItem = ServiceBindingUtils.SERVICE_TYPE_AUTHORITY.equals(serviceType);
+ this.vocabulary = vocabulary;
+
+ this.resource = isAuthorityItem
+ ? AuthorityResource.getResourceForItem(serviceContext.getResourceMap(), serviceContext.getTenantId(), docType)
+ : (NuxeoBasedResource) serviceContext.getResource(serviceName.toLowerCase());
+
+ this.query = query;
+
+ getResults(query);
+ }
+
+ private void getResults(InvocationContext.Query query) throws Exception {
+ UriInfo uriInfo = createUriInfo(query);
+
+ resultList = isAuthorityItem
+ ? ((AuthorityResource<?, ?>) resource).getAuthorityItemList(serviceContext, vocabulary == null ? AuthorityResource.PARENT_WILDCARD : vocabulary, uriInfo)
+ : resource.getList(serviceContext, uriInfo);
+
+ resultItemIterator = (resultList == null) ? null : getListItems(resultList).iterator();
+ }
+
+ protected abstract List<ListItemType> getListItems(AbstractCommonList list);
+
+ private boolean hasMoreResultPages() {
+ if (resultList == null || query.getPgNum() != null) {
+ return false;
+ }
+
+ long pageSize = resultList.getPageSize();
+ long pageNum = resultList.getPageNum();
+ long totalItems = resultList.getTotalItems();
+
+ return (totalItems > (pageSize * (pageNum + 1)));
+ }
+
+ private void getNextResultPage() throws Exception {
+ if (hasMoreResultPages()) {
+ long pageSize = resultList.getPageSize();
+ long pageNum = resultList.getPageNum();
+
+ InvocationContext.Query nextPageQuery = new InvocationContext.Query();
+
+ nextPageQuery.setAs(query.getAs());
+ nextPageQuery.setKw(query.getKw());
+ nextPageQuery.setPgNum(BigInteger.valueOf(pageNum + 1));
+ nextPageQuery.setPgSz(BigInteger.valueOf(pageSize));
+ nextPageQuery.setWfDeleted(query.isWfDeleted());
+
+ getResults(nextPageQuery);
+ }
+ }
+
+ @Override
+ public boolean hasNext() {
+ return (
+ resultList != null
+ && resultItemIterator != null
+ && (resultItemIterator.hasNext() || hasMoreResultPages())
+ );
+ }
+
+ @Override
+ public PoxPayloadOut next() {
+ if (resultList == null || resultItemIterator == null) {
+ throw new NoSuchElementException();
+ }
+
+ if (!resultItemIterator.hasNext()) {
+ if (!hasMoreResultPages()) {
+ throw new NoSuchElementException();
+ }
+
+ try {
+ getNextResultPage();
+ }
+ catch (Exception e) {
+ logger.warn("Could not get result page", e);
+
+ return null;
+ }
+ }
+
+ return getDocument(resultItemIterator.next());
+ }
+
+ protected PoxPayloadOut getDocument(ListItemType item) {
+ String csid = getListItemCsid(item);
+
+ try {
+ return (isAuthorityItem
+ ? ((AuthorityResource<?, ?>) resource).getAuthorityItemWithExistingContext(serviceContext, AuthorityResource.PARENT_WILDCARD, csid)
+ : resource.getWithParentCtx(serviceContext, csid));
+ }
+ catch (Exception e) {
+ logger.warn("Could not get document with csid " + csid, e);
+
+ return null;
+ }
+ }
+
+ protected abstract String getListItemCsid(ListItemType listItem);
+
+ protected UriInfo createUriInfo(InvocationContext.Query query) throws URISyntaxException {
+ URI absolutePath = new URI("");
+ URI baseUri = new URI("");
+ String encodedPath = "";
+
+ // Some code in services assumes pathSegments will have at least one element, so add an
+ // empty one.
+ List<PathSegment> pathSegments = Arrays.asList((PathSegment) new PathSegmentImpl("", false));
+
+ URIBuilder uriBuilder = new URIBuilder();
+
+ String as = query.getAs();
+
+ if (StringUtils.isNotEmpty(as)) {
+ uriBuilder.addParameter("as", as);
+ }
+
+ String kw = query.getKw();
+
+ if (StringUtils.isNotEmpty(kw)) {
+ uriBuilder.addParameter("kw", kw);
+ }
+
+ BigInteger pgNum = query.getPgNum();
+
+ if (pgNum != null) {
+ uriBuilder.addParameter("pgNum", pgNum.toString());
+ }
+
+ BigInteger pgSz = query.getPgSz();
+
+ if (pgSz != null) {
+ uriBuilder.addParameter("pgSz", pgSz.toString());
+ }
+
+ Boolean wfDeleted = query.isWfDeleted();
+
+ if (wfDeleted != null) {
+ uriBuilder.addParameter("wf_deleted", Boolean.toString(wfDeleted));
+ }
+
+ String sbj = query.getSbj();
+
+ if (StringUtils.isNotEmpty(sbj)) {
+ uriBuilder.addParameter("sbj", sbj);
+ }
+
+ String sbjType = query.getSbjType();
+
+ if (StringUtils.isNotEmpty(sbjType)) {
+ uriBuilder.addParameter("sbjType", sbjType);
+ }
+
+ String prd = query.getPrd();
+
+ if (StringUtils.isNotEmpty(prd)) {
+ uriBuilder.addParameter("prd", prd);
+ }
+
+ String obj = query.getObj();
+
+ if (StringUtils.isNotEmpty(obj)) {
+ uriBuilder.addParameter("obj", obj);
+ }
+
+ String objType = query.getObjType();
+
+ if (StringUtils.isNotEmpty(objType)) {
+ uriBuilder.addParameter("objType", objType);
+ }
+
+ Boolean andReciprocal = query.isAndReciprocal();
+
+ if (andReciprocal != null) {
+ uriBuilder.addParameter("andReciprocal", Boolean.toString(andReciprocal));
+ }
+
+ String queryString = uriBuilder.toString();
+
+ if (StringUtils.isNotEmpty(queryString)) {
+ queryString = queryString.substring(1); // Remove ? from beginning
+ }
+
+ return new UriInfoImpl(absolutePath, baseUri, encodedPath, queryString, pathSegments);
+ }
+}
--- /dev/null
+package org.collectionspace.services.export;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.collectionspace.services.client.PoxPayloadIn;
+import org.collectionspace.services.client.PoxPayloadOut;
+import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
+import org.collectionspace.services.common.context.ServiceContext;
+import org.collectionspace.services.common.invocable.InvocationContext;
+
+public abstract class AbstractExportWriter implements ExportWriter {
+ protected InvocationContext invocationContext;
+ protected ServiceContext<PoxPayloadIn, PoxPayloadOut> serviceContext;
+ protected TenantBindingConfigReaderImpl tenantBindingConfigReader;
+ protected Writer writer;
+
+ @Override
+ public void setInvocationContext(InvocationContext invocationContext) {
+ this.invocationContext = invocationContext;
+ }
+
+ @Override
+ public void setOutputStream(OutputStream outputStream) {
+ this.writer = new OutputStreamWriter(outputStream);
+ }
+
+ @Override
+ public void setServiceContext(ServiceContext<PoxPayloadIn, PoxPayloadOut> serviceContext) {
+ this.serviceContext = serviceContext;
+ }
+
+ @Override
+ public void setTenantBindingConfigReader(TenantBindingConfigReaderImpl tenantBindingConfigReader) {
+ this.tenantBindingConfigReader = tenantBindingConfigReader;
+ }
+
+ @Override
+ public void start() throws Exception {
+ };
+
+ @Override
+ public abstract void writeDocument(PoxPayloadOut document) throws Exception;
+
+ @Override
+ public void finish() throws Exception {
+ }
+
+ @Override
+ public void close() throws Exception {
+ writer.close();
+ }
+}
--- /dev/null
+package org.collectionspace.services.export;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.csv.CSVFormat;
+import org.apache.commons.csv.CSVPrinter;
+import org.apache.commons.lang.StringUtils;
+import org.collectionspace.services.client.PayloadOutputPart;
+import org.collectionspace.services.client.PoxPayloadOut;
+import org.collectionspace.services.common.api.RefNameUtils;
+import org.collectionspace.services.common.context.ServiceBindingUtils;
+import org.collectionspace.services.common.invocable.InvocationContext;
+import org.collectionspace.services.config.service.ServiceBindingType;
+import org.collectionspace.services.config.service.ServiceObjectType;
+import org.dom4j.Element;
+import org.dom4j.Namespace;
+import org.dom4j.Node;
+import org.dom4j.VisitorSupport;
+
+public class CsvExportWriter extends AbstractExportWriter {
+ private static final Pattern VALID_FIELD_XPATH_PATTERN = Pattern.compile("^\\w+:(\\w+\\/)*(\\w+)$");
+ private static final String AUTH_ITEM_TERM_GROUP_SUFFIX = "TermGroup";
+
+ private CSVPrinter csvPrinter;
+ private Map<String, Map<String, Set<String>>> refFieldsByDocType = new HashMap<>();
+
+ @Override
+ public void start() throws Exception {
+ // For CSV output, the invocation context must specify the exact fields to be included
+ // (no wildcard xpaths), so that the columns can be known in advance. Otherwise the entire
+ // result set would need to be scanned first, in order to determine the fields that are
+ // present.
+
+ InvocationContext.IncludeFields includeFields = invocationContext.getIncludeFields();
+ List<String> fields = (includeFields != null ? includeFields.getField() : new ArrayList<String>());
+
+ if (fields.size() == 0) {
+ throw new Exception("For CSV output, the fields to export must be specified using includeFields.");
+ }
+
+ List<String> headers = new ArrayList<>();
+
+ for (String field : fields) {
+ Matcher matcher = VALID_FIELD_XPATH_PATTERN.matcher(field);
+
+ if (!matcher.matches()) {
+ throw new Exception("The includeField XPath expression \"" + field + "\" is not valid for CSV output. For CSV output, all included fields must be individually specified without using wildcards.");
+ }
+
+ String fieldName = matcher.group(2);
+
+ headers.add(fieldName);
+
+ if (isFieldWithinAuthItemTermGroup(field)) {
+ headers.add(fieldName + "NonPreferred");
+ }
+ }
+
+ String[] headersArray = new String[headers.size()];
+
+ this.csvPrinter = new CSVPrinter(writer, CSVFormat.DEFAULT.withHeader(headers.toArray(headersArray)));
+ }
+
+ @Override
+ public void writeDocument(PoxPayloadOut document) throws Exception {
+ InvocationContext.IncludeFields includeFields = invocationContext.getIncludeFields();
+
+ if (includeFields == null) {
+ return;
+ }
+
+ List<String> fields = includeFields.getField();
+ List<String> csvRecord = new ArrayList<>();
+
+ for (String field : fields) {
+ if (isFieldWithinAuthItemTermGroup(field)) {
+ // Write a column for values within the preferred (primary) term group.
+ csvRecord.add(collectValues(document, field.replace(AUTH_ITEM_TERM_GROUP_SUFFIX + "/", AUTH_ITEM_TERM_GROUP_SUFFIX + "[position()=1]/")));
+
+ // Write a column for values within non-preferred term groups.
+ csvRecord.add(collectValues(document, field.replace(AUTH_ITEM_TERM_GROUP_SUFFIX + "/", AUTH_ITEM_TERM_GROUP_SUFFIX + "[position()>1]/")));
+ }
+ else {
+ csvRecord.add(collectValues(document, field));
+ }
+ }
+
+ if (csvRecord.size() > 0) {
+ csvPrinter.printRecord(csvRecord);
+ }
+ }
+
+ @Override
+ public void close() throws Exception {
+ csvPrinter.close();
+ }
+
+ private boolean isFieldWithinAuthItemTermGroup(String field) {
+ // FIXME: How to know a NonPreferred column is needed without hardcoding "TermGroup"?
+
+ return field.contains(AUTH_ITEM_TERM_GROUP_SUFFIX + "/");
+ }
+
+ private String collectValues(PoxPayloadOut document, String field) {
+ String delimitedValues = "";
+ String[] segments = field.split(":", 2);
+ String partName = segments[0];
+ String xpath = segments[1];
+
+ PayloadOutputPart part = document.getPart(partName);
+
+ if (part != null) {
+ delimitedValues = collectValues(document.getName(), partName, part.getElementBody(), Arrays.asList(xpath.split("/")), 0);
+ }
+
+ return delimitedValues;
+ }
+
+ private String collectValues(String docType, String partName, Element element, List<String> path, int depth) {
+ String delimitedValues = "";
+ String fieldName = path.get(depth);
+ String delimiter = (depth / 2 > 0) ? "^^" : ";";
+ List<Node> matches = element.createXPath(fieldName).selectNodes(element);
+
+ if (matches.size() > 0) {
+ List<String> values = new ArrayList<>();
+ boolean hasValue = false;
+
+ for (Node node : matches) {
+ String textValue = "";
+
+ if (depth < path.size() - 1) {
+ textValue = collectValues(docType, partName, (Element) node, path, depth + 1);
+ }
+ else {
+ textValue = node.getText();
+
+ boolean isRefName = isRefField(docType, partName, fieldName);
+
+ if (isRefName && StringUtils.isNotEmpty(textValue)) {
+ textValue = RefNameUtils.getDisplayName(textValue);
+ }
+ }
+
+ if (StringUtils.isNotEmpty(textValue)) {
+ hasValue = true;
+ }
+
+ values.add(textValue);
+ }
+
+ if (hasValue) {
+ delimitedValues = String.join(delimiter, values);
+ }
+ }
+
+ return delimitedValues;
+ }
+
+ private boolean isRefField(String docType, String partName, String fieldName) {
+ return getRefFields(docType, partName).contains(fieldName);
+ }
+
+ private Set<String> getRefFields(String docType, String partName) {
+ Set<String> refFields = refFieldsByDocType.containsKey(docType)
+ ? refFieldsByDocType.get(docType).get(partName)
+ : null;
+
+ if (refFields != null) {
+ return refFields;
+ }
+
+ refFields = new HashSet<>();
+
+ ServiceBindingType serviceBinding = tenantBindingConfigReader.getServiceBinding(serviceContext.getTenantId(), docType);
+
+ for (String termRefField : ServiceBindingUtils.getPropertyValuesForPart(serviceBinding, partName, ServiceBindingUtils.TERM_REF_PROP, false)) {
+ String[] segments = termRefField.split("[\\/\\|]");
+ String fieldName = segments[segments.length - 1];
+
+ refFields.add(fieldName);
+ }
+
+ for (String authRefField : ServiceBindingUtils.getPropertyValuesForPart(serviceBinding, partName, ServiceBindingUtils.AUTH_REF_PROP, false)) {
+ String[] segments = authRefField.split("[\\/\\|]");
+ String fieldName = segments[segments.length - 1];
+
+ refFields.add(fieldName);
+ }
+
+ if (!refFieldsByDocType.containsKey(docType)) {
+ refFieldsByDocType.put(docType, new HashMap<String, Set<String>>());
+ }
+
+ refFieldsByDocType.get(docType).put(partName, refFields);
+
+ return refFields;
+ }
+}
--- /dev/null
+package org.collectionspace.services.export;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.collectionspace.services.client.PoxPayloadIn;
+import org.collectionspace.services.client.PoxPayloadOut;
+import org.collectionspace.services.common.NuxeoBasedResource;
+import org.collectionspace.services.common.ServiceMain;
+import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
+import org.collectionspace.services.common.context.ServiceBindingUtils;
+import org.collectionspace.services.common.context.ServiceContext;
+import org.collectionspace.services.common.vocabulary.AuthorityResource;
+import org.collectionspace.services.config.service.ServiceBindingType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DocumentsByCsidIterator implements Iterator<PoxPayloadOut> {
+ private final Logger logger = LoggerFactory.getLogger(DocumentsByCsidIterator.class);
+
+ private NuxeoBasedResource resource;
+ private String vocabulary;
+ private ServiceContext<PoxPayloadIn, PoxPayloadOut> serviceContext;
+ private Iterator<String> csidIterator;
+ private boolean isAuthorityItem = false;
+
+ DocumentsByCsidIterator(
+ ServiceContext<PoxPayloadIn, PoxPayloadOut> serviceContext,
+ String docType,
+ String vocabulary,
+ List<String> csids) throws Exception {
+
+ TenantBindingConfigReaderImpl tenantBindingConfigReader = ServiceMain.getInstance().getTenantBindingConfigReader();
+ ServiceBindingType serviceBinding = tenantBindingConfigReader.getServiceBindingForDocType(serviceContext.getTenantId(), docType);
+ String serviceType = serviceBinding.getType();
+ String serviceName = serviceBinding.getName();
+
+ this.serviceContext = serviceContext;
+ this.csidIterator = csids.iterator();
+ this.isAuthorityItem = ServiceBindingUtils.SERVICE_TYPE_AUTHORITY.equals(serviceType);
+ this.vocabulary = vocabulary;
+
+ this.resource = isAuthorityItem
+ ? AuthorityResource.getResourceForItem(serviceContext.getResourceMap(), serviceContext.getTenantId(), docType)
+ : (NuxeoBasedResource) serviceContext.getResource(serviceName.toLowerCase());
+ }
+
+ @Override
+ public boolean hasNext() {
+ return csidIterator.hasNext();
+ }
+
+ @Override
+ public PoxPayloadOut next() {
+ String csid = csidIterator.next();
+
+ try {
+ return (isAuthorityItem
+ ? ((AuthorityResource<?, ?>) resource).getAuthorityItemWithExistingContext(serviceContext, vocabulary == null ? AuthorityResource.PARENT_WILDCARD : vocabulary, csid)
+ : resource.getWithParentCtx(serviceContext, csid));
+ }
+ catch (Exception e) {
+ logger.warn("Could not get document with csid " + csid, e);
+
+ return null;
+ }
+ }
+}
--- /dev/null
+package org.collectionspace.services.export;
+
+import java.util.Iterator;
+
+import org.collectionspace.services.client.PoxPayloadIn;
+import org.collectionspace.services.client.PoxPayloadOut;
+import org.collectionspace.services.client.RelationClient;
+import org.collectionspace.services.common.context.ServiceContext;
+import org.collectionspace.services.common.invocable.InvocationContext;
+
+public class DocumentsByGroupIterator implements Iterator<PoxPayloadOut> {
+ private RelationObjectsByQueryIterator relationsIterator;
+
+ DocumentsByGroupIterator(
+ ServiceContext<PoxPayloadIn, PoxPayloadOut> serviceContext,
+ String csid) throws Exception {
+
+ InvocationContext.Query query = new InvocationContext.Query();
+
+ query.setSbjType("Group");
+ query.setSbj(csid);
+ query.setPrd("affects");
+ query.setWfDeleted(false);
+
+ relationsIterator = new RelationObjectsByQueryIterator(serviceContext, RelationClient.SERVICE_DOC_TYPE, null, query);
+ }
+
+ @Override
+ public boolean hasNext() {
+ return (
+ relationsIterator != null
+ && relationsIterator.hasNext()
+ );
+ }
+
+ @Override
+ public PoxPayloadOut next() {
+ return relationsIterator.next();
+ }
+}
--- /dev/null
+/**
+ * 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.export;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+import org.collectionspace.services.client.ExportClient;
+import org.collectionspace.services.client.PayloadOutputPart;
+import org.collectionspace.services.client.PoxPayloadIn;
+import org.collectionspace.services.client.PoxPayloadOut;
+import org.collectionspace.services.client.RelationClient;
+import org.collectionspace.services.common.AbstractCollectionSpaceResourceImpl;
+import org.collectionspace.services.common.ServiceMessages;
+import org.collectionspace.services.common.context.MultipartServiceContextFactory;
+import org.collectionspace.services.common.context.ServiceContext;
+import org.collectionspace.services.common.context.ServiceContextFactory;
+import org.collectionspace.services.common.invocable.Invocable;
+import org.collectionspace.services.common.invocable.InvocationContext;
+import org.dom4j.Node;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+@Path(ExportClient.SERVICE_PATH)
+@Consumes("application/xml")
+@Produces("application/xml")
+public class ExportResource extends AbstractCollectionSpaceResourceImpl<PoxPayloadIn, PoxPayloadOut> {
+ private final Logger logger = LoggerFactory.getLogger(ExportResource.class);
+
+ // There is no way to tell from config that collectionspace_core should not be exported, so it
+ // has to be hardcoded here. At that point we might as well also hardcode account_permission,
+ // so we don't need to look at config at all.
+
+ private static final List<String> EXCLUDE_PARTS = Arrays.asList("collectionspace_core", "account_permission");
+
+ private static final String MIME_TYPE_CSV = "text/csv";
+ private static final String MIME_TYPE_XML = "application/xml";
+ private static final String INCLUDE_ATTRIBUTE_NAME = "cspace-export-include";
+
+ @Override
+ protected String getVersionString() {
+ final String lastChangeRevision = "$LastChangedRevision: 1982 $";
+ return lastChangeRevision;
+ }
+
+ @Override
+ public String getServiceName() {
+ return ExportClient.SERVICE_NAME;
+ }
+
+ @Override
+ public Class<?> getCommonPartClass() {
+ return ExportsCommon.class;
+ }
+
+ @Override
+ public ServiceContextFactory<PoxPayloadIn, PoxPayloadOut> getServiceContextFactory() {
+ return MultipartServiceContextFactory.get();
+ }
+
+ @GET
+ @Produces("text/html")
+ public String getInputForm() {
+ return "<html><head></head><body>Export</body></html>";
+ }
+
+ @POST
+ public Response invokeExport(@Context UriInfo uriInfo, InvocationContext invocationContext) throws Exception {
+ String outputMimeType = getOutputMimeType(invocationContext);
+
+ if (!(outputMimeType.equals(MIME_TYPE_XML) || outputMimeType.equals(MIME_TYPE_CSV))) {
+ throw new Exception("Unsupported output MIME type " + outputMimeType);
+ }
+
+ String outputFileName = "export." + (outputMimeType.equals(MIME_TYPE_XML) ? "xml" : "csv");
+
+ try {
+ ServiceContext<PoxPayloadIn, PoxPayloadOut> serviceContext = createServiceContext();
+ InputStream exportStream = invokeExport(serviceContext, invocationContext);
+
+ return Response.ok(exportStream, outputMimeType)
+ .header("Content-Disposition", "inline;filename=\"" + outputFileName + "\"").build();
+ } catch (Exception e) {
+ String message = e.getMessage();
+
+ throw bigReThrow(e, ServiceMessages.POST_FAILED + (message != null ? message : ""));
+ }
+ }
+
+ private String getOutputMimeType(InvocationContext invocationContext) {
+ String outputMimeType = invocationContext.getOutputMIME();
+
+ if (StringUtils.isEmpty(outputMimeType)) {
+ outputMimeType = MIME_TYPE_XML;
+ }
+
+ return outputMimeType;
+ }
+
+ private InputStream invokeExport(ServiceContext<PoxPayloadIn, PoxPayloadOut> serviceContext,
+ InvocationContext invocationContext) throws Exception {
+
+ Iterator<PoxPayloadOut> documents = getDocuments(serviceContext, invocationContext);
+
+ return exportDocuments(serviceContext, invocationContext, documents);
+ }
+
+ private InputStream exportDocuments(ServiceContext<PoxPayloadIn, PoxPayloadOut> serviceContext,
+ InvocationContext invocationContext, Iterator<PoxPayloadOut> documents) throws Exception {
+
+ File exportFile = File.createTempFile("export-", null);
+ FileOutputStream outputStream = new FileOutputStream(exportFile);
+ ExportWriter exportWriter = getExportWriter(serviceContext, invocationContext, outputStream);
+
+ exportWriter.start();
+
+ while (documents.hasNext()) {
+ PoxPayloadOut document = documents.next();
+
+ if (document != null) {
+ filterFields(document, invocationContext);
+
+ exportWriter.writeDocument(document);
+ }
+ }
+
+ exportWriter.finish();
+ exportWriter.close();
+
+ return new FileInputStream(exportFile);
+ }
+
+ private void filterFields(PoxPayloadOut document, InvocationContext invocationContext) {
+ if (document == null) {
+ return;
+ }
+
+ for (String partName : EXCLUDE_PARTS) {
+ PayloadOutputPart part = document.getPart(partName);
+
+ if (part != null) {
+ document.removePart(part);
+ }
+ }
+
+ InvocationContext.ExcludeFields excludeFields = invocationContext.getExcludeFields();
+
+ if (excludeFields != null) {
+ List<String> fields = excludeFields.getField();
+
+ for (String field : fields) {
+ String[] segments = field.split(":", 2);
+
+ String partName = segments[0];
+ String xpath = segments[1];
+
+ PayloadOutputPart part = document.getPart(partName);
+
+ if (part != null) {
+ org.dom4j.Element partElement = part.getElementBody();
+ List<Node> matches = (List<Node>) partElement.createXPath(xpath).selectNodes(partElement);
+
+ for (Node excludeNode : matches) {
+ if (excludeNode.getNodeType() == Node.ELEMENT_NODE) {
+ excludeNode.detach();
+ }
+ }
+ }
+ }
+ }
+
+ InvocationContext.IncludeFields includeFields = invocationContext.getIncludeFields();
+
+ if (includeFields != null) {
+ List<String> fields = includeFields.getField();
+
+ for (String field : fields) {
+ String[] segments = field.split(":", 2);
+
+ String partName = segments[0];
+ String xpath = segments[1];
+
+ PayloadOutputPart part = document.getPart(partName);
+
+ if (part != null) {
+ org.dom4j.Element partElement = part.getElementBody();
+ List<Node> matches = (List<Node>) partElement.createXPath(xpath).selectNodes(partElement);
+
+ for (Node includeNode : matches) {
+ if (includeNode.getNodeType() == Node.ELEMENT_NODE) {
+ markIncluded((org.dom4j.Element) includeNode);
+ }
+ }
+ }
+ }
+
+ ArrayList<PayloadOutputPart> includedParts = new ArrayList<>();
+
+ for (PayloadOutputPart part : document.getParts()) {
+ org.dom4j.Element partElement = part.getElementBody();
+
+ if (partElement.attributeValue(INCLUDE_ATTRIBUTE_NAME) != null) {
+ includedParts.add(part);
+ removeUnincluded(partElement);
+ }
+ }
+
+ document.setParts(includedParts);
+ }
+ }
+
+ private void markIncluded(org.dom4j.Element element) {
+ org.dom4j.Element parentElement = element.getParent();
+
+ if (parentElement != null) {
+ markIncluded(parentElement);
+ }
+
+ element.addAttribute(INCLUDE_ATTRIBUTE_NAME, "1");
+ }
+
+ private void removeUnincluded(org.dom4j.Element element) {
+ if (element.attributeValue(INCLUDE_ATTRIBUTE_NAME) == null) {
+ element.detach();
+ }
+ else {
+ element.addAttribute(INCLUDE_ATTRIBUTE_NAME, null);
+
+ Iterator childIterator = element.elementIterator();
+
+ while (childIterator.hasNext()) {
+ org.dom4j.Element childElement = (org.dom4j.Element) childIterator.next();
+
+ removeUnincluded(childElement);
+ }
+ }
+ }
+
+ private ExportWriter getExportWriter(
+ ServiceContext<PoxPayloadIn, PoxPayloadOut> serviceContext,
+ InvocationContext invocationContext,
+ OutputStream outputStream) {
+
+ String outputMimeType = getOutputMimeType(invocationContext);
+ AbstractExportWriter exportWriter = null;
+
+ if (outputMimeType.equals(MIME_TYPE_XML)) {
+ exportWriter = new XmlExportWriter();
+ }
+ else if (outputMimeType.equals(MIME_TYPE_CSV)) {
+ exportWriter = new CsvExportWriter();
+ }
+
+ if (exportWriter != null) {
+ exportWriter.setInvocationContext(invocationContext);
+ exportWriter.setOutputStream(outputStream);
+ exportWriter.setServiceContext(serviceContext);
+ exportWriter.setTenantBindingConfigReader(getTenantBindingsReader());
+ }
+
+ return exportWriter;
+ }
+
+ private Iterator<PoxPayloadOut> getDocuments(
+ ServiceContext<PoxPayloadIn, PoxPayloadOut> serviceContext,
+ InvocationContext invocationContext) throws Exception {
+
+ String targetDocType = invocationContext.getDocType();
+ String targetVocabulary = invocationContext.getVocabulary();
+
+ switch (invocationContext.getMode().toLowerCase()) {
+ case Invocable.INVOCATION_MODE_QUERY:
+ return getDocumentsByQuery(serviceContext, targetDocType, targetVocabulary, invocationContext.getQuery());
+ case Invocable.INVOCATION_MODE_SINGLE:
+ return getDocumentByCsid(serviceContext, targetDocType, targetVocabulary, invocationContext.getSingleCSID());
+ case Invocable.INVOCATION_MODE_LIST:
+ return getDocumentsByCsid(serviceContext, targetDocType, targetVocabulary, invocationContext.getListCSIDs().getCsid());
+ case Invocable.INVOCATION_MODE_GROUP:
+ return getDocumentsByGroup(serviceContext, invocationContext.getGroupCSID());
+ case Invocable.INVOCATION_MODE_NO_CONTEXT:
+ return getDocumentsByType(serviceContext, targetDocType, targetVocabulary);
+ default:
+ throw new UnsupportedOperationException("Unsupported invocation mode: " + invocationContext.getMode());
+ }
+ }
+
+ private Iterator<PoxPayloadOut> getDocumentsByType(
+ ServiceContext<PoxPayloadIn, PoxPayloadOut> serviceContext,
+ String docType,
+ String vocabulary) throws Exception {
+
+ return getDocumentsByQuery(serviceContext, docType, vocabulary, new InvocationContext.Query());
+ }
+
+ private Iterator<PoxPayloadOut> getDocumentsByQuery(
+ ServiceContext<PoxPayloadIn, PoxPayloadOut> serviceContext,
+ String docType,
+ String vocabulary,
+ InvocationContext.Query query) throws Exception {
+
+ if (RelationClient.SERVICE_DOC_TYPE.equals(docType)) {
+ return new RelationsByQueryIterator(serviceContext, docType, vocabulary, query);
+ }
+
+ return new StandardDocumentsByQueryIterator(serviceContext, docType, vocabulary, query);
+ }
+
+ private Iterator<PoxPayloadOut> getDocumentByCsid(
+ ServiceContext<PoxPayloadIn, PoxPayloadOut> serviceContext,
+ String docType,
+ String vocabulary,
+ String csid) throws Exception {
+
+ return getDocumentsByCsid(serviceContext, docType, vocabulary, Arrays.asList(csid));
+ }
+
+ private Iterator<PoxPayloadOut> getDocumentsByCsid(
+ ServiceContext<PoxPayloadIn, PoxPayloadOut> serviceContext,
+ String docType,
+ String vocabulary,
+ List<String> csids) throws Exception {
+
+ return new DocumentsByCsidIterator(serviceContext, docType, vocabulary, csids);
+ }
+
+ private Iterator<PoxPayloadOut> getDocumentsByGroup(
+ ServiceContext<PoxPayloadIn, PoxPayloadOut> serviceContext,
+ String csid) throws Exception {
+
+ return new DocumentsByGroupIterator(serviceContext, csid);
+ }
+}
--- /dev/null
+package org.collectionspace.services.export;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Set;
+
+import org.collectionspace.services.client.PoxPayloadIn;
+import org.collectionspace.services.client.PoxPayloadOut;
+import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
+import org.collectionspace.services.common.context.ServiceContext;
+import org.collectionspace.services.common.invocable.InvocationContext;
+
+public interface ExportWriter {
+ public void setInvocationContext(InvocationContext invocationContext);
+ public void setOutputStream(OutputStream outputStream);
+ public void setServiceContext(ServiceContext<PoxPayloadIn, PoxPayloadOut> serviceContext);
+ public void setTenantBindingConfigReader(TenantBindingConfigReaderImpl tenantBindingConfigReader);
+
+ public void start() throws Exception;
+ public void writeDocument(PoxPayloadOut document) throws Exception;
+ public void finish() throws Exception;
+ public void close() throws Exception;
+}
--- /dev/null
+package org.collectionspace.services.export;
+
+import java.util.Iterator;
+
+import org.collectionspace.services.client.PoxPayloadIn;
+import org.collectionspace.services.client.PoxPayloadOut;
+import org.collectionspace.services.common.NuxeoBasedResource;
+import org.collectionspace.services.common.ServiceMain;
+import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
+import org.collectionspace.services.common.context.ServiceBindingUtils;
+import org.collectionspace.services.common.context.ServiceContext;
+import org.collectionspace.services.common.invocable.InvocationContext;
+import org.collectionspace.services.common.vocabulary.AuthorityResource;
+import org.collectionspace.services.config.service.ServiceBindingType;
+import org.collectionspace.services.relation.RelationsCommonList.RelationListItem;
+import org.collectionspace.services.relation.RelationsDocListItem;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RelationObjectsByQueryIterator extends RelationsByQueryIterator implements Iterator<PoxPayloadOut> {
+ private final Logger logger = LoggerFactory.getLogger(RelationObjectsByQueryIterator.class);
+
+ RelationObjectsByQueryIterator(
+ ServiceContext<PoxPayloadIn, PoxPayloadOut> serviceContext,
+ String docType,
+ String vocabulary,
+ InvocationContext.Query query) throws Exception {
+
+ super(serviceContext, docType, vocabulary, query);
+ }
+
+ @Override
+ protected PoxPayloadOut getDocument(RelationListItem item) {
+ RelationsDocListItem relationObject = item.getObject();
+
+ String relationObjectCsid = relationObject.getCsid();
+ String relationObjectDocType = relationObject.getDocumentType();
+
+ TenantBindingConfigReaderImpl tenantBindingConfigReader = ServiceMain.getInstance().getTenantBindingConfigReader();
+ ServiceBindingType relationObjectServiceBinding = tenantBindingConfigReader.getServiceBindingForDocType(serviceContext.getTenantId(), relationObjectDocType);
+ String relationObjectServiceType = relationObjectServiceBinding.getType();
+ String relationObjectServiceName = relationObjectServiceBinding.getName();
+
+ boolean relationObjectIsAuthorityItem = ServiceBindingUtils.SERVICE_TYPE_AUTHORITY.equals(relationObjectServiceType);
+
+ try {
+ NuxeoBasedResource relationObjectResource = relationObjectIsAuthorityItem
+ ? AuthorityResource.getResourceForItem(serviceContext.getResourceMap(), serviceContext.getTenantId(), relationObjectDocType)
+ : (NuxeoBasedResource) serviceContext.getResource(relationObjectServiceName.toLowerCase());
+
+ return (relationObjectIsAuthorityItem
+ ? ((AuthorityResource<?, ?>) relationObjectResource).getAuthorityItemWithExistingContext(serviceContext, AuthorityResource.PARENT_WILDCARD, relationObjectCsid)
+ : relationObjectResource.getWithParentCtx(serviceContext, relationObjectCsid));
+ }
+ catch (Exception e) {
+ logger.warn("Could not get document with csid " + relationObjectCsid, e);
+
+ return null;
+ }
+ }
+}
--- /dev/null
+
+package org.collectionspace.services.export;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.collectionspace.services.client.PoxPayloadIn;
+import org.collectionspace.services.client.PoxPayloadOut;
+import org.collectionspace.services.common.context.ServiceContext;
+import org.collectionspace.services.common.invocable.InvocationContext;
+import org.collectionspace.services.jaxb.AbstractCommonList;
+import org.collectionspace.services.relation.RelationsCommonList;
+import org.collectionspace.services.relation.RelationsCommonList.RelationListItem;
+
+public class RelationsByQueryIterator extends AbstractDocumentsByQueryIterator<RelationListItem> implements Iterator<PoxPayloadOut> {
+ RelationsByQueryIterator(
+ ServiceContext<PoxPayloadIn, PoxPayloadOut> serviceContext,
+ String docType,
+ String vocabulary,
+ InvocationContext.Query query) throws Exception {
+
+ super(serviceContext, docType, vocabulary, query);
+ }
+
+ @Override
+ protected List<RelationListItem> getListItems(AbstractCommonList list) {
+ return ((RelationsCommonList) list).getRelationListItem();
+ }
+
+ @Override
+ protected String getListItemCsid(RelationListItem listItem) {
+ return listItem.getCsid();
+ }
+}
--- /dev/null
+package org.collectionspace.services.export;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.collectionspace.services.client.PoxPayloadIn;
+import org.collectionspace.services.client.PoxPayloadOut;
+import org.collectionspace.services.common.context.ServiceContext;
+import org.collectionspace.services.common.invocable.InvocationContext;
+import org.collectionspace.services.jaxb.AbstractCommonList;
+import org.collectionspace.services.jaxb.AbstractCommonList.ListItem;
+
+import org.w3c.dom.Element;
+
+public class StandardDocumentsByQueryIterator extends AbstractDocumentsByQueryIterator<ListItem> implements Iterator<PoxPayloadOut> {
+ StandardDocumentsByQueryIterator(
+ ServiceContext<PoxPayloadIn, PoxPayloadOut> serviceContext,
+ String docType,
+ String vocabulary,
+ InvocationContext.Query query) throws Exception {
+
+ super(serviceContext, docType, vocabulary, query);
+ }
+
+ @Override
+ protected List<ListItem> getListItems(AbstractCommonList list) {
+ return list.getListItem();
+ }
+
+ @Override
+ protected String getListItemCsid(ListItem listItem) {
+ for (Element element : listItem.getAny()) {
+ if (element.getTagName().equals("csid")) {
+ return element.getTextContent();
+ }
+ }
+
+ return null;
+ }
+}
--- /dev/null
+package org.collectionspace.services.export;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+import org.collectionspace.services.client.PayloadOutputPart;
+import org.collectionspace.services.client.PoxPayloadOut;
+import org.collectionspace.services.config.service.ServiceBindingType;
+import org.collectionspace.services.config.service.ServiceObjectType;
+import org.dom4j.Element;
+import org.dom4j.Namespace;
+
+public class XmlExportWriter extends AbstractExportWriter {
+ private int seqNum = 0;
+
+ @Override
+ public void start() throws Exception {
+ seqNum = 0;
+
+ writer.write("<imports>\n");
+ }
+
+ @Override
+ public void writeDocument(PoxPayloadOut document) throws Exception {
+ String docType = document.getName();
+ ServiceBindingType serviceBinding = tenantBindingConfigReader.getServiceBinding(serviceContext.getTenantId(), docType);
+
+ String serviceName = serviceBinding.getName();
+ ServiceObjectType objectConfig = serviceBinding.getObject();
+ String objectName = objectConfig.getName();
+
+ seqNum += 1;
+
+ writer.write(String.format("<import seq=\"%d\" service=\"%s\" type=\"%s\">\n", seqNum, serviceName, objectName));
+
+ for (PayloadOutputPart part : document.getParts()) {
+ String partLabel = part.getLabel();
+ Element element = part.asElement();
+ Namespace partNamespace = element.getNamespaceForPrefix("ns2");
+ String partNamespaceUri = partNamespace.getURI();
+
+ for (Object namespace : element.additionalNamespaces()) {
+ element.remove((Namespace) namespace);
+ }
+
+ element.remove(partNamespace);
+
+ element.setName("schema");
+ element.addAttribute("name", partLabel);
+ element.addNamespace(partLabel, partNamespaceUri);
+
+ writer.write(element.asXML());
+ }
+
+ writer.write("</import>\n");
+ }
+
+ @Override
+ public void finish() throws Exception {
+ writer.write("</imports>");
+ }
+}
--- /dev/null
+/**
+ * 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.export.nuxeo;
+
+public class ExportConstants {
+ public final static String NUXEO_DOCTYPE = "Export";
+ public final static String NUXEO_SCHEMA_NAME = "export";
+ public final static String DB_COMMON_PART_TABLE_NAME = "exports_common";
+ public final static String NUXEO_DC_TITLE = "CollectionSpace-Export";
+}
--- /dev/null
+/**
+ * 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.export.nuxeo;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.ws.rs.core.MediaType;
+import javax.naming.NamingException;
+import javax.ws.rs.core.Response;
+
+import org.apache.commons.lang.StringUtils;
+import org.collectionspace.authentication.AuthN;
+import org.collectionspace.services.ExportJAXBSchema;
+import org.collectionspace.services.account.AccountResource;
+import org.collectionspace.services.authorization.AuthZ;
+import org.collectionspace.services.authorization.CSpaceResource;
+import org.collectionspace.services.authorization.PermissionException;
+import org.collectionspace.services.authorization.URIResourceImpl;
+import org.collectionspace.services.authorization.perms.ActionType;
+import org.collectionspace.services.client.PoxPayloadIn;
+import org.collectionspace.services.client.PoxPayloadOut;
+import org.collectionspace.services.client.ExportClient;
+import org.collectionspace.services.common.CSWebApplicationException;
+import org.collectionspace.services.common.NuxeoBasedResource;
+import org.collectionspace.services.common.ResourceMap;
+import org.collectionspace.services.common.ServiceMain;
+import org.collectionspace.services.common.api.JEEServerDeployment;
+import org.collectionspace.services.common.api.FileTools;
+import org.collectionspace.services.common.api.Tools;
+import org.collectionspace.services.common.authorization_mgt.ActionGroup;
+import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
+import org.collectionspace.services.common.context.ServiceBindingUtils;
+import org.collectionspace.services.common.context.ServiceContext;
+import org.collectionspace.services.common.document.BadRequestException;
+import org.collectionspace.services.common.document.DocumentException;
+import org.collectionspace.services.common.document.DocumentWrapper;
+import org.collectionspace.services.common.invocable.Invocable;
+import org.collectionspace.services.common.invocable.InvocationContext;
+import org.collectionspace.services.common.invocable.InvocationContext.ListCSIDs;
+import org.collectionspace.services.common.storage.JDBCTools;
+import org.collectionspace.services.config.service.ServiceBindingType;
+import org.collectionspace.services.config.types.PropertyItemType;
+import org.collectionspace.services.export.ExportsCommon;
+import org.collectionspace.services.jaxb.InvocableJAXBSchema;
+import org.collectionspace.services.nuxeo.client.java.NuxeoDocumentModelHandler;
+import org.collectionspace.services.nuxeo.client.java.CoreSessionInterface;
+import org.collectionspace.services.nuxeo.client.java.NuxeoRepositoryClientImpl;
+import org.collectionspace.services.nuxeo.util.NuxeoUtils;
+
+import org.nuxeo.ecm.core.api.model.PropertyException;
+import org.nuxeo.ecm.core.api.DocumentModel;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * ExportDocumentModelHandler
+ *
+ * $LastChangedRevision: $
+ * $LastChangedDate: $
+ */
+public class ExportDocumentModelHandler extends NuxeoDocumentModelHandler<ExportsCommon> {
+ private final Logger logger = LoggerFactory.getLogger(ExportDocumentModelHandler.class);
+
+ public InputStream invokeExport(
+ TenantBindingConfigReaderImpl tenantBindingReader,
+ ResourceMap resourceMap,
+ ServiceContext<PoxPayloadIn, PoxPayloadOut> serviceContext,
+ InvocationContext invocationContext,
+ StringBuffer outputMimeType,
+ StringBuffer outputFileName) throws Exception {
+
+ NuxeoRepositoryClientImpl repoClient = (NuxeoRepositoryClientImpl) this.getRepositoryClient(serviceContext);
+ boolean releaseRepoSession = false;
+ CoreSessionInterface repoSession = this.getRepositorySession();
+
+ if (repoSession == null) {
+ repoSession = repoClient.getRepositorySession(serviceContext);
+ releaseRepoSession = true;
+ }
+
+ try {
+ Iterator<DocumentModel> documents = findDocuments(tenantBindingReader, resourceMap, serviceContext, repoSession, invocationContext);
+
+ }
+ finally {
+ if (releaseRepoSession && repoSession != null) {
+ repoClient.releaseRepositorySession(serviceContext, repoSession);
+ }
+ }
+
+ return null;
+ // return buildExportResult(csid, params, exportFileNameProperty, outMimeType.toString(), outExportFileName);
+ }
+
+ private Iterator<DocumentModel> findDocuments(
+ TenantBindingConfigReaderImpl tenantBindingReader,
+ ResourceMap resourceMap,
+ ServiceContext<PoxPayloadIn, PoxPayloadOut> serviceContext,
+ CoreSessionInterface repoSession,
+ InvocationContext invocationContext) throws Exception {
+
+ String docType = invocationContext.getDocType();
+ ServiceBindingType binding = tenantBindingReader.getServiceBindingForDocType(serviceContext.getTenantId(), docType);
+ String serviceName = binding.getName();
+
+ switch (invocationContext.getMode().toLowerCase()) {
+ case Invocable.INVOCATION_MODE_SINGLE:
+ return findDocumentByCsid(resourceMap, serviceContext, repoSession, serviceName, invocationContext.getSingleCSID());
+ case Invocable.INVOCATION_MODE_LIST:
+ return findDocumentsByCsid(resourceMap, serviceContext, repoSession, serviceName, invocationContext.getListCSIDs().getCsid());
+ case Invocable.INVOCATION_MODE_GROUP:
+ return findDocumentsByGroup(resourceMap, serviceContext, repoSession, invocationContext.getGroupCSID());
+ case Invocable.INVOCATION_MODE_NO_CONTEXT:
+ return findDocumentsByType(resourceMap, serviceContext, repoSession, invocationContext.getDocType());
+ default:
+ return null;
+ }
+ }
+
+ private Iterator<DocumentModel> findDocumentByCsid(
+ ResourceMap resourceMap,
+ ServiceContext<PoxPayloadIn, PoxPayloadOut> serviceContext,
+ CoreSessionInterface repoSession,
+ String serviceName,
+ String csid) throws Exception {
+
+ return findDocumentsByCsid(resourceMap, serviceContext, repoSession, serviceName, Arrays.asList(csid));
+ }
+
+ private Iterator<DocumentModel> findDocumentsByCsid(
+ ResourceMap resourceMap,
+ ServiceContext<PoxPayloadIn, PoxPayloadOut> serviceContext,
+ CoreSessionInterface repoSession,
+ String serviceName,
+ List<String> csids) throws Exception {
+
+ return new DocumentsByCsidIterator(resourceMap, serviceContext, repoSession, serviceName, csids);
+ }
+
+ private Iterator<DocumentModel> findDocumentsByType(
+ ResourceMap resourceMap,
+ ServiceContext<PoxPayloadIn, PoxPayloadOut> serviceContext,
+ CoreSessionInterface repoSession,
+ String docType) {
+
+ return null;
+ }
+
+ private Iterator<DocumentModel> findDocumentsByGroup(
+ ResourceMap resourceMap,
+ ServiceContext<PoxPayloadIn, PoxPayloadOut> serviceContext,
+ CoreSessionInterface repoSession,
+ String docType) {
+
+ return null;
+ }
+
+ // private InputStream buildExportResult(String exportCSID,
+ // HashMap<String, Object> params,
+ // String exportFileName,
+ // String outputMimeType,
+ // StringBuffer outExportFileName) throws Exception {
+ // Connection conn = null;
+ // InputStream result = null;
+
+ // return result;
+ // }
+
+ private class DocumentsByCsidIterator implements Iterator<DocumentModel> {
+ private NuxeoBasedResource resource;
+ private ServiceContext<PoxPayloadIn, PoxPayloadOut> serviceContext;
+ private CoreSessionInterface repoSession;
+ private Iterator<String> csidIterator;
+
+ DocumentsByCsidIterator(
+ ResourceMap resourceMap,
+ ServiceContext<PoxPayloadIn, PoxPayloadOut> serviceContext,
+ CoreSessionInterface repoSession,
+ String serviceName,
+ List<String> csids) throws Exception {
+
+ NuxeoBasedResource resource = (NuxeoBasedResource) resourceMap.get(serviceName.toLowerCase());
+
+ if (resource == null) {
+ throw new Exception("Resource not found for service name " + serviceName);
+ }
+
+ this.resource = resource;
+ this.serviceContext = serviceContext;
+ this.repoSession = repoSession;
+ this.csidIterator = csids.iterator();
+ }
+
+ @Override
+ public boolean hasNext() {
+ return csidIterator.hasNext();
+ }
+
+ @Override
+ public DocumentModel next() {
+ String csid = csidIterator.next();
+
+ try {
+ // PoxPayloadOut payload = resource.getWithParentCtx(serviceContext, csid);
+ return null;
+ }
+ catch (Exception e) {
+ logger.warn("Could not get document with csid " + csid, e);
+
+ return null;
+ }
+ }
+ }
+}
--- /dev/null
+package org.collectionspace.services.export.nuxeo;
+
+import org.collectionspace.services.common.context.ServiceContext;
+import org.collectionspace.services.common.document.InvalidDocumentException;
+import org.collectionspace.services.common.document.ValidatorHandler;
+import org.collectionspace.services.common.document.DocumentHandler.Action;
+
+public class ExportValidatorHandler implements ValidatorHandler {
+
+ @Override
+ public void validate(Action action, ServiceContext ctx)
+ throws InvalidDocumentException {
+ // TODO Auto-generated method stub
+ System.out.println("ExportValidatorHandler executed.");
+
+ }
+
+}
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
Invocation Context schema (XSD)
-
+
Entity : Invocation
Used for: JAXB binding between XML and Java objects
<xs:element name="mode" type="xs:string"></xs:element>
<xs:element name="updateCoreValues" type="xs:string"></xs:element>
<xs:element name="docType" type="xs:string"></xs:element>
+ <xs:element name="vocabulary" type="xs:string"></xs:element>
<xs:element name="singleCSID" type="xs:string"></xs:element>
<xs:element name="groupCSID" type="xs:string"></xs:element>
<xs:element name="listCSIDs">
</xs:sequence>
</xs:complexType>
</xs:element>
+ <xs:element name="query">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="kw" type="xs:string"></xs:element>
+ <xs:element name="as" type="xs:string"></xs:element>
+ <xs:element name="pgSz" type="xs:integer"></xs:element>
+ <xs:element name="pgNum" type="xs:integer"></xs:element>
+ <xs:element name="wf_deleted" type="xs:boolean" minOccurs="0"></xs:element>
+
+ <!-- Relation query parameters -->
+ <xs:element name="sbj" type="xs:string"></xs:element>
+ <xs:element name="sbjType" type="xs:string"></xs:element>
+ <xs:element name="prd" type="xs:string"></xs:element>
+ <xs:element name="obj" type="xs:string"></xs:element>
+ <xs:element name="objType" type="xs:string"></xs:element>
+ <xs:element name="andReciprocal" type="xs:boolean" minOccurs="0"></xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="includeFields">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="field" type="xs:string" minOccurs="0" maxOccurs="unbounded"></xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="excludeFields">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="field" type="xs:string" minOccurs="0" maxOccurs="unbounded"></xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
<xs:element name="params">
<xs:complexType>
<xs:sequence>
<module>pottag</module>
<module>batch</module>
<module>imports</module>
+ <module>export</module>
<module>location</module>
<module>place</module>
<module>work</module>