) RemoteServiceContextFactory
+ .get();
+ }
+
+ @Override
+ public String getServiceName() {
+ return AdvancedSearchConstants.SERVICE_NAME;
+ }
+
+ @Override
+ protected String getVersionString() {
+ return "0.01";
+ }
+}
\ No newline at end of file
diff --git a/services/advancedsearch/service/src/main/java/org/collectionspace/services/advancedsearch/AdvancedSearchConstants.java b/services/advancedsearch/service/src/main/java/org/collectionspace/services/advancedsearch/AdvancedSearchConstants.java
new file mode 100644
index 0000000000..98d2879778
--- /dev/null
+++ b/services/advancedsearch/service/src/main/java/org/collectionspace/services/advancedsearch/AdvancedSearchConstants.java
@@ -0,0 +1,12 @@
+package org.collectionspace.services.advancedsearch;
+
+/**
+ * Constants for the AdvancedSearch API
+ */
+public interface AdvancedSearchConstants {
+
+ String SERVICE_NAME = "advancedsearch";
+ String SERVICE_PATH_COMPONENT = SERVICE_NAME;
+ String SERVICE_PATH = "/" + SERVICE_PATH_COMPONENT;
+
+}
diff --git a/services/advancedsearch/service/src/main/java/org/collectionspace/services/advancedsearch/AdvancedSearchJAXBContext.java b/services/advancedsearch/service/src/main/java/org/collectionspace/services/advancedsearch/AdvancedSearchJAXBContext.java
new file mode 100644
index 0000000000..9a1bb24d94
--- /dev/null
+++ b/services/advancedsearch/service/src/main/java/org/collectionspace/services/advancedsearch/AdvancedSearchJAXBContext.java
@@ -0,0 +1,33 @@
+package org.collectionspace.services.advancedsearch;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+
+import org.collectionspace.collectionspace_core.CollectionSpaceCore;
+import org.collectionspace.services.collectionobject.CollectionobjectsCommon;
+import org.collectionspace.services.collectionobject.domain.nagpra.CollectionObjectsNAGPRA;
+import org.collectionspace.services.collectionobject.domain.naturalhistory_extension.CollectionobjectsNaturalhistory;
+
+/**
+ * Singleton for the {@link JAXBContext} which the AdvancedSearch will use
+ * Eventually this should just be a bean which can be injected
+ * @since 8.3.0
+ */
+public final class AdvancedSearchJAXBContext {
+ private static final AdvancedSearchJAXBContext INSTANCE = new AdvancedSearchJAXBContext();
+
+ private final JAXBContext jaxbContext;
+
+ private AdvancedSearchJAXBContext() {
+ try {
+ jaxbContext = JAXBContext.newInstance(CollectionSpaceCore.class, CollectionobjectsCommon.class,
+ CollectionobjectsNaturalhistory.class, CollectionObjectsNAGPRA.class);
+ } catch (JAXBException e) {
+ throw new RuntimeException("Unable to create JAXBContext for AdvancedSearch");
+ }
+ }
+
+ public static JAXBContext getJaxbContext() {
+ return INSTANCE.jaxbContext;
+ }
+}
diff --git a/services/advancedsearch/service/src/main/java/org/collectionspace/services/advancedsearch/mapper/CollectionObjectMapper.java b/services/advancedsearch/service/src/main/java/org/collectionspace/services/advancedsearch/mapper/CollectionObjectMapper.java
new file mode 100644
index 0000000000..08c0311f9a
--- /dev/null
+++ b/services/advancedsearch/service/src/main/java/org/collectionspace/services/advancedsearch/mapper/CollectionObjectMapper.java
@@ -0,0 +1,178 @@
+package org.collectionspace.services.advancedsearch.mapper;
+
+import static org.collectionspace.services.client.CollectionSpaceClient.COLLECTIONSPACE_CORE_SCHEMA;
+import static org.collectionspace.services.client.CollectionSpaceClient.NAGPRA_EXTENSION_NAME;
+import static org.collectionspace.services.client.CollectionSpaceClient.NATURALHISTORY_EXT_EXTENSION_NAME;
+import static org.collectionspace.services.client.CollectionSpaceClient.PART_COMMON_LABEL;
+import static org.collectionspace.services.client.CollectionSpaceClient.PART_LABEL_SEPARATOR;
+
+import java.util.Map;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+import org.collectionspace.collectionspace_core.CollectionSpaceCore;
+import org.collectionspace.services.MediaJAXBSchema;
+import org.collectionspace.services.advancedsearch.AdvancedsearchCommonList.AdvancedsearchListItem;
+import org.collectionspace.services.advancedsearch.ObjectFactory;
+import org.collectionspace.services.advancedsearch.model.AgentModel;
+import org.collectionspace.services.advancedsearch.model.BriefDescriptionListModel;
+import org.collectionspace.services.advancedsearch.model.ContentConceptListModel;
+import org.collectionspace.services.advancedsearch.model.FieldCollectionModel;
+import org.collectionspace.services.advancedsearch.model.MaterialModel;
+import org.collectionspace.services.advancedsearch.model.NAGPRACategoryModel;
+import org.collectionspace.services.advancedsearch.model.ObjectNameListModel;
+import org.collectionspace.services.advancedsearch.model.ObjectProductionModel;
+import org.collectionspace.services.advancedsearch.model.ResponsibleDepartmentsListModel;
+import org.collectionspace.services.advancedsearch.model.TaxonModel;
+import org.collectionspace.services.advancedsearch.model.TitleGroupListModel;
+import org.collectionspace.services.client.CollectionObjectClient;
+import org.collectionspace.services.client.PayloadOutputPart;
+import org.collectionspace.services.client.PoxPayloadOut;
+import org.collectionspace.services.collectionobject.CollectionobjectsCommon;
+import org.collectionspace.services.collectionobject.domain.nagpra.CollectionObjectsNAGPRA;
+import org.collectionspace.services.collectionobject.domain.naturalhistory_extension.CollectionobjectsNaturalhistory;
+import org.collectionspace.services.nuxeo.client.handler.CSDocumentModelList.CSDocumentModelResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+
+/**
+ * A class for mapping {@link CSDocumentModelResponse} to {@link AdvancedsearchListItem}.
+ *
+ * @since 8.3.0
+ */
+public class CollectionObjectMapper {
+
+ private static final Logger logger = LoggerFactory.getLogger(CollectionObjectMapper.class);
+
+ private static final String COMMON_PART_NAME =
+ CollectionObjectClient.SERVICE_NAME + PART_LABEL_SEPARATOR + PART_COMMON_LABEL;
+
+ private static final String NATHIST_PART_NAME =
+ CollectionObjectClient.SERVICE_NAME + PART_LABEL_SEPARATOR + NATURALHISTORY_EXT_EXTENSION_NAME;
+
+ private static final String NAGPRA_PART_NAME =
+ CollectionObjectClient.SERVICE_NAME + PART_LABEL_SEPARATOR + NAGPRA_EXTENSION_NAME;
+
+ private final ObjectFactory objectFactory;
+ private final Unmarshaller unmarshaller;
+
+ public CollectionObjectMapper(Unmarshaller unmarshaller) {
+ this.unmarshaller = unmarshaller;
+ this.objectFactory = new ObjectFactory();
+ }
+
+ /**
+ * Map a {@link CSDocumentModelResponse} to a {@link AdvancedsearchListItem}. This looks at the response for each
+ * of the collectionspace_core, collectionobjects_common, collectionobjects_nagpra, and
+ * collectionobjects_naturalhistory_extension parts and pulls fields out of each based on the search specification.
+ * We don't differentiate between profiles here and instead return everything available for the ui.
+ *
+ * Note that this doesn't handle the {@link AdvancedsearchListItem#setRelated(Boolean)} as that requires access to
+ * the RelationResource. Maybe worth doing through an additional parameter.
+ * @param response The response from the CollectionObjectResource for a single object
+ * @param blobCsids The blobs associated with the object
+ * @return the advanced search list item
+ */
+ public AdvancedsearchListItem asListItem(final CSDocumentModelResponse response,
+ final Map blobInfo) {
+ // todo: what makes sense here?
+ if (response == null || response.getPayload() == null) {
+ return objectFactory.createAdvancedsearchCommonListAdvancedsearchListItem();
+ }
+
+ final AdvancedsearchListItem item = objectFactory.createAdvancedsearchCommonListAdvancedsearchListItem();
+
+ final PoxPayloadOut outputPayload = response.getPayload();
+
+ final CollectionSpaceCore core =
+ unmarshall(CollectionSpaceCore.class, COLLECTIONSPACE_CORE_SCHEMA, outputPayload, unmarshaller);
+
+ final CollectionobjectsCommon collectionObject =
+ unmarshall(CollectionobjectsCommon.class, COMMON_PART_NAME, outputPayload, unmarshaller);
+
+ final CollectionObjectsNAGPRA objectsNAGPRA =
+ unmarshall(CollectionObjectsNAGPRA.class, NAGPRA_PART_NAME, outputPayload, unmarshaller);
+
+ final CollectionobjectsNaturalhistory naturalHistory =
+ unmarshall(CollectionobjectsNaturalhistory.class, NATHIST_PART_NAME, outputPayload, unmarshaller);
+
+ final String csid = response.getCsid();
+ item.setCsid(csid);
+ if (core != null) {
+ item.setRefName(core.getRefName());
+ item.setUri(core.getUri());
+ item.setUpdatedAt(core.getUpdatedAt());
+ } else {
+ logger.warn("advancedsearch: could not find collectionspace_core associated with csid {}", csid);
+ }
+
+ if (collectionObject != null) {
+ item.setObjectNumber(collectionObject.getObjectNumber());
+ item.setBriefDescription(BriefDescriptionListModel.briefDescriptionListToDisplayString(
+ collectionObject.getBriefDescriptions()));
+ item.setComputedCurrentLocation(collectionObject.getComputedCurrentLocation());
+
+ item.setTitle(TitleGroupListModel.titleGroupListToDisplayString(collectionObject.getTitleGroupList()));
+ item.setResponsibleDepartment(
+ ResponsibleDepartmentsListModel.responsibleDepartmentString(collectionObject));
+
+ item.setObjectName(ObjectNameListModel.objectName(collectionObject));
+ item.setObjectNameControlled(ObjectNameListModel.objectNameControlled(collectionObject));
+
+ item.setContentConcepts(ContentConceptListModel.contentConceptList(collectionObject));
+
+ // Field collection items (place, site, date, collector, role)
+ item.setFieldCollectionPlace(FieldCollectionModel.fieldCollectionPlace(collectionObject));
+ item.setFieldCollectionSite(FieldCollectionModel.fieldCollectionSite(collectionObject));
+ item.setFieldCollectionDate(FieldCollectionModel.fieldCollectionDate(collectionObject));
+ FieldCollectionModel.fieldCollector(collectionObject).ifPresent(collector -> {
+ item.setFieldCollector(collector);
+ item.setFieldCollectorRole("field collector"); // todo: how would we i18n this?
+ });
+
+ // Object Production Information (place, date, agent, agent role)
+ item.setObjectProductionDate(ObjectProductionModel.objectProductionDate(collectionObject));
+ item.setObjectProductionPlace(ObjectProductionModel.objectProductionPlace(collectionObject));
+
+ AgentModel.agent(collectionObject).ifPresent(agent -> {
+ item.setAgent(agent.getAgent());
+ item.setAgentRole(agent.getRole());
+ });
+
+ item.setForm(TaxonModel.preservationForm(collectionObject));
+ item.setMaterial(MaterialModel.material(collectionObject));
+
+ // from media resource
+ if (!blobInfo.isEmpty()) {
+ item.setBlobCsid(blobInfo.get(MediaJAXBSchema.blobCsid));
+ item.setBlobAltText(blobInfo.get(MediaJAXBSchema.altText));
+ }
+ } else {
+ logger.warn("advancedsearch: could not find CollectionobjectsCommon associated with csid {}", csid);
+ }
+
+ if (naturalHistory != null) {
+ item.setTaxon(TaxonModel.taxon(naturalHistory));
+ item.setDeterminationTaxon(TaxonModel.determinationTaxon(naturalHistory));
+ }
+
+ if (objectsNAGPRA != null) {
+ item.setNagpraCategories(NAGPRACategoryModel.napgraCategories(objectsNAGPRA));
+ }
+
+ return item;
+ }
+
+ public T unmarshall(Class clazz, String namespace, PoxPayloadOut out, Unmarshaller unmarshaller) {
+ PayloadOutputPart part = out.getPart(namespace);
+ if (part == null) {
+ return null;
+ }
+
+ try {
+ return clazz.cast(unmarshaller.unmarshal((Document) part.getBody()));
+ } catch (JAXBException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/services/authentication/pstore/pom.xml b/services/authentication/pstore/pom.xml
index f30e550361..3b61d781b7 100644
--- a/services/authentication/pstore/pom.xml
+++ b/services/authentication/pstore/pom.xml
@@ -19,10 +19,6 @@
-
- mysql
- mysql-connector-java
-
org.postgresql
postgresql
diff --git a/services/authentication/service/src/test/java/org/collectionspace/authentication/AppTest.java b/services/authentication/service/src/test/java/org/collectionspace/authentication/AppTest.java
deleted file mode 100644
index 737ba7aaa6..0000000000
--- a/services/authentication/service/src/test/java/org/collectionspace/authentication/AppTest.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.collectionspace.authentication;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-/**
- * Unit test for simple App.
- */
-public class AppTest
- extends TestCase
-{
- /**
- * Create the test case
- *
- * @param testName name of the test case
- */
- public AppTest( String testName )
- {
- super( testName );
- }
-
- /**
- * @return the suite of tests being tested
- */
- public static Test suite()
- {
- return new TestSuite( AppTest.class );
- }
-
- /**
- * Rigourous Test :-)
- */
- public void testApp()
- {
- assertTrue( true );
- }
-}
diff --git a/services/authority/pom.xml b/services/authority/pom.xml
index 0b8aca118d..62f9ec0bb8 100644
--- a/services/authority/pom.xml
+++ b/services/authority/pom.xml
@@ -44,10 +44,6 @@
jacc
1.0
provided
-
-
- mysql
- mysql-connector-java
org.postgresql
diff --git a/services/authority/service/pom.xml b/services/authority/service/pom.xml
index 6fc97ecfb1..d0ec4e86ba 100644
--- a/services/authority/service/pom.xml
+++ b/services/authority/service/pom.xml
@@ -136,10 +136,6 @@
1.0
provided
-
- mysql
- mysql-connector-java
-
org.postgresql
postgresql
diff --git a/services/authorization-mgt/client/pom.xml b/services/authorization-mgt/client/pom.xml
index 4cac00d993..3bfc04abb6 100644
--- a/services/authorization-mgt/client/pom.xml
+++ b/services/authorization-mgt/client/pom.xml
@@ -133,11 +133,6 @@
ehcache
true
-
- mysql
- mysql-connector-java
- test
-
org.postgresql
postgresql
diff --git a/services/authorization-mgt/import/pom.xml b/services/authorization-mgt/import/pom.xml
index 0963bf1e7b..74e88e9590 100644
--- a/services/authorization-mgt/import/pom.xml
+++ b/services/authorization-mgt/import/pom.xml
@@ -135,10 +135,6 @@
ehcache
2.10.2
-
- mysql
- mysql-connector-java
-
org.postgresql
postgresql
@@ -146,6 +142,16 @@
ch.elca.el4j.modules
module-xml_merge-common
+
+
+ commons-codec
+ commons-codec
+
+
+ xml-apis
+ xml-apis
+
+
org.collectionspace.services
diff --git a/services/authorization/pstore/pom.xml b/services/authorization/pstore/pom.xml
index 5a5c1f23d9..e4753e2985 100644
--- a/services/authorization/pstore/pom.xml
+++ b/services/authorization/pstore/pom.xml
@@ -19,10 +19,6 @@
org.collectionspace.services
org.collectionspace.services.authorization.jaxb
${project.version}
-
-
- mysql
- mysql-connector-java
org.postgresql
diff --git a/services/authorization/service/pom.xml b/services/authorization/service/pom.xml
index fff5e47465..1f2146fc15 100644
--- a/services/authorization/service/pom.xml
+++ b/services/authorization/service/pom.xml
@@ -106,11 +106,6 @@
net.sf.ehcache
ehcache
true
-
-
- mysql
- mysql-connector-java
- test
org.postgresql
diff --git a/services/blob/blob-test-utils/pom.xml b/services/blob/blob-test-utils/pom.xml
new file mode 100644
index 0000000000..87d3b79e05
--- /dev/null
+++ b/services/blob/blob-test-utils/pom.xml
@@ -0,0 +1,39 @@
+
+
+ 4.0.0
+
+
+ org.collectionspace.services
+ org.collectionspace.services.blob
+ ${revision}
+
+
+ org.collectionspace.services.blob
+ blob-test-utils
+ services.blob.blob-test-utils
+ jar
+
+
+
+
+ org.apache.maven.plugins
+ maven-remote-resources-plugin
+
+
+
+ bundle
+
+
+
+
+
+ **/*.jpg
+
+
+
+
+
+
+
diff --git a/services/blob/blob-test-utils/src/main/java/org/collectionspace/serivces/blob/StaticImage.java b/services/blob/blob-test-utils/src/main/java/org/collectionspace/serivces/blob/StaticImage.java
new file mode 100644
index 0000000000..a73d9df342
--- /dev/null
+++ b/services/blob/blob-test-utils/src/main/java/org/collectionspace/serivces/blob/StaticImage.java
@@ -0,0 +1,28 @@
+package org.collectionspace.serivces.blob;
+
+/**
+ * Static images which are served by an embedded jetty server. These are the images found under src/main/resources and
+ * it's expected that they're served on /static in jetty, e.g. /static/bird.jpg
+ *
+ * @since 8.3.0
+ */
+public enum StaticImage {
+ BIRD("bird.jpg"),
+ DECK("deck.jpg");
+
+ private final String path;
+
+ StaticImage(final String path) {
+ this.path = path;
+ }
+
+ public String getUrl() {
+ final String port = System.getProperty("jetty.port");
+ if (port == null) {
+ throw new RuntimeException("jetty.port property is not set; check your maven plugin configuration");
+ }
+
+ return "http://localhost:" + port + "/static/" + path;
+ }
+
+}
diff --git a/services/blob/blob-test-utils/src/main/resources/bird.jpg b/services/blob/blob-test-utils/src/main/resources/bird.jpg
new file mode 100644
index 0000000000..6a744c90fe
Binary files /dev/null and b/services/blob/blob-test-utils/src/main/resources/bird.jpg differ
diff --git a/services/blob/blob-test-utils/src/main/resources/deck.jpg b/services/blob/blob-test-utils/src/main/resources/deck.jpg
new file mode 100644
index 0000000000..23f43dd243
Binary files /dev/null and b/services/blob/blob-test-utils/src/main/resources/deck.jpg differ
diff --git a/services/blob/client/pom.xml b/services/blob/client/pom.xml
index c9362cc777..9e004c39ca 100644
--- a/services/blob/client/pom.xml
+++ b/services/blob/client/pom.xml
@@ -1,84 +1,141 @@
-
- org.collectionspace.services
- org.collectionspace.services.blob
- ${revision}
-
+ 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">
+
+ org.collectionspace.services
+ org.collectionspace.services.blob
+ ${revision}
+
- 4.0.0
- org.collectionspace.services.blob.client
- services.blob.client
+ 4.0.0
+ org.collectionspace.services.blob.client
+ services.blob.client
-
-
- org.nuxeo.ecm.core
- nuxeo-core-storage-sql-management
- ${nuxeo.general.release}
-
-
- org.slf4j
- slf4j-log4j17
-
-
-
+
+
+
+ org.collectionspace.services
+ org.collectionspace.services.jaxb
+ ${project.version}
+
+
+ org.collectionspace.services
+ org.collectionspace.services.client
+ ${project.version}
+
+
+ org.collectionspace.services
+ org.collectionspace.services.person.client
+ ${project.version}
+ test
+
+
+ org.collectionspace.services.blob
+ blob-test-utils
+ ${project.version}
+ test
+
+
+
+ org.jboss.resteasy
+ resteasy-multipart-provider
+
-
-
- org.collectionspace.services
- org.collectionspace.services.authority.jaxb
- true
- ${project.version}
-
-
- org.collectionspace.services
- org.collectionspace.services.jaxb
- ${project.version}
-
-
-
- org.collectionspace.services
- org.collectionspace.services.client
- ${project.version}
-
-
- org.collectionspace.services
- org.collectionspace.services.person.client
- ${project.version}
-
-
-
- org.testng
- testng
-
-
- org.jboss.resteasy
- resteasy-jaxrs
-
-
- org.jboss.resteasy
- resteasy-jaxb-provider
-
-
- org.jboss.resteasy
- resteasy-multipart-provider
-
-
- commons-httpclient
- commons-httpclient
-
-
+
+ org.testng
+ testng
+ test
+
+
-
- collectionspace-services-blob-client
-
+
+ collectionspace-services-blob-client
+
+
+ org.apache.maven.plugins
+ maven-remote-resources-plugin
+
+
+ org.collectionspace.services.blob:blob-test-utils:${project.version}
+
+
+
+
+
+ process
+
+
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+ 3.6.0
+
+
+ jetty.port
+ jetty.stop.port
+
+
+
+
+
+
+
+
+
+ reserve-port
+ test-compile
+
+ reserve-network-port
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.5.3
+
+
+ **/*IT.class
+
+
+
+
+
+ org.eclipse.jetty
+ jetty-maven-plugin
+
+
+ ${jetty.port}
+
+ quit
+ ${jetty.stop.port}
+ 10
+
+
+ /static
+ ${project.build.directory}/maven-shared-archive-resources
+
+
+
+ jar
+
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+ ${jetty.port}
+
+
+
+
+
diff --git a/services/blob/client/src/test/java/org/collectionspace/services/client/test/BlobScaleTest.java b/services/blob/client/src/test/java/org/collectionspace/services/client/test/BlobScaleIT.java
similarity index 78%
rename from services/blob/client/src/test/java/org/collectionspace/services/client/test/BlobScaleTest.java
rename to services/blob/client/src/test/java/org/collectionspace/services/client/test/BlobScaleIT.java
index 2742c23c64..a1ddfe696b 100644
--- a/services/blob/client/src/test/java/org/collectionspace/services/client/test/BlobScaleTest.java
+++ b/services/blob/client/src/test/java/org/collectionspace/services/client/test/BlobScaleIT.java
@@ -6,8 +6,6 @@
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
@@ -15,6 +13,7 @@
import javax.imageio.ImageIO;
import javax.ws.rs.core.Response;
+import org.collectionspace.serivces.blob.StaticImage;
import org.collectionspace.services.client.BlobClient;
import org.collectionspace.services.client.CollectionSpaceClient;
import org.collectionspace.services.client.Profiler;
@@ -24,9 +23,9 @@
import org.testng.annotations.Test;
@SuppressWarnings("rawtypes")
-public class BlobScaleTest extends BaseServiceTest {
+public class BlobScaleIT extends BaseServiceTest {
- private final Logger logger = LoggerFactory.getLogger(BlobScaleTest.class);
+ private final Logger logger = LoggerFactory.getLogger(BlobScaleIT.class);
private static final int IMAGE_SIZE = 1000;
private static final int IMAGE_EDGE = -15;
@@ -34,7 +33,6 @@ public class BlobScaleTest extends BaseServiceTest {
private static final int MAX_FONTSIZE = 60;
private static final String IMAGES_TO_CREATE_PROP = "imagesToCreate";
private static final int DEFAULT_IMAGES_TO_CREATE = 3; // Override this value by setting a system property named 'imagesToCreate' -i.e., mvn test -DimagesToCreate=30
- private static final int DEFAULT_IMAGES_TO_GET = DEFAULT_IMAGES_TO_CREATE;
private static final String GENERATED_IMAGES = "target/generated_images";
private List allGeneratedImages = new ArrayList();
@@ -71,9 +69,7 @@ private int getImagesToCreate() {
+ IMAGES_TO_CREATE_PROP
+ "' was defined, so we'll use the default instead.");
} finally {
- logger.info("Testing blob scaling by creating "
- + result
- + " images.");
+ logger.info("Testing blob scaling by creating {} images.", result);
}
return result;
@@ -89,14 +85,14 @@ public void scaleGETTest(String testName) throws Exception {
Thread.sleep(3000); // sleep for 3 seconds
for (int i = 0; i < allGeneratedImages.size(); i++) {
- Response res = client.getDerivativeContent(allGeneratedImages.get(i), "Thumbnail");
- try {
- assertStatusCode(res, testName);
- logger.debug(String.format("Performed GET operation on Thumbnail derivative of image blob ID = '%s'.",
- allGeneratedImages.get(i)));
- } finally {
- res.close();
- }
+ Response res = client.getDerivativeContent(allGeneratedImages.get(i), "Thumbnail");
+ try {
+ assertStatusCode(res, testName);
+ logger.debug("Performed GET operation on Thumbnail derivative of image blob ID = '{}'.",
+ allGeneratedImages.get(i));
+ } finally {
+ res.close();
+ }
}
}
@@ -110,21 +106,15 @@ public void scaleTest(String testName) throws Exception {
for (int i = 0; i < imagesToCreate; i++, profiler.reset()) {
File jpegFile = createJpeg(GENERATED_IMAGES);
- URL url = jpegFile.toURI().toURL();
- profiler.start();
- Response res = client.createBlobFromURI("https://farm6.static.flickr.com/5289/5688023100_15e00cde47_o.jpg");//url.toString());
+ profiler.start();
+ Response res = client.createBlobFromURI(StaticImage.BIRD.getUrl());
try {
profiler.stop();
assertStatusCode(res, testName);
- logger.debug(
- i + ": Uploaded image to Nuxeo in "
- + profiler.getCumulativeTime()
- + " milleseconds "
- + " - "
- + " : "
- + jpegFile.getAbsolutePath());
+ logger.debug("{}: Uploaded image to Nuxeo in {} milleseconds - : {}", i, profiler.getCumulativeTime(),
+ jpegFile.getAbsolutePath());
String csid = extractId(res);
this.knownResourceId = csid;
@@ -138,14 +128,12 @@ public void scaleTest(String testName) throws Exception {
}
}
- private void createDirectory(String dirName) {
- boolean success = (
- new File(dirName)).mkdir();
- if (success) {
- logger.debug("Directory: "
- + dirName + " created");
- }
- }
+ private void createDirectory(String dirName) {
+ boolean success = (new File(dirName)).mkdir();
+ if (success) {
+ logger.debug("Directory: {} created", dirName);
+ }
+ }
public File createJpeg(String destDir) {
File result = null;
diff --git a/services/blob/client/src/test/java/org/collectionspace/services/client/test/BlobServiceTest.java b/services/blob/client/src/test/java/org/collectionspace/services/client/test/BlobServiceIT.java
similarity index 76%
rename from services/blob/client/src/test/java/org/collectionspace/services/client/test/BlobServiceTest.java
rename to services/blob/client/src/test/java/org/collectionspace/services/client/test/BlobServiceIT.java
index 52fce8a546..c47448d20e 100644
--- a/services/blob/client/src/test/java/org/collectionspace/services/client/test/BlobServiceTest.java
+++ b/services/blob/client/src/test/java/org/collectionspace/services/client/test/BlobServiceIT.java
@@ -30,6 +30,7 @@
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
+import org.collectionspace.serivces.blob.StaticImage;
import org.collectionspace.services.client.CollectionSpaceClient;
import org.collectionspace.services.client.BlobClient;
import org.collectionspace.services.client.PayloadOutputPart;
@@ -51,22 +52,17 @@
* $LastChangedDate: $
*/
@SuppressWarnings("rawtypes")
-public class BlobServiceTest extends AbstractPoxServiceTestImpl {
+public class BlobServiceIT extends AbstractPoxServiceTestImpl {
- private final String CLASS_NAME = BlobServiceTest.class.getName();
- private final Logger logger = LoggerFactory.getLogger(CLASS_NAME);
+ private final Logger logger = LoggerFactory.getLogger(BlobServiceIT.class);
private final static String KNOWN_IMAGE_FILENAME = "01-03-09_1546.jpg";
private final static int WIDTH_DIMENSION_INDEX = 0;
private final static int HEIGHT_DIMENSION_INDEX = 1;
- private final static String KNOWN_IMAGE_SIZE = "56261";
- private final static BigDecimal KNOWN_IMAGE_WIDTH = new BigDecimal(640.0);
- private final static BigDecimal KNOWN_IMAGE_HEIGHT = new BigDecimal(480.0);
-
- private final static String PUBLIC_URL_BIRD = "https://farm6.static.flickr.com/5289/5688023100_15e00cde47_o.jpg";
- private final static String PUBLIC_URL_DECK = "https://farm8.staticflickr.com/7231/6962564226_4bdfc17599_k_d.jpg";
-
+ private static final String KNOWN_IMAGE_SIZE = "56261";
+ private static final BigDecimal KNOWN_IMAGE_WIDTH = new BigDecimal("640.0");
+ private static final BigDecimal KNOWN_IMAGE_HEIGHT = new BigDecimal("480.0");
private boolean blobCleanup = true;
@@ -131,44 +127,44 @@ protected void createBlob(String testName, boolean fromUri, String uri) throws E
String blobsDirPath = currentDir + File.separator + BLOBS_DIR;
File blobsDir = new File(blobsDirPath);
if (blobsDir != null && blobsDir.exists()) {
- File[] children = blobsDir.listFiles();
- if (children != null && children.length > 0) {
- for (File child : children) {
- if (isBlobbable(child) == true) {
- Response res = null;
- String mimeType = this.getMimeType(child);
- logger.debug("Processing file URI: " + child.getAbsolutePath());
- logger.debug("MIME type is: " + mimeType);
- if (fromUri == true) {
- if (uri != null) {
- res = client.createBlobFromURI(uri);
- //break;
- } else {
- URL childUrl = child.toURI().toURL();
- res = client.createBlobFromURI(childUrl.toString());
- }
- } else {
- MultipartFormDataOutput form = new MultipartFormDataOutput();
- OutputPart outputPart = form.addFormData("file", child, MediaType.valueOf(mimeType));
- res = client.createBlobFromFormData(form);
- }
- try {
- assertStatusCode(res, testName);
- if (isBlobCleanup() == true) {
- allResourceIdsCreated.add(extractId(res));
- }
- } finally {
- if (res != null) {
- res.close();
- }
- }
- }
- }
- } else {
- logger.debug("Directory: " + blobsDirPath + " is empty or cannot be read.");
- }
+ File[] children = blobsDir.listFiles();
+ if (children != null && children.length > 0) {
+ for (File child : children) {
+ if (isBlobbable(child)) {
+ Response res = null;
+ String mimeType = this.getMimeType(child);
+ logger.debug("Processing file URI: {}", child.getAbsolutePath());
+ logger.debug("MIME type is: {}", mimeType);
+ if (fromUri) {
+ if (uri != null) {
+ res = client.createBlobFromURI(uri);
+ // break;
+ } else {
+ URL childUrl = child.toURI().toURL();
+ res = client.createBlobFromURI(childUrl.toString());
+ }
+ } else {
+ MultipartFormDataOutput form = new MultipartFormDataOutput();
+ OutputPart outputPart = form.addFormData("file", child, MediaType.valueOf(mimeType));
+ res = client.createBlobFromFormData(form);
+ }
+ try {
+ assertStatusCode(res, testName);
+ if (isBlobCleanup()) {
+ allResourceIdsCreated.add(extractId(res));
+ }
+ } finally {
+ if (res != null) {
+ res.close();
+ }
+ }
+ }
+ }
+ } else {
+ logger.debug("Directory: {} is empty or cannot be read.", blobsDirPath);
+ }
} else {
- logger.debug("Directory: " + blobsDirPath + " is missing or cannot be read.");
+ logger.debug("Directory: {} is missing or cannot be read.", blobsDirPath);
}
}
@@ -189,17 +185,17 @@ public void testImageDimensions(String testName) throws Exception {
// Create the blob
//
BlobClient client = new BlobClient();
- Response res = null;
- res = client.createBlobFromURI(uri);
- String blobCsid = null;
- try {
- assertStatusCode(res, testName);
- blobCsid = extractId(res);
- if (isBlobCleanup() == true) {
- allResourceIdsCreated.add(blobCsid);
- }
- } finally {
- if (res != null) {
+ Response res = null;
+ res = client.createBlobFromURI(uri);
+ String blobCsid = null;
+ try {
+ assertStatusCode(res, testName);
+ blobCsid = extractId(res);
+ if (isBlobCleanup()) {
+ allResourceIdsCreated.add(blobCsid);
+ }
+ } finally {
+ if (res != null) {
res.close();
}
}
@@ -243,13 +239,13 @@ public void createBlobWithURI(String testName) throws Exception {
@Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
dependsOnMethods = {"CRUDTests"})
public void createBlobWithURL1(String testName) throws Exception {
- createBlob(testName, true /*with URI*/, PUBLIC_URL_BIRD);
+ createBlob(testName, true /*with URI*/, StaticImage.BIRD.getUrl());
}
@Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
dependsOnMethods = {"CRUDTests"})
public void createBlobWithURL2(String testName) throws Exception {
- createBlob(testName, true /*with URI*/, PUBLIC_URL_DECK);
+ createBlob(testName, true /*with URI*/, StaticImage.DECK.getUrl());
}
@Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
@@ -275,10 +271,8 @@ private PoxPayloadOut createBlobInstance(String exitNumber) throws Exception {
PoxPayloadOut multipart = new PoxPayloadOut(BlobClient.SERVICE_PAYLOAD_NAME);
PayloadOutputPart commonPart = multipart.addPart(client.getCommonPartName(), blob);
- if (logger.isDebugEnabled()) {
- logger.debug("to be created, blob common");
- logger.debug(objectAsXmlString(blob, BlobsCommon.class));
- }
+ logger.debug("to be created, blob common");
+ logger.debug(objectAsXmlString(blob, BlobsCommon.class));
return multipart;
}
diff --git a/services/blob/pom.xml b/services/blob/pom.xml
index 16fa38bd51..b484c38baa 100644
--- a/services/blob/pom.xml
+++ b/services/blob/pom.xml
@@ -13,6 +13,7 @@
http://www.collectionspace.org
+ blob-test-utils
client
3rdparty
service
diff --git a/services/blob/service/src/test/java/org/collectionspace/services/test/BlobServiceTest.java b/services/blob/service/src/test/java/org/collectionspace/services/test/BlobServiceTest.java
deleted file mode 100644
index 50eb4b713e..0000000000
--- a/services/blob/service/src/test/java/org/collectionspace/services/test/BlobServiceTest.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package org.collectionspace.services.test;
-
-//import org.collectionspace.services.blob.Blob;
-//import org.collectionspace.services.blob.BlobList;
-
-/**
- * Placeholder for server-side testing of Loan Out service code.
- *
- * @version $Revision: 2108 $
- */
-public class BlobServiceTest {
- //empty
-}
diff --git a/services/build.xml b/services/build.xml
index 2243e471e4..0ab996d00e 100644
--- a/services/build.xml
+++ b/services/build.xml
@@ -200,6 +200,7 @@
+
@@ -207,6 +208,7 @@
+
@@ -307,6 +309,7 @@
+
diff --git a/services/client/src/main/java/org/collectionspace/services/client/CollectionSpaceClient.java b/services/client/src/main/java/org/collectionspace/services/client/CollectionSpaceClient.java
index 8324310e87..d57aee8ea3 100644
--- a/services/client/src/main/java/org/collectionspace/services/client/CollectionSpaceClient.java
+++ b/services/client/src/main/java/org/collectionspace/services/client/CollectionSpaceClient.java
@@ -98,6 +98,7 @@ public interface CollectionSpaceClient {
-
- public GenericAuthorityClientImpl() throws Exception {
- super();
- }
-
- @Override
- public String getItemCommonPartName() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public String getInAuthority(Object item) {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public void setInAuthority(Object item, String inAuthorityCsid) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public Class getProxyClass() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public String getServiceName() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public String getServicePathComponent() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public String createAuthorityInstance(String shortIdentifier, String displayName) {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public String createAuthorityItemInstance(String shortIdentifier, String displayName) {
- // TODO Auto-generated method stub
- return null;
- }
-
-}
diff --git a/services/client/src/main/java/org/collectionspace/services/client/PoxPayloadIn.java b/services/client/src/main/java/org/collectionspace/services/client/PoxPayloadIn.java
index 65c3186eb5..9113d88aed 100644
--- a/services/client/src/main/java/org/collectionspace/services/client/PoxPayloadIn.java
+++ b/services/client/src/main/java/org/collectionspace/services/client/PoxPayloadIn.java
@@ -1,25 +1,10 @@
package org.collectionspace.services.client;
-//import java.io.ByteArrayInputStream; //FIXME: REM - Remove these unneeded import statements
-//import java.io.InputStream;
-//import java.io.Reader;
-//import java.io.StringReader;
-//import java.util.Iterator;
-//import java.util.List;
-
-//import javax.xml.transform.Source;
-//import javax.xml.transform.stream.StreamSource;
-
-//import org.dom4j.Attribute;
-//import org.dom4j.Document;
import java.io.File;
import java.io.IOException;
import org.dom4j.DocumentException;
import org.dom4j.Element;
-//import org.dom4j.Namespace;
-//import org.dom4j.io.SAXReader;
-//import org.xml.sax.InputSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/services/collectionobject/client/src/main/java/org/collectionspace/services/client/CollectionObjectFactory.java b/services/collectionobject/client/src/main/java/org/collectionspace/services/client/CollectionObjectFactory.java
index 2af0aa313b..90d8c91c64 100644
--- a/services/collectionobject/client/src/main/java/org/collectionspace/services/client/CollectionObjectFactory.java
+++ b/services/collectionobject/client/src/main/java/org/collectionspace/services/client/CollectionObjectFactory.java
@@ -24,10 +24,8 @@
package org.collectionspace.services.client;
-import org.collectionspace.services.client.PayloadOutputPart;
-import org.collectionspace.services.client.PoxPayloadOut;
import org.collectionspace.services.collectionobject.CollectionobjectsCommon;
-import org.collectionspace.services.collectionobject.domain.naturalhistory.CollectionobjectsNaturalhistory;
+import org.collectionspace.services.collectionobject.domain.naturalhistory_extension.CollectionobjectsNaturalhistory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/services/collectionobject/client/src/test/java/org/collectionspace/services/client/test/CollectionObjectServiceTest.java b/services/collectionobject/client/src/test/java/org/collectionspace/services/client/test/CollectionObjectServiceTest.java
index 41c6b4c0d1..74e68a241d 100644
--- a/services/collectionobject/client/src/test/java/org/collectionspace/services/client/test/CollectionObjectServiceTest.java
+++ b/services/collectionobject/client/src/test/java/org/collectionspace/services/client/test/CollectionObjectServiceTest.java
@@ -35,7 +35,6 @@
import org.collectionspace.services.client.PoxPayloadOut;
import org.collectionspace.services.collectionobject.BriefDescriptionList;
import org.collectionspace.services.collectionobject.CollectionobjectsCommon;
-import org.collectionspace.services.collectionobject.domain.naturalhistory.CollectionobjectsNaturalhistory;
import org.collectionspace.services.collectionobject.DimensionSubGroup;
import org.collectionspace.services.collectionobject.DimensionSubGroupList;
import org.collectionspace.services.collectionobject.MeasuredPartGroup;
@@ -47,6 +46,7 @@
import org.collectionspace.services.collectionobject.ResponsibleDepartmentList;
import org.collectionspace.services.collectionobject.TitleGroup;
import org.collectionspace.services.collectionobject.TitleGroupList;
+import org.collectionspace.services.collectionobject.domain.naturalhistory_extension.CollectionobjectsNaturalhistory;
import org.collectionspace.services.jaxb.AbstractCommonList;
import org.testng.Assert;
import org.testng.annotations.Test;
diff --git a/services/collectionobject/jaxb/src/main/resources/collectionobjects_common.xsd b/services/collectionobject/jaxb/src/main/resources/collectionobjects_common.xsd
index 89d0a3d6e7..818ea1ace4 100644
--- a/services/collectionobject/jaxb/src/main/resources/collectionobjects_common.xsd
+++ b/services/collectionobject/jaxb/src/main/resources/collectionobjects_common.xsd
@@ -165,7 +165,8 @@
-
+
+
@@ -217,6 +218,7 @@
+
@@ -815,6 +817,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/services/collectionobject/jaxb/src/main/resources/collectionobjects_nagpra.xsd b/services/collectionobject/jaxb/src/main/resources/collectionobjects_nagpra.xsd
new file mode 100644
index 0000000000..bfc3b8d2a8
--- /dev/null
+++ b/services/collectionobject/jaxb/src/main/resources/collectionobjects_nagpra.xsd
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/services/collectionobject/jaxb/src/main/resources/collectionobjects_naturalhistory.xsd b/services/collectionobject/jaxb/src/main/resources/collectionobjects_naturalhistory.xsd
index 5be1b09c1b..6830cc5424 100644
--- a/services/collectionobject/jaxb/src/main/resources/collectionobjects_naturalhistory.xsd
+++ b/services/collectionobject/jaxb/src/main/resources/collectionobjects_naturalhistory.xsd
@@ -2,7 +2,7 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
@@ -49,99 +42,117 @@
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/services/common-api/src/main/java/org/collectionspace/services/common/api/RefNameUtils.java b/services/common-api/src/main/java/org/collectionspace/services/common/api/RefNameUtils.java
index add4ae3038..e2482c7701 100644
--- a/services/common-api/src/main/java/org/collectionspace/services/common/api/RefNameUtils.java
+++ b/services/common-api/src/main/java/org/collectionspace/services/common/api/RefNameUtils.java
@@ -285,13 +285,13 @@ public static String getItemShortId(String refName) {
*/
public static String getDisplayName(String refName) throws IllegalArgumentException {
String displayName = null;
-
+
try {
AuthorityTermInfo authorityTermInfo = parseAuthorityTermInfo(refName);
displayName = authorityTermInfo.displayName;
}
catch(IllegalArgumentException invalidAuthorityTermRefNameException) {
- try {
+ try {
AuthorityInfo authorityInfo = parseAuthorityInfo(refName);
displayName = authorityInfo.displayName;
}
@@ -299,10 +299,23 @@ public static String getDisplayName(String refName) throws IllegalArgumentExcept
throw new IllegalArgumentException("Invalid refName");
}
}
-
+
return displayName;
}
+ /**
+ * @param refName A string representation of the CollectionSpace {@link RefName} to parse
+ * @return The {@link AuthorityInfo for the refname}
+ * @throws IllegalArgumentException if the refName cannot be parsed
+ */
+ public static AuthorityTermInfo getAuthorityTermInfo(String refName) throws IllegalArgumentException {
+ try {
+ return parseAuthorityTermInfo(refName);
+ } catch(IllegalArgumentException invalidAuthorityTermRefNameException) {
+ throw new IllegalArgumentException("Invalid refName");
+ }
+ }
+
/**
* Compare two refname strings. They're considered equal if the short IDs match
*
diff --git a/services/common/build.xml b/services/common/build.xml
index b04d3c24b4..e50e136850 100644
--- a/services/common/build.xml
+++ b/services/common/build.xml
@@ -118,48 +118,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -186,32 +144,11 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -219,110 +156,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/services/common/pom.xml b/services/common/pom.xml
index c218439365..7dc3204024 100644
--- a/services/common/pom.xml
+++ b/services/common/pom.xml
@@ -188,11 +188,6 @@
1.0
provided
-
- mysql
- mysql-connector-java
- provided
-
org.postgresql
postgresql
@@ -355,10 +350,6 @@
ch.elca.el4j.modules
module-xml_merge-common
-
- commons-io
- commons-io
-
org.springframework.security
spring-security-acl
diff --git a/services/common/src/main/cspace/config/services/tenants/anthro/anthro-tenant-bindings.delta.xml b/services/common/src/main/cspace/config/services/tenants/anthro/anthro-tenant-bindings.delta.xml
index cc47b8dc61..5d2b1c2844 100644
--- a/services/common/src/main/cspace/config/services/tenants/anthro/anthro-tenant-bindings.delta.xml
+++ b/services/common/src/main/cspace/config/services/tenants/anthro/anthro-tenant-bindings.delta.xml
@@ -58,6 +58,7 @@
"collectionobjects_common:contentEvents",
"collectionobjects_common:contentOrganizations",
"collectionobjects_common:contentPersons",
+ "collectionobjects_common:contentPlaces",
"collectionobjects_common:fieldCollectionDateGroup",
"collectionobjects_common:fieldCollectors",
"collectionobjects_common:materialGroupList",
@@ -75,6 +76,7 @@
"collectionobjects_common:objectStatusList",
"collectionobjects_common:otherNumberList",
"collectionobjects_common:ownersContributionNote",
+ "collectionobjects_common:publishedRelatedLinkGroupList",
"collectionobjects_common:publishToList",
"collectionobjects_common:responsibleDepartments",
"collectionobjects_common:rightsGroupList.rightStatement",
@@ -83,13 +85,17 @@
"collectionobjects_common:techniqueGroupList",
"collectionobjects_common:titleGroupList",
"collectionobjects_common:viewersContributionNote",
+ "collectionobjects_anthro:materialTechniqueDescription",
"collectionobjects_naturalhistory_extension:taxonomicIdentGroupList",
"collectionspace_core:*",
"collectionspace_denorm:*",
"ecm:currentLifeCycleState",
"ecm:name",
"ecm:primaryType",
- "media_common:blobCsid"
+ "media_common:blobCsid",
+ "media_common:identificationNumber",
+ "media_common:title",
+ "media_common:altText"
]
},
"properties" : {
@@ -113,6 +119,10 @@
"type": "date",
"format": "date_time"
},
+ "collectionspace_core:updatedAt": {
+ "type": "date",
+ "format": "date_time"
+ },
"collectionobjects_common:publishToList": {
"type": "keyword",
"fields": {
@@ -184,6 +194,9 @@
}
}
},
+ "collectionspace_denorm:objectCsid": {
+ "type": "keyword"
+ },
"collectionobjects_common:objectNumber": {
"type": "keyword",
@@ -341,6 +354,10 @@
}
}
},
+ "collectionobjects_common:contentPlaces": {
+ "type": "keyword",
+ "copy_to": "all_field"
+ },
"collectionobjects_common:techniqueGroupList": {
"type": "object",
"properties": {
@@ -381,6 +398,17 @@
"media_common:blobCsid": {
"type": "keyword"
},
+ "media_common:identificationNumber": {
+ "type": "keyword",
+ "normalizer": "sorting_normalizer"
+ },
+ "media_common:altText": {
+ "type": "text"
+ },
+ "media_common:title": {
+ "type": "keyword",
+ "normalizer": "sorting_normalizer"
+ },
"media_common:publishToList": {
"type": "keyword",
"fields": {
diff --git a/services/common/src/main/cspace/config/services/tenants/bonsai/bonsai-tenant-bindings.delta.xml b/services/common/src/main/cspace/config/services/tenants/bonsai/bonsai-tenant-bindings.delta.xml
index c37742173f..2f12109df3 100644
--- a/services/common/src/main/cspace/config/services/tenants/bonsai/bonsai-tenant-bindings.delta.xml
+++ b/services/common/src/main/cspace/config/services/tenants/bonsai/bonsai-tenant-bindings.delta.xml
@@ -29,6 +29,7 @@
"collectionobjects_common:contentEvents",
"collectionobjects_common:contentOrganizations",
"collectionobjects_common:contentPersons",
+ "collectionobjects_common:contentPlaces",
"collectionobjects_common:materialGroupList",
"collectionobjects_common:measuredPartGroupList",
"collectionobjects_common:numberOfObjects",
@@ -44,6 +45,7 @@
"collectionobjects_common:objectStatusList",
"collectionobjects_common:otherNumberList",
"collectionobjects_common:ownersContributionNote",
+ "collectionobjects_common:publishedRelatedLinkGroupList",
"collectionobjects_common:publishToList",
"collectionobjects_common:responsibleDepartments",
"collectionobjects_common:rightsGroupList.rightStatement",
@@ -57,7 +59,10 @@
"ecm:currentLifeCycleState",
"ecm:name",
"ecm:primaryType",
- "media_common:blobCsid"
+ "media_common:blobCsid",
+ "media_common:identificationNumber",
+ "media_common:title",
+ "media_common:altText"
]
},
"properties" : {
@@ -81,6 +86,10 @@
"type": "date",
"format": "date_time"
},
+ "collectionspace_core:updatedAt": {
+ "type": "date",
+ "format": "date_time"
+ },
"collectionobjects_common:publishToList": {
"type": "keyword",
"fields": {
@@ -149,6 +158,9 @@
}
}
},
+ "collectionspace_denorm:objectCsid": {
+ "type": "keyword"
+ },
"collectionobjects_common:objectNumber": {
"type": "keyword",
@@ -300,6 +312,10 @@
}
}
},
+ "collectionobjects_common:contentPlaces": {
+ "type": "keyword",
+ "copy_to": "all_field"
+ },
"collectionobjects_common:techniqueGroupList": {
"type": "object",
"properties": {
@@ -325,6 +341,17 @@
"media_common:blobCsid": {
"type": "keyword"
},
+ "media_common:identificationNumber": {
+ "type": "keyword",
+ "normalizer": "sorting_normalizer"
+ },
+ "media_common:altText": {
+ "type": "text"
+ },
+ "media_common:title": {
+ "type": "keyword",
+ "normalizer": "sorting_normalizer"
+ },
"media_common:publishToList": {
"type": "keyword",
"fields": {
diff --git a/services/common/src/main/cspace/config/services/tenants/fcart/fcart-tenant-bindings.delta.xml b/services/common/src/main/cspace/config/services/tenants/fcart/fcart-tenant-bindings.delta.xml
index f7a728c936..0045ce0287 100644
--- a/services/common/src/main/cspace/config/services/tenants/fcart/fcart-tenant-bindings.delta.xml
+++ b/services/common/src/main/cspace/config/services/tenants/fcart/fcart-tenant-bindings.delta.xml
@@ -38,6 +38,7 @@
"collectionobjects_common:contentEvents",
"collectionobjects_common:contentOrganizations",
"collectionobjects_common:contentPersons",
+ "collectionobjects_common:contentPlaces",
"collectionobjects_common:materialGroupList",
"collectionobjects_common:measuredPartGroupList",
"collectionobjects_common:numberOfObjects",
@@ -68,7 +69,10 @@
"ecm:currentLifeCycleState",
"ecm:name",
"ecm:primaryType",
- "media_common:blobCsid"
+ "media_common:blobCsid",
+ "media_common:identificationNumber",
+ "media_common:title",
+ "media_common:altText"
]
},
"properties" : {
@@ -92,6 +96,10 @@
"type": "date",
"format": "date_time"
},
+ "collectionspace_core:updatedAt": {
+ "type": "date",
+ "format": "date_time"
+ },
"collectionobjects_common:publishToList": {
"type": "keyword",
"fields": {
@@ -160,7 +168,9 @@
}
}
},
-
+ "collectionspace_denorm:objectCsid": {
+ "type": "keyword"
+ },
"collectionobjects_common:objectNumber": {
"type": "keyword",
"copy_to": "all_field"
@@ -311,6 +321,10 @@
}
}
},
+ "collectionobjects_common:contentPlaces": {
+ "type": "keyword",
+ "copy_to": "all_field"
+ },
"collectionobjects_common:techniqueGroupList": {
"type": "object",
"properties": {
@@ -336,6 +350,17 @@
"media_common:blobCsid": {
"type": "keyword"
},
+ "media_common:identificationNumber": {
+ "type": "keyword",
+ "normalizer": "sorting_normalizer"
+ },
+ "media_common:altText": {
+ "type": "text"
+ },
+ "media_common:title": {
+ "type": "keyword",
+ "normalizer": "sorting_normalizer"
+ },
"media_common:publishToList": {
"type": "keyword",
"fields": {
diff --git a/services/common/src/main/cspace/config/services/tenants/lhmc/lhmc-tenant-bindings.delta.xml b/services/common/src/main/cspace/config/services/tenants/lhmc/lhmc-tenant-bindings.delta.xml
index b839782926..f836218cc5 100644
--- a/services/common/src/main/cspace/config/services/tenants/lhmc/lhmc-tenant-bindings.delta.xml
+++ b/services/common/src/main/cspace/config/services/tenants/lhmc/lhmc-tenant-bindings.delta.xml
@@ -29,6 +29,7 @@
"collectionobjects_common:contentEvents",
"collectionobjects_common:contentOrganizations",
"collectionobjects_common:contentPersons",
+ "collectionobjects_common:contentPlaces",
"collectionobjects_common:materialGroupList",
"collectionobjects_common:measuredPartGroupList",
"collectionobjects_common:numberOfObjects",
@@ -44,6 +45,7 @@
"collectionobjects_common:objectStatusList",
"collectionobjects_common:otherNumberList",
"collectionobjects_common:ownersContributionNote",
+ "collectionobjects_common:publishedRelatedLinkGroupList",
"collectionobjects_common:publishToList",
"collectionobjects_common:responsibleDepartments",
"collectionobjects_common:rightsGroupList.rightStatement",
@@ -57,7 +59,10 @@
"ecm:currentLifeCycleState",
"ecm:name",
"ecm:primaryType",
- "media_common:blobCsid"
+ "media_common:blobCsid",
+ "media_common:identificationNumber",
+ "media_common:title",
+ "media_common:altText"
]
},
"properties" : {
@@ -81,6 +86,10 @@
"type": "date",
"format": "date_time"
},
+ "collectionspace_core:updatedAt": {
+ "type": "date",
+ "format": "date_time"
+ },
"collectionobjects_common:publishToList": {
"type": "keyword",
"fields": {
@@ -149,7 +158,9 @@
}
}
},
-
+ "collectionspace_denorm:objectCsid": {
+ "type": "keyword"
+ },
"collectionobjects_common:objectNumber": {
"type": "keyword",
"copy_to": "all_field"
@@ -300,6 +311,10 @@
}
}
},
+ "collectionobjects_common:contentPlaces": {
+ "type": "keyword",
+ "copy_to": "all_field"
+ },
"collectionobjects_common:techniqueGroupList": {
"type": "object",
"properties": {
@@ -325,6 +340,17 @@
"media_common:blobCsid": {
"type": "keyword"
},
+ "media_common:identificationNumber": {
+ "type": "keyword",
+ "normalizer": "sorting_normalizer"
+ },
+ "media_common:altText": {
+ "type": "text"
+ },
+ "media_common:title": {
+ "type": "keyword",
+ "normalizer": "sorting_normalizer"
+ },
"media_common:publishToList": {
"type": "keyword",
"fields": {
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
index a0e104fa16..64e57db8e8 100644
--- 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
@@ -75,9 +75,11 @@
"collectionobjects_common:contentEvents",
"collectionobjects_common:contentOrganizations",
"collectionobjects_common:contentPersons",
+ "collectionobjects_common:contentPlaces",
"collectionobjects_common:objectHistoryNote",
"collectionobjects_common:objectNumber",
"collectionobjects_common:objectStatusList",
+ "collectionobjects_common:publishedRelatedLinkGroupList",
"collectionobjects_common:publishToList",
"collectionobjects_common:materialGroupList",
"collectionobjects_common:otherNumberList",
@@ -101,6 +103,9 @@
"collectionobjects_common:rightsGroupList.standardizedRightStatement",
"collectionobjects_common:rightsInGroupList.rightReproductionStatement",
"media_common:blobCsid",
+ "media_common:identificationNumber",
+ "media_common:title",
+ "media_common:altText",
"media_materials:publishToList"
]
},
@@ -164,6 +169,9 @@
}
}
},
+ "collectionspace_denorm:objectCsid": {
+ "type": "keyword"
+ },
"collectionspace_core:createdAt": {
"type": "date",
@@ -171,6 +179,12 @@
// From imported data??
"format" : "date_time||yyyy-MM-dd'T'HH:mm:ss.SSZZ"
},
+ "collectionspace_core:updatedAt": {
+ "type": "date",
+ // Sometimes the timestamp only has a two digit fractional second, instead of three.
+ // From imported data??
+ "format" : "date_time||yyyy-MM-dd'T'HH:mm:ss.SSZZ"
+ },
"materials_common:shortIdentifier": {
"type": "keyword",
@@ -665,6 +679,10 @@
}
}
},
+ "collectionobjects_common:contentPlaces": {
+ "type": "keyword",
+ "copy_to": "all_field"
+ },
"collectionobjects_common:materialGroupList": {
"type": "object",
"properties": {
@@ -696,7 +714,17 @@
"type": "text",
"copy_to": "all_field"
},
-
+ "media_common:identificationNumber": {
+ "type": "keyword",
+ "normalizer": "sorting_normalizer"
+ },
+ "media_common:altText": {
+ "type": "text"
+ },
+ "media_common:title": {
+ "type": "keyword",
+ "normalizer": "sorting_normalizer"
+ },
"media_materials:publishToList": {
"type": "keyword",
"fields": {
diff --git a/services/common/src/main/cspace/config/services/tenants/publicart/publicart-tenant-bindings.delta.xml b/services/common/src/main/cspace/config/services/tenants/publicart/publicart-tenant-bindings.delta.xml
index a6b71878ef..5e9d84131b 100644
--- a/services/common/src/main/cspace/config/services/tenants/publicart/publicart-tenant-bindings.delta.xml
+++ b/services/common/src/main/cspace/config/services/tenants/publicart/publicart-tenant-bindings.delta.xml
@@ -26,6 +26,10 @@
report
full_obj_place
+
+ report
+ full_obj_place_creator_role_combined
+
diff --git a/services/common/src/main/cspace/config/services/tenants/tenant-bindings-proto-unified.xml b/services/common/src/main/cspace/config/services/tenants/tenant-bindings-proto-unified.xml
index 1c25c4624c..8932e09aef 100644
--- a/services/common/src/main/cspace/config/services/tenants/tenant-bindings-proto-unified.xml
+++ b/services/common/src/main/cspace/config/services/tenants/tenant-bindings-proto-unified.xml
@@ -87,6 +87,10 @@
sqlScriptName
fnc-public-get_deplname.sql
+
+ sqlScriptName
+ deurn_function.sql
+
@@ -209,6 +213,13 @@
version="1.0">
default-domain
+
+
+
+
+ default-domain
+
@@ -1189,6 +1200,7 @@
"collectionobjects_common:contentEvents",
"collectionobjects_common:contentOrganizations",
"collectionobjects_common:contentPersons",
+ "collectionobjects_common:contentPlaces",
"collectionobjects_common:materialGroupList",
"collectionobjects_common:measuredPartGroupList",
"collectionobjects_common:numberOfObjects",
@@ -1218,7 +1230,10 @@
"ecm:currentLifeCycleState",
"ecm:name",
"ecm:primaryType",
- "media_common:blobCsid"
+ "media_common:blobCsid",
+ "media_common:identificationNumber",
+ "media_common:title",
+ "media_common:altText"
]
},
"properties" : {
@@ -1242,6 +1257,10 @@
"type": "date",
"format": "date_time"
},
+ "collectionspace_core:updatedAt": {
+ "type": "date",
+ "format": "date_time"
+ },
"collectionobjects_common:publishToList": {
"type": "keyword",
"fields": {
@@ -1310,7 +1329,9 @@
}
}
},
-
+ "collectionspace_denorm:objectCsid": {
+ "type": "keyword"
+ },
"collectionobjects_common:objectNumber": {
"type": "keyword",
"copy_to": "all_field"
@@ -1455,6 +1476,10 @@
}
}
},
+ "collectionobjects_common:contentPlaces": {
+ "type": "keyword",
+ "copy_to": "all_field"
+ },
"collectionobjects_common:techniqueGroupList": {
"type": "object",
"properties": {
@@ -1480,6 +1505,17 @@
"media_common:blobCsid": {
"type": "keyword"
},
+ "media_common:identificationNumber": {
+ "type": "keyword",
+ "normalizer": "sorting_normalizer"
+ },
+ "media_common:altText": {
+ "type": "text"
+ },
+ "media_common:title": {
+ "type": "keyword",
+ "normalizer": "sorting_normalizer"
+ },
"media_common:publishToList": {
"type": "keyword",
"fields": {
diff --git a/services/common/src/main/java/org/collectionspace/services/common/AbstractCollectionSpaceResourceImpl.java b/services/common/src/main/java/org/collectionspace/services/common/AbstractCollectionSpaceResourceImpl.java
index e508740297..9b016ef662 100644
--- a/services/common/src/main/java/org/collectionspace/services/common/AbstractCollectionSpaceResourceImpl.java
+++ b/services/common/src/main/java/org/collectionspace/services/common/AbstractCollectionSpaceResourceImpl.java
@@ -39,7 +39,6 @@
import org.collectionspace.services.authorization.PermissionException;
import org.collectionspace.services.client.CollectionSpaceClient;
-import org.collectionspace.services.common.CSWebApplicationException;
import org.collectionspace.services.common.api.Tools;
import org.collectionspace.services.common.config.ServiceConfigUtils;
import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
@@ -87,7 +86,13 @@ public abstract class AbstractCollectionSpaceResourceImpl
/** The storage client. */
private StorageClient storageClient;
-
+
+ /**
+ * A DocumentHandler provided for use instead of the default from the ServiceContext
+ * Note: considering a provider or something here, not entirely sure yet
+ */
+ private Class extends DocumentHandler> documentHandlerClass;
+
/**
* Extract id.
*
@@ -159,9 +164,16 @@ public DocumentHandler createDocumentHandler(ServiceContext ctx) throws
*
* @throws Exception the exception
*/
- public DocumentHandler createDocumentHandler(ServiceContext ctx,
- Object commonPart) throws Exception {
- DocumentHandler docHandler = ctx.getDocumentHandler();
+ public DocumentHandler createDocumentHandler(ServiceContext ctx, Object commonPart) throws Exception {
+ DocumentHandler docHandler;
+ if (documentHandlerClass != null) {
+ docHandler = documentHandlerClass.newInstance();
+ docHandler.setServiceContext(ctx);
+ } else {
+ docHandler = ctx.getDocumentHandler();
+ }
+
+ // common part is the jaxb class?
docHandler.setCommonPart(commonPart);
return docHandler;
}
@@ -779,5 +791,9 @@ protected Response.ResponseBuilder setCacheControl(ServiceContext ctx, R
}
return responseBuilder;
- }
+ }
+
+ public void setDocumentHandlerClass(Class extends DocumentHandler> dhClass) {
+ this.documentHandlerClass = dhClass;
+ }
}
diff --git a/services/common/src/main/java/org/collectionspace/services/common/AbstractMultiPartCollectionSpaceResourceImpl.java b/services/common/src/main/java/org/collectionspace/services/common/AbstractMultiPartCollectionSpaceResourceImpl.java
index 57948fcade..1a3a05acda 100644
--- a/services/common/src/main/java/org/collectionspace/services/common/AbstractMultiPartCollectionSpaceResourceImpl.java
+++ b/services/common/src/main/java/org/collectionspace/services/common/AbstractMultiPartCollectionSpaceResourceImpl.java
@@ -26,9 +26,6 @@
*/
package org.collectionspace.services.common;
-import java.util.Iterator;
-import java.util.List;
-
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
diff --git a/services/common/src/main/java/org/collectionspace/services/common/HttpDownloadUtility.java b/services/common/src/main/java/org/collectionspace/services/common/HttpDownloadUtility.java
index 9e9c865ce1..fff647523a 100644
--- a/services/common/src/main/java/org/collectionspace/services/common/HttpDownloadUtility.java
+++ b/services/common/src/main/java/org/collectionspace/services/common/HttpDownloadUtility.java
@@ -42,7 +42,7 @@ private static String getDestDir(String destDir) {
}
return null;
}
-
+
return destDir;
}
@@ -54,7 +54,7 @@ public static File downloadFile(String fileURL) throws IOException {
if (tmpdir.endsWith(File.separator) == false) {
tmpdir = tmpdir + File.separator;
}
-
+
String destDir = getDestDir(tmpdir + UUID.randomUUID() + File.separator);
String filePath = downloadFile(fileURL, destDir);
result = new File(filePath);
@@ -62,13 +62,13 @@ public static File downloadFile(String fileURL) throws IOException {
String msg = String.format("Could not download file use this URL: %s", fileURL);
logger.error(msg, e);
}
-
+
return result;
}
-
+
/**
* Downloads a file from a URL
- *
+ *
* @param fileURL HTTP URL of the file to be downloaded
* @param saveDir path of the directory to save the file
* @throws IOException
@@ -81,7 +81,7 @@ private static String downloadFile(String fileURL, String saveDir) throws IOExce
try {
httpResponseCode = httpConn.getResponseCode();
-
+
// always check HTTP response code first
if (httpResponseCode == HttpURLConnection.HTTP_OK) {
String fileName = "";
@@ -96,8 +96,13 @@ private static String downloadFile(String fileURL, String saveDir) throws IOExce
} else {
// extracts file name from URL
fileName = fileURL.substring(fileURL.lastIndexOf("/") + 1, fileURL.length());
+ // Remove query parameters from filename
+ int qIndex = fileName.indexOf("?");
+ if (qIndex > -1) {
+ fileName = fileName.substring(0, qIndex);
+ }
}
-
+
if (logger.isDebugEnabled()) {
String contentType = httpConn.getContentType();
int contentLength = httpConn.getContentLength();
@@ -105,15 +110,15 @@ private static String downloadFile(String fileURL, String saveDir) throws IOExce
logger.debug("Disposition is:" + disposition != null ? disposition : "");
logger.debug("Content type is:" + contentType != null ? contentType : "");
logger.debug("Content length is:" + contentLength);
- }
+ }
// opens input stream from the HTTP connection
InputStream inputStream = httpConn.getInputStream();
String saveFilePath = saveDir + File.separator + fileName; //FIXME: File.separator NOT needed
-
+
// opens an output stream to save into file
FileOutputStream outputStream = new FileOutputStream(saveFilePath);
-
+
try {
int bytesRead = -1;
byte[] buffer = new byte[BUFFER_SIZE];
diff --git a/services/common/src/main/java/org/collectionspace/services/common/context/MultipartServiceContext.java b/services/common/src/main/java/org/collectionspace/services/common/context/MultipartServiceContext.java
index 694f5c91f5..bdd9887a49 100644
--- a/services/common/src/main/java/org/collectionspace/services/common/context/MultipartServiceContext.java
+++ b/services/common/src/main/java/org/collectionspace/services/common/context/MultipartServiceContext.java
@@ -30,9 +30,6 @@
import org.collectionspace.services.client.PoxPayloadIn;
import org.collectionspace.services.client.PoxPayloadOut;
import org.dom4j.Element;
-import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
-import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
-import org.dom4j.Document;
/**
* RemoteServiceContext is used to encapsulate the service context of a
diff --git a/services/common/src/main/java/org/collectionspace/services/common/document/AbstractDocumentHandlerImpl.java b/services/common/src/main/java/org/collectionspace/services/common/document/AbstractDocumentHandlerImpl.java
index aa296e7962..9218b5485d 100644
--- a/services/common/src/main/java/org/collectionspace/services/common/document/AbstractDocumentHandlerImpl.java
+++ b/services/common/src/main/java/org/collectionspace/services/common/document/AbstractDocumentHandlerImpl.java
@@ -107,14 +107,10 @@ public void setProperties(Map properties) {
this.properties = properties;
}
-// public void initializeDocumentFilter(ServiceContext ctx) {
-// DocumentFilter docFilter = this.createDocumentFilter(ctx);
-// this.setDocumentFilter(docFilter);
-// }
- /* (non-Javadoc)
- * @see org.collectionspace.services.common.document.DocumentHandler#createDocumentFilter()
- */
-@Override
+ /**
+ * @see org.collectionspace.services.common.document.DocumentHandler#createDocumentFilter()
+ */
+ @Override
public abstract DocumentFilter createDocumentFilter();
/**
diff --git a/services/common/src/main/java/org/collectionspace/services/common/document/DocumentUtils.java b/services/common/src/main/java/org/collectionspace/services/common/document/DocumentUtils.java
index 184d6d75c7..c1b7ab430a 100644
--- a/services/common/src/main/java/org/collectionspace/services/common/document/DocumentUtils.java
+++ b/services/common/src/main/java/org/collectionspace/services/common/document/DocumentUtils.java
@@ -31,7 +31,6 @@
import java.io.ByteArrayInputStream;
import java.io.StringWriter;
import java.text.DecimalFormat;
-import java.text.FieldPosition;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Calendar;
@@ -65,7 +64,6 @@
import org.dom4j.io.DOMReader;
import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
import org.jboss.resteasy.plugins.providers.multipart.InputPart;
-//import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
import org.nuxeo.ecm.core.io.ExportConstants;
import org.nuxeo.common.collections.PrimitiveArrays;
@@ -93,13 +91,6 @@
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
-import org.w3c.dom.Text;
-
-//import org.dom4j.Document;
-//import org.dom4j.Element;
-//import org.dom4j.Node;
-//import org.dom4j.NodeList;
-//import org.dom4j.Text;
/**
* DocumentUtils is a collection of utilities related to document management
@@ -565,7 +556,7 @@ public static org.dom4j.Element buildDocument(ObjectPartType partMeta,
Schema schema = getSchemaFromName(partMeta.getLabel());
buildDocument(document, root, objectProps, schema);
- String w3cDocumentStr = xmlToString(document);
+ // String w3cDocumentStr = xmlToString(document);
DOMReader reader = new DOMReader();
org.dom4j.Document dom4jDoc = reader.read(document);
@@ -573,8 +564,7 @@ public static org.dom4j.Element buildDocument(ObjectPartType partMeta,
result.detach(); // return just the root element detached from the DOM
// document
- return result;// FIXME: REM - Add if (logger.isTraceEnabled() == true)
- // logger.trace(document.asXML());
+ return result;
}
/**
@@ -656,8 +646,7 @@ private static String encodeValue(Type type, Object value) {
* @throws IOException
* Signals that an I/O exception has occurred.
*/
- private static void buildProperty(Document document, Element parent,
- Field field, Object value) throws IOException {
+ public static void buildProperty(Document document, Element parent, Field field, Object value) throws IOException {
Type type = field.getType();
// no need to qualify each element name as namespace is already added
String propName = field.getName().getLocalName();
diff --git a/services/common/src/main/java/org/collectionspace/services/common/relation/RelationResource.java b/services/common/src/main/java/org/collectionspace/services/common/relation/RelationResource.java
index 503b0826ed..a371832d33 100644
--- a/services/common/src/main/java/org/collectionspace/services/common/relation/RelationResource.java
+++ b/services/common/src/main/java/org/collectionspace/services/common/relation/RelationResource.java
@@ -108,6 +108,9 @@ public RelationsCommonList getList(ServiceContext p
return resultList;
}
+ public RelationsCommonList getRelationForSubject(String subject, String object, UriInfo uriInfo) {
+ return getRelationList(null, uriInfo, subject, null, null, object, null, false);
+ }
private RelationsCommonList getRelationList(
ServiceContext parentCtx,
@@ -129,7 +132,7 @@ private RelationsCommonList getRelationList(
//
// Handle keyword clause
//
- String keywords = uriInfo.getQueryParameters().getFirst(IQueryManager.SEARCH_TYPE_KEYWORDS_KW);
+ String keywords = uriInfo.getQueryParameters().getFirst(IQueryManager.SEARCH_TYPE_KEYWORDS_KW);
if (keywords != null && keywords.isEmpty() == false) {
String keywordClause = QueryManager.createWhereClauseFromKeywords(keywords);
handler.getDocumentFilter().appendWhereClause(keywordClause, IQueryManager.SEARCH_QUALIFIER_AND);
diff --git a/services/common/src/main/java/org/collectionspace/services/common/security/CSpaceSaml2ResponseAuthenticationConverter.java b/services/common/src/main/java/org/collectionspace/services/common/security/CSpaceSaml2ResponseAuthenticationConverter.java
index 0a2aa3564a..d91bae9ca6 100644
--- a/services/common/src/main/java/org/collectionspace/services/common/security/CSpaceSaml2ResponseAuthenticationConverter.java
+++ b/services/common/src/main/java/org/collectionspace/services/common/security/CSpaceSaml2ResponseAuthenticationConverter.java
@@ -22,124 +22,139 @@
import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
public class CSpaceSaml2ResponseAuthenticationConverter implements Converter {
- private final Logger logger = LoggerFactory.getLogger(CSpaceSaml2ResponseAuthenticationConverter.class);
-
- private CSpaceUserDetailsService userDetailsService;
-
- public CSpaceSaml2ResponseAuthenticationConverter(CSpaceUserDetailsService userDetailsService) {
- this.userDetailsService = userDetailsService;
- }
-
- @Override
- public CSpaceSaml2Authentication convert(ResponseToken responseToken) {
- Saml2Authentication authentication = OpenSamlAuthenticationProvider
- .createDefaultResponseAuthenticationConverter()
- .convert(responseToken);
-
- String registrationId = responseToken.getToken().getRelyingPartyRegistration().getRegistrationId();
- ServiceConfig serviceConfig = ServiceMain.getInstance().getServiceConfig();
- SAMLRelyingPartyType relyingPartyRegistration = ConfigUtils.getSAMLRelyingPartyRegistration(serviceConfig, registrationId);
- CSpaceUser user = findUser(relyingPartyRegistration, responseToken);
-
- if (user != null) {
- return new CSpaceSaml2Authentication(user, authentication);
- }
-
- return null;
- }
-
- /**
- * Attempt to find a CSpace user for a SAML response.
- *
- * @param relyingPartyRegistration
- * @param responseToken
- * @return
- */
- private CSpaceUser findUser(SAMLRelyingPartyType relyingPartyRegistration, ResponseToken responseToken) {
- AssertionProbesType assertionSsoIdProbes = (
- relyingPartyRegistration != null
- ? relyingPartyRegistration.getAssertionSsoIdProbes()
- : null
- );
-
- AssertionProbesType assertionUsernameProbes = (
- relyingPartyRegistration != null
- ? relyingPartyRegistration.getAssertionUsernameProbes()
- : null
- );
-
- List attemptedUsernames = new ArrayList<>();
- List assertions = responseToken.getResponse().getAssertions();
-
- SecurityUtils.logSamlAssertions(assertions);
-
- for (Assertion assertion : assertions) {
- CSpaceUser user = null;
- String ssoId = SecurityUtils.getSamlAssertionSsoId(assertion, assertionSsoIdProbes);
-
- // First, look for a CSpace user whose SSO ID is the ID in the assertion.
-
- if (ssoId != null) {
- try {
- user = (CSpaceUser) userDetailsService.loadUserBySsoId(ssoId);
- }
- catch (UsernameNotFoundException e) {
- }
- }
-
- if (user != null) {
- return user;
- }
-
- // Next, look for a CSpace user whose username is the email address in the assertion.
-
- Set candidateUsernames = SecurityUtils.findSamlAssertionCandidateUsernames(assertion, assertionUsernameProbes);
-
- for (String candidateUsername : candidateUsernames) {
- try {
- user = (CSpaceUser) userDetailsService.loadUserByUsername(candidateUsername);
-
- if (user != null) {
- String expectedSsoId = user.getSsoId();
-
- if (expectedSsoId == null) {
- // Store the ID from the IdP to use in future log ins. Note that this does not save
- // the SSO ID to the database. That happens in CSpaceAuthenticationSuccessEvent.
-
- user.setSsoId(ssoId);
-
- // TODO: If the email address in the assertion differs from the CSpace user's email,
- // update the CSpace user.
- } else if (!StringUtils.equals(expectedSsoId, ssoId)) {
- // If the user previously logged in via SSO, but they had a different ID from the
- // IdP, something's wrong. (Did an account on the IdP get assigned an email that
- // previously belonged to a different account on the IdP?)
-
- logger.warn("User with username {} has expected SSO ID {}, but received {} in SAML assertion",
- candidateUsername, expectedSsoId, ssoId);
-
- user = null;
- }
-
- if (user != null) {
- return user;
- }
- }
- }
- catch(UsernameNotFoundException e) {
- }
- }
-
- attemptedUsernames.addAll(candidateUsernames);
- }
-
- // No CSpace user was found for this SAML response.
- // TODO: Auto-create a CSpace user, using the display name, email address, and ID in the response.
-
- String errorMessage = attemptedUsernames.size() == 0
- ? "The SAML response did not contain a CollectionSpace username."
- : "No CollectionSpace account found for " + StringUtils.join(attemptedUsernames, " / ") + ".";
-
- throw(new UsernameNotFoundException(errorMessage));
- }
+ private final Logger logger = LoggerFactory.getLogger(CSpaceSaml2ResponseAuthenticationConverter.class);
+
+ private CSpaceUserDetailsService userDetailsService;
+
+ public CSpaceSaml2ResponseAuthenticationConverter(CSpaceUserDetailsService userDetailsService) {
+ this.userDetailsService = userDetailsService;
+ }
+
+ @Override
+ public CSpaceSaml2Authentication convert(ResponseToken responseToken) {
+ Saml2Authentication authentication = OpenSamlAuthenticationProvider
+ .createDefaultResponseAuthenticationConverter().convert(responseToken);
+
+ String registrationId = responseToken.getToken().getRelyingPartyRegistration().getRegistrationId();
+ ServiceConfig serviceConfig = ServiceMain.getInstance().getServiceConfig();
+ SAMLRelyingPartyType relyingPartyRegistration = ConfigUtils.getSAMLRelyingPartyRegistration(serviceConfig,
+ registrationId);
+ CSpaceUser user = findUser(relyingPartyRegistration, responseToken);
+
+ if (user != null) {
+ return new CSpaceSaml2Authentication(user, authentication);
+ }
+
+ return null;
+ }
+
+ /**
+ * Attempt to find a CSpace user for from a list of relying parties
+ * (from the services configuration) and a list of assertions (from the SAML response)
+ *
+ * @param relyingPartyRegistration object representing relying parties from the
+ * service config
+ * @param assertions list of SAML assertions to test
+ * @return the found CSpace user, if any
+ */
+ private CSpaceUser findUser(SAMLRelyingPartyType relyingPartyRegistration, List assertions) {
+ AssertionProbesType assertionSsoIdProbes = (relyingPartyRegistration != null
+ ? relyingPartyRegistration.getAssertionSsoIdProbes()
+ : null);
+
+ AssertionProbesType assertionUsernameProbes = (relyingPartyRegistration != null
+ ? relyingPartyRegistration.getAssertionUsernameProbes()
+ : null);
+
+ List attemptedUsernames = new ArrayList<>();
+
+ SecurityUtils.logSamlAssertions(assertions);
+
+ for (Assertion assertion : assertions) {
+ CSpaceUser user = null;
+ String ssoId = SecurityUtils.getSamlAssertionSsoId(assertion, assertionSsoIdProbes);
+
+ // First, look for a CSpace user whose SSO ID is the ID in the assertion.
+
+ if (ssoId != null) {
+ try {
+ user = (CSpaceUser) userDetailsService.loadUserBySsoId(ssoId);
+ } catch (UsernameNotFoundException e) {
+ }
+ }
+
+ if (user != null) {
+ return user;
+ }
+
+ // Next, look for a CSpace user whose username is the email address in the
+ // assertion.
+
+ Set candidateUsernames = SecurityUtils.findSamlAssertionCandidateUsernames(assertion,
+ assertionUsernameProbes);
+
+ for (String candidateUsername : candidateUsernames) {
+ try {
+ user = (CSpaceUser) userDetailsService.loadUserByUsername(candidateUsername);
+
+ if (user != null) {
+ String expectedSsoId = user.getSsoId();
+
+ if (expectedSsoId == null) {
+ // Store the ID from the IdP to use in future log ins. Note that this does not
+ // save
+ // the SSO ID to the database. That happens in CSpaceAuthenticationSuccessEvent.
+
+ user.setSsoId(ssoId);
+
+ // TODO: If the email address in the assertion differs from the CSpace user's
+ // email,
+ // update the CSpace user.
+ } else if (!StringUtils.equals(expectedSsoId, ssoId)) {
+ // If the user previously logged in via SSO, but they had a different ID from
+ // the
+ // IdP, something's wrong. (Did an account on the IdP get assigned an email that
+ // previously belonged to a different account on the IdP?)
+
+ logger.warn(
+ "User with username {} has expected SSO ID {}, but received {} in SAML assertion",
+ candidateUsername, expectedSsoId, ssoId);
+
+ user = null;
+ }
+
+ if (user != null) {
+ return user;
+ }
+ }
+ } catch (UsernameNotFoundException e) {
+ }
+ }
+
+ attemptedUsernames.addAll(candidateUsernames);
+ }
+
+ // No CSpace user was found for this SAML response.
+ // TODO: Auto-create a CSpace user, using the display name, email address, and
+ // ID in the response.
+
+ String errorMessage = attemptedUsernames.size() == 0
+ ? "The SAML response did not contain a CollectionSpace username."
+ : "No CollectionSpace account found for " + StringUtils.join(attemptedUsernames, " / ") + ".";
+
+ throw (new UsernameNotFoundException(errorMessage));
+ }
+
+ /**
+ * Attempt to find a CSpace user for a SAML response.
+ *
+ * @deprecated
+ * @param relyingPartyRegistration
+ * @param responseToken
+ * @return a CSpace user
+ */
+ private CSpaceUser findUser(SAMLRelyingPartyType relyingPartyRegistration, ResponseToken responseToken) {
+ List assertions = responseToken.getResponse().getAssertions();
+ return findUser(relyingPartyRegistration,assertions);
+ }
}
diff --git a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/handler/CSDocumentModelList.java b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/handler/CSDocumentModelList.java
new file mode 100644
index 0000000000..65e18063cd
--- /dev/null
+++ b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/handler/CSDocumentModelList.java
@@ -0,0 +1,50 @@
+package org.collectionspace.services.nuxeo.client.handler;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.collectionspace.services.client.PoxPayloadOut;
+import org.collectionspace.services.jaxb.AbstractCommonList;
+
+/**
+ * A CollectionSpace version of the {@link org.nuxeo.ecm.core.api.DocumentModelList}. Primarily used in order to
+ * response with a full dataset rather than the simpler list views previously done in CollectionSpace.
+ *
+ * @since 8.3.0
+ */
+@XmlAccessorType(XmlAccessType.NONE)
+@XmlRootElement(name = "abstract-common-list")
+public class CSDocumentModelList extends AbstractCommonList {
+
+ public static class CSDocumentModelResponse {
+ private final String csid;
+ private final PoxPayloadOut payload;
+
+ public CSDocumentModelResponse(final String csid, final PoxPayloadOut out) {
+ this.csid = csid;
+ this.payload = out;
+ }
+
+ public String getCsid() {
+ return csid;
+ }
+
+ public PoxPayloadOut getPayload() {
+ return payload;
+ }
+ }
+
+ private final List responseList = new ArrayList<>();
+
+ public List getResponseList() {
+ return responseList;
+ }
+
+ public void addResponsePayload(final String csid, final PoxPayloadOut out) {
+ responseList.add(new CSDocumentModelResponse(csid, out));
+ }
+}
diff --git a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/handler/UnfilteredDocumentModelHandler.java b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/handler/UnfilteredDocumentModelHandler.java
new file mode 100644
index 0000000000..63d5e15c80
--- /dev/null
+++ b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/handler/UnfilteredDocumentModelHandler.java
@@ -0,0 +1,249 @@
+package org.collectionspace.services.nuxeo.client.handler;
+
+import java.util.Collection;
+import java.util.List;
+
+import javax.ws.rs.core.MultivaluedMap;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.collectionspace.services.client.IQueryManager;
+import org.collectionspace.services.client.PoxPayloadIn;
+import org.collectionspace.services.client.PoxPayloadOut;
+import org.collectionspace.services.client.workflow.WorkflowClient;
+import org.collectionspace.services.common.authorityref.AuthorityRefList;
+import org.collectionspace.services.common.context.ServiceContext;
+import org.collectionspace.services.common.document.DocumentException;
+import org.collectionspace.services.common.document.DocumentFilter;
+import org.collectionspace.services.common.document.DocumentUtils;
+import org.collectionspace.services.common.document.DocumentWrapper;
+import org.collectionspace.services.common.vocabulary.RefNameServiceUtils;
+import org.collectionspace.services.jaxb.AbstractCommonList;
+import org.collectionspace.services.lifecycle.TransitionDef;
+import org.collectionspace.services.nuxeo.client.java.DocumentModelHandler;
+import org.collectionspace.services.nuxeo.client.java.NuxeoDocumentFilter;
+import org.dom4j.io.DOMReader;
+import org.nuxeo.ecm.core.api.DocumentModel;
+import org.nuxeo.ecm.core.api.DocumentModelList;
+import org.nuxeo.ecm.core.api.model.Property;
+import org.nuxeo.ecm.core.schema.types.Field;
+import org.nuxeo.ecm.core.schema.types.Schema;
+
+/**
+ * A DocumentModelHandler which does not restrict the view to a single xml part (e.g. collectionobjects_common)
+ *
+ * Note: currently the only use for this is the AdvancedSearch API which requires a full view of the Document being
+ * returned to us by Nuxeo.
+ *
+ * @since 8.3.0
+ */
+public class UnfilteredDocumentModelHandler extends DocumentModelHandler {
+
+ private static final String NAME = "unfiltered-search-result";
+
+ private AbstractCommonList commonList;
+ private DocumentModel document;
+ private DocumentFilter filter;
+
+ @Override
+ public DocumentFilter getDocumentFilter() {
+ if (filter == null) {
+ ServiceContext context = getServiceContext();
+ if (context == null) {
+ throw new RuntimeException("DocumentModelHandler is missing its ServiceContext and cannot complete the "
+ + "current request");
+ }
+
+ filter = new NuxeoDocumentFilter(context);
+
+ // Initialize the sort, paging, and workflow params
+ MultivaluedMap queryParameters = context.getQueryParams();
+ if (queryParameters != null && !queryParameters.isEmpty()) {
+ filter.setSortOrder(queryParameters);
+ filter.setPagination(queryParameters);
+ String workflowWhereClause = buildWorkflowWhereClause(queryParameters);
+ if (workflowWhereClause != null) {
+ filter.appendWhereClause(workflowWhereClause, IQueryManager.SEARCH_QUALIFIER_AND);
+ }
+ }
+ }
+
+ return filter;
+ }
+
+ /**
+ * yoinked from AbstractServiceContextImpl. Might move into a common class since it's only returning a string.
+ */
+ private String buildWorkflowWhereClause(MultivaluedMap queryParams) {
+ String result = null;
+
+ String includeDeleted = queryParams.getFirst(WorkflowClient.WORKFLOW_QUERY_DELETED_QP);
+ // if set to true, it doesn't matter what the value is for 'includeDeleted'
+ String includeOnlyDeleted = queryParams.getFirst(WorkflowClient.WORKFLOW_QUERY_ONLY_DELETED_QP);
+
+ if (includeOnlyDeleted != null) {
+ if (Boolean.parseBoolean(includeOnlyDeleted)) {
+ // A value of 'true' for 'includeOnlyDeleted' means we're looking *only* for soft-deleted records/documents.
+ result = String.format("(ecm:currentLifeCycleState = '%s' OR ecm:currentLifeCycleState = '%s' OR ecm:currentLifeCycleState = '%s')",
+ WorkflowClient.WORKFLOWSTATE_DELETED,
+ WorkflowClient.WORKFLOWSTATE_LOCKED_DELETED,
+ WorkflowClient.WORKFLOWSTATE_REPLICATED_DELETED);
+ }
+ } else if (includeDeleted != null && !Boolean.parseBoolean(includeDeleted)) {
+ // We can only get here if the 'includeOnlyDeleted' query param is missing altogether.
+ // Ensure we don't return soft-deleted records
+ result = String.format("(ecm:currentLifeCycleState <> '%s' AND ecm:currentLifeCycleState <> '%s' AND ecm:currentLifeCycleState <> '%s')",
+ WorkflowClient.WORKFLOWSTATE_DELETED,
+ WorkflowClient.WORKFLOWSTATE_LOCKED_DELETED,
+ WorkflowClient.WORKFLOWSTATE_REPLICATED_DELETED);
+ }
+
+ return result;
+ }
+
+
+ /**
+ * This is similar to the implementation in
+ * {@link org.collectionspace.services.nuxeo.client.java.NuxeoDocumentModelHandler#extractAllParts(DocumentWrapper)}
+ * except for a list result
+ *
+ * @param wrapDoc The document model list from nuxeo
+ * @return A {@link CSDocumentModelList} with the {@link org.collectionspace.services.client.PayloadOutputPart}s
+ * for each document
+ * @throws Exception if there are any errors handling the XML
+ */
+ @Override
+ public AbstractCommonList extractCommonPartList(DocumentWrapper wrapDoc) throws Exception {
+ final String xmlNs = "ns2";
+ final DocumentModelList documentModelList = wrapDoc.getWrappedObject();
+
+ final CSDocumentModelList cspaceDocModelList = new CSDocumentModelList();
+ final DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+
+ final DocumentFilter docFilter = getDocumentFilter();
+ long pageSize = docFilter.getPageSize();
+ long pageNum = pageSize != 0 ? docFilter.getOffset() / pageSize : pageSize;
+ // set the page size and page number
+ cspaceDocModelList.setPageNum(pageNum);
+ cspaceDocModelList.setPageSize(pageSize);
+ DocumentModelList docList = wrapDoc.getWrappedObject();
+ // Set num of items in list. this is useful to our testing framework.
+ cspaceDocModelList.setItemsInPage(docList.size());
+ // set the total result size
+ cspaceDocModelList.setTotalItems(docList.totalSize());
+
+ for (DocumentModel documentModel : documentModelList) {
+ final PoxPayloadOut out = new PoxPayloadOut(NAME);
+
+ // todo: only work on schemas we support
+ for (Schema schema : documentModel.getDocumentType().getSchemas()) {
+ final String schemaName = schema.getName();
+ org.w3c.dom.Document document = documentBuilder.newDocument();
+ final String namespaceUri = schema.getNamespace().uri;
+ final String qualifiedName = xmlNs + ":" + schemaName;
+
+ org.w3c.dom.Element root = document.createElementNS(namespaceUri, qualifiedName);
+ root.setAttribute("xmlns:" + xmlNs, namespaceUri);
+ document.appendChild(root);
+
+ final Collection properties = documentModel.getPropertyObjects(schemaName);
+ for (Property property : properties) {
+ final Field field = property.getField();
+ final Object value = property.getValue();
+
+ if (value != null) {
+ DocumentUtils.buildProperty(document, root, field, value);
+ }
+ }
+
+ out.addPart(schemaName, document);
+ }
+
+ cspaceDocModelList.addResponsePayload(documentModel.getName(), out);
+ }
+
+ return cspaceDocModelList;
+ }
+
+ @Override
+ public DocumentModel extractCommonPart(DocumentWrapper wrapDoc) throws Exception {
+ return wrapDoc.getWrappedObject();
+ }
+
+ @Override
+ public DocumentModel getCommonPart() {
+ return document;
+ }
+
+ @Override
+ public void setCommonPart(DocumentModel document) {
+ this.document = document;
+ }
+
+ @Override
+ public AbstractCommonList getCommonPartList() {
+ return commonList;
+ }
+
+ @Override
+ public void setCommonPartList(AbstractCommonList obj) {
+ commonList = obj;
+ }
+
+ @Override
+ public String getQProperty(String prop) throws DocumentException {
+ return "";
+ }
+
+ @Override
+ public boolean supportsWorkflowStates() {
+ return false;
+ }
+
+ // unsupported (for now)
+
+ @Override
+ protected String getRefnameDisplayName(DocumentWrapper docWrapper) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void handleWorkflowTransition(ServiceContext ctx, DocumentWrapper wrapDoc,
+ TransitionDef transitionDef) throws Exception {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void completeUpdate(DocumentWrapper wrapDoc) throws Exception {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void extractAllParts(DocumentWrapper wrapDoc) throws Exception {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void fillAllParts(DocumentWrapper wrapDoc, Action action) throws Exception {
+
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void fillCommonPart(DocumentModel obj, DocumentWrapper wrapDoc) throws Exception {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public AbstractCommonList extractPagingInfo(AbstractCommonList theCommonList,
+ DocumentWrapper wrapDoc) throws Exception {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public AuthorityRefList getAuthorityRefs(String csid,
+ List authRefConfigInfoList)
+ throws Exception {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/DocumentModelHandler.java b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/DocumentModelHandler.java
index c5970e51c5..828260d44a 100644
--- a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/DocumentModelHandler.java
+++ b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/DocumentModelHandler.java
@@ -23,7 +23,6 @@
*/
package org.collectionspace.services.nuxeo.client.java;
-import java.util.Collection;
import java.util.List;
import javax.ws.rs.core.MultivaluedMap;
@@ -31,7 +30,6 @@
import org.apache.commons.lang.StringUtils;
import org.collectionspace.services.client.Profiler;
import org.collectionspace.services.client.CollectionSpaceClient;
-import org.collectionspace.services.client.IClientQueryParams;
import org.collectionspace.services.client.IQueryManager;
import org.collectionspace.services.client.IRelationsManager;
import org.collectionspace.services.client.PoxPayloadIn;
@@ -47,7 +45,6 @@
import org.collectionspace.services.common.document.AbstractMultipartDocumentHandlerImpl;
import org.collectionspace.services.common.document.DocumentException;
import org.collectionspace.services.common.document.DocumentFilter;
-import org.collectionspace.services.common.document.DocumentNotFoundException;
import org.collectionspace.services.common.document.DocumentWrapper;
import org.collectionspace.services.common.document.DocumentWrapperImpl;
import org.collectionspace.services.nuxeo.util.NuxeoUtils;
@@ -57,18 +54,10 @@
import org.collectionspace.services.common.vocabulary.RefNameServiceUtils.AuthRefConfigInfo;
import org.collectionspace.services.common.vocabulary.RefNameServiceUtils.Specifier;
import org.collectionspace.services.lifecycle.Lifecycle;
-import org.collectionspace.services.lifecycle.State;
-import org.collectionspace.services.lifecycle.StateList;
-import org.collectionspace.services.lifecycle.TransitionDef;
-import org.collectionspace.services.lifecycle.TransitionDefList;
-import org.collectionspace.services.lifecycle.TransitionList;
-import org.nuxeo.ecm.core.NXCore;
import org.nuxeo.ecm.core.api.ClientException;
import org.nuxeo.ecm.core.api.DocumentModel;
import org.nuxeo.ecm.core.api.DocumentModelList;
import org.nuxeo.ecm.core.api.model.PropertyException;
-import org.nuxeo.ecm.core.lifecycle.LifeCycle;
-import org.nuxeo.ecm.core.lifecycle.LifeCycleService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -391,22 +380,19 @@ protected void handleRefNameChanges(ServiceContext
* @see org.collectionspace.services.common.document.AbstractDocumentHandlerImpl#isCMISQuery()
*/
public boolean isCMISQuery() {
- boolean result = false;
-
- MultivaluedMap queryParams = getServiceContext().getQueryParams();
- //
- // Look the query params to see if we need to make a CMSIS query.
- //
- String asSubjectCsid = (String)queryParams.getFirst(IQueryManager.SEARCH_RELATED_TO_CSID_AS_SUBJECT);
- String asOjectCsid = (String)queryParams.getFirst(IQueryManager.SEARCH_RELATED_TO_CSID_AS_OBJECT);
- String asEither = (String)queryParams.getFirst(IQueryManager.SEARCH_RELATED_TO_CSID_AS_EITHER);
- if (asSubjectCsid != null || asOjectCsid != null || asEither != null) {
- result = true;
- }
-
- return result;
+ boolean result = false;
+
+ MultivaluedMap queryParams = getServiceContext().getQueryParams();
+ String asSubjectCsid = queryParams.getFirst(IQueryManager.SEARCH_RELATED_TO_CSID_AS_SUBJECT);
+ String asObjectCsid = queryParams.getFirst(IQueryManager.SEARCH_RELATED_TO_CSID_AS_OBJECT);
+ String asEither = queryParams.getFirst(IQueryManager.SEARCH_RELATED_TO_CSID_AS_EITHER);
+ if (asSubjectCsid != null || asObjectCsid != null || asEither != null) {
+ result = true;
+ }
+
+ return result;
}
-
+
@Override
public String getDocumentsToIndexQuery(String indexId, String csid) throws DocumentException, Exception {
String result = null;
diff --git a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RemoteDocumentModelHandlerImpl.java b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RemoteDocumentModelHandlerImpl.java
index 2844812bd2..eb6b0158ca 100644
--- a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RemoteDocumentModelHandlerImpl.java
+++ b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RemoteDocumentModelHandlerImpl.java
@@ -101,10 +101,10 @@
*
* $LastChangedRevision: $
* $LastChangedDate: $
- * @param
+ * @param
* @param
*/
-public abstract class RemoteDocumentModelHandlerImpl
+public abstract class RemoteDocumentModelHandlerImpl
extends DocumentModelHandler {
/** The logger. */
@@ -674,9 +674,10 @@ protected Map extractPart(
* @throws Exception
*/
@Deprecated
- protected Map extractPart(
- DocumentModel docModel, String schema, ObjectPartType partMeta,
- Map addToMap)
+ protected Map extractPart(DocumentModel docModel,
+ String schema,
+ ObjectPartType partMeta,
+ Map addToMap)
throws Exception {
Map result = null;
@@ -685,58 +686,6 @@ protected Map extractPart(
return result;
}
- /*
- public String getStringPropertyFromDoc(
- ServiceContext ctx,
- String csid,
- String propertyXPath ) throws DocumentNotFoundException, DocumentException {
- RepositoryInstance repoSession = null;
- boolean releaseRepoSession = false;
- String returnValue = null;
-
- try{
- RepositoryClientImpl repoClient = (RepositoryClientImpl)this.getRepositoryClient(ctx);
- repoSession = this.getRepositorySession();
- if (repoSession == null) {
- repoSession = repoClient.getRepositorySession();
- releaseRepoSession = true;
- }
-
- try {
- DocumentWrapper wrapper = repoClient.getDoc(repoSession, ctx, csid);
- DocumentModel docModel = wrapper.getWrappedObject();
- returnValue = (String) docModel.getPropertyValue(propertyXPath);
- } catch (PropertyException pe) {
- throw pe;
- } catch (DocumentException de) {
- throw de;
- } catch (Exception e) {
- if (logger.isDebugEnabled()) {
- logger.debug("Caught exception ", e);
- }
- throw new DocumentException(e);
- } finally {
- if (releaseRepoSession && repoSession != null) {
- repoClient.releaseRepositorySession(repoSession);
- }
- }
- } catch (Exception e) {
- if (logger.isDebugEnabled()) {
- logger.debug("Caught exception ", e);
- }
- throw new DocumentException(e);
- }
-
-
- if (logger.isWarnEnabled() == true) {
- logger.warn("Returned DocumentModel instance was created with a repository session that is now closed.");
- }
- return returnValue;
- }
- */
-
-
-
/* (non-Javadoc)
* @see org.collectionspace.services.nuxeo.client.java.DocumentModelHandler#getAuthorityRefs(org.collectionspace.services.common.document.DocumentWrapper, java.util.List)
*/
diff --git a/services/common/src/main/resources/db/postgresql/deurn_function.sql b/services/common/src/main/resources/db/postgresql/deurn_function.sql
new file mode 100644
index 0000000000..155ce99fa4
--- /dev/null
+++ b/services/common/src/main/resources/db/postgresql/deurn_function.sql
@@ -0,0 +1,3 @@
+-- Convert a URN (often refname) (DRYD-1748: Add deurn function to database)
+CREATE OR REPLACE FUNCTION deurn(urnstr VARCHAR) RETURNS VARCHAR
+AS $BODY$ BEGIN RETURN ((regexp_match(urnstr, '''([^''\\]*(\\.[^''\\]*)*)'''))[1]); END $BODY$ LANGUAGE plpgsql IMMUTABLE;
diff --git a/services/common/src/main/resources/db/postgresql/unaccent_text_search_configuration.sql b/services/common/src/main/resources/db/postgresql/unaccent_text_search_configuration.sql
index 72ec6968a7..f6d71da680 100644
--- a/services/common/src/main/resources/db/postgresql/unaccent_text_search_configuration.sql
+++ b/services/common/src/main/resources/db/postgresql/unaccent_text_search_configuration.sql
@@ -19,22 +19,7 @@ BEGIN
WITH unaccent, english_stem;
CREATE OR REPLACE FUNCTION nx_to_tsvector(string VARCHAR) RETURNS TSVECTOR AS $func$
- DECLARE
- search_namespace TEXT;
- result TSVECTOR;
- BEGIN
- SELECT
- nspname INTO search_namespace
- FROM
- pg_namespace
- INNER JOIN pg_ts_config ON pg_namespace.oid = pg_ts_config.cfgnamespace
- AND cfgname = 'cspace_english' :: text;
-
- PERFORM set_config('search_path', search_namespace, true);
-
- result := TO_TSVECTOR('cspace_english', SUBSTR($1, 1, 250000));
- RETURN result;
- END;
+ SELECT TO_TSVECTOR('cspace_english', SUBSTR($1, 1, 250000));
$func$ LANGUAGE plpgsql IMMUTABLE;
END IF;
END IF;
diff --git a/services/common/src/test/java/org/collectionspace/services/common/test/AbstractSecurityTestBase.java b/services/common/src/test/java/org/collectionspace/services/common/test/AbstractSecurityTestBase.java
new file mode 100644
index 0000000000..2fdd5da6ed
--- /dev/null
+++ b/services/common/src/test/java/org/collectionspace/services/common/test/AbstractSecurityTestBase.java
@@ -0,0 +1,209 @@
+package org.collectionspace.services.common.test;
+
+import java.io.ByteArrayInputStream;
+
+import javax.xml.bind.JAXBException;
+import javax.xml.namespace.QName;
+
+import org.collectionspace.services.common.config.ServicesConfigReaderImpl;
+import org.collectionspace.services.config.ServiceConfig;
+import org.joda.time.DateTime;
+import org.opensaml.core.config.ConfigurationService;
+import org.opensaml.core.config.InitializationException;
+import org.opensaml.core.config.InitializationService;
+import org.opensaml.core.xml.XMLObjectBuilder;
+import org.opensaml.core.xml.XMLObjectBuilderFactory;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistry;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.core.xml.schema.XSAny;
+import org.opensaml.core.xml.schema.XSString;
+import org.opensaml.saml.common.SAMLObject;
+import org.opensaml.saml.common.SAMLVersion;
+import org.opensaml.saml.saml2.core.Assertion;
+import org.opensaml.saml.saml2.core.Attribute;
+import org.opensaml.saml.saml2.core.AttributeStatement;
+import org.opensaml.saml.saml2.core.AttributeValue;
+import org.opensaml.saml.saml2.core.NameID;
+import org.opensaml.saml.saml2.core.Subject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.BeforeSuite;
+
+public class AbstractSecurityTestBase {
+ private static final Logger logger = LoggerFactory.getLogger(SecurityUtilsTest.class);
+ protected static String BANNER = "-------------------------------------------------------";
+ protected static String FRIENDLY_ATTR_NAME = "mail";
+ protected static String ATTR_NAME = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress";
+ protected static String ATTR_NAME_FORMAT = "urn:oasis:names:tc:SAML:2.0:attrname-format:uri";
+ protected static String EMAIL_ADDRESS = "example@example.org";
+ protected static final String USERNAME_ATTRIBUTE = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress";
+ protected static final String SSOID_ATTRIBUTE = "http://schemas.auth0.com/identifier";
+ protected static final String SSO_CONFIG_STRING = createDefaultTestConfig();
+
+ protected static String createDefaultTestConfig() {
+ return createTestConfig(USERNAME_ATTRIBUTE, SSOID_ATTRIBUTE);
+ }
+
+ protected static String createTestConfig(String usernameAttribute, String ssoAttribute) {
+ return new StringBuilder().append("\n")
+ .append("")
+ .append("").append("").append("").append("")
+ .append("").append("")
+ .append("Auth0 - Scenario 11")
+ .append("")
+ .append("")
+ .append("").append("")
+ .append("").append("")
+ .append("").append("")
+ .append("").append("").append("")
+ .append("\n").append("").append("").toString();
+ }
+
+ protected static final String MOCK_ROOT_DIR = "./";
+
+ protected ServiceConfig parseServiceConfigString() throws JAXBException {
+ return parseServiceConfigString(MOCK_ROOT_DIR, SSO_CONFIG_STRING);
+ }
+
+ protected ServiceConfig parseServiceConfigString(String mockRootDir, String seviceConfigString)
+ throws JAXBException {
+ ServicesConfigReaderImpl rdr = new ServicesConfigReaderImpl(mockRootDir);
+ ByteArrayInputStream in = new ByteArrayInputStream(seviceConfigString.getBytes());
+ try {
+ serviceConfig = (ServiceConfig) rdr.parse(in, ServiceConfig.class);
+ } catch (JAXBException e) {
+ logger.warn("Could not create test service config: " + e.getLocalizedMessage());
+ throw e;
+ }
+ return serviceConfig;
+ }
+
+ /* for mocking useful SAML objects */
+ protected T createNewSAMLObject(Class clazz)
+ throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
+ XMLObjectBuilderFactory builderFactory = XMLObjectProviderRegistrySupport.getBuilderFactory();
+ QName defaultElementName = (QName) clazz.getDeclaredField("DEFAULT_ELEMENT_NAME").get(null);
+
+ @SuppressWarnings("unchecked") // NOTE: the T extends SAMLObject ought to guarantee this works
+ T theObject = (T) builderFactory.getBuilder(defaultElementName).buildObject(defaultElementName);
+ return theObject;
+ }
+
+ protected XSString createNewXSString(String value) {
+ XMLObjectBuilderFactory builderFactory = XMLObjectProviderRegistrySupport.getBuilderFactory();
+ @SuppressWarnings("unchecked")
+ XMLObjectBuilder stringBuilder = (XMLObjectBuilder) builderFactory
+ .getBuilder(XSString.TYPE_NAME);
+ XSString theString = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSString.TYPE_NAME);
+ theString.setValue(value);
+ return theString;
+ }
+
+ // NOTE: making the assumption that OpenSAML parses an untyped attribute value
+ // into XSAny with value in the text content
+ protected XSAny createNewXSAny(String value) {
+ XMLObjectBuilderFactory builderFactory = XMLObjectProviderRegistrySupport.getBuilderFactory();
+ @SuppressWarnings("unchecked")
+ XMLObjectBuilder stringBuilder = (XMLObjectBuilder) builderFactory.getBuilder(XSAny.TYPE_NAME);
+ XSAny theAny = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSAny.TYPE_NAME);
+ theAny.setTextContent(value);
+ return theAny;
+ }
+
+ protected Assertion createTestAssertionNoAttributes()
+ throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
+ Assertion testAssertion = createNewSAMLObject(Assertion.class);
+ testAssertion.setVersion(SAMLVersion.VERSION_20);
+ testAssertion.setIssueInstant(new DateTime());
+
+ Subject testSubject = createNewSAMLObject(Subject.class);
+ NameID testNameId = createNewSAMLObject(NameID.class);
+ testNameId.setValue("test subject nameid");
+ testSubject.setNameID(testNameId);
+ testAssertion.setSubject(testSubject);
+
+ return testAssertion;
+ }
+
+ protected Attribute createTestAttribute(boolean hasTypedAttributeValues, String attributeName,
+ String attributeNameFormat)
+ throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
+ Attribute attr = createNewSAMLObject(Attribute.class);
+ attr.setFriendlyName(FRIENDLY_ATTR_NAME);
+ attr.setName(attributeName);
+ attr.setNameFormat(attributeNameFormat);
+ if (hasTypedAttributeValues) {
+ XSString attrValue = createNewXSString(EMAIL_ADDRESS);
+ attr.getAttributeValues().add(attrValue);
+ } else {
+ XSAny attrValue = createNewXSAny(EMAIL_ADDRESS);
+ attr.getAttributeValues().add(attrValue);
+ }
+
+ return attr;
+ }
+
+ protected Attribute createDefaultTestAttribute(boolean hasTypedAttributeValues)
+ throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
+ return createTestAttribute(hasTypedAttributeValues, ATTR_NAME, ATTR_NAME_FORMAT);
+ }
+
+ protected Assertion createTestAssertion(Attribute attribute)
+ throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
+ Assertion testAssertion = createTestAssertionNoAttributes();
+
+ AttributeStatement attrStmt = createNewSAMLObject(AttributeStatement.class);
+ attrStmt.getAttributes().add(attribute);
+ testAssertion.getAttributeStatements().add(attrStmt);
+
+ return testAssertion;
+ }
+
+ protected Assertion createTestAssertionTypedAttributeValues()
+ throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
+ return createTestAssertion(createDefaultTestAttribute(true));
+ }
+
+ protected Assertion createTestAssertionUntypedAttributeValues()
+ throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
+ return createTestAssertion(createDefaultTestAttribute(false));
+ }
+
+ /* test suite setup below */
+ protected Assertion testAssertionTypedAttributeValues = null;
+ protected Assertion testAssertionUntypedAttributeValues = null;
+ protected ServiceConfig serviceConfig = null;
+
+ @BeforeSuite
+ protected void setup() throws InitializationException, NoSuchFieldException, IllegalAccessException, JAXBException {
+ /* try to set up openSAML */
+ XMLObjectProviderRegistry registry = new XMLObjectProviderRegistry();
+ ConfigurationService.register(XMLObjectProviderRegistry.class, registry);
+ try {
+ InitializationService.initialize();
+ } catch (InitializationException e) {
+ logger.error("Could not initialize openSAML: " + e.getLocalizedMessage(), e);
+ throw e;
+ }
+ // try to create a test assertion with typed attribute values; fail the test if
+ // this doesn't work
+ try {
+ testAssertionTypedAttributeValues = createTestAssertionTypedAttributeValues();
+ } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) {
+ logger.error("Could not create test assertion with typed attribute values: " + e.getLocalizedMessage(), e);
+ throw e;
+ }
+ // try to create a test assertion with untyped attribute values; fail the test
+ // if this doesn't work
+ try {
+ testAssertionUntypedAttributeValues = createTestAssertionUntypedAttributeValues();
+ } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) {
+ logger.error("Could not create test assertion with untyped attribute values: " + e.getLocalizedMessage(),
+ e);
+ throw e;
+ }
+
+ /* try to set up mock config */
+ serviceConfig = parseServiceConfigString();
+ }
+}
diff --git a/services/common/src/test/java/org/collectionspace/services/common/test/SecurityUtilsTest.java b/services/common/src/test/java/org/collectionspace/services/common/test/SecurityUtilsTest.java
index 1677792fa0..22b6fc62b7 100644
--- a/services/common/src/test/java/org/collectionspace/services/common/test/SecurityUtilsTest.java
+++ b/services/common/src/test/java/org/collectionspace/services/common/test/SecurityUtilsTest.java
@@ -1,222 +1,127 @@
package org.collectionspace.services.common.test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.Assert;
-import org.testng.annotations.BeforeSuite;
-import org.testng.annotations.Test;
-import org.w3c.dom.Element;
-
-import java.util.ArrayList;
import java.util.Set;
-import javax.xml.namespace.QName;
-import javax.xml.transform.OutputKeys;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerConfigurationException;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
+import javax.xml.bind.JAXBException;
import org.collectionspace.services.common.security.SecurityUtils;
-import org.collectionspace.services.config.AssertionAttributeProbeType;
import org.collectionspace.services.config.AssertionProbesType;
-import org.joda.time.DateTime;
-import org.opensaml.core.config.ConfigurationService;
-import org.opensaml.core.config.InitializationException;
-import org.opensaml.core.config.InitializationService;
-import org.opensaml.core.xml.XMLObject;
-import org.opensaml.core.xml.XMLObjectBuilder;
-import org.opensaml.core.xml.XMLObjectBuilderFactory;
-import org.opensaml.core.xml.config.XMLObjectProviderRegistry;
-import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
-import org.opensaml.core.xml.io.Marshaller;
-import org.opensaml.core.xml.io.MarshallingException;
-import org.opensaml.core.xml.schema.XSAny;
-import org.opensaml.core.xml.schema.XSString;
-import org.opensaml.saml.common.SAMLObject;
-import org.opensaml.saml.common.SAMLVersion;
-import org.opensaml.saml.saml2.core.AttributeStatement;
-import org.opensaml.saml.saml2.core.AttributeValue;
-import org.opensaml.saml.saml2.core.NameID;
-import org.opensaml.saml.saml2.core.Subject;
+import org.collectionspace.services.config.SAMLRelyingPartyRegistrationsType;
+import org.collectionspace.services.config.SAMLRelyingPartyType;
+import org.collectionspace.services.config.ServiceConfig;
import org.opensaml.saml.saml2.core.Assertion;
import org.opensaml.saml.saml2.core.Attribute;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
-public class SecurityUtilsTest {
+public class SecurityUtilsTest extends AbstractSecurityTestBase {
private static final Logger logger = LoggerFactory.getLogger(SecurityUtilsTest.class);
- private static String BANNER = "-------------------------------------------------------";
- private static String FRIENDLY_ATTR_NAME = "mail";
- private static String ATTR_NAME = "urn:oid:0.9.2342.19200300.100.1.3";
- private static String ATTR_NAME_FORMAT = "urn:oasis:names:tc:SAML:2.0:attrname-format:uri";
- private static String EMAIL_ADDRESS = "example@example.org";
- private void testBanner(String msg) {
- logger.info("\r" + BANNER + "\r\n" + this.getClass().getName() + "\r\n" + msg + "\r\n" + BANNER);
- }
- /*
- private String xml2String(XMLObject xmlObject) {
- Element element = null;
- String xmlString = "";
- try {
- Marshaller out = XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(xmlObject);
- out.marshall(xmlObject);
- element = xmlObject.getDOM();
-
- } catch (MarshallingException e) {
- logger.error(e.getMessage(), e);
- e.printStackTrace();
- }
-
- try {
- Transformer transformer = TransformerFactory.newInstance().newTransformer();
- transformer.setOutputProperty(OutputKeys.INDENT, "yes");
- StreamResult result = new StreamResult(new java.io.StringWriter());
-
- transformer.transform(new DOMSource(element), result);
- xmlString = result.getWriter().toString();
- } catch (TransformerConfigurationException e) {
- logger.error("Transformer configuration exception: " + e.getLocalizedMessage());
- e.printStackTrace();
- } catch (TransformerException e) {
- logger.error("Exception in transformer: " + e.getLocalizedMessage());
- e.printStackTrace();
- }
-
- return xmlString;
+
+ private void testBanner(String msg) {
+ logger.info("\r" + BANNER + "\r\n" + this.getClass().getName() + "\r\n" + msg + "\r\n" + BANNER);
}
- */
- private T createNewSAMLObject(Class clazz) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
- XMLObjectBuilderFactory builderFactory = XMLObjectProviderRegistrySupport.getBuilderFactory();
- QName defaultElementName = (QName) clazz.getDeclaredField("DEFAULT_ELEMENT_NAME").get(null);
-
- @SuppressWarnings("unchecked") // NOTE: the T extends SAMLObject ought to guarantee this works
- T theObject = (T) builderFactory.getBuilder(defaultElementName).buildObject(defaultElementName);
- return theObject;
- }
- private XSString createNewXSString(String value) {
- XMLObjectBuilderFactory builderFactory = XMLObjectProviderRegistrySupport.getBuilderFactory();
- @SuppressWarnings("unchecked")
- XMLObjectBuilder stringBuilder = (XMLObjectBuilder) builderFactory.getBuilder(XSString.TYPE_NAME);
- XSString theString = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSString.TYPE_NAME);
- theString.setValue(value);
- return theString;
- }
- // NOTE: making the assumption that OpenSAML parses an untyped attribute value into XSAny with value in the text content
- private XSAny createNewXSAny(String value) {
- XMLObjectBuilderFactory builderFactory = XMLObjectProviderRegistrySupport.getBuilderFactory();
- @SuppressWarnings("unchecked")
- XMLObjectBuilder stringBuilder = (XMLObjectBuilder) builderFactory.getBuilder(XSAny.TYPE_NAME);
- XSAny theAny = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME,XSAny.TYPE_NAME);
- theAny.setTextContent(value);
- return theAny;
- }
- private Assertion createTestAssertionNoAttributes() throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
- Assertion testAssertion = createNewSAMLObject(Assertion.class);
- testAssertion.setVersion(SAMLVersion.VERSION_20);
- testAssertion.setIssueInstant(new DateTime());
-
- Subject testSubject = createNewSAMLObject(Subject.class);
- NameID testNameId = createNewSAMLObject(NameID.class);
- testNameId.setValue("test subject nameid");
- testSubject.setNameID(testNameId);
- testAssertion.setSubject(testSubject);
-
- return testAssertion;
- }
- private Attribute createAttribute(boolean hasTypedAttributeValues) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
- Attribute attr = createNewSAMLObject(Attribute.class);
- attr.setFriendlyName(FRIENDLY_ATTR_NAME);
- attr.setName(ATTR_NAME);
- attr.setNameFormat(ATTR_NAME_FORMAT);
- if(hasTypedAttributeValues) {
- XSString attrValue = createNewXSString(EMAIL_ADDRESS);
- attr.getAttributeValues().add(attrValue);
- }
- else {
- XSAny attrValue = createNewXSAny(EMAIL_ADDRESS);
- attr.getAttributeValues().add(attrValue);
- }
-
- return attr;
- }
- private Assertion createTestAssertionTypedAttributeValues() throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
- Assertion testAssertion = createTestAssertionNoAttributes();
-
- Attribute attr = createAttribute(true);
-
- AttributeStatement attrStmt = createNewSAMLObject(AttributeStatement.class);
- attrStmt.getAttributes().add(attr);
- testAssertion.getAttributeStatements().add(attrStmt);
-
- return testAssertion;
- }
- private Assertion createTestAssertionUntypedAttributeValues() throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
- Assertion testAssertion = createTestAssertionNoAttributes();
-
- Attribute attr = createAttribute(false);
-
- AttributeStatement attrStmt = createNewSAMLObject(AttributeStatement.class);
- attrStmt.getAttributes().add(attr);
- testAssertion.getAttributeStatements().add(attrStmt);
-
- return testAssertion;
- }
-
- // the tests are below
- private Assertion testAssertionTypedAttributeValues = null;
- private Assertion testAssertionUntypedAttributeValues = null;
- @BeforeSuite
- private void setup() throws InitializationException,NoSuchFieldException,IllegalAccessException {
- // try to set up openSAML
- XMLObjectProviderRegistry registry = new XMLObjectProviderRegistry();
- ConfigurationService.register(XMLObjectProviderRegistry.class, registry);
+
+ @Test
+ public void assertionWithTypedAttributeValuesIsNotNull() {
+ testBanner("the mock assertion with typed attribute values is not null");
+ Assert.assertNotNull(testAssertionTypedAttributeValues);
+ }
+
+ @Test
+ public void assertionWithUntypedAttributeValuesIsNotNull() {
+ testBanner("the mock assertion with untyped attribute values is not null");
+ Assert.assertNotNull(testAssertionUntypedAttributeValues);
+ }
+
+ @Test(dependsOnMethods = { "assertionWithTypedAttributeValuesIsNotNull" })
+ public void candidateUsernamesTypedNotNullOrEmpty() {
+ testBanner("findSamlAssertionCandidateUsernames finds candidate usernames when they are typed as string");
+ Set candidateUsernames = SecurityUtils
+ .findSamlAssertionCandidateUsernames(testAssertionTypedAttributeValues, null);
+ Assert.assertNotNull(candidateUsernames);
+ if (null != candidateUsernames)
+ Assert.assertFalse(candidateUsernames.isEmpty());
+ }
+
+ @Test(dependsOnMethods = { "assertionWithUntypedAttributeValuesIsNotNull" })
+ public void candidateUsernamesUntypedNotNullOrEmpty() {
+ testBanner("findSamlAssertionCandidateUsernames finds candidate usernames when they are not typed");
+ Set candidateUsernames = SecurityUtils
+ .findSamlAssertionCandidateUsernames(testAssertionUntypedAttributeValues, null);
+ Assert.assertNotNull(candidateUsernames);
+ if (null != candidateUsernames)
+ Assert.assertFalse(candidateUsernames.isEmpty());
+ }
+
+ @Test(dependsOnMethods = { "assertionWithUntypedAttributeValuesIsNotNull" })
+ public void candidateUsernamesUntypedIsCorrect() {
+ testBanner("findSamlAssertionCandidateUsernames finds candidate usernames when they are not typed");
+ Set candidateUsernames = SecurityUtils
+ .findSamlAssertionCandidateUsernames(testAssertionUntypedAttributeValues, null);
+ Assert.assertNotNull(candidateUsernames);
+ if (null != candidateUsernames)
+ Assert.assertEquals(candidateUsernames.iterator().next(), EMAIL_ADDRESS);
+ }
+
+ @Test(dependsOnMethods = { "assertionWithTypedAttributeValuesIsNotNull" })
+ public void candidateUsernamesTypedIsCorrect() {
+ testBanner("findSamlAssertionCandidateUsernames finds candidate usernames when they are typed as string");
+ Set candidateUsernames = SecurityUtils
+ .findSamlAssertionCandidateUsernames(testAssertionTypedAttributeValues, null);
+ Assert.assertNotNull(candidateUsernames);
+ if (null != candidateUsernames)
+ Assert.assertEquals(candidateUsernames.iterator().next(), EMAIL_ADDRESS);
+ }
+
+ @Test
+ public void idenfitiferProbeFindsSsoId() throws JAXBException, IllegalArgumentException, IllegalAccessException,
+ NoSuchFieldException, SecurityException {
+ testBanner("identifier probe finds sso id");
+
+ String nameFormat = "urn:oasis:names:tc:SAML:2.0:attrname-format:uri";
+ String identifierName = "http://schemas.auth0.com/identifier";
+
+ // set up a minimal mock configuration string with the SSO ID probe we wish to
+ // test
+ String theConfigString = createTestConfig(USERNAME_ATTRIBUTE, identifierName);
+ ServiceConfig theServiceConfig = null;
try {
- InitializationService.initialize();
- } catch (InitializationException e) {
- logger.error("Could not initialize openSAML: " + e.getLocalizedMessage(), e);
+ theServiceConfig = parseServiceConfigString(MOCK_ROOT_DIR, theConfigString);
+ } catch (JAXBException e) {
+ logger.warn("Could not create mock service config: " + e.getLocalizedMessage());
throw e;
- }
- // try to create a test assertion with typed attribute values; fail the test if this doesn't work
+ }
+ SAMLRelyingPartyRegistrationsType relyingPartyRegistrations = theServiceConfig.getSecurity().getSso().getSaml()
+ .getRelyingPartyRegistrations();
+ SAMLRelyingPartyType relyingPartyRegistration = relyingPartyRegistrations.getRelyingParty().get(0);
+ AssertionProbesType assertionSsoIdProbes = (relyingPartyRegistration != null
+ ? relyingPartyRegistration.getAssertionSsoIdProbes()
+ : null);
+
+ // create an attribute with the same name identifier as the test probe
+ Attribute attribute = null;
try {
- testAssertionTypedAttributeValues = createTestAssertionTypedAttributeValues();
+ attribute = createTestAttribute(true, identifierName, nameFormat);
} catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) {
- logger.error("Could not create test assertion with typed attribute values: " + e.getLocalizedMessage(), e);
+ logger.warn("Could not create mock attribute: " + e.getLocalizedMessage());
throw e;
}
- // try to create a test assertion with untyped attribute values; fail the test if this doesn't work
+ // create a SAML assertion with the attribute
+ Assertion assertion = null;
try {
- testAssertionUntypedAttributeValues = createTestAssertionUntypedAttributeValues();
+ assertion = createTestAssertion(attribute);
} catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) {
- logger.error("Could not create test assertion with untyped attribute values: " + e.getLocalizedMessage(), e);
+ logger.warn("Could not create SAML assertion" + e.getLocalizedMessage());
throw e;
}
- }
-
- @Test
- public void assertionWithTypedAttributeValuesIsNotNull() {
- testBanner("the mock assertion with typed attribute values is not null");
- Assert.assertNotNull(testAssertionTypedAttributeValues);
- }
- @Test
- public void assertionWithUntypedAttributeValuesIsNotNull() {
- testBanner("the mock assertion with untyped attribute values is not null");
- Assert.assertNotNull(testAssertionUntypedAttributeValues);
- }
- @Test(dependsOnMethods = {"assertionWithTypedAttributeValuesIsNotNull"})
- public void candidateUsernamesTypedNotNullOrEmpty() {
- testBanner("findSamlAssertionCandidateUsernames finds candidate usernames when they are typed as string");
- Set candidateUsernames = SecurityUtils.findSamlAssertionCandidateUsernames(testAssertionTypedAttributeValues, null);
- Assert.assertNotNull(candidateUsernames);
- if(null != candidateUsernames)
- Assert.assertFalse(candidateUsernames.isEmpty());
- }
- @Test(dependsOnMethods = {"assertionWithUntypedAttributeValuesIsNotNull"})
- public void candidateUsernamesUntypedNotNullOrEmpty() {
- testBanner("findSamlAssertionCandidateUsernames finds candidate usernames when they are not typed");
- Set candidateUsernames = SecurityUtils.findSamlAssertionCandidateUsernames(testAssertionUntypedAttributeValues, null);
- Assert.assertNotNull(candidateUsernames);
- if(null != candidateUsernames)
- Assert.assertFalse(candidateUsernames.isEmpty());
- }
+
+ // check whether getSamlAssertionSsoId finds the SSO ID we put in the assertion
+ // using the test probe
+ String ssoId = SecurityUtils.getSamlAssertionSsoId(assertion, assertionSsoIdProbes);
+ Assert.assertNotNull(ssoId);
+ Assert.assertFalse(ssoId.isEmpty());
+ Assert.assertEquals(ssoId, EMAIL_ADDRESS);
+ }
}
diff --git a/services/config/pom.xml b/services/config/pom.xml
index 1adf618ee1..71136d8951 100644
--- a/services/config/pom.xml
+++ b/services/config/pom.xml
@@ -30,6 +30,17 @@
javax.xml.bind
jaxb-api
+
+ com.sun.xml.bind
+ jaxb-core
+ test
+
+
+ xerces
+ xercesImpl
+ 2.12.2
+ test
+
org.jvnet.jaxb2_commons
jaxb2-basics
diff --git a/services/config/src/main/java/org/collectionspace/services/common/config/AbstractConfigReaderImpl.java b/services/config/src/main/java/org/collectionspace/services/common/config/AbstractConfigReaderImpl.java
index eff40cbf44..a03e118f35 100644
--- a/services/config/src/main/java/org/collectionspace/services/common/config/AbstractConfigReaderImpl.java
+++ b/services/config/src/main/java/org/collectionspace/services/common/config/AbstractConfigReaderImpl.java
@@ -121,7 +121,7 @@ List getDirectories(File rootDir) throws IOException {
return getFileChildren(rootDir, true);
}
- protected Object parse(File configFile, Class> clazz)
+ public Object parse(File configFile, Class> clazz)
throws FileNotFoundException, JAXBException {
Object result = null;
@@ -144,7 +144,7 @@ protected Object parse(File configFile, Class> clazz)
* @throws JAXBException
* @throws Exception
*/
- protected Object parse(InputStream configFileStream, Class> clazz)
+ public Object parse(InputStream configFileStream, Class> clazz)
throws JAXBException {
Object result = null;
diff --git a/services/config/src/main/resources/service.xsd b/services/config/src/main/resources/service.xsd
index bc4c786d1b..32faa9e066 100644
--- a/services/config/src/main/resources/service.xsd
+++ b/services/config/src/main/resources/service.xsd
@@ -76,6 +76,7 @@
+
diff --git a/services/config/src/test/java/org/collectionspace/services/common/config/ServicesConfigReaderImplTest.java b/services/config/src/test/java/org/collectionspace/services/common/config/ServicesConfigReaderImplTest.java
new file mode 100644
index 0000000000..73c612ccf0
--- /dev/null
+++ b/services/config/src/test/java/org/collectionspace/services/common/config/ServicesConfigReaderImplTest.java
@@ -0,0 +1,139 @@
+package org.collectionspace.services.common.config;
+
+import java.io.ByteArrayInputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.JAXBException;
+
+import org.collectionspace.services.config.AssertionAttributeProbeType;
+import org.collectionspace.services.config.SAMLRelyingPartyType;
+import org.collectionspace.services.config.SAMLType;
+import org.collectionspace.services.config.ServiceConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.BeforeSuite;
+import org.testng.annotations.Test;
+
+public class ServicesConfigReaderImplTest {
+ private static final Logger logger = LoggerFactory.getLogger(ServicesConfigReaderImplTest.class);
+ private static String BANNER = "-------------------------------------------------------";
+ // NOTE: adapted from https://collectionspace.atlassian.net/browse/DRYD-1702?focusedCommentId=60649
+ private static final String USERNAME_ATTRIBUTE = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress";
+ private static final String SSOID_ATTRIBUTE = "http://schemas.auth0.com/identifier";
+ private static final String SSO_CONFIG_STRING = new StringBuilder()
+ .append("\n")
+ .append("")
+ .append("")
+ .append("")
+ .append("")
+ .append("")
+ .append("")
+ .append("")
+ .append("Auth0 - Scenario 11")
+ .append("")
+ .append("")
+ .append("")
+ .append("")
+ .append("")
+ .append("")
+ .append("")
+ .append("")
+ .append("")
+ .append("")
+ .append("")
+ .append("\n")
+ .append("")
+ .append("")
+ .toString();
+ private static final String MOCK_ROOT_DIR = "./";
+ private void testBanner(String msg) {
+ logger.info("\r" + BANNER + "\r\n" + this.getClass().getName() + "\r\n" + msg + "\r\n" + BANNER);
+ }
+ private List getUserNameProbesFromConfig() {
+ return getUserNameProbesFromConfig(serviceConfig);
+ }
+ private List getUserNameProbesFromConfig(ServiceConfig serviceConfig) {
+ SAMLType samlConfig = serviceConfig.getSecurity().getSso().getSaml();
+ List relyingParties = samlConfig.getRelyingPartyRegistrations().getRelyingParty();
+ SAMLRelyingPartyType relyingParty = relyingParties.get(0);
+
+ List
-
- org.hibernate
- hibernate-c3p0
- 3.6.10.Final
-
-
- org.jvnet.hyperjaxb3
-
- hyperjaxb3-ejb-runtime
- 0.6.0
-
-
- mysql
- mysql-connector-java
- ${mysql.driver.version}
-
-
- org.postgresql
- postgresql
- ${postgres.driver.version}
-
diff --git a/services/report/3rdparty/jasper-cs-report/src/main/resources/coreIntake.jrxml b/services/report/3rdparty/jasper-cs-report/src/main/resources/coreIntake.jrxml
index 58ed644efa..0bd4ab6607 100644
--- a/services/report/3rdparty/jasper-cs-report/src/main/resources/coreIntake.jrxml
+++ b/services/report/3rdparty/jasper-cs-report/src/main/resources/coreIntake.jrxml
@@ -24,7 +24,7 @@ inc.entryDate entryDate,
inc.returnDate returnDate,
h1.name AS "csid",
co.objectnumber AS "objectnumber",
-co.fieldcollectionplace AS site,
+fieldcollectionplace.item AS site,
ong.objectName AS "objectname",
bd.item AS description,
oppp.objectproductionpeople AS productionpeople
@@ -36,6 +36,7 @@ LEFT OUTER JOIN collectionobjects_common co ON (h2.id=co.id)
LEFT OUTER JOIN hierarchy h3 ON (co.id = h3.parentid AND h3.primarytype='objectNameGroup' AND h3.pos=0)
LEFT OUTER JOIN objectnamegroup ong ON (ong.id=h3.id)
LEFT OUTER JOIN collectionobjects_common_briefdescriptions bd ON (bd.id=co.id and bd.pos=0)
+LEFT OUTER JOIN collectionobjects_common_fieldcollectionplaces fieldcollectionplace ON (fieldcollectionplace.id = co.id AND fieldcollectionplace.pos = 0)
left outer join hierarchy h4 on (co.id=h4.parentid and h4.pos=0 and h4.name='collectionobjects_common:objectProductionPeopleGroupList')
left outer join objectproductionpeoplegroup oppp on (oppp.id=h4.id)
LEFT OUTER JOIN misc m ON (m.id = co.id)
diff --git a/services/report/3rdparty/jasper-cs-report/src/main/resources/coreLoanIn.jrxml b/services/report/3rdparty/jasper-cs-report/src/main/resources/coreLoanIn.jrxml
index 3b0e096c45..5529f0b0f7 100644
--- a/services/report/3rdparty/jasper-cs-report/src/main/resources/coreLoanIn.jrxml
+++ b/services/report/3rdparty/jasper-cs-report/src/main/resources/coreLoanIn.jrxml
@@ -28,7 +28,7 @@ lic.loanReturnDate as loanReturnDate,
lic.loanInNote as loanInNote,
h1.name AS "csid",
co.objectnumber AS "objectnumber",
-co.fieldcollectionplace AS site,
+fieldcollectionplace.item AS site,
ong.objectName AS "objectname",
bd.item AS description,
oppp.objectproductionpeople AS productionpeople
@@ -40,6 +40,7 @@ LEFT OUTER JOIN collectionobjects_common co ON (h2.id=co.id)
LEFT OUTER JOIN hierarchy h3 ON (co.id = h3.parentid AND h3.primarytype='objectNameGroup' AND h3.pos=0)
LEFT OUTER JOIN objectnamegroup ong ON (ong.id=h3.id)
LEFT OUTER JOIN collectionobjects_common_briefdescriptions bd ON (bd.id=co.id and bd.pos=0)
+LEFT OUTER JOIN collectionobjects_common_fieldcollectionplaces fieldcollectionplace ON (fieldcollectionplace.id = co.id AND fieldcollectionplace.pos = 0)
left outer join hierarchy h4 on (co.id=h4.parentid and h4.pos=0 and h4.name='collectionobjects_common:objectProductionPeopleGroupList')
left outer join objectproductionpeoplegroup oppp on (oppp.id=h4.id)
left outer join hierarchy hlgl on (lic.id=hlgl.parentid and hlgl.pos=0 and hlgl.name='loansin_common:lenderGroupList')
diff --git a/services/report/3rdparty/jasper-cs-report/src/main/resources/coreLoanOut.jrxml b/services/report/3rdparty/jasper-cs-report/src/main/resources/coreLoanOut.jrxml
index 09263b0372..e3f54bd106 100644
--- a/services/report/3rdparty/jasper-cs-report/src/main/resources/coreLoanOut.jrxml
+++ b/services/report/3rdparty/jasper-cs-report/src/main/resources/coreLoanOut.jrxml
@@ -28,7 +28,7 @@ loc.loanReturnDate loanReturnDate,
loc.loanOutNote loanOutNote,
h1.name AS "csid",
co.objectnumber AS "objectnumber",
-co.fieldcollectionplace AS site,
+fieldcollectionplace.item AS site,
ong.objectName AS "objectname",
bd.item AS description,
oppp.objectproductionpeople as productionpeople
@@ -40,6 +40,7 @@ LEFT OUTER JOIN collectionobjects_common co ON (h2.id=co.id)
LEFT OUTER JOIN hierarchy h3 ON (co.id = h3.parentid AND h3.primarytype='objectNameGroup' AND h3.pos=0)
LEFT OUTER JOIN objectnamegroup ong ON (ong.id=h3.id)
LEFT OUTER JOIN collectionobjects_common_briefdescriptions bd ON (bd.id=co.id and bd.pos=0)
+LEFT OUTER JOIN collectionobjects_common_fieldcollectionplaces fieldcollectionplace ON (fieldcollectionplace.id = co.id AND fieldcollectionplace.pos = 0)
left outer join hierarchy h4 on (co.id=h4.parentid and h4.pos=0 and h4.name='collectionobjects_common:objectProductionPeopleGroupList')
left outer join objectproductionpeoplegroup oppp on (oppp.id=h4.id)
LEFT OUTER JOIN misc m ON (m.id = co.id)
diff --git a/services/report/3rdparty/jasper-cs-report/src/main/resources/coreObjectExit.jrxml b/services/report/3rdparty/jasper-cs-report/src/main/resources/coreObjectExit.jrxml
index 7c8351ae3d..9227a0613b 100644
--- a/services/report/3rdparty/jasper-cs-report/src/main/resources/coreObjectExit.jrxml
+++ b/services/report/3rdparty/jasper-cs-report/src/main/resources/coreObjectExit.jrxml
@@ -27,7 +27,7 @@ case when (oec.currentOwner is not null and oec.currentOwner <> '') then
end AS owner,
h1.name AS "csid",
co.objectnumber AS "objectnumber",
-co.fieldcollectionplace AS site,
+fieldcollectionplace.item AS site,
-- co.fieldcollectionnote fieldcollectionnote,
ong.objectName AS "objectname",
bd.item AS description,
@@ -40,6 +40,7 @@ LEFT OUTER JOIN collectionobjects_common co ON (h2.id=co.id)
LEFT OUTER JOIN hierarchy h3 ON (co.id = h3.parentid AND h3.primarytype='objectNameGroup' AND h3.pos=0)
LEFT OUTER JOIN objectnamegroup ong ON (ong.id=h3.id)
LEFT OUTER JOIN collectionobjects_common_briefdescriptions bd ON (bd.id=co.id and bd.pos=0)
+LEFT OUTER JOIN collectionobjects_common_fieldcollectionplaces fieldcollectionplace ON (fieldcollectionplace.id = co.id AND fieldcollectionplace.pos = 0)
left outer join hierarchy h4 on (co.id=h4.parentid and h4.pos=0 and h4.name='collectionobjects_common:objectProductionPeopleGroupList')
left outer join objectproductionpeoplegroup oppp on (oppp.id=h4.id)
left outer join hierarchy h5 on (oec.id=h5.parentid and h5.name='objectexit_common:exitDateGroup')
diff --git a/services/report/3rdparty/jasper-cs-report/src/main/resources/full_obj_place.jrxml b/services/report/3rdparty/jasper-cs-report/src/main/resources/full_obj_place.jrxml
index bbaf555c5b..e2a26b12f8 100644
--- a/services/report/3rdparty/jasper-cs-report/src/main/resources/full_obj_place.jrxml
+++ b/services/report/3rdparty/jasper-cs-report/src/main/resources/full_obj_place.jrxml
@@ -10,7 +10,7 @@
-
+
@@ -25,26 +25,26 @@
tg.title,
dategroup.publicartproductiondatetype,
proddate.datedisplaydate AS objectproductiondate,
- creator.publicartproductionperson,
- creator.publicartproductionpersonrole,
+ coalesce(creator_agg.publicartproductionpersons, '{}') as publicartproductionpersons,
+ coalesce(creator_agg.publicartproductionpersonroles, '{}') as publicartproductionpersonroles,
rd.item AS responsibledepartment,
obj.recordstatus,
publishto.item AS publishto,
installationtype.item AS installationtype,
objectCountGroup.objectcount AS numberofobjects,
- worktype.objectname AS worktype,
- material.material, -- deurn
+ coalesce(worktype_agg.worktypes, '{}') AS worktypes,
+ coalesce(material_agg.materials, '{}') AS materials,
bd.item AS briefdescription,
comment.item AS comment,
- publicart_collections.collections,
+ coalesce(publicart_collections.collections, '{}') as collections,
owners.item AS owner,
dimension.dimension,
obj.computedcurrentlocation,
movement.currentlocationnote,
place.placenote,
- placement.item AS placementtype,
+ coalesce(placementtype_agg.placementtypes, '{}') AS placementtypes,
place_pa.placementenvironment,
- placetype.item AS placetype,
+ coalesce(placetype_agg.placetypes, '{}') AS placetypes,
placeowner.owner AS placeowner,
placeowner.ownershipnote,
placeowner.ownertype,
@@ -69,17 +69,42 @@ LEFT JOIN hierarchy proddategroup_hier ON proddategroup_hier.parentid = obj.id A
LEFT JOIN publicartproductiondategroup dategroup ON dategroup.id = proddategroup_hier.id
LEFT JOIN hierarchy proddate_hier ON proddate_hier.parentid = proddategroup_hier.id
LEFT JOIN structureddategroup proddate ON proddate.id = proddate_hier.id
-LEFT JOIN hierarchy creator_hier ON creator_hier.parentid = obj.id AND creator_hier.primarytype = 'publicartProductionPersonGroup' AND creator_hier.pos = 0
-LEFT JOIN publicartproductionpersongroup creator ON creator.id = creator_hier.id
+-- AGGREGATE ALL CREATORS AND ROLES
+LEFT JOIN (
+ SELECT
+ creator_hier.parentid AS obj_id,
+ array_agg(coalesce(creator.publicartproductionperson, '')) AS publicartproductionpersons,
+ array_agg(coalesce(creator.publicartproductionpersonrole, '')) AS publicartproductionpersonroles
+ FROM hierarchy creator_hier
+ LEFT JOIN publicartproductionpersongroup creator ON creator.id = creator_hier.id
+ WHERE creator_hier.primarytype = 'publicartProductionPersonGroup'
+ GROUP BY creator_hier.parentid
+) creator_agg ON creator_agg.obj_id = obj.id
LEFT JOIN collectionobjects_common_responsibledepartments rd ON rd.id = obj.id AND rd.pos = 0
LEFT JOIN collectionobjects_common_publishtolist publishto ON publishto.id = obj.id AND publishto.pos = 0
LEFT JOIN collectionobjects_common_inventorystatuslist installationtype ON installationtype.id = obj.id AND installationtype.pos = 0
LEFT JOIN collectionobjects_common_briefdescriptions bd ON bd.id = obj.id AND bd.pos = 0
LEFT JOIN collectionobjects_common_comments comment ON comment.id = obj.id AND comment.pos = 0
-LEFT JOIN hierarchy work_hier on work_hier.parentid = obj.id and work_hier.primarytype = 'objectNameGroup' and work_hier.pos = 0
-LEFT JOIN objectnamegroup worktype on worktype.id = work_hier.id
-LEFT JOIN hierarchy material_hier on material_hier.parentid = obj.id and material_hier.primarytype = 'materialGroup' and material_hier.pos = 0
-LEFT JOIN materialgroup material on material.id = material_hier.id
+-- AGGREGATE ALL WORK TYPES
+LEFT JOIN (
+ SELECT
+ work_hier.parentid AS obj_id,
+ array_agg(coalesce(worktype.objectname, '')) AS worktypes
+ FROM hierarchy work_hier
+ LEFT JOIN objectnamegroup worktype ON worktype.id = work_hier.id
+ WHERE work_hier.primarytype = 'objectNameGroup'
+ GROUP BY work_hier.parentid
+) worktype_agg ON worktype_agg.obj_id = obj.id
+-- AGGREGATE ALL MATERIALS
+LEFT JOIN (
+ SELECT
+ material_hier.parentid AS obj_id,
+ array_agg(coalesce(material.material, '')) AS materials
+ FROM hierarchy material_hier
+ LEFT JOIN materialgroup material ON material.id = material_hier.id
+ WHERE material_hier.primarytype = 'materialGroup'
+ GROUP BY material_hier.parentid
+) material_agg ON material_agg.obj_id = obj.id
LEFT JOIN (
SELECT
id AS obj_id,
@@ -115,9 +140,23 @@ LEFT JOIN (
) movement ON movement.objectcsid = hier.name AND movement.currentlocation = obj.computedcurrentlocation
-- place and all place fields
LEFT JOIN places_common place on place.refname = obj.computedcurrentlocation
-LEFT JOIN places_publicart_placementtypes placement on placement.id = place.id AND placement.pos = 0
+-- AGGREGATE ALL PLACEMENTTYPES
+LEFT JOIN (
+ SELECT
+ placementtypes.id AS place_id,
+ array_agg(placementtypes.item) AS placementtypes
+ FROM places_publicart_placementtypes placementtypes
+ GROUP BY placementtypes.id
+) placementtype_agg ON placementtype_agg.place_id = place.id
LEFT JOIN places_publicart place_pa on place_pa.id = place.id
-LEFT JOIN places_publicart_publicartplacetypes placetype on placetype.id = place.id AND placetype.pos = 0
+-- AGGREGATE ALL PLACETYPES
+LEFT JOIN (
+ SELECT
+ placetype.id AS place_id,
+ array_agg(placetype.item) AS placetypes
+ FROM places_publicart_publicartplacetypes placetype
+ GROUP BY placetype.id
+) placetype_agg ON placetype_agg.place_id = place.id
LEFT JOIN hierarchy placeowner_hier on placeowner_hier.parentid = place.id and placeowner_hier.primarytype = 'publicartPlaceOwnerGroup' and placeowner_hier.pos = 0
LEFT JOIN hierarchy placeownerdate_hier on placeownerdate_hier.parentid = placeowner_hier.id
LEFT JOIN publicartplaceownergroup placeowner on placeowner.id = placeowner_hier.id
@@ -150,14 +189,14 @@ $P!{whereclause}]]>
-
-
-
+
+
+
-
-
-
+
+
+
@@ -185,14 +224,14 @@ $P!{whereclause}]]>
-
-
-
+
+
+
-
-
-
+
+
+
@@ -229,9 +268,9 @@ $P!{whereclause}]]>
-
-
-
+
+
+
@@ -239,9 +278,9 @@ $P!{whereclause}]]>
-
-
-
+
+
+
@@ -415,7 +454,7 @@ $P!{whereclause}]]>
-
+
@@ -625,13 +664,13 @@ $P!{whereclause}]]>
-
+
-
+
@@ -667,13 +706,13 @@ $P!{whereclause}]]>
-
+
-
+
@@ -721,7 +760,7 @@ $P!{whereclause}]]>
-
+
@@ -733,7 +772,7 @@ $P!{whereclause}]]>
-
+
diff --git a/services/report/3rdparty/jasper-cs-report/src/main/resources/full_obj_place_creator_role_combined.jrxml b/services/report/3rdparty/jasper-cs-report/src/main/resources/full_obj_place_creator_role_combined.jrxml
new file mode 100644
index 0000000000..8456234f24
--- /dev/null
+++ b/services/report/3rdparty/jasper-cs-report/src/main/resources/full_obj_place_creator_role_combined.jrxml
@@ -0,0 +1,869 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ !!value).join('; ')
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/services/report/3rdparty/jasper-cs-report/src/main/resources/full_obj_place_creator_role_combined.xml b/services/report/3rdparty/jasper-cs-report/src/main/resources/full_obj_place_creator_role_combined.xml
new file mode 100644
index 0000000000..f45a558d41
--- /dev/null
+++ b/services/report/3rdparty/jasper-cs-report/src/main/resources/full_obj_place_creator_role_combined.xml
@@ -0,0 +1,16 @@
+
+
+
+ Full Object with Place Details: Creator Name and Role Combined
+ This object report exclusive to the Public Art profile includes descriptive object record fields combined with current place details. The creator's name and role are combined in a single column.
+
+ CollectionObject
+
+ true
+ false
+ false
+ true
+ full_obj_place_creator_role_combined.jrxml
+ application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
+
+
diff --git a/services/report/3rdparty/jasper-cs-report/src/main/resources/notice_of_intent_to_repatriate.jrxml b/services/report/3rdparty/jasper-cs-report/src/main/resources/notice_of_intent_to_repatriate.jrxml
index 67e3d3237f..59073bb421 100644
--- a/services/report/3rdparty/jasper-cs-report/src/main/resources/notice_of_intent_to_repatriate.jrxml
+++ b/services/report/3rdparty/jasper-cs-report/src/main/resources/notice_of_intent_to_repatriate.jrxml
@@ -13,7 +13,7 @@
-
+
@@ -59,7 +59,8 @@ SELECT
coalesce(partiesinvolved.involvedparty, '{}') as involved_party,
coalesce(partiesinvolved.title, '{}') as involved_party_title,
coalesce(partiesinvolved.email, '{}') as involved_party_email,
- statusgroup.status,
+ coalesce(statusgroup.statusgroup_statuses, '{}') as statusgroup_statuses,
+ coalesce(statusgroup.statusgroup_status_dates, '{}') as statusgroup_status_dates,
coalesce(field_collection_places.places, '{}') AS places,
coalesce(field_collection_sites.sites, '{}') AS sites,
coalesce(field_collectors.collectors, '{}') AS collectors,
@@ -119,12 +120,13 @@ FROM hierarchy summary_hierarchy
) culturalgroup ON culturalgroup.parentid = summary.id -- status group or whatever
LEFT JOIN LATERAL (
SELECT hierarchy.parentid,
- status.status
+ array_agg(status.status) AS statusgroup_statuses,
+ array_agg(status.statusdate) AS statusgroup_status_dates
FROM hierarchy
INNER JOIN statusgroup status ON status.id = hierarchy.id
AND hierarchy.name = 'summarydocumentations_common:statusGroupList'
- AND hierarchy.pos = 0
AND hierarchy.parentid = summary.id
+ GROUP BY hierarchy.parentid
) statusgroup ON statusgroup.parentid = summary.id
-- Object Fields:
-- + computedcurrentlocation | collectionobjects_common | agg
@@ -272,10 +274,13 @@ WHERE summary_hierarchy.primarytype = 'SummaryDocumentation' $P!{whereclause}]]>
-
-
-
-
+
+
+
+
+
+
+
@@ -653,7 +658,20 @@ WHERE summary_hierarchy.primarytype = 'SummaryDocumentation' $P!{whereclause}]]>
-
+
+ !!value).join('; ')
+ ]]>
+
diff --git a/services/report/3rdparty/jasper-cs-report/src/main/resources/notice_of_inventory_completion.jrxml b/services/report/3rdparty/jasper-cs-report/src/main/resources/notice_of_inventory_completion.jrxml
index 73ba0c9704..b4b753d6d7 100644
--- a/services/report/3rdparty/jasper-cs-report/src/main/resources/notice_of_inventory_completion.jrxml
+++ b/services/report/3rdparty/jasper-cs-report/src/main/resources/notice_of_inventory_completion.jrxml
@@ -13,7 +13,7 @@
-
+
@@ -55,6 +55,7 @@ SELECT nt.item AS notice_type,
coalesce(object_count_afo.object_count_afo, 0) as object_count_afo,
coalesce(object_category.object_category_units, '{}') AS object_category_units,
coalesce(object_category.object_category_counts, '{}') AS object_category_counts,
+ coalesce(object_category.object_category_categories, '{}') AS object_category_categories,
coalesce(object_names.object_names, '{}') as object_names,
coalesce(object_names.controlled_object_names, '{}') AS controlled_object_names,
coalesce(acquisition_data.acquisition_numbers, '{}') as acquisition_numbers,
@@ -120,7 +121,8 @@ FROM hierarchy
LEFT JOIN LATERAL (
SELECT category_hierarchy.parentid,
array_agg(category.categorycountunit) AS object_category_units,
- array_agg(category.categorycount) AS object_category_counts
+ array_agg(category.categorycount) AS object_category_counts,
+ array_agg(category.category) AS object_category_categories
FROM hierarchy category_hierarchy
INNER JOIN objectcategorygroup category ON category.id = category_hierarchy.id
WHERE category_hierarchy.name = 'collectionobjects_objectcategory_extension:objectCategoryGroupList'
@@ -230,6 +232,10 @@ $P!{whereclause}]]>
+
+
+
+
@@ -402,14 +408,18 @@ $P!{whereclause}]]>
- !!value).join('; ')
+ !!value).join('; ')
]]>
diff --git a/services/restrictedmedia/client/pom.xml b/services/restrictedmedia/client/pom.xml
index 1a3623c7fb..2ccb0db6f1 100644
--- a/services/restrictedmedia/client/pom.xml
+++ b/services/restrictedmedia/client/pom.xml
@@ -34,6 +34,18 @@
org.collectionspace.services.restrictedmedia.jaxb
${project.version}