diff --git a/3rdparty/nuxeo/nuxeo-platform-elasticsearch/src/main/java/org/collectionspace/services/nuxeo/elasticsearch/DefaultESDocumentWriter.java b/3rdparty/nuxeo/nuxeo-platform-elasticsearch/src/main/java/org/collectionspace/services/nuxeo/elasticsearch/DefaultESDocumentWriter.java index 43d242e2c1..e9dea8ffed 100644 --- a/3rdparty/nuxeo/nuxeo-platform-elasticsearch/src/main/java/org/collectionspace/services/nuxeo/elasticsearch/DefaultESDocumentWriter.java +++ b/3rdparty/nuxeo/nuxeo-platform-elasticsearch/src/main/java/org/collectionspace/services/nuxeo/elasticsearch/DefaultESDocumentWriter.java @@ -78,6 +78,13 @@ public ObjectNode getDenormValues(DocumentModel doc) { List> prodDateGroupList = (List>) doc.getProperty("collectionobjects_common", "objectProductionDateGroupList"); denormValues.putArray("prodYears").addAll(structDatesToYearNodes(prodDateGroupList)); + } else if ("Media".equals(docType) && isMediaPublished(doc)) { + CoreSession session = doc.getCoreSession(); + String csid = doc.getName(); + String tenantId = (String) doc.getProperty("collectionspace_core", "tenantId"); + + // Add media-specific denormalized fields + denormRelatedObjects(session, csid, tenantId, denormValues); } return denormValues; @@ -135,6 +142,31 @@ private void denormMediaRecords(CoreSession session, String csid, String tenantI denormValues.put("hasMedia", mediaCsids.size() > 0); } + private void denormRelatedObjects(CoreSession session, String csid, String tenantId, ObjectNode denormValues) { + // Store the objectCsid of objects that are related to this media. + + String relatedRecordQuery = String.format( + "SELECT * FROM Relation WHERE relations_common:objectCsid = '%s' AND relations_common:subjectDocumentType = 'CollectionObject' AND ecm:currentLifeCycleState = 'project' AND collectionspace_core:tenantId = '%s'", + csid, tenantId); + DocumentModelList relationDocs = session.query(relatedRecordQuery); + List objectCsids = new ArrayList(); + + if (relationDocs.size() > 0) { + Iterator iterator = relationDocs.iterator(); + + while (iterator.hasNext()) { + DocumentModel relationDoc = iterator.next(); + String objectCsid = (String) relationDoc.getProperty("relations_common", "subjectCsid"); + + if (objectCsid != null) { + objectCsids.add(new TextNode(objectCsid)); + } + } + } + + denormValues.putArray("objectCsid").addAll(objectCsids); + } + private void denormAcquisitionRecords(CoreSession session, String csid, String tenantId, ObjectNode denormValues) { // Store the credit lines of acquisition records that are related to this object. @@ -266,6 +298,7 @@ private void denormConceptFields(final DocumentModel doc, final ObjectNode denor final List fields = Arrays.asList("contentConcepts", "contentEvents", "contentPersons", + "contentPlaces", "contentOrganizations"); for (String field : fields) { @@ -274,7 +307,18 @@ private void denormConceptFields(final DocumentModel doc, final ObjectNode denor for (String content : contentList) { if (content != null) { final ObjectNode node = objectMapper.createObjectNode(); - node.put("subject", RefNameUtils.getDisplayName(content)); + String subjectValue; + + if (RefNameUtils.isTermRefname(content)) { + try { + subjectValue = RefNameUtils.getDisplayName(content); + } catch (Exception e) { + subjectValue = content; + } + } else { + subjectValue = content; + } + node.put("subject", subjectValue); denormContentSubject.add(node); } } diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000..8833db28ec --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,18 @@ +# CollectionSpace Services Changelog + +## 8.3.0 + +* Add new endpoint for returning search results +* Add JDBC_URL_OPTS build parameter +* Add mapping for ElasticSearch imagine ordering +* Add CSV Authority export parameter +* Update notice of inventory completion report +* Update notice of intent to repatriate report +* Update full object with place details report +* Add contentPlaces to ES mapping +* Add blob alt text to media responses +* Remove cspace_english namespace search + +### Bug Fixes + +* Remove flickr urls from tests diff --git a/build.properties b/build.properties index 8e1afaa6a2..f622b3fe4f 100644 --- a/build.properties +++ b/build.properties @@ -9,7 +9,7 @@ host=127.0.0.1 # # Release version info # -release.version=8.2.0 +release.version=8.3.0-RC.1 cspace.release=${release.version} cspace.instance.id=${env.CSPACE_INSTANCE_ID} @@ -27,15 +27,15 @@ cspace.im.root= # UI settings cspace.ui.package.name=cspace-ui cspace.ui.library.name=cspaceUI -cspace.ui.version=10.1.0 -cspace.ui.build.branch=main +cspace.ui.version=10.2.0-rc1.0 +cspace.ui.build.branch=develop cspace.ui.build.node.ver=20 service.ui.library.name=${cspace.ui.library.name}-service # Public browser settings cspace.public.browser.package.name=@collectionspace/cspace-public-browser cspace.public.browser.library.name=cspacePublicBrowser -cspace.public.browser.version=3.4.0 +cspace.public.browser.version=3.5.0-rc1.0 cspace.public.browser.build.branch=main cspace.public.browser.build.node.ver=20 @@ -198,10 +198,11 @@ db.jdbc.default.datasource=jdbc/default #db.jdbc.urloptions.encoded=ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory&foo=true # -# By default, as placeholders, we'll supply meaningless JDBC options -both encoded and non-encode forms. +# Use the JDBC_URL_PARAMS env var to set the urloptions for the jdbc connection string +# The db.jdbc.urloptions.encoded needs to be created in each ant target which uses it by calling the +# urlencode scriptdef. We can still reference it below as it will be added at runtime. # -db.jdbc.urloptions=foo=true&bar=false -db.jdbc.urloptions.encoded=foo=true&bar=false +db.jdbc.urloptions=${env.JDBC_URL_PARAMS} # # JDBC urls that CollectionSpace needs to talk to the "admin" database, Nuxeo databases, and the "cspace" database (i.e., the AuthN/AuthZ database) diff --git a/build.xml b/build.xml index c335011fb7..d026cd9117 100644 --- a/build.xml +++ b/build.xml @@ -14,6 +14,15 @@ + + + + + @@ -215,10 +224,10 @@ + @@ -303,6 +312,7 @@ + diff --git a/cspace-ui/anthro/build.properties b/cspace-ui/anthro/build.properties index ba0a85fc89..242e2b1b2e 100644 --- a/cspace-ui/anthro/build.properties +++ b/cspace-ui/anthro/build.properties @@ -3,7 +3,7 @@ tenant.ui.basename=/cspace/${tenant.shortname} tenant.ui.profile.plugin.package.name=cspace-ui-plugin-profile-anthro tenant.ui.profile.plugin.library.name=cspaceUIPluginProfileAnthro -tenant.ui.profile.plugin.version=9.1.0 +tenant.ui.profile.plugin.version=9.2.0-rc1.0 tenant.ui.profile.plugin.build.branch=main # If not set, defaults to /gateway/${tenant.shortname} on the current host. diff --git a/pom.xml b/pom.xml index 85c1ab8032..6e7ed0f7b8 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ services - 8.2.0 + 8.3.0-RC.1 UTF-8 ${revision} ${revision} @@ -318,6 +318,63 @@ + + + + org.eclipse.jetty + jetty-maven-plugin + 9.4.57.v20241219 + + + start-jetty + pre-integration-test + + start + + + ${skipTests} + + + + stop-jetty + post-integration-test + + stop + + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + 3.5.3 + + + integration-test + + integration-test + + + + verify + + verify + + + + + + **/*IT.class + + + + + + org.apache.maven.plugins + maven-remote-resources-plugin + 3.3.0 + diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/collectionobject/related/responses/sortRelated.res.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/collectionobject/related/responses/sortRelated.res.xml index 4d33ad6d1c..8743d0105d 100644 --- a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/collectionobject/related/responses/sortRelated.res.xml +++ b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/collectionobject/related/responses/sortRelated.res.xml @@ -3,7 +3,7 @@ 3 3 - csid|uri|refName|updatedAt|workflowState|identificationNumber|blobCsid|title + csid|uri|refName|updatedAt|workflowState|altText|identificationNumber|blobCsid|title ${first} @@ -32,4 +32,4 @@ project ${identificationNumberLast} - \ No newline at end of file + diff --git a/services/JaxRsServiceProvider/build.xml b/services/JaxRsServiceProvider/build.xml index dcad21410c..c03e19ce95 100644 --- a/services/JaxRsServiceProvider/build.xml +++ b/services/JaxRsServiceProvider/build.xml @@ -5,11 +5,12 @@ + - - + + @@ -52,10 +53,12 @@ + + @@ -150,15 +153,15 @@ - + diff --git a/services/JaxRsServiceProvider/pom.xml b/services/JaxRsServiceProvider/pom.xml index d36f60f626..25221eaf1a 100644 --- a/services/JaxRsServiceProvider/pom.xml +++ b/services/JaxRsServiceProvider/pom.xml @@ -466,6 +466,11 @@ org.collectionspace.services.restrictedmedia.service ${project.version} + + org.collectionspace.services + org.collectionspace.services.advancedsearch.service + ${project.version} + diff --git a/services/advancedsearch/build.xml b/services/advancedsearch/build.xml new file mode 100644 index 0000000000..8c7e47b66c --- /dev/null +++ b/services/advancedsearch/build.xml @@ -0,0 +1,116 @@ + + + advancedsearch service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/services/advancedsearch/client/pom.xml b/services/advancedsearch/client/pom.xml new file mode 100644 index 0000000000..6b3226169e --- /dev/null +++ b/services/advancedsearch/client/pom.xml @@ -0,0 +1,61 @@ + + + + org.collectionspace.services + org.collectionspace.services.advancedsearch + ${revision} + + + 4.0.0 + org.collectionspace.services.advancedsearch.client + services.advancedsearch.client + + + + + org.collectionspace.services + org.collectionspace.services.client + ${project.version} + + + org.collectionspace.services + org.collectionspace.services.advancedsearch.jaxb + ${project.version} + + + + + org.testng + testng + + + org.jboss.resteasy + resteasy-jaxrs + + + + tjws + webserver + + + + + org.jboss.resteasy + resteasy-jaxb-provider + + + org.jboss.resteasy + resteasy-multipart-provider + + + commons-httpclient + commons-httpclient + + + + + collectionspace-services-advancedsearch-client + + \ No newline at end of file diff --git a/services/advancedsearch/client/src/main/java/org/collectionspace/services/client/AdvancedSearchClient.java b/services/advancedsearch/client/src/main/java/org/collectionspace/services/client/AdvancedSearchClient.java new file mode 100644 index 0000000000..45b2966e43 --- /dev/null +++ b/services/advancedsearch/client/src/main/java/org/collectionspace/services/client/AdvancedSearchClient.java @@ -0,0 +1,51 @@ +/* + * This document is a part of the source code and related artifacts + * for CollectionSpace, an open source collections management system + * for museums and related institutions: + * + * http://www.collectionspace.org + * http://wiki.collectionspace.org + * + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + * + * You may obtain a copy of the ECL 2.0 License at + * https://source.collectionspace.org/collection-space/LICENSE.txt + */ +package org.collectionspace.services.client; + +import org.collectionspace.services.advancedsearch.AdvancedsearchCommonList.AdvancedsearchListItem; + +/** + * ConsultationClient.java + */ +public class AdvancedSearchClient extends AbstractCommonListPoxServiceClientImpl { + + public static final String SERVICE_NAME = "advancedsearch"; + public static final String SERVICE_PATH_COMPONENT = SERVICE_NAME; + public static final String SERVICE_PATH = "/" + SERVICE_PATH_COMPONENT; + public static final String SERVICE_PATH_PROXY = SERVICE_PATH + "/"; + + public AdvancedSearchClient() throws Exception { + super(); + } + + public AdvancedSearchClient(String clientPropertiesFilename) throws Exception { + super(clientPropertiesFilename); + } + + @Override + public String getServicePathComponent() { + return SERVICE_PATH_COMPONENT; + } + + @Override + public String getServiceName() { + return SERVICE_NAME; + } + + @Override + public Class getProxyClass() { + return AdvancedSearchProxy.class; + } +} diff --git a/services/advancedsearch/client/src/main/java/org/collectionspace/services/client/AdvancedSearchProxy.java b/services/advancedsearch/client/src/main/java/org/collectionspace/services/client/AdvancedSearchProxy.java new file mode 100644 index 0000000000..1012a04038 --- /dev/null +++ b/services/advancedsearch/client/src/main/java/org/collectionspace/services/client/AdvancedSearchProxy.java @@ -0,0 +1,27 @@ +/* + * This document is a part of the source code and related artifacts + * for CollectionSpace, an open source collections management system + * for museums and related institutions: + * + * http://www.collectionspace.org + * http://wiki.collectionspace.org + * + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + * + * You may obtain a copy of the ECL 2.0 License at + * https://source.collectionspace.org/collection-space/LICENSE.txt + */ +package org.collectionspace.services.client; + +import javax.ws.rs.Consumes; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; + +/** + * ConsultationProxy.java + */ +@Path(AdvancedSearchClient.SERVICE_PATH_PROXY) +@Produces({"application/xml"}) +@Consumes({"application/xml"}) +public interface AdvancedSearchProxy extends CollectionSpaceCommonListPoxProxy {} diff --git a/services/advancedsearch/client/src/main/resources/collectionspace-client.properties b/services/advancedsearch/client/src/main/resources/collectionspace-client.properties new file mode 100644 index 0000000000..973918a75a --- /dev/null +++ b/services/advancedsearch/client/src/main/resources/collectionspace-client.properties @@ -0,0 +1,13 @@ +# +# URL of the CollectionSpace server and user credentials +# +cspace.url=http://localhost:8180/cspace-services/ +cspace.ssl=false +cspace.auth=true +cspace.user=admin@core.collectionspace.org +cspace.password=Administrator +# +# default tenant information +# +cspace.tenant=1 +cspace.tenantID=core.collectionspace.org diff --git a/services/advancedsearch/jaxb/pom.xml b/services/advancedsearch/jaxb/pom.xml new file mode 100644 index 0000000000..110fcc0bb6 --- /dev/null +++ b/services/advancedsearch/jaxb/pom.xml @@ -0,0 +1,43 @@ + + + + org.collectionspace.services.advancedsearch + org.collectionspace.services + ${revision} + + + 4.0.0 + org.collectionspace.services.advancedsearch.jaxb + services.advancedsearch.jaxb + + + + org.collectionspace.services + org.collectionspace.services.jaxb + ${project.version} + + + org.collectionspace.services + org.collectionspace.services.collectionobject.jaxb + ${project.version} + + + org.collectionspace.services + org.collectionspace.services.common-api + ${project.version} + + + + + collectionspace-services-advancedsearch-jaxb + install + + + org.jvnet.jaxb2.maven2 + maven-jaxb2-plugin + + + + \ No newline at end of file diff --git a/services/advancedsearch/jaxb/src/main/java/org/collectionspace/services/advancedsearch/model/AgentModel.java b/services/advancedsearch/jaxb/src/main/java/org/collectionspace/services/advancedsearch/model/AgentModel.java new file mode 100644 index 0000000000..bfab77633f --- /dev/null +++ b/services/advancedsearch/jaxb/src/main/java/org/collectionspace/services/advancedsearch/model/AgentModel.java @@ -0,0 +1,92 @@ +package org.collectionspace.services.advancedsearch.model; + +import java.util.Objects; +import java.util.Optional; +import java.util.function.Supplier; +import java.util.stream.Stream; + +import org.collectionspace.services.collectionobject.CollectionobjectsCommon; +import org.collectionspace.services.collectionobject.ObjectProductionOrganizationGroup; +import org.collectionspace.services.collectionobject.ObjectProductionOrganizationGroupList; +import org.collectionspace.services.collectionobject.ObjectProductionPeopleGroup; +import org.collectionspace.services.collectionobject.ObjectProductionPeopleGroupList; +import org.collectionspace.services.collectionobject.ObjectProductionPersonGroup; +import org.collectionspace.services.collectionobject.ObjectProductionPersonGroupList; + +public class AgentModel { + + public static Optional agent(CollectionobjectsCommon collectionObject) { + if (collectionObject == null) { + return Optional.empty(); + } + + ObjectProductionPersonGroupList persons = collectionObject.getObjectProductionPersonGroupList(); + ObjectProductionOrganizationGroupList orgs = collectionObject.getObjectProductionOrganizationGroupList(); + ObjectProductionPeopleGroupList people = collectionObject.getObjectProductionPeopleGroupList(); + return Stream.>of( + () -> personAgent(persons), + () -> orgAgent(orgs), + () -> peopleAgent(people)) + .map(Supplier::get) + .filter(Objects::nonNull) + .findFirst(); + } + + private static AgentWithRole personAgent(ObjectProductionPersonGroupList personGroupList) { + AgentWithRole agent = null; + if (personGroupList != null && !personGroupList.getObjectProductionPersonGroup().isEmpty()) { + ObjectProductionPersonGroup personGroup = personGroupList.getObjectProductionPersonGroup().get(0); + String person = personGroup.getObjectProductionPerson(); + if (person != null && !person.isEmpty()) { + agent = new AgentWithRole(person); + agent.role = personGroup.getObjectProductionPersonRole(); + } + } + return agent; + } + + private static AgentWithRole orgAgent(ObjectProductionOrganizationGroupList organizationGroupList) { + AgentWithRole agent = null; + if (organizationGroupList != null && !organizationGroupList.getObjectProductionOrganizationGroup().isEmpty()) { + ObjectProductionOrganizationGroup orgGroup = + organizationGroupList.getObjectProductionOrganizationGroup().get(0); + String org = orgGroup.getObjectProductionOrganization(); + if (org != null && !org.isEmpty()) { + agent = new AgentWithRole(org); + agent.role = orgGroup.getObjectProductionOrganizationRole(); + } + } + return agent; + } + + private static AgentWithRole peopleAgent(ObjectProductionPeopleGroupList peopleGroupList) { + AgentWithRole agent = null; + if (peopleGroupList != null && !peopleGroupList.getObjectProductionPeopleGroup().isEmpty()) { + ObjectProductionPeopleGroup peopleGroup = peopleGroupList.getObjectProductionPeopleGroup().get(0); + String people = peopleGroup.getObjectProductionPeople(); + if (people != null && !people.isEmpty()) { + agent = new AgentWithRole(people); + agent.role = peopleGroup.getObjectProductionPeopleRole(); + } + } + return agent; + } + + public static class AgentWithRole { + private final String agent; + private String role; + + public AgentWithRole(final String agent) { + this.agent = agent; + } + + public String getAgent() { + return agent; + } + + public String getRole() { + return role; + } + } + +} diff --git a/services/advancedsearch/jaxb/src/main/java/org/collectionspace/services/advancedsearch/model/BriefDescriptionListModel.java b/services/advancedsearch/jaxb/src/main/java/org/collectionspace/services/advancedsearch/model/BriefDescriptionListModel.java new file mode 100644 index 0000000000..1216984c19 --- /dev/null +++ b/services/advancedsearch/jaxb/src/main/java/org/collectionspace/services/advancedsearch/model/BriefDescriptionListModel.java @@ -0,0 +1,29 @@ +package org.collectionspace.services.advancedsearch.model; + +import java.util.List; + +import org.collectionspace.services.collectionobject.BriefDescriptionList; + +public class BriefDescriptionListModel { + private static final int DESCRIPTION_LENGTH = 255; + + public static String briefDescriptionListToDisplayString(BriefDescriptionList bdList) { + List bds = bdList.getBriefDescription(); + StringBuilder buf = new StringBuilder(); + if (null != bds) { + if (!bds.isEmpty()) { + // get the 1st 255 characters of the 1st defined brief description if there is one + String description = bds.get(0); + if (null != description) { + int length = description.length(); + buf.append(description); + if (length > DESCRIPTION_LENGTH) { + buf.replace(DESCRIPTION_LENGTH, buf.length(), "..."); + } + } + + } + } + return buf.toString(); + } +} diff --git a/services/advancedsearch/jaxb/src/main/java/org/collectionspace/services/advancedsearch/model/ContentConceptListModel.java b/services/advancedsearch/jaxb/src/main/java/org/collectionspace/services/advancedsearch/model/ContentConceptListModel.java new file mode 100644 index 0000000000..ae45b7ad60 --- /dev/null +++ b/services/advancedsearch/jaxb/src/main/java/org/collectionspace/services/advancedsearch/model/ContentConceptListModel.java @@ -0,0 +1,25 @@ +package org.collectionspace.services.advancedsearch.model; + +import java.util.List; + +import org.collectionspace.services.advancedsearch.ContentConcepts; +import org.collectionspace.services.advancedsearch.ObjectFactory; +import org.collectionspace.services.collectionobject.CollectionobjectsCommon; + +public class ContentConceptListModel { + + public static ContentConcepts contentConceptList(CollectionobjectsCommon collectionObject) { + ContentConcepts concepts = null; + final ObjectFactory objectFactory = new ObjectFactory(); + + if (collectionObject != null && collectionObject.getContentConcepts() != null) { + List objectConcepts = collectionObject.getContentConcepts().getContentConcept(); + if (!objectConcepts.isEmpty()) { + concepts = objectFactory.createContentConcepts(); + concepts.getContentConcept().addAll(objectConcepts); + } + } + + return concepts; + } +} diff --git a/services/advancedsearch/jaxb/src/main/java/org/collectionspace/services/advancedsearch/model/FieldCollectionModel.java b/services/advancedsearch/jaxb/src/main/java/org/collectionspace/services/advancedsearch/model/FieldCollectionModel.java new file mode 100644 index 0000000000..4acfa60855 --- /dev/null +++ b/services/advancedsearch/jaxb/src/main/java/org/collectionspace/services/advancedsearch/model/FieldCollectionModel.java @@ -0,0 +1,54 @@ +package org.collectionspace.services.advancedsearch.model; + +import java.util.List; +import java.util.Optional; + +import org.collectionspace.services.collectionobject.CollectionobjectsCommon; +import org.collectionspace.services.collectionobject.StructuredDateGroup; + +public class FieldCollectionModel { + + public static String fieldCollectionPlace(CollectionobjectsCommon common) { + String fieldCollectionPlace = null; + if (common != null && common.getFieldCollectionPlaces() != null) { + List places = common.getFieldCollectionPlaces().getFieldCollectionPlace(); + if (!places.isEmpty()) { + fieldCollectionPlace = places.get(0); + } + } + return fieldCollectionPlace; + } + + public static String fieldCollectionSite(CollectionobjectsCommon common) { + String fieldCollectionSite = null; + if (common != null && common.getFieldCollectionSites() != null) { + List sites = common.getFieldCollectionSites().getFieldCollectionSite(); + if (!sites.isEmpty()) { + fieldCollectionSite = sites.get(0); + } + } + return fieldCollectionSite; + } + + public static String fieldCollectionDate(CollectionobjectsCommon common) { + String fieldCollectionDate = null; + if (common != null && common.getFieldCollectionDateGroup() != null) { + StructuredDateGroup fieldCollectionDateGroup = common.getFieldCollectionDateGroup(); + fieldCollectionDate = fieldCollectionDateGroup.getDateDisplayDate(); + } + return fieldCollectionDate; + } + + + public static Optional fieldCollector(CollectionobjectsCommon common) { + String fieldCollector = null; + if (common != null && common.getFieldCollectors() != null) { + final List fieldCollectors = common.getFieldCollectors().getFieldCollector(); + if (!fieldCollectors.isEmpty()) { + fieldCollector = fieldCollectors.get(0); + } + } + + return Optional.ofNullable(fieldCollector); + } +} diff --git a/services/advancedsearch/jaxb/src/main/java/org/collectionspace/services/advancedsearch/model/NAGPRACategoryModel.java b/services/advancedsearch/jaxb/src/main/java/org/collectionspace/services/advancedsearch/model/NAGPRACategoryModel.java new file mode 100644 index 0000000000..a45a160f31 --- /dev/null +++ b/services/advancedsearch/jaxb/src/main/java/org/collectionspace/services/advancedsearch/model/NAGPRACategoryModel.java @@ -0,0 +1,22 @@ +package org.collectionspace.services.advancedsearch.model; + +import org.collectionspace.services.advancedsearch.NagpraCategories; +import org.collectionspace.services.advancedsearch.ObjectFactory; +import org.collectionspace.services.collectionobject.domain.nagpra.CollectionObjectsNAGPRA; + +public class NAGPRACategoryModel { + + public static NagpraCategories napgraCategories(CollectionObjectsNAGPRA nagpra) { + final ObjectFactory asObjectFactory = new ObjectFactory(); + final CollectionObjectsNAGPRA.NagpraCategories objectNAGPRACategories = nagpra.getNagpraCategories(); + + NagpraCategories searchCategories = null; + if (objectNAGPRACategories != null && !objectNAGPRACategories.getNagpraCategory().isEmpty()) { + searchCategories = asObjectFactory.createNagpraCategories(); + searchCategories.getNagpraCategory().addAll(objectNAGPRACategories.getNagpraCategory()); + } + + return searchCategories; + } + +} diff --git a/services/advancedsearch/jaxb/src/main/java/org/collectionspace/services/advancedsearch/model/ObjectNameListModel.java b/services/advancedsearch/jaxb/src/main/java/org/collectionspace/services/advancedsearch/model/ObjectNameListModel.java new file mode 100644 index 0000000000..09024828d2 --- /dev/null +++ b/services/advancedsearch/jaxb/src/main/java/org/collectionspace/services/advancedsearch/model/ObjectNameListModel.java @@ -0,0 +1,48 @@ +package org.collectionspace.services.advancedsearch.model; + +import java.util.List; + +import org.collectionspace.services.collectionobject.CollectionobjectsCommon; +import org.collectionspace.services.collectionobject.ObjectNameGroup; +import org.collectionspace.services.common.api.RefNameUtils; + +public class ObjectNameListModel { + + /** + * @param collectionObject The CollectionObject Common part + * @return The value of the objectNameControlled field + */ + public static String objectNameControlled(final CollectionobjectsCommon collectionObject) { + String objectNameControlled = null; + + if (collectionObject != null && collectionObject.getObjectNameList() != null) { + final List objectNameGroups = collectionObject.getObjectNameList().getObjectNameGroup(); + if (!objectNameGroups.isEmpty()) { + final ObjectNameGroup objectNameGroup = objectNameGroups.get(0); + try { + objectNameControlled = RefNameUtils.getDisplayName(objectNameGroup.getObjectNameControlled()); + } catch (IllegalArgumentException ignored) { + } + } + } + + return objectNameControlled; + } + + /** + * @param collectionObject The CollectionObject Common part + * @return The value of the objectName field + */ + public static String objectName(final CollectionobjectsCommon collectionObject) { + String objectName = null; + if (collectionObject!= null && collectionObject.getObjectNameList() != null) { + final List objectNameGroups = collectionObject.getObjectNameList().getObjectNameGroup(); + if (!objectNameGroups.isEmpty()) { + final ObjectNameGroup objectNameGroup = objectNameGroups.get(0); + objectName = objectNameGroup.getObjectName(); + } + } + + return objectName; + } +} diff --git a/services/advancedsearch/jaxb/src/main/java/org/collectionspace/services/advancedsearch/model/ObjectProductionModel.java b/services/advancedsearch/jaxb/src/main/java/org/collectionspace/services/advancedsearch/model/ObjectProductionModel.java new file mode 100644 index 0000000000..9f865efd01 --- /dev/null +++ b/services/advancedsearch/jaxb/src/main/java/org/collectionspace/services/advancedsearch/model/ObjectProductionModel.java @@ -0,0 +1,35 @@ +package org.collectionspace.services.advancedsearch.model; + +import java.util.List; + +import org.collectionspace.services.collectionobject.CollectionobjectsCommon; +import org.collectionspace.services.collectionobject.ObjectProductionDateGroupList; +import org.collectionspace.services.collectionobject.ObjectProductionPlaceGroup; + +public class ObjectProductionModel { + + public static String objectProductionDate(CollectionobjectsCommon collectionObject) { + String date = null; + if (collectionObject != null && collectionObject.getObjectProductionDateGroupList() != null) { + ObjectProductionDateGroupList dateGroup = collectionObject.getObjectProductionDateGroupList(); + if (!dateGroup.getObjectProductionDateGroup().isEmpty()) { + date = dateGroup.getObjectProductionDateGroup().get(0).getDateDisplayDate(); + } + } + return date; + } + + public static String objectProductionPlace(CollectionobjectsCommon collectionObject) { + String place = null; + if (collectionObject != null && collectionObject.getObjectProductionPlaceGroupList() != null) { + List placeGroup = collectionObject.getObjectProductionPlaceGroupList() + .getObjectProductionPlaceGroup(); + + if (!placeGroup.isEmpty()) { + place = placeGroup.get(0).getObjectProductionPlace(); + } + } + + return place; + } +} diff --git a/services/advancedsearch/jaxb/src/main/java/org/collectionspace/services/advancedsearch/model/ResponsibleDepartmentsListModel.java b/services/advancedsearch/jaxb/src/main/java/org/collectionspace/services/advancedsearch/model/ResponsibleDepartmentsListModel.java new file mode 100644 index 0000000000..862742de5a --- /dev/null +++ b/services/advancedsearch/jaxb/src/main/java/org/collectionspace/services/advancedsearch/model/ResponsibleDepartmentsListModel.java @@ -0,0 +1,19 @@ +package org.collectionspace.services.advancedsearch.model; + +import org.collectionspace.services.collectionobject.CollectionobjectsCommon; +import org.collectionspace.services.collectionobject.ResponsibleDepartmentList; + +public class ResponsibleDepartmentsListModel { + + public static String responsibleDepartmentString(CollectionobjectsCommon collectionObject) { + String responsibleDepartment = null; + if (collectionObject != null && collectionObject.getResponsibleDepartments() != null) { + ResponsibleDepartmentList responsibleDepartments = collectionObject.getResponsibleDepartments(); + if (!responsibleDepartments.getResponsibleDepartment().isEmpty()) { + responsibleDepartment = responsibleDepartments.getResponsibleDepartment().get(0); + } + } + return responsibleDepartment; + } + +} diff --git a/services/advancedsearch/jaxb/src/main/java/org/collectionspace/services/advancedsearch/model/TaxonModel.java b/services/advancedsearch/jaxb/src/main/java/org/collectionspace/services/advancedsearch/model/TaxonModel.java new file mode 100644 index 0000000000..1be0f9c250 --- /dev/null +++ b/services/advancedsearch/jaxb/src/main/java/org/collectionspace/services/advancedsearch/model/TaxonModel.java @@ -0,0 +1,37 @@ +package org.collectionspace.services.advancedsearch.model; + +import java.util.List; + +import org.collectionspace.services.collectionobject.CollectionobjectsCommon; +import org.collectionspace.services.collectionobject.domain.naturalhistory_extension.CollectionobjectsNaturalhistory; +import org.collectionspace.services.collectionobject.domain.naturalhistory_extension.TaxonomicIdentGroup; +import org.collectionspace.services.collectionobject.domain.naturalhistory_extension.TaxonomicIdentGroupList; + +public class TaxonModel { + + public static String taxon(final CollectionobjectsNaturalhistory naturalHistory) { + String taxon = null; + if (naturalHistory != null && naturalHistory.getTaxonomicIdentGroupList() != null) { + TaxonomicIdentGroupList taxonomicIdentGroupList = naturalHistory.getTaxonomicIdentGroupList(); + List taxonomicIdentGroups = taxonomicIdentGroupList.getTaxonomicIdentGroup(); + if (!taxonomicIdentGroups.isEmpty()) { + TaxonomicIdentGroup taxonGroup = taxonomicIdentGroups.get(0); + taxon = taxonGroup.getTaxon(); + } + } + + return taxon; + } + + public static String preservationForm(final CollectionobjectsCommon common) { + String form = null; + if (common != null && common.getForms() != null) { + List forms = common.getForms().getForm(); + if (!forms.isEmpty()) { + form = forms.get(0); + } + } + + return form; + } +} diff --git a/services/advancedsearch/jaxb/src/main/java/org/collectionspace/services/advancedsearch/model/TitleGroupListModel.java b/services/advancedsearch/jaxb/src/main/java/org/collectionspace/services/advancedsearch/model/TitleGroupListModel.java new file mode 100644 index 0000000000..7b55a5dade --- /dev/null +++ b/services/advancedsearch/jaxb/src/main/java/org/collectionspace/services/advancedsearch/model/TitleGroupListModel.java @@ -0,0 +1,29 @@ +package org.collectionspace.services.advancedsearch.model; + +import java.util.List; + +import org.collectionspace.services.collectionobject.TitleGroup; +import org.collectionspace.services.collectionobject.TitleGroupList; + +public class TitleGroupListModel { + + /** + * @param tlList The TitleGroupList + * @return the value of the title field for the first TitleGroup + */ + public static String titleGroupListToDisplayString(TitleGroupList tlList) { + if (tlList == null) { + return null; + } + + String title = null; + List titleGroups = tlList.getTitleGroup(); + + if (!titleGroups.isEmpty() && titleGroups.get(0) != null) { + TitleGroup titleGroup = titleGroups.get(0); + title = titleGroup.getTitle(); + } + + return title; + } +} diff --git a/services/advancedsearch/jaxb/src/main/resources/advanced-search_common.xsd b/services/advancedsearch/jaxb/src/main/resources/advanced-search_common.xsd new file mode 100644 index 0000000000..50fb31c202 --- /dev/null +++ b/services/advancedsearch/jaxb/src/main/resources/advanced-search_common.xsd @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/services/advancedsearch/jaxb/src/test/java/org/collectionspace/services/advancedsearch/model/AgentModelTest.java b/services/advancedsearch/jaxb/src/test/java/org/collectionspace/services/advancedsearch/model/AgentModelTest.java new file mode 100644 index 0000000000..60435490ae --- /dev/null +++ b/services/advancedsearch/jaxb/src/test/java/org/collectionspace/services/advancedsearch/model/AgentModelTest.java @@ -0,0 +1,112 @@ +package org.collectionspace.services.advancedsearch.model; + +import java.util.Optional; +import java.util.UUID; + +import org.collectionspace.services.advancedsearch.model.AgentModel.AgentWithRole; +import org.collectionspace.services.collectionobject.CollectionobjectsCommon; +import org.collectionspace.services.collectionobject.ObjectFactory; +import org.collectionspace.services.collectionobject.ObjectProductionOrganizationGroup; +import org.collectionspace.services.collectionobject.ObjectProductionOrganizationGroupList; +import org.collectionspace.services.collectionobject.ObjectProductionPeopleGroup; +import org.collectionspace.services.collectionobject.ObjectProductionPeopleGroupList; +import org.collectionspace.services.collectionobject.ObjectProductionPersonGroup; +import org.collectionspace.services.collectionobject.ObjectProductionPersonGroupList; +import org.testng.Assert; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +/** + * Basic tests to ensure that the preferred ordering is used for the Agent and Agent Role response data + */ +public class AgentModelTest { + + private ObjectFactory objectFactory; + private ObjectProductionPersonGroupList personGroupList; + private ObjectProductionOrganizationGroupList orgGroupList; + private ObjectProductionPeopleGroupList peopleGroupList; + + @BeforeClass + public void setup() { + objectFactory = new ObjectFactory(); + + ObjectProductionPersonGroup personGroup = objectFactory.createObjectProductionPersonGroup(); + personGroup.setObjectProductionPerson(UUID.randomUUID().toString()); + personGroup.setObjectProductionPersonRole(UUID.randomUUID().toString()); + personGroupList = objectFactory.createObjectProductionPersonGroupList(); + personGroupList.getObjectProductionPersonGroup().add(personGroup); + + ObjectProductionOrganizationGroup orgGroup = objectFactory.createObjectProductionOrganizationGroup(); + orgGroup.setObjectProductionOrganization(UUID.randomUUID().toString()); + orgGroup.setObjectProductionOrganizationRole(UUID.randomUUID().toString()); + orgGroupList = objectFactory.createObjectProductionOrganizationGroupList(); + orgGroupList.getObjectProductionOrganizationGroup().add(orgGroup); + + ObjectProductionPeopleGroup peopleGroup = objectFactory.createObjectProductionPeopleGroup(); + peopleGroup.setObjectProductionPeople(UUID.randomUUID().toString()); + peopleGroup.setObjectProductionPeopleRole(UUID.randomUUID().toString()); + peopleGroupList = objectFactory.createObjectProductionPeopleGroupList(); + peopleGroupList.getObjectProductionPeopleGroup().add(peopleGroup); + } + + @Test + public void testOrderWithProductionPerson() { + final ObjectProductionPersonGroup agentGroup = personGroupList.getObjectProductionPersonGroup().get(0); + final String expectedAgent = agentGroup.getObjectProductionPerson(); + final String expectedRole = agentGroup.getObjectProductionPersonRole(); + + final CollectionobjectsCommon common = objectFactory.createCollectionobjectsCommon(); + common.setObjectProductionPersonGroupList(personGroupList); + common.setObjectProductionOrganizationGroupList(orgGroupList); + common.setObjectProductionPeopleGroupList(peopleGroupList); + + final Optional agentWithRole = AgentModel.agent(common); + Assert.assertTrue(agentWithRole.isPresent()); + + final AgentWithRole agent = agentWithRole.get(); + Assert.assertEquals(agent.getAgent(), expectedAgent); + Assert.assertEquals(agent.getRole(), expectedRole); + } + + @Test + public void testOrderWithProductionOrganization() { + final ObjectProductionOrganizationGroup agentGroup = orgGroupList.getObjectProductionOrganizationGroup().get(0); + final String expectedAgent = agentGroup.getObjectProductionOrganization(); + final String expectedRole = agentGroup.getObjectProductionOrganizationRole(); + + final CollectionobjectsCommon common = objectFactory.createCollectionobjectsCommon(); + common.setObjectProductionOrganizationGroupList(orgGroupList); + common.setObjectProductionPeopleGroupList(peopleGroupList); + + final Optional agentWithRole = AgentModel.agent(common); + Assert.assertTrue(agentWithRole.isPresent()); + + final AgentWithRole agent = agentWithRole.get(); + Assert.assertEquals(agent.getAgent(), expectedAgent); + Assert.assertEquals(agent.getRole(), expectedRole); + } + + @Test + public void testOrderWithProductionPeople() { + final ObjectProductionPeopleGroup agentGroup = peopleGroupList.getObjectProductionPeopleGroup().get(0); + final String expectedAgent = agentGroup.getObjectProductionPeople(); + final String expectedRole = agentGroup.getObjectProductionPeopleRole(); + + final CollectionobjectsCommon common = objectFactory.createCollectionobjectsCommon(); + common.setObjectProductionPeopleGroupList(peopleGroupList); + + final Optional agentWithRole = AgentModel.agent(common); + Assert.assertTrue(agentWithRole.isPresent()); + + final AgentWithRole agent = agentWithRole.get(); + Assert.assertEquals(agent.getAgent(), expectedAgent); + Assert.assertEquals(agent.getRole(), expectedRole); + } + + @Test + public void testAllEmpty() { + final CollectionobjectsCommon common = objectFactory.createCollectionobjectsCommon(); + final Optional agentWithRole = AgentModel.agent(common); + Assert.assertFalse(agentWithRole.isPresent()); + } +} \ No newline at end of file diff --git a/services/advancedsearch/jaxb/src/test/java/org/collectionspace/services/advancedsearch/model/BriefDescriptionListModelTest.java b/services/advancedsearch/jaxb/src/test/java/org/collectionspace/services/advancedsearch/model/BriefDescriptionListModelTest.java new file mode 100644 index 0000000000..b86f7bf6c5 --- /dev/null +++ b/services/advancedsearch/jaxb/src/test/java/org/collectionspace/services/advancedsearch/model/BriefDescriptionListModelTest.java @@ -0,0 +1,36 @@ +package org.collectionspace.services.advancedsearch.model; + +import org.apache.commons.lang3.RandomStringUtils; +import org.collectionspace.services.collectionobject.BriefDescriptionList; +import org.collectionspace.services.collectionobject.ObjectFactory; +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * Test that we truncate the Brief Description when required + */ +public class BriefDescriptionListModelTest { + private final ObjectFactory objectFactory = new ObjectFactory(); + + @Test + public void testShortBriefDescription() { + final String description = "short description"; + final BriefDescriptionList briefDescriptionList = objectFactory.createBriefDescriptionList(); + briefDescriptionList.getBriefDescription().add(description); + + Assert.assertEquals(BriefDescriptionListModel.briefDescriptionListToDisplayString(briefDescriptionList), + description); + + } + + @Test + public void testTruncatedBriefDescription() { + String longDescription = RandomStringUtils.randomAlphabetic(300); + final BriefDescriptionList briefDescriptionList = objectFactory.createBriefDescriptionList(); + briefDescriptionList.getBriefDescription().add(longDescription); + + String truncated = BriefDescriptionListModel.briefDescriptionListToDisplayString(briefDescriptionList); + Assert.assertTrue(longDescription.length() > truncated.length()); + Assert.assertTrue(truncated.endsWith("...")); + } +} \ No newline at end of file diff --git a/services/advancedsearch/pom.xml b/services/advancedsearch/pom.xml new file mode 100644 index 0000000000..8b9d7b83b5 --- /dev/null +++ b/services/advancedsearch/pom.xml @@ -0,0 +1,58 @@ + + + + org.collectionspace.services + org.collectionspace.services.main + ${revision} + + + 4.0.0 + org.collectionspace.services.advancedsearch + services.advancedsearch + pom + + + + 2.30.0 + + + + + + com.diffplug.spotless + spotless-maven-plugin + ${spotless.version} + + + + + + src/main/java/**/*.java + src/test/java/**/*.java + + + + + true + 4 + + + + + + + + + + + + + + jaxb + service + client + + + \ No newline at end of file diff --git a/services/advancedsearch/service/pom.xml b/services/advancedsearch/service/pom.xml new file mode 100644 index 0000000000..b77426cfc1 --- /dev/null +++ b/services/advancedsearch/service/pom.xml @@ -0,0 +1,110 @@ + + + + + org.collectionspace.services + org.collectionspace.services.advancedsearch + ${revision} + + + 4.0.0 + org.collectionspace.services.advancedsearch.service + services.advancedsearch.service + jar + + + + org.collectionspace.services + org.collectionspace.services.common + ${project.version} + + + org.collectionspace.services + org.collectionspace.services.jaxb + ${project.version} + + + org.collectionspace.services + org.collectionspace.services.common-api + ${project.version} + + + org.collectionspace.services + org.collectionspace.services.advancedsearch.jaxb + ${project.version} + + + org.collectionspace.services + org.collectionspace.services.advancedsearch.client + ${project.version} + + + org.collectionspace.services + org.collectionspace.services.collectionobject.service + ${project.version} + + + org.collectionspace.services + org.collectionspace.services.media.service + ${project.version} + + + + + junit + junit + test + + + org.testng + testng + test + + + + + javax.security + jaas + 1.0.01 + provided + + + + + org.jboss.resteasy + resteasy-jaxrs + + + tjws + webserver + + + + + org.jboss.resteasy + resteasy-jaxb-provider + + + org.jboss.resteasy + resteasy-multipart-provider + + + + + org.nuxeo.ecm.core + nuxeo-core-api + + + jboss-remoting + jboss + + + + + + + collectionspace-services-advancedsearch + + diff --git a/services/advancedsearch/service/src/main/java/org/collectionspace/services/advancedsearch/AdvancedSearch.java b/services/advancedsearch/service/src/main/java/org/collectionspace/services/advancedsearch/AdvancedSearch.java new file mode 100644 index 0000000000..b30045e08e --- /dev/null +++ b/services/advancedsearch/service/src/main/java/org/collectionspace/services/advancedsearch/AdvancedSearch.java @@ -0,0 +1,166 @@ +package org.collectionspace.services.advancedsearch; + +import java.util.Collections; +import java.util.Map; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Request; +import javax.ws.rs.core.UriInfo; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; + +import org.collectionspace.services.MediaJAXBSchema; +import org.collectionspace.services.advancedsearch.AdvancedsearchCommonList.AdvancedsearchListItem; +import org.collectionspace.services.advancedsearch.mapper.CollectionObjectMapper; +import org.collectionspace.services.client.IQueryManager; +import org.collectionspace.services.collectionobject.CollectionObjectResource; +import org.collectionspace.services.common.AbstractCollectionSpaceResourceImpl; +import org.collectionspace.services.common.UriInfoWrapper; +import org.collectionspace.services.common.context.RemoteServiceContextFactory; +import org.collectionspace.services.common.context.ServiceContextFactory; +import org.collectionspace.services.common.relation.RelationResource; +import org.collectionspace.services.jaxb.AbstractCommonList; +import org.collectionspace.services.media.MediaResource; +import org.collectionspace.services.nuxeo.client.handler.CSDocumentModelList; +import org.collectionspace.services.nuxeo.client.handler.CSDocumentModelList.CSDocumentModelResponse; +import org.collectionspace.services.nuxeo.client.handler.UnfilteredDocumentModelHandler; +import org.collectionspace.services.relation.RelationsCommonList; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; + +/** + * This class defines the advanced search endpoints. + */ +@Path(AdvancedSearchConstants.SERVICE_PATH) +@Consumes("application/xml") +@Produces("application/xml") +public class AdvancedSearch + extends AbstractCollectionSpaceResourceImpl { + // FIXME: it's not great to hardcode either of these + private static final String FIELDS_RETURNED = "uri|csid|refName|blobCsid|updatedAt|objectId|objectNumber|objectName|title|computedCurrentLocation|responsibleDepartments|responsibleDepartment|contentConcepts|briefDescription"; + + private final Logger logger = LoggerFactory.getLogger(AdvancedSearch.class); + private final CollectionObjectResource cor = new CollectionObjectResource(); + private final MediaResource mr = new MediaResource(); + private final RelationResource relations = new RelationResource(); + + public AdvancedSearch() { + super(); + } + + /** + * Primary advanced search API endpoint. + * + * @param request The incoming request. Injected. + * @param uriInfo The URI info of the incoming request, including query parameters and other search control parameters. Injected. + * @return A possibly-empty AbstractCommonList of the advanced search results corresponding to the query + */ + @GET + public AbstractCommonList getList(@Context Request request, @Context UriInfo uriInfo) { + logger.info("advancedsearch called with path: {}", uriInfo.getPath()); + MultivaluedMap queryParams = uriInfo.getQueryParameters(true); + logger.info("advancedsearch called with query params: {}", queryParams); + final String markRelated = queryParams.getFirst(IQueryManager.MARK_RELATED_TO_CSID_AS_SUBJECT); + + cor.setDocumentHandlerClass(UnfilteredDocumentModelHandler.class); + ObjectFactory objectFactory = new ObjectFactory(); + AdvancedsearchCommonList resultsList = objectFactory.createAdvancedsearchCommonList(); + + AbstractCommonList abstractCommonList = cor.getList(uriInfo); + if (!(abstractCommonList instanceof CSDocumentModelList)) { + return resultsList; + } + + Unmarshaller unmarshaller; + CSDocumentModelList collectionObjectList = (CSDocumentModelList) abstractCommonList; + try { + unmarshaller = AdvancedSearchJAXBContext.getJaxbContext().createUnmarshaller(); + } catch (JAXBException e) { + // this should result in a 500, need to verify from bigReThrow to see what exception it should be + throw new RuntimeException("Unable to create unmarshaller for AdvancedSearch", e); + } + + final CollectionObjectMapper responseMapper = new CollectionObjectMapper(unmarshaller); + for (CSDocumentModelResponse response : collectionObjectList.getResponseList()) { + String csid = response.getCsid(); + UriInfoWrapper wrappedUriInfo = new UriInfoWrapper(uriInfo); + Map blobInfo = findBlobInfo(csid, wrappedUriInfo); + + AdvancedsearchListItem listItem = responseMapper.asListItem(response, blobInfo); + if (listItem != null) { + if (markRelated != null) { + RelationsCommonList relationsList = relations.getRelationForSubject(markRelated, csid, uriInfo); + listItem.setRelated(!relationsList.getRelationListItem().isEmpty()); + } + resultsList.getAdvancedsearchListItem().add(listItem); + } + } + + resultsList.setItemsInPage(collectionObjectList.getItemsInPage()); + resultsList.setPageNum(collectionObjectList.getPageNum()); + resultsList.setPageSize(collectionObjectList.getPageSize()); + resultsList.setTotalItems(collectionObjectList.getTotalItems()); + resultsList.setFieldsReturned(FIELDS_RETURNED); + + return resultsList; + } + + /** + * Retrieves the blob CSIDs associated with a given object's CSID + * + * @param csid The CSID of an object whose associated blobs (thumbnails) is desired + * @param wrappedUriInfo The wrapped (mutable) UriInfo of the incoming query that ultimately triggered this call + * @return A possibly-empty list of strings of the blob CSIDs associated with CSID + */ + private Map findBlobInfo(String csid, UriInfoWrapper wrappedUriInfo) { + MultivaluedMap wrappedQueryParams = wrappedUriInfo.getQueryParameters(); + wrappedQueryParams.clear(); + wrappedQueryParams.add(IQueryManager.SEARCH_RELATED_TO_CSID_AS_SUBJECT, csid); + wrappedQueryParams.add("pgSz", "1"); + wrappedQueryParams.add("pgNum", "0"); + wrappedQueryParams.add("sortBy", "media_common:title"); + AbstractCommonList associatedMedia = mr.getList(wrappedUriInfo); + if (associatedMedia == null || associatedMedia.getListItem() == null) { + return Collections.emptyMap(); + } + + Predicate tagFilter = (element -> MediaJAXBSchema.blobCsid.equals(element.getTagName()) || + MediaJAXBSchema.altText.equals(element.getTagName())); + Predicate tagNotEmpty = (element -> element.getTextContent() != null && + !element.getTextContent().isEmpty()); + + return associatedMedia.getListItem().stream() + .filter(item -> item != null && item.getAny() != null) + .flatMap(li -> li.getAny().stream()) + .filter(tagFilter.and(tagNotEmpty)) + .collect(Collectors.toMap(Element::getTagName, Element::getTextContent)); + } + + @Override + public Class getCommonPartClass() { + return null; + } + + @Override + public ServiceContextFactory getServiceContextFactory() { + return (ServiceContextFactory) 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..4dd3622e4c --- /dev/null +++ b/services/advancedsearch/service/src/main/java/org/collectionspace/services/advancedsearch/mapper/CollectionObjectMapper.java @@ -0,0 +1,175 @@ +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.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)); + + // 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)); + } + + 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/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 aba3397d7f..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-log4j12 - - - + + + + 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..a501ca71e7 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 @@ - - - - - - - - + + + + + + + + + + @@ -54,94 +47,91 @@ - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + 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/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 133938613a..0729f76811 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", @@ -90,7 +91,10 @@ "ecm:currentLifeCycleState", "ecm:name", "ecm:primaryType", - "media_common:blobCsid" + "media_common:blobCsid", + "media_common:identificationNumber", + "media_common:title", + "media_common:altText" ] }, "properties" : { @@ -114,6 +118,10 @@ "type": "date", "format": "date_time" }, + "collectionspace_core:updatedAt": { + "type": "date", + "format": "date_time" + }, "collectionobjects_common:publishToList": { "type": "keyword", "fields": { @@ -185,6 +193,9 @@ } } }, + "collectionspace_denorm:objectCsid": { + "type": "keyword" + }, "collectionobjects_common:objectNumber": { "type": "keyword", @@ -342,6 +353,10 @@ } } }, + "collectionobjects_common:contentPlaces": { + "type": "keyword", + "copy_to": "all_field" + }, "collectionobjects_common:techniqueGroupList": { "type": "object", "properties": { @@ -382,6 +397,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 47d06a8472..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", @@ -58,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" : { @@ -82,6 +86,10 @@ "type": "date", "format": "date_time" }, + "collectionspace_core:updatedAt": { + "type": "date", + "format": "date_time" + }, "collectionobjects_common:publishToList": { "type": "keyword", "fields": { @@ -150,6 +158,9 @@ } } }, + "collectionspace_denorm:objectCsid": { + "type": "keyword" + }, "collectionobjects_common:objectNumber": { "type": "keyword", @@ -301,6 +312,10 @@ } } }, + "collectionobjects_common:contentPlaces": { + "type": "keyword", + "copy_to": "all_field" + }, "collectionobjects_common:techniqueGroupList": { "type": "object", "properties": { @@ -326,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 ccd9cdffa7..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", @@ -58,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" : { @@ -82,6 +86,10 @@ "type": "date", "format": "date_time" }, + "collectionspace_core:updatedAt": { + "type": "date", + "format": "date_time" + }, "collectionobjects_common:publishToList": { "type": "keyword", "fields": { @@ -150,7 +158,9 @@ } } }, - + "collectionspace_denorm:objectCsid": { + "type": "keyword" + }, "collectionobjects_common:objectNumber": { "type": "keyword", "copy_to": "all_field" @@ -301,6 +311,10 @@ } } }, + "collectionobjects_common:contentPlaces": { + "type": "keyword", + "copy_to": "all_field" + }, "collectionobjects_common:techniqueGroupList": { "type": "object", "properties": { @@ -326,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 27679ab6b1..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,6 +75,7 @@ "collectionobjects_common:contentEvents", "collectionobjects_common:contentOrganizations", "collectionobjects_common:contentPersons", + "collectionobjects_common:contentPlaces", "collectionobjects_common:objectHistoryNote", "collectionobjects_common:objectNumber", "collectionobjects_common:objectStatusList", @@ -102,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" ] }, @@ -165,6 +169,9 @@ } } }, + "collectionspace_denorm:objectCsid": { + "type": "keyword" + }, "collectionspace_core:createdAt": { "type": "date", @@ -172,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", @@ -666,6 +679,10 @@ } } }, + "collectionobjects_common:contentPlaces": { + "type": "keyword", + "copy_to": "all_field" + }, "collectionobjects_common:materialGroupList": { "type": "object", "properties": { @@ -697,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 ad0e626e8e..91411631c4 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 @@ -201,6 +201,13 @@ version="1.0"> default-domain + + + + + default-domain + @@ -1181,6 +1188,7 @@ "collectionobjects_common:contentEvents", "collectionobjects_common:contentOrganizations", "collectionobjects_common:contentPersons", + "collectionobjects_common:contentPlaces", "collectionobjects_common:materialGroupList", "collectionobjects_common:measuredPartGroupList", "collectionobjects_common:numberOfObjects", @@ -1210,7 +1218,10 @@ "ecm:currentLifeCycleState", "ecm:name", "ecm:primaryType", - "media_common:blobCsid" + "media_common:blobCsid", + "media_common:identificationNumber", + "media_common:title", + "media_common:altText" ] }, "properties" : { @@ -1234,6 +1245,10 @@ "type": "date", "format": "date_time" }, + "collectionspace_core:updatedAt": { + "type": "date", + "format": "date_time" + }, "collectionobjects_common:publishToList": { "type": "keyword", "fields": { @@ -1302,7 +1317,9 @@ } } }, - + "collectionspace_denorm:objectCsid": { + "type": "keyword" + }, "collectionobjects_common:objectNumber": { "type": "keyword", "copy_to": "all_field" @@ -1447,6 +1464,10 @@ } } }, + "collectionobjects_common:contentPlaces": { + "type": "keyword", + "copy_to": "all_field" + }, "collectionobjects_common:techniqueGroupList": { "type": "object", "properties": { @@ -1472,6 +1493,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 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 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/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/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/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/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/export/service/pom.xml b/services/export/service/pom.xml index 2cd3e7114b..ae5d39314b 100644 --- a/services/export/service/pom.xml +++ b/services/export/service/pom.xml @@ -13,18 +13,6 @@ jar - - org.collectionspace.services - org.collectionspace.services.authentication.service - ${project.version} - provided - - - org.collectionspace.services - org.collectionspace.services.account.service - ${project.version} - provided - org.collectionspace.services org.collectionspace.services.authority.service @@ -36,12 +24,6 @@ org.collectionspace.services.config ${project.version} - - org.collectionspace.services - org.collectionspace.services.authority.jaxb - true - ${project.version} - org.collectionspace.services org.collectionspace.services.common @@ -56,53 +38,20 @@ org.collectionspace.services.export.client ${project.version} - - org.collectionspace.services - org.collectionspace.services.collectionobject.jaxb - ${project.version} - - - junit - junit - test - - - org.testng - testng - org.apache.commons commons-csv 1.8 - - - - javax.security - jaas - 1.0.01 - provided - - - org.jboss.resteasy resteasy-jaxrs - - org.jboss.resteasy - resteasy-jaxb-provider - - - org.jboss.resteasy - resteasy-multipart-provider - - org.nuxeo.ecm.core nuxeo-core-api diff --git a/services/export/service/src/main/java/org/collectionspace/services/export/AbstractDocumentsByQueryIterator.java b/services/export/service/src/main/java/org/collectionspace/services/export/AbstractDocumentsByQueryIterator.java index 9a6ad70275..7d3b79114c 100644 --- a/services/export/service/src/main/java/org/collectionspace/services/export/AbstractDocumentsByQueryIterator.java +++ b/services/export/service/src/main/java/org/collectionspace/services/export/AbstractDocumentsByQueryIterator.java @@ -148,7 +148,7 @@ protected PoxPayloadOut getDocument(ListItemType item) { : resource.getWithParentCtx(serviceContext, csid)); } catch (Exception e) { - logger.warn("Could not get document with csid " + csid, e); + logger.warn("Could not get document with csid {}", csid, e); return null; } @@ -163,7 +163,7 @@ protected UriInfo createUriInfo(InvocationContext.Query query) throws URISyntaxE // Some code in services assumes pathSegments will have at least one element, so add an // empty one. - List pathSegments = Arrays.asList((PathSegment) new PathSegmentImpl("", false)); + List pathSegments = Arrays.asList(new PathSegmentImpl("", false)); URIBuilder uriBuilder = new URIBuilder(); diff --git a/services/export/service/src/main/java/org/collectionspace/services/export/AbstractExportWriter.java b/services/export/service/src/main/java/org/collectionspace/services/export/AbstractExportWriter.java index 80d1fd02a0..a2ecbe3301 100644 --- a/services/export/service/src/main/java/org/collectionspace/services/export/AbstractExportWriter.java +++ b/services/export/service/src/main/java/org/collectionspace/services/export/AbstractExportWriter.java @@ -1,11 +1,8 @@ package org.collectionspace.services.export; -import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; -import java.util.HashSet; -import java.util.Set; import org.collectionspace.services.client.PoxPayloadIn; import org.collectionspace.services.client.PoxPayloadOut; diff --git a/services/export/service/src/main/java/org/collectionspace/services/export/CsvExportWriter.java b/services/export/service/src/main/java/org/collectionspace/services/export/CsvExportWriter.java index 6c00082dcb..9b80afda88 100644 --- a/services/export/service/src/main/java/org/collectionspace/services/export/CsvExportWriter.java +++ b/services/export/service/src/main/java/org/collectionspace/services/export/CsvExportWriter.java @@ -1,36 +1,56 @@ package org.collectionspace.services.export; +import static org.collectionspace.services.common.context.ServiceBindingUtils.AUTH_REF_PROP; +import static org.collectionspace.services.common.context.ServiceBindingUtils.TERM_REF_PROP; +import static org.collectionspace.services.common.context.ServiceBindingUtils.getPropertyValuesForPart; + import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.TreeMap; +import java.util.function.Predicate; import java.util.regex.Matcher; import java.util.regex.Pattern; +import com.google.common.collect.HashBasedTable; +import com.google.common.collect.Table; import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVPrinter; import org.apache.commons.lang.StringUtils; +import org.apache.logging.log4j.util.Strings; import org.collectionspace.services.client.PayloadOutputPart; import org.collectionspace.services.client.PoxPayloadOut; import org.collectionspace.services.common.api.RefNameUtils; -import org.collectionspace.services.common.context.ServiceBindingUtils; import org.collectionspace.services.common.invocable.Field; import org.collectionspace.services.common.invocable.InvocationContext; +import org.collectionspace.services.config.service.AuthorityInstanceType; import org.collectionspace.services.config.service.ServiceBindingType; +import org.collectionspace.services.config.tenant.TenantBindingType; import org.dom4j.Element; import org.dom4j.Node; public class CsvExportWriter extends AbstractExportWriter { - private static final Pattern VALID_FIELD_XPATH_PATTERN = Pattern.compile("^\\w+:(\\w+\\/)*(\\w+)(\\[.*\\])?$"); + private static final Pattern VALID_FIELD_XPATH_PATTERN = Pattern.compile("^\\w+:(\\w+/)*(\\w+)(\\[.*])?$"); private static final String VALUE_DELIMITER_PARAM_NAME = "valuedelimiter"; + private static final String INCLUDE_AUTHORITY_PARAM = "includeauthority"; + private static final String AUTHORITY_SUFFIX = "AuthorityVocabulary"; private CSVPrinter csvPrinter; - private Map>> refFieldsByDocType = new HashMap<>(); + private Map>> refFieldsByDocType = new HashMap<>(); private String valueDelimiter = "|"; private String nestedValueDelimiter = "^^"; + private boolean includeAuthority = false; + + /** + * Authority names in the service bindings start with a single capital letter, e.g. Personauthorities, but in + * refnames they are all lowercase. Instead of using toLower just set case-insensitive. + */ + private Map authorityDisplayNames = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); @Override public void start() throws Exception { @@ -40,12 +60,25 @@ public void start() throws Exception { // present. InvocationContext.IncludeFields includeFields = invocationContext.getIncludeFields(); - List fields = (includeFields != null ? includeFields.getField() : new ArrayList()); + List fields = (includeFields != null ? includeFields.getField() : new ArrayList<>()); if (fields.size() == 0) { throw new Exception("For CSV output, the fields to export must be specified using includeFields."); } + // Set the export parameters. + InvocationContext.Params params = invocationContext.getParams(); + if (params != null) { + for (InvocationContext.Params.Param param : params.getParam()) { + if (param.getKey().equals(VALUE_DELIMITER_PARAM_NAME)) { + this.valueDelimiter = param.getValue(); + } else if (param.getKey().equals(INCLUDE_AUTHORITY_PARAM)) { + this.includeAuthority = Boolean.parseBoolean(param.getValue()); + collectAuthorityVocabs(); + } + } + } + List headers = new ArrayList<>(); for (Field field : fields) { @@ -63,25 +96,20 @@ public void start() throws Exception { } headers.add(fieldName); + + // Create additional authority vocabulary column if requested + if (includeAuthority) { + String partName = fieldSpec.split(":", 2)[0]; + String docType = partName.substring(0, partName.indexOf("_")); + FieldType fieldType = getFieldType(docType, partName, fieldName); + if (fieldType == FieldType.AUTH_REF) { + headers.add(fieldName + AUTHORITY_SUFFIX); + } + } } String[] headersArray = new String[headers.size()]; - this.csvPrinter = new CSVPrinter(writer, CSVFormat.DEFAULT.withHeader(headers.toArray(headersArray))); - - // Set the delimiter. - - InvocationContext.Params params = invocationContext.getParams(); - - if (params != null) { - for (InvocationContext.Params.Param param : params.getParam()) { - if (param.getKey().equals(VALUE_DELIMITER_PARAM_NAME)) { - this.valueDelimiter = param.getValue(); - - break; - } - }; - } } @Override @@ -96,7 +124,12 @@ public void writeDocument(PoxPayloadOut document) throws Exception { List csvRecord = new ArrayList<>(); for (Field field : fields) { - csvRecord.add(collectValues(document, field.getValue())); + FieldType fieldType = getFieldType(document, field); + + csvRecord.add(collectValues(document, field.getValue(), fieldType, ColumnType.FIELD)); + if (fieldType == FieldType.AUTH_REF && includeAuthority) { + csvRecord.add(collectValues(document, field.getValue(), fieldType, ColumnType.AUTHORITY)); + } } if (csvRecord.size() > 0) { @@ -106,10 +139,10 @@ public void writeDocument(PoxPayloadOut document) throws Exception { @Override public void close() throws Exception { - csvPrinter.close(); + csvPrinter.close(); } - private String collectValues(PoxPayloadOut document, String fieldSpec) { + private String collectValues(PoxPayloadOut document, String fieldSpec, FieldType fieldType, ColumnType columnType) { String delimitedValues = ""; String[] segments = fieldSpec.split(":", 2); String partName = segments[0]; @@ -118,13 +151,15 @@ private String collectValues(PoxPayloadOut document, String fieldSpec) { PayloadOutputPart part = document.getPart(partName); if (part != null) { - delimitedValues = collectValues(document.getName(), partName, part.getElementBody(), Arrays.asList(xpath.split("/")), 0); + delimitedValues = collectValues(part.getElementBody(), Arrays.asList(xpath.split("/")), 0, fieldType, + columnType); } return delimitedValues; } - private String collectValues(String docType, String partName, Element element, List path, int depth) { + private String collectValues(Element element, List path, int depth, FieldType fieldType, + ColumnType columnType) { String delimitedValues = ""; String fieldName = path.get(depth); String delimiter = (depth / 2 > 0) ? this.nestedValueDelimiter : this.valueDelimiter; @@ -135,17 +170,32 @@ private String collectValues(String docType, String partName, Element element, L boolean hasValue = false; for (Node node : matches) { - String textValue = ""; + String textValue; if (depth < path.size() - 1) { - textValue = collectValues(docType, partName, (Element) node, path, depth + 1); - } - else { + textValue = collectValues((Element) node, path, depth + 1, fieldType, columnType); + } else if (columnType == ColumnType.AUTHORITY) { textValue = node.getText(); - boolean isRefName = isRefField(docType, partName, fieldName.replaceFirst("\\[.*\\]", "")); + if (Strings.isNotEmpty(textValue)) { + final RefNameUtils.AuthorityTermInfo termInfo = RefNameUtils.getAuthorityTermInfo(textValue); + final String authority = termInfo.inAuthority.resource; + final String shortId = termInfo.inAuthority.name; + + String authorityDisplayName = authority; + String vocabDisplayName = shortId; + final AuthorityDisplayMapping mapping = authorityDisplayNames.get(authority); + if (mapping != null) { + authorityDisplayName = mapping.getAuthorityDisplayName(); + vocabDisplayName = mapping.getVocabDisplayName(shortId); + } - if (isRefName && StringUtils.isNotEmpty(textValue)) { + textValue = authorityDisplayName + "/" + vocabDisplayName; + } + } else { + textValue = node.getText(); + + if (fieldType.isRefField() && StringUtils.isNotEmpty(textValue)) { textValue = RefNameUtils.getDisplayName(textValue); } } @@ -165,43 +215,140 @@ private String collectValues(String docType, String partName, Element element, L return delimitedValues; } - private boolean isRefField(String docType, String partName, String fieldName) { - return getRefFields(docType, partName).contains(fieldName); + /** + * Get the {@link FieldType} for a given {@link Field}. We expect {@link Field#getValue} to return + * something which matches our Field Spec, i.e. "namespace:path/to/field". We allow for some xpath operations, + * such as contains, so we also need to be mindful of that and filter them out appropriately. + * + * @param document the document we're searching in + * @param field the field being searched for + * @return the field type + */ + private FieldType getFieldType(PoxPayloadOut document, Field field) { + final String fieldSpec = field.getValue(); + final String[] segments = fieldSpec.split(":", 2); + final String partName = segments[0]; + final List xpath = Arrays.asList(segments[1].split("/")); + final String fieldName = xpath.get(xpath.size() - 1); + + return getFieldType(document.getName(), partName, fieldName.replaceFirst("\\[.*]", "")); + } + + private FieldType getFieldType(String docType, String partName, String fieldName) { + Map> refs = getRefFields(docType, partName); + if (refs.getOrDefault(TERM_REF_PROP, Collections.emptySet()).contains(fieldName)) { + return FieldType.TERM_REF; + } else if (refs.getOrDefault(AUTH_REF_PROP, Collections.emptySet()).contains(fieldName)) { + return FieldType.AUTH_REF; + } + + return FieldType.STANDARD; } - private Set getRefFields(String docType, String partName) { - Set refFields = refFieldsByDocType.containsKey(docType) - ? refFieldsByDocType.get(docType).get(partName) - : null; + private Map> getRefFields(String docType, String partName) { + boolean containsDocTypeAndPart = refFieldsByDocType.containsKey(docType) + && refFieldsByDocType.get(docType).containsRow(partName); + Map> refFields = containsDocTypeAndPart ? refFieldsByDocType.get(docType).row(partName) : null; if (refFields != null) { return refFields; } - refFields = new HashSet<>(); + Set authRefs = new HashSet<>(); + Set termRefs = new HashSet<>(); + Table> refTable = HashBasedTable.create(); - ServiceBindingType serviceBinding = tenantBindingConfigReader.getServiceBinding(serviceContext.getTenantId(), docType); + ServiceBindingType serviceBinding = + tenantBindingConfigReader.getServiceBinding(serviceContext.getTenantId(), docType); - for (String termRefField : ServiceBindingUtils.getPropertyValuesForPart(serviceBinding, partName, ServiceBindingUtils.TERM_REF_PROP, false)) { - String[] segments = termRefField.split("[\\/\\|]"); + for (String termRefField : getPropertyValuesForPart(serviceBinding, partName, TERM_REF_PROP, false)) { + String[] segments = termRefField.split("[/|]"); String fieldName = segments[segments.length - 1]; - refFields.add(fieldName); + termRefs.add(fieldName); } - for (String authRefField : ServiceBindingUtils.getPropertyValuesForPart(serviceBinding, partName, ServiceBindingUtils.AUTH_REF_PROP, false)) { - String[] segments = authRefField.split("[\\/\\|]"); + for (String authRefField : getPropertyValuesForPart(serviceBinding, partName, AUTH_REF_PROP, false)) { + String[] segments = authRefField.split("[/|]"); String fieldName = segments[segments.length - 1]; - refFields.add(fieldName); + authRefs.add(fieldName); } + refTable.put(partName, TERM_REF_PROP, termRefs); + refTable.put(partName, AUTH_REF_PROP, authRefs); + if (!refFieldsByDocType.containsKey(docType)) { - refFieldsByDocType.put(docType, new HashMap>()); + refFieldsByDocType.put(docType, HashBasedTable.create()); + } + + refFieldsByDocType.get(docType).putAll(refTable); + return refTable.row(partName); + } + + /** + * Create the mapping of Authority name to Authority displayName and Authority Vocabularies shortId to Authority + * Vocabulary displayName (title) + */ + private void collectAuthorityVocabs() { + if (!includeAuthority) { + return; + } + + TenantBindingType tenantBinding = tenantBindingConfigReader.getTenantBinding(serviceContext.getTenantId()); + + Predicate hasAuthorityInstances = (binding) -> + binding.getAuthorityInstanceList() != null && + binding.getAuthorityInstanceList().getAuthorityInstance() != null; + + Predicate hasAuthorityDisplayName = (binding) -> + binding.getDisplayName() != null && !binding.getDisplayName().isEmpty(); + + tenantBinding.getServiceBindings().stream() + .filter(hasAuthorityInstances.and(hasAuthorityDisplayName)) + .map(AuthorityDisplayMapping::new) + .forEach((mapping) -> authorityDisplayNames.put(mapping.authority, mapping)); + } + + /** + * The type of column which we want to collect data for. + * Field - the text value or display name if a refname is present + * Authority - The aggregate of the Authority display name and Authority Vocabulary display name + */ + private enum ColumnType { + FIELD, AUTHORITY + } + + private enum FieldType { + STANDARD, TERM_REF, AUTH_REF; + + public boolean isRefField() { + return this == TERM_REF || this == AUTH_REF; } + } - refFieldsByDocType.get(docType).put(partName, refFields); + private static class AuthorityDisplayMapping { + final String authority; + final String displayName; + final Map vocabDisplayNames; - return refFields; + public AuthorityDisplayMapping(ServiceBindingType binding) { + this.authority = binding.getName(); + this.displayName = binding.getDisplayName(); + this.vocabDisplayNames = new HashMap<>(); + binding.getAuthorityInstanceList().getAuthorityInstance().forEach(this::addVocabMapping); + } + + private void addVocabMapping(AuthorityInstanceType instance) { + vocabDisplayNames.put(instance.getTitleRef(), instance.getTitle()); + } + + public String getAuthorityDisplayName() { + return displayName; + } + + public String getVocabDisplayName(String shortId) { + return vocabDisplayNames.getOrDefault(shortId, shortId); + } } } diff --git a/services/export/service/src/main/java/org/collectionspace/services/export/DocumentsByCsidIterator.java b/services/export/service/src/main/java/org/collectionspace/services/export/DocumentsByCsidIterator.java index 787065b750..d3dece2e44 100644 --- a/services/export/service/src/main/java/org/collectionspace/services/export/DocumentsByCsidIterator.java +++ b/services/export/service/src/main/java/org/collectionspace/services/export/DocumentsByCsidIterator.java @@ -16,7 +16,7 @@ import org.slf4j.LoggerFactory; public class DocumentsByCsidIterator implements Iterator { - private final Logger logger = LoggerFactory.getLogger(DocumentsByCsidIterator.class); + private final Logger logger = LoggerFactory.getLogger(DocumentsByCsidIterator.class); private NuxeoBasedResource resource; private String vocabulary; @@ -60,8 +60,7 @@ public PoxPayloadOut next() { : resource.getWithParentCtx(serviceContext, csid)); } catch (Exception e) { - logger.warn("Could not get document with csid " + csid, e); - + logger.warn("Could not get document with csid {}", csid, e); return null; } } diff --git a/services/export/service/src/main/java/org/collectionspace/services/export/ExportResource.java b/services/export/service/src/main/java/org/collectionspace/services/export/ExportResource.java index dcdc5a8fc9..a4449f537e 100644 --- a/services/export/service/src/main/java/org/collectionspace/services/export/ExportResource.java +++ b/services/export/service/src/main/java/org/collectionspace/services/export/ExportResource.java @@ -33,6 +33,14 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; import com.google.common.collect.ImmutableMap; import org.apache.commons.lang3.StringUtils; @@ -51,30 +59,18 @@ import org.collectionspace.services.common.invocable.InvocationContext; import org.dom4j.Element; import org.dom4j.Node; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.ws.rs.Consumes; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriInfo; @Path(ExportClient.SERVICE_PATH) @Consumes("application/xml") @Produces("application/xml") public class ExportResource extends AbstractCollectionSpaceResourceImpl { - private final Logger logger = LoggerFactory.getLogger(ExportResource.class); // There is no way to tell from config that collectionspace_core should not be exported, so it // has to be hardcoded here. At that point we might as well also hardcode account_permission, // so we don't need to look at config at all. private static final ImmutableMap> EXCLUDE_PARTS = ImmutableMap.of( "collectionspace_core", Arrays.asList("workflowState", "tenantId", "refName"), - "account_permission", Collections.emptyList()); + "account_permission", Collections.emptyList()); private static final String MIME_TYPE_CSV = "text/csv"; private static final String MIME_TYPE_XML = "application/xml"; @@ -229,12 +225,12 @@ private void filterFields(PoxPayloadOut document, InvocationContext invocationCo PayloadOutputPart part = document.getPart(partName); if (part != null) { - org.dom4j.Element partElement = part.getElementBody(); - List matches = (List) partElement.selectNodes(xpath); + Element partElement = part.getElementBody(); + List matches = partElement.selectNodes(xpath); for (Node includeNode : matches) { if (includeNode.getNodeType() == Node.ELEMENT_NODE) { - markIncluded((org.dom4j.Element) includeNode); + markIncluded((Element) includeNode); } } } @@ -243,7 +239,7 @@ private void filterFields(PoxPayloadOut document, InvocationContext invocationCo ArrayList includedParts = new ArrayList<>(); for (PayloadOutputPart part : document.getParts()) { - org.dom4j.Element partElement = part.getElementBody(); + Element partElement = part.getElementBody(); if (partElement.attributeValue(INCLUDE_ATTRIBUTE_NAME) != null) { includedParts.add(part); @@ -257,7 +253,7 @@ private void filterFields(PoxPayloadOut document, InvocationContext invocationCo private void detach(final String xpath, final Element element) { if (element != null) { - List matches = (List) element.selectNodes(xpath); + List matches = element.selectNodes(xpath); for (Node excludeNode : matches) { if (excludeNode.getNodeType() == Node.ELEMENT_NODE) { @@ -267,8 +263,8 @@ private void detach(final String xpath, final Element element) { } } - private void markIncluded(org.dom4j.Element element) { - org.dom4j.Element parentElement = element.getParent(); + private void markIncluded(Element element) { + Element parentElement = element.getParent(); if (parentElement != null) { markIncluded(parentElement); @@ -277,17 +273,17 @@ private void markIncluded(org.dom4j.Element element) { element.addAttribute(INCLUDE_ATTRIBUTE_NAME, "1"); } - private void removeUnincluded(org.dom4j.Element element) { + private void removeUnincluded(Element element) { if (element.attributeValue(INCLUDE_ATTRIBUTE_NAME) == null) { element.detach(); } else { element.addAttribute(INCLUDE_ATTRIBUTE_NAME, null); - Iterator childIterator = element.elementIterator(); + Iterator childIterator = element.elementIterator(); while (childIterator.hasNext()) { - org.dom4j.Element childElement = (org.dom4j.Element) childIterator.next(); + Element childElement = childIterator.next(); removeUnincluded(childElement); } diff --git a/services/export/service/src/main/java/org/collectionspace/services/export/ExportWriter.java b/services/export/service/src/main/java/org/collectionspace/services/export/ExportWriter.java index fc8f719633..279edd7d08 100644 --- a/services/export/service/src/main/java/org/collectionspace/services/export/ExportWriter.java +++ b/services/export/service/src/main/java/org/collectionspace/services/export/ExportWriter.java @@ -1,8 +1,6 @@ package org.collectionspace.services.export; -import java.io.IOException; import java.io.OutputStream; -import java.util.Set; import org.collectionspace.services.client.PoxPayloadIn; import org.collectionspace.services.client.PoxPayloadOut; @@ -11,13 +9,13 @@ import org.collectionspace.services.common.invocable.InvocationContext; public interface ExportWriter { - public void setInvocationContext(InvocationContext invocationContext); - public void setOutputStream(OutputStream outputStream); - public void setServiceContext(ServiceContext serviceContext); - public void setTenantBindingConfigReader(TenantBindingConfigReaderImpl tenantBindingConfigReader); + void setInvocationContext(InvocationContext invocationContext); + void setOutputStream(OutputStream outputStream); + void setServiceContext(ServiceContext serviceContext); + void setTenantBindingConfigReader(TenantBindingConfigReaderImpl tenantBindingConfigReader); - public void start() throws Exception; - public void writeDocument(PoxPayloadOut document) throws Exception; - public void finish() throws Exception; - public void close() throws Exception; + void start() throws Exception; + void writeDocument(PoxPayloadOut document) throws Exception; + void finish() throws Exception; + void close() throws Exception; } diff --git a/services/export/service/src/main/java/org/collectionspace/services/export/RelationObjectsByQueryIterator.java b/services/export/service/src/main/java/org/collectionspace/services/export/RelationObjectsByQueryIterator.java index 857bb2426e..6ea7d1e313 100644 --- a/services/export/service/src/main/java/org/collectionspace/services/export/RelationObjectsByQueryIterator.java +++ b/services/export/service/src/main/java/org/collectionspace/services/export/RelationObjectsByQueryIterator.java @@ -18,7 +18,7 @@ import org.slf4j.LoggerFactory; public class RelationObjectsByQueryIterator extends RelationsByQueryIterator implements Iterator { - private final Logger logger = LoggerFactory.getLogger(RelationObjectsByQueryIterator.class); + private final Logger logger = LoggerFactory.getLogger(RelationObjectsByQueryIterator.class); RelationObjectsByQueryIterator( ServiceContext serviceContext, @@ -36,7 +36,7 @@ protected PoxPayloadOut getDocument(RelationListItem item) { String relationObjectCsid = relationObject.getCsid(); String relationObjectDocType = relationObject.getDocumentType(); - TenantBindingConfigReaderImpl tenantBindingConfigReader = ServiceMain.getInstance().getTenantBindingConfigReader(); + TenantBindingConfigReaderImpl tenantBindingConfigReader = ServiceMain.getInstance().getTenantBindingConfigReader(); ServiceBindingType relationObjectServiceBinding = tenantBindingConfigReader.getServiceBindingForDocType(serviceContext.getTenantId(), relationObjectDocType); String relationObjectServiceType = relationObjectServiceBinding.getType(); String relationObjectServiceName = relationObjectServiceBinding.getName(); @@ -53,8 +53,7 @@ protected PoxPayloadOut getDocument(RelationListItem item) { : relationObjectResource.getWithParentCtx(serviceContext, relationObjectCsid)); } catch (Exception e) { - logger.warn("Could not get document with csid " + relationObjectCsid, e); - + logger.warn("Could not get document with csid {}", relationObjectCsid, e); return null; } } diff --git a/services/export/service/src/main/java/org/collectionspace/services/export/XmlExportWriter.java b/services/export/service/src/main/java/org/collectionspace/services/export/XmlExportWriter.java index 35ffa549f9..5b996ec58b 100644 --- a/services/export/service/src/main/java/org/collectionspace/services/export/XmlExportWriter.java +++ b/services/export/service/src/main/java/org/collectionspace/services/export/XmlExportWriter.java @@ -1,9 +1,5 @@ package org.collectionspace.services.export; -import java.io.IOException; -import java.util.Arrays; -import java.util.List; - import org.collectionspace.services.client.PayloadOutputPart; import org.collectionspace.services.client.PoxPayloadOut; import org.collectionspace.services.config.service.ServiceBindingType; @@ -40,8 +36,8 @@ public void writeDocument(PoxPayloadOut document) throws Exception { Namespace partNamespace = element.getNamespaceForPrefix("ns2"); String partNamespaceUri = partNamespace.getURI(); - for (Object namespace : element.additionalNamespaces()) { - element.remove((Namespace) namespace); + for (Namespace namespace : element.additionalNamespaces()) { + element.remove(namespace); } element.remove(partNamespace); diff --git a/services/export/service/src/main/java/org/collectionspace/services/export/nuxeo/ExportDocumentModelHandler.java b/services/export/service/src/main/java/org/collectionspace/services/export/nuxeo/ExportDocumentModelHandler.java index a971eb5bbe..c0f282f94c 100644 --- a/services/export/service/src/main/java/org/collectionspace/services/export/nuxeo/ExportDocumentModelHandler.java +++ b/services/export/service/src/main/java/org/collectionspace/services/export/nuxeo/ExportDocumentModelHandler.java @@ -23,69 +23,8 @@ */ package org.collectionspace.services.export.nuxeo; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.InputStream; -import java.nio.file.Files; -import java.sql.Connection; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import javax.ws.rs.core.MediaType; -import javax.naming.NamingException; -import javax.ws.rs.core.Response; - -import org.apache.commons.lang.StringUtils; -import org.collectionspace.authentication.AuthN; -import org.collectionspace.services.ExportJAXBSchema; -import org.collectionspace.services.account.AccountResource; -import org.collectionspace.services.authorization.AuthZ; -import org.collectionspace.services.authorization.CSpaceResource; -import org.collectionspace.services.authorization.PermissionException; -import org.collectionspace.services.authorization.URIResourceImpl; -import org.collectionspace.services.authorization.perms.ActionType; -import org.collectionspace.services.client.PoxPayloadIn; -import org.collectionspace.services.client.PoxPayloadOut; -import org.collectionspace.services.client.ExportClient; -import org.collectionspace.services.common.CSWebApplicationException; -import org.collectionspace.services.common.NuxeoBasedResource; -import org.collectionspace.services.common.ResourceMap; -import org.collectionspace.services.common.ServiceMain; -import org.collectionspace.services.common.api.JEEServerDeployment; -import org.collectionspace.services.common.api.FileTools; -import org.collectionspace.services.common.api.Tools; -import org.collectionspace.services.common.authorization_mgt.ActionGroup; -import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl; -import org.collectionspace.services.common.context.ServiceBindingUtils; -import org.collectionspace.services.common.context.ServiceContext; -import org.collectionspace.services.common.document.BadRequestException; -import org.collectionspace.services.common.document.DocumentException; -import org.collectionspace.services.common.document.DocumentWrapper; -import org.collectionspace.services.common.invocable.Invocable; -import org.collectionspace.services.common.invocable.InvocationContext; -import org.collectionspace.services.common.invocable.InvocationContext.ListCSIDs; -import org.collectionspace.services.common.storage.JDBCTools; -import org.collectionspace.services.config.service.ServiceBindingType; -import org.collectionspace.services.config.types.PropertyItemType; import org.collectionspace.services.export.ExportsCommon; -import org.collectionspace.services.jaxb.InvocableJAXBSchema; import org.collectionspace.services.nuxeo.client.java.NuxeoDocumentModelHandler; -import org.collectionspace.services.nuxeo.client.java.CoreSessionInterface; -import org.collectionspace.services.nuxeo.client.java.NuxeoRepositoryClientImpl; -import org.collectionspace.services.nuxeo.util.NuxeoUtils; - -import org.nuxeo.ecm.core.api.model.PropertyException; -import org.nuxeo.ecm.core.api.DocumentModel; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * ExportDocumentModelHandler @@ -93,157 +32,4 @@ * $LastChangedRevision: $ * $LastChangedDate: $ */ -public class ExportDocumentModelHandler extends NuxeoDocumentModelHandler { - private final Logger logger = LoggerFactory.getLogger(ExportDocumentModelHandler.class); - - public InputStream invokeExport( - TenantBindingConfigReaderImpl tenantBindingReader, - ResourceMap resourceMap, - ServiceContext serviceContext, - InvocationContext invocationContext, - StringBuffer outputMimeType, - StringBuffer outputFileName) throws Exception { - - NuxeoRepositoryClientImpl repoClient = (NuxeoRepositoryClientImpl) this.getRepositoryClient(serviceContext); - boolean releaseRepoSession = false; - CoreSessionInterface repoSession = this.getRepositorySession(); - - if (repoSession == null) { - repoSession = repoClient.getRepositorySession(serviceContext); - releaseRepoSession = true; - } - - try { - Iterator documents = findDocuments(tenantBindingReader, resourceMap, serviceContext, repoSession, invocationContext); - - } - finally { - if (releaseRepoSession && repoSession != null) { - repoClient.releaseRepositorySession(serviceContext, repoSession); - } - } - - return null; - // return buildExportResult(csid, params, exportFileNameProperty, outMimeType.toString(), outExportFileName); - } - - private Iterator findDocuments( - TenantBindingConfigReaderImpl tenantBindingReader, - ResourceMap resourceMap, - ServiceContext serviceContext, - CoreSessionInterface repoSession, - InvocationContext invocationContext) throws Exception { - - String docType = invocationContext.getDocType(); - ServiceBindingType binding = tenantBindingReader.getServiceBindingForDocType(serviceContext.getTenantId(), docType); - String serviceName = binding.getName(); - - switch (invocationContext.getMode().toLowerCase()) { - case Invocable.INVOCATION_MODE_SINGLE: - return findDocumentByCsid(resourceMap, serviceContext, repoSession, serviceName, invocationContext.getSingleCSID()); - case Invocable.INVOCATION_MODE_LIST: - return findDocumentsByCsid(resourceMap, serviceContext, repoSession, serviceName, invocationContext.getListCSIDs().getCsid()); - case Invocable.INVOCATION_MODE_GROUP: - return findDocumentsByGroup(resourceMap, serviceContext, repoSession, invocationContext.getGroupCSID()); - case Invocable.INVOCATION_MODE_NO_CONTEXT: - return findDocumentsByType(resourceMap, serviceContext, repoSession, invocationContext.getDocType()); - default: - return null; - } - } - - private Iterator findDocumentByCsid( - ResourceMap resourceMap, - ServiceContext serviceContext, - CoreSessionInterface repoSession, - String serviceName, - String csid) throws Exception { - - return findDocumentsByCsid(resourceMap, serviceContext, repoSession, serviceName, Arrays.asList(csid)); - } - - private Iterator findDocumentsByCsid( - ResourceMap resourceMap, - ServiceContext serviceContext, - CoreSessionInterface repoSession, - String serviceName, - List csids) throws Exception { - - return new DocumentsByCsidIterator(resourceMap, serviceContext, repoSession, serviceName, csids); - } - - private Iterator findDocumentsByType( - ResourceMap resourceMap, - ServiceContext serviceContext, - CoreSessionInterface repoSession, - String docType) { - - return null; - } - - private Iterator findDocumentsByGroup( - ResourceMap resourceMap, - ServiceContext serviceContext, - CoreSessionInterface repoSession, - String docType) { - - return null; - } - - // private InputStream buildExportResult(String exportCSID, - // HashMap params, - // String exportFileName, - // String outputMimeType, - // StringBuffer outExportFileName) throws Exception { - // Connection conn = null; - // InputStream result = null; - - // return result; - // } - - private class DocumentsByCsidIterator implements Iterator { - private NuxeoBasedResource resource; - private ServiceContext serviceContext; - private CoreSessionInterface repoSession; - private Iterator csidIterator; - - DocumentsByCsidIterator( - ResourceMap resourceMap, - ServiceContext serviceContext, - CoreSessionInterface repoSession, - String serviceName, - List csids) throws Exception { - - NuxeoBasedResource resource = (NuxeoBasedResource) resourceMap.get(serviceName.toLowerCase()); - - if (resource == null) { - throw new Exception("Resource not found for service name " + serviceName); - } - - this.resource = resource; - this.serviceContext = serviceContext; - this.repoSession = repoSession; - this.csidIterator = csids.iterator(); - } - - @Override - public boolean hasNext() { - return csidIterator.hasNext(); - } - - @Override - public DocumentModel next() { - String csid = csidIterator.next(); - - try { - // PoxPayloadOut payload = resource.getWithParentCtx(serviceContext, csid); - return null; - } - catch (Exception e) { - logger.warn("Could not get document with csid " + csid, e); - - return null; - } - } - } -} +public class ExportDocumentModelHandler extends NuxeoDocumentModelHandler { } diff --git a/services/export/service/src/main/java/org/collectionspace/services/export/nuxeo/ExportValidatorHandler.java b/services/export/service/src/main/java/org/collectionspace/services/export/nuxeo/ExportValidatorHandler.java index e184902ae1..bc94e74c38 100644 --- a/services/export/service/src/main/java/org/collectionspace/services/export/nuxeo/ExportValidatorHandler.java +++ b/services/export/service/src/main/java/org/collectionspace/services/export/nuxeo/ExportValidatorHandler.java @@ -1,18 +1,15 @@ package org.collectionspace.services.export.nuxeo; import org.collectionspace.services.common.context.ServiceContext; -import org.collectionspace.services.common.document.InvalidDocumentException; import org.collectionspace.services.common.document.ValidatorHandler; import org.collectionspace.services.common.document.DocumentHandler.Action; public class ExportValidatorHandler implements ValidatorHandler { @Override - public void validate(Action action, ServiceContext ctx) - throws InvalidDocumentException { + public void validate(Action action, ServiceContext ctx) { // TODO Auto-generated method stub System.out.println("ExportValidatorHandler executed."); - } } diff --git a/services/jaxb/src/main/resources/collectionspace_core.xsd b/services/jaxb/src/main/resources/collectionspace_core.xsd new file mode 100644 index 0000000000..44ca1ae29e --- /dev/null +++ b/services/jaxb/src/main/resources/collectionspace_core.xsd @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/services/jaxb/src/main/resources/invocationContext.xsd b/services/jaxb/src/main/resources/invocationContext.xsd index 39624e9933..3f7a85bc0e 100644 --- a/services/jaxb/src/main/resources/invocationContext.xsd +++ b/services/jaxb/src/main/resources/invocationContext.xsd @@ -13,50 +13,50 @@ - - - - - - - + + + + + + + - + - - - - - + + + + + - - - - - - + + + + + + - + - + @@ -66,8 +66,8 @@ - - + + diff --git a/services/media/client/pom.xml b/services/media/client/pom.xml index 638fd70432..14c06f01b9 100644 --- a/services/media/client/pom.xml +++ b/services/media/client/pom.xml @@ -50,6 +50,12 @@ org.collectionspace.services.person.client ${project.version} + + org.collectionspace.services.blob + blob-test-utils + ${project.version} + test + org.testng @@ -74,6 +80,93 @@ - collectionspace-services-media-client + collectionspace-services-media-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/media/client/src/test/java/org/collectionspace/services/client/test/MediaServiceTest.java b/services/media/client/src/test/java/org/collectionspace/services/client/test/MediaServiceIT.java similarity index 96% rename from services/media/client/src/test/java/org/collectionspace/services/client/test/MediaServiceTest.java rename to services/media/client/src/test/java/org/collectionspace/services/client/test/MediaServiceIT.java index fef0017cce..245b6d403f 100644 --- a/services/media/client/src/test/java/org/collectionspace/services/client/test/MediaServiceTest.java +++ b/services/media/client/src/test/java/org/collectionspace/services/client/test/MediaServiceIT.java @@ -29,6 +29,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.MediaClient; import org.collectionspace.services.client.PayloadOutputPart; @@ -49,11 +50,9 @@ * $LastChangedRevision: $ * $LastChangedDate: $ */ -public class MediaServiceTest extends AbstractPoxServiceTestImpl { +public class MediaServiceIT extends AbstractPoxServiceTestImpl { - private final String CLASS_NAME = MediaServiceTest.class.getName(); - private final Logger logger = LoggerFactory.getLogger(MediaServiceTest.class); - private final static String PUBLIC_URL_DECK = "https://farm8.staticflickr.com/7231/6962564226_4bdfc17599_k_d.jpg"; + private final Logger logger = LoggerFactory.getLogger(MediaServiceIT.class); private boolean mediaCleanup = true; @@ -77,7 +76,7 @@ private boolean isMediaCleanup() { } - @Override + @Override public String getServicePathComponent() { return MediaClient.SERVICE_PATH_COMPONENT; } @@ -206,7 +205,7 @@ public void createWithBlobUri(String testName) throws Exception { public void createMediaAndBlobWithUri(String testName) throws Exception { MediaClient client = new MediaClient(); PoxPayloadOut multipart = createMediaInstance(createIdentifier()); - Response mediaRes = client.createMediaAndBlobWithUri(multipart, PUBLIC_URL_DECK, true); // purge the original + Response mediaRes = client.createMediaAndBlobWithUri(multipart, StaticImage.DECK.getUrl(), true); // purge the original String mediaCsid = null; try { assertStatusCode(mediaRes, testName); diff --git a/services/media/jaxb/src/main/java/org/collectionspace/services/MediaJAXBSchema.java b/services/media/jaxb/src/main/java/org/collectionspace/services/MediaJAXBSchema.java index 0a41337ce5..c54bf7c688 100644 --- a/services/media/jaxb/src/main/java/org/collectionspace/services/MediaJAXBSchema.java +++ b/services/media/jaxb/src/main/java/org/collectionspace/services/MediaJAXBSchema.java @@ -1,30 +1,31 @@ -/** - * - */ package org.collectionspace.services; +/** + * Field names for the Media Schema + */ public interface MediaJAXBSchema { - final static String contributor = "contributor"; - final static String copyrightStatement = "copyrightStatement"; - final static String coverage = "coverage"; - final static String creator = "creator"; - final static String dates = "dates"; - final static String dateCreated = "dateCreated"; - final static String dateModified = "dateModified"; - final static String description = "description"; - final static String dimensions = "dimensions"; - final static String filename = "filename"; - final static String format = "format"; - final static String identificationNumber = "identificationNumber"; - final static String languages = "languages"; - final static String location = "location"; - final static String publisher = "publisher"; - final static String relation = "relation"; - final static String rightsHolder = "rightsHolder"; - final static String source = "source"; - final static String subjects = "subjects"; - final static String title = "title"; - final static String type = "type"; - final static String uri = "uri"; - final static String blobCsid = "blobCsid"; + String altText = "altText"; + String contributor = "contributor"; + String copyrightStatement = "copyrightStatement"; + String coverage = "coverage"; + String creator = "creator"; + String dates = "dates"; + String dateCreated = "dateCreated"; + String dateModified = "dateModified"; + String description = "description"; + String dimensions = "dimensions"; + String filename = "filename"; + String format = "format"; + String identificationNumber = "identificationNumber"; + String languages = "languages"; + String location = "location"; + String publisher = "publisher"; + String relation = "relation"; + String rightsHolder = "rightsHolder"; + String source = "source"; + String subjects = "subjects"; + String title = "title"; + String type = "type"; + String uri = "uri"; + String blobCsid = "blobCsid"; } diff --git a/services/pom.xml b/services/pom.xml index f7414ca6df..8f81baa9b4 100644 --- a/services/pom.xml +++ b/services/pom.xml @@ -108,6 +108,7 @@ security login logout + advancedsearch JaxRsServiceProvider 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 bc7a4c1de0..6587a43cf6 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 @@