From 676faa9cf37ee4d99816d3392eb1984d247cfb0b Mon Sep 17 00:00:00 2001 From: Ray Lee Date: Wed, 3 May 2023 00:32:54 -0400 Subject: [PATCH] DRYD-1230: Automatically add/update reports on startup. (#344) --- .../jaxrs/CSpaceResteasyBootstrap.java | 210 +++++++++++++++--- .../services/batch/BatchResource.java | 8 + .../services/client/IQueryManager.java | 29 ++- .../publicart-tenant-bindings.delta.xml | 26 ++- .../tenants/tenant-bindings-proto-unified.xml | 203 ++++++++++++----- .../services/common/query/QueryManager.java | 11 + .../query/nuxeo/QueryManagerNuxeoImpl.java | 46 +++- .../services/jaxb/InvocableJAXBSchema.java | 3 +- services/report/3rdparty/build.xml | 22 +- .../src/main/resources/Acq_List_Basic.xml | 16 ++ .../src/main/resources/CC_List_Basic.xml | 16 ++ .../main/resources/Exhibition_List_Basic.xml | 16 ++ .../src/main/resources/Group_List_Basic.xml | 16 ++ .../src/main/resources/LoansIn_List_Basic.xml | 16 ++ .../main/resources/LoansOut_List_Basic.xml | 16 ++ .../src/main/resources/acq_basic.xml | 16 ++ .../src/main/resources/coreAcquisition.xml | 16 ++ .../src/main/resources/coreGroupObject.xml | 16 ++ .../src/main/resources/coreIntake.xml | 16 ++ .../src/main/resources/coreLoanIn.xml | 16 ++ .../src/main/resources/coreLoanOut.xml | 16 ++ .../src/main/resources/coreObjectExit.xml | 16 ++ .../src/main/resources/object_valuation.xml | 16 ++ .../main/resources/systematicInventory.xml | 16 ++ .../services/client/ReportClient.java | 79 ++++--- .../services/report/ReportResource.java | 37 +++ .../nuxeo/ReportDocumentModelHandler.java | 77 ++++--- 27 files changed, 791 insertions(+), 200 deletions(-) create mode 100644 services/report/3rdparty/jasper-cs-report/src/main/resources/Acq_List_Basic.xml create mode 100644 services/report/3rdparty/jasper-cs-report/src/main/resources/CC_List_Basic.xml create mode 100644 services/report/3rdparty/jasper-cs-report/src/main/resources/Exhibition_List_Basic.xml create mode 100644 services/report/3rdparty/jasper-cs-report/src/main/resources/Group_List_Basic.xml create mode 100644 services/report/3rdparty/jasper-cs-report/src/main/resources/LoansIn_List_Basic.xml create mode 100644 services/report/3rdparty/jasper-cs-report/src/main/resources/LoansOut_List_Basic.xml create mode 100644 services/report/3rdparty/jasper-cs-report/src/main/resources/acq_basic.xml create mode 100644 services/report/3rdparty/jasper-cs-report/src/main/resources/coreAcquisition.xml create mode 100644 services/report/3rdparty/jasper-cs-report/src/main/resources/coreGroupObject.xml create mode 100644 services/report/3rdparty/jasper-cs-report/src/main/resources/coreIntake.xml create mode 100644 services/report/3rdparty/jasper-cs-report/src/main/resources/coreLoanIn.xml create mode 100644 services/report/3rdparty/jasper-cs-report/src/main/resources/coreLoanOut.xml create mode 100644 services/report/3rdparty/jasper-cs-report/src/main/resources/coreObjectExit.xml create mode 100644 services/report/3rdparty/jasper-cs-report/src/main/resources/object_valuation.xml create mode 100644 services/report/3rdparty/jasper-cs-report/src/main/resources/systematicInventory.xml diff --git a/services/JaxRsServiceProvider/src/main/java/org/collectionspace/services/jaxrs/CSpaceResteasyBootstrap.java b/services/JaxRsServiceProvider/src/main/java/org/collectionspace/services/jaxrs/CSpaceResteasyBootstrap.java index 82244d93e..abc0e7ea1 100644 --- a/services/JaxRsServiceProvider/src/main/java/org/collectionspace/services/jaxrs/CSpaceResteasyBootstrap.java +++ b/services/JaxRsServiceProvider/src/main/java/org/collectionspace/services/jaxrs/CSpaceResteasyBootstrap.java @@ -3,23 +3,32 @@ package org.collectionspace.services.jaxrs; import static org.nuxeo.elasticsearch.ElasticSearchConstants.ES_ENABLED_PROPERTY; import javax.servlet.ServletContextEvent; +import javax.ws.rs.core.PathSegment; import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; import org.jboss.resteasy.core.Dispatcher; import org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap; - +import org.jboss.resteasy.specimpl.PathSegmentImpl; +import org.collectionspace.authentication.AuthN; import org.collectionspace.authentication.CSpaceTenant; import org.collectionspace.services.account.Tenant; import org.collectionspace.services.account.TenantResource; import org.collectionspace.services.authorization.AuthZ; +import org.collectionspace.services.client.AbstractCommonListUtils; import org.collectionspace.services.client.AuthorityClient; - +import org.collectionspace.services.client.CollectionSpaceClient; +import org.collectionspace.services.client.PayloadOutputPart; +import org.collectionspace.services.client.PoxPayloadOut; +import org.collectionspace.services.client.ReportClient; +import org.collectionspace.services.client.workflow.WorkflowClient; import org.collectionspace.services.common.CSWebApplicationException; import org.collectionspace.services.common.ResourceMap; import org.collectionspace.services.common.ServiceMain; import org.collectionspace.services.common.api.RefName; import org.collectionspace.services.common.config.ConfigUtils; import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl; +import org.collectionspace.services.common.query.UriInfoImpl; import org.collectionspace.services.common.vocabulary.AuthorityResource; import org.collectionspace.services.config.service.AuthorityInstanceType; @@ -28,51 +37,73 @@ import org.collectionspace.services.config.service.ServiceBindingType.AuthorityI import org.collectionspace.services.config.service.Term; import org.collectionspace.services.config.service.TermList; import org.collectionspace.services.config.tenant.TenantBindingType; +import org.collectionspace.services.config.types.PropertyItemType; +import org.collectionspace.services.config.types.PropertyType; +import org.collectionspace.services.jaxb.AbstractCommonList; +import org.collectionspace.services.jaxb.AbstractCommonList.ListItem; import org.collectionspace.services.nuxeo.util.NuxeoUtils; - +import org.collectionspace.services.report.ReportResource; import org.nuxeo.elasticsearch.ElasticSearchComponent; import org.nuxeo.elasticsearch.api.ElasticSearchService; import org.nuxeo.runtime.api.Framework; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.File; import java.lang.reflect.Constructor; -import java.util.Date; +import java.net.URI; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.util.Arrays; +import java.util.HashSet; import java.util.Hashtable; import java.util.List; -import java.util.logging.Level; +import java.util.Set; public class CSpaceResteasyBootstrap extends ResteasyBootstrap { + private static final Logger logger = LoggerFactory.getLogger(CSpaceResteasyBootstrap.class); - java.util.logging.Logger logger = java.util.logging.Logger.getAnonymousLogger(); - static final String RESET_AUTHORITIES_PROPERTY = "org.collectionspace.services.authorities.reset"; + private static final String RESET_AUTHORITIES_PROPERTY = "org.collectionspace.services.authorities.reset"; private static final String RESET_ELASTICSEARCH_INDEX_PROPERTY = "org.collectionspace.services.elasticsearch.reset"; + private static final String RESET_REPORTS_PROPERTY = "org.collectionspace.services.reports.reset"; private static final String QUICK_BOOT_PROPERTY = "org.collectionspace.services.quickboot"; + private static final String REPORT_PROPERTY = "report"; @Override - public void contextInitialized(ServletContextEvent event) { + public void contextInitialized(ServletContextEvent event) { try { // - // This call to super instantiates and initializes our JAX-RS application class. - // The application class is org.collectionspace.services.jaxrs.CollectionSpaceJaxRsApplication. - // - logger.log(Level.INFO, String.format("%tc [INFO] Starting up the CollectionSpace Services' JAX-RS application.", new Date())); + // This call to super instantiates and initializes our JAX-RS application class. + // The application class is org.collectionspace.services.jaxrs.CollectionSpaceJaxRsApplication. + // + logger.info("Starting up the CollectionSpace Services JAX-RS application."); super.contextInitialized(event); CollectionSpaceJaxRsApplication app = (CollectionSpaceJaxRsApplication)deployment.getApplication(); Dispatcher disp = deployment.getDispatcher(); disp.getDefaultContextObjects().put(ResourceMap.class, app.getResourceMap()); - String quickBoot = System.getProperty(QUICK_BOOT_PROPERTY, Boolean.FALSE.toString()); // Property can be set in the tomcat/bin/setenv.sh (or setenv.bat) file + // Property can be set in the tomcat/bin/setenv.sh (or setenv.bat) file + String quickBoot = System.getProperty(QUICK_BOOT_PROPERTY, Boolean.FALSE.toString()); + if (Boolean.valueOf(quickBoot) == false) { - String resetAuthsString = System.getProperty(RESET_AUTHORITIES_PROPERTY, Boolean.FALSE.toString()); // Property can be set in the tomcat/bin/setenv.sh (or setenv.bat) file - initializeAuthorities(app.getResourceMap(), Boolean.valueOf(resetAuthsString)); + // The below properties can be set in the tomcat/bin/setenv.sh (or setenv.bat) file. + String resetAuthsString = System.getProperty(RESET_AUTHORITIES_PROPERTY, Boolean.FALSE.toString()); + String resetElasticsearchIndexString = System.getProperty(RESET_ELASTICSEARCH_INDEX_PROPERTY, Boolean.FALSE.toString()); + String resetReportsString = System.getProperty(RESET_REPORTS_PROPERTY, Boolean.TRUE.toString()); - String resetElasticsearchIndexString = System.getProperty(RESET_ELASTICSEARCH_INDEX_PROPERTY, Boolean.FALSE.toString()); // Property can be set in the tomcat/bin/setenv.sh (or setenv.bat) file + initializeAuthorities(app.getResourceMap(), Boolean.valueOf(resetAuthsString)); if (Boolean.valueOf(resetElasticsearchIndexString) == true) { resetElasticSearchIndex(); } + + if (Boolean.valueOf(resetReportsString) == true) { + resetReports(); + } } - logger.log(Level.INFO, String.format("%tc [INFO] CollectionSpace Services' JAX-RS application started.", new Date())); + logger.info("CollectionSpace Services JAX-RS application started."); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); @@ -82,9 +113,125 @@ public class CSpaceResteasyBootstrap extends ResteasyBootstrap { @Override public void contextDestroyed(ServletContextEvent event) { - logger.log(Level.INFO, "[INFO] Shutting down the CollectionSpace Services' JAX-RS application."); + logger.info("Shutting down the CollectionSpace Services JAX-RS application."); //Do something if needed. - logger.log(Level.INFO, "[INFO] CollectionSpace Services' JAX-RS application stopped."); + logger.info("CollectionSpace Services JAX-RS application stopped."); + } + + public void resetReports() throws Exception { + logger.info("Resetting reports"); + + TenantBindingConfigReaderImpl tenantBindingConfigReader = ServiceMain.getInstance().getTenantBindingConfigReader(); + Hashtable tenantBindingsTable = tenantBindingConfigReader.getTenantBindings(false); + + for (TenantBindingType tenantBinding : tenantBindingsTable.values()) { + ServiceBindingType reportServiceBinding = null; + + for (ServiceBindingType serviceBinding : tenantBinding.getServiceBindings()) { + if (serviceBinding.getName().toLowerCase().trim().equals(ReportClient.SERVICE_NAME)) { + reportServiceBinding = serviceBinding; + + break; + } + } + + Set reportNames = new HashSet(); + + if (reportServiceBinding != null) { + for (PropertyType property : reportServiceBinding.getProperties()) { + for (PropertyItemType item : property.getItem()) { + if (item.getKey().equals(REPORT_PROPERTY)) { + reportNames.add(item.getValue()); + } + } + } + } + + if (reportNames.size() > 0) { + CSpaceTenant tenant = new CSpaceTenant(tenantBinding.getId(), tenantBinding.getName()); + + resetTenantReports(tenant, reportNames); + } + } + } + + private void resetTenantReports(CSpaceTenant tenant, Set reportNames) throws Exception { + logger.info("Resetting reports for tenant {}", tenant.getId()); + + AuthZ.get().login(tenant); + + CollectionSpaceJaxRsApplication app = (CollectionSpaceJaxRsApplication) deployment.getApplication(); + ResourceMap resourceMap = app.getResourceMap(); + ReportResource reportResource = (ReportResource) resourceMap.get(ReportClient.SERVICE_NAME); + + for (String reportName : reportNames) { + File reportMetadataFile = ReportResource.getReportMetadataFile(reportName); + + if (!reportMetadataFile.exists()) { + logger.warn( + "Metadata file not found for report {} at {}", + reportName, reportMetadataFile.getAbsolutePath()); + + continue; + } + + String payload = new String(Files.readAllBytes(reportMetadataFile.toPath())); + String reportFilename = reportName + ".jrxml"; + + UriInfo uriInfo = new UriInfoImpl( + new URI(""), + new URI(""), + "", + "pgSz=0&filename=" + URLEncoder.encode(reportFilename, StandardCharsets.UTF_8.toString()), + Arrays.asList((PathSegment) new PathSegmentImpl("", false)) + ); + + AbstractCommonList list = reportResource.getList(uriInfo); + + if (list.getTotalItems() == 0) { + logger.info("Adding report " + reportName); + + try { + reportResource.create(resourceMap, null, payload); + } catch(Exception e) { + logger.error(e.getMessage(), e); + } + } else { + for (ListItem item : list.getListItem()) { + String csid = AbstractCommonListUtils.ListItemGetCSID(item); + + // Update an existing report iff: + // - it was created autmatically (i.e., by the SPRING_ADMIN user) + // - it was last updated automatically (i.e., by the SPRING_ADMIN user) + // - it is not soft-deleted + + PoxPayloadOut reportPayload = reportResource.getResourceFromCsid(null, null, csid); + PayloadOutputPart corePart = reportPayload.getPart(CollectionSpaceClient.COLLECTIONSPACE_CORE_SCHEMA); + + String createdBy = corePart.asElement().selectSingleNode(CollectionSpaceClient.COLLECTIONSPACE_CORE_CREATED_BY).getText(); + String updatedBy = corePart.asElement().selectSingleNode(CollectionSpaceClient.COLLECTIONSPACE_CORE_UPDATED_BY).getText(); + String workflowState = corePart.asElement().selectSingleNode(CollectionSpaceClient.COLLECTIONSPACE_CORE_WORKFLOWSTATE).getText(); + + if ( + createdBy.equals(AuthN.SPRING_ADMIN_USER) + && updatedBy.equals(AuthN.SPRING_ADMIN_USER) + && !workflowState.equals(WorkflowClient.WORKFLOWSTATE_DELETED) + ) { + logger.info("Updating report {} with csid {}", reportName, csid); + + try { + reportResource.update(resourceMap, null, csid, payload); + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + } else { + logger.info( + "Not updating report {} with csid {} - it was not auto-created, or was updated or soft-deleted", + reportName, csid); + } + } + } + } } public void resetElasticSearchIndex() throws Exception { @@ -97,7 +244,7 @@ public class CSpaceResteasyBootstrap extends ResteasyBootstrap { ElasticSearchComponent es = (ElasticSearchComponent) Framework.getService(ElasticSearchService.class); for (String repositoryName : es.getRepositoryNames()) { - logger.log(Level.INFO, String.format("%tc [INFO] Rebuilding Elasticsearch index for repository %s", new Date(), repositoryName)); + logger.info("Rebuilding Elasticsearch index for repository {}", repositoryName); es.dropAndInitRepositoryIndex(repositoryName); } @@ -118,7 +265,7 @@ public class CSpaceResteasyBootstrap extends ResteasyBootstrap { String repositoryName = ConfigUtils.getRepositoryName(tenantBinding, servicesRepoDomainName); String docType = NuxeoUtils.getTenantQualifiedDocType(tenantBinding.getId(), serviceBinding.getObject().getName()); - logger.log(Level.INFO, String.format("%tc [INFO] Starting Elasticsearch reindexing for docType %s in repository %s", new Date(), docType, repositoryName)); + logger.info("Starting Elasticsearch reindexing for docType {} in repository {}", docType, repositoryName); es.runReindexingWorker(repositoryName, String.format("SELECT ecm:uuid FROM %s", docType)); } @@ -137,8 +284,7 @@ public class CSpaceResteasyBootstrap extends ResteasyBootstrap { for (TenantBindingType tenantBindings : tenantBindingsTable.values()) { CSpaceTenant tenant = new CSpaceTenant(tenantBindings.getId(), tenantBindings.getName()); if (shouldInitializeAuthorities(tenant, reset) == true) { - logger.log(Level.INFO, String.format("Initializing vocabularies and authorities of tenant '%s'.", - tenant.getId())); + logger.info("Initializing vocabularies and authorities of tenant '{}'.", tenant.getId()); for (ServiceBindingType serviceBinding : tenantBindings.getServiceBindings()) { AuthorityInstanceList element = serviceBinding.getAuthorityInstanceList(); if (element != null && element.getAuthorityInstance() != null) { @@ -147,7 +293,7 @@ public class CSpaceResteasyBootstrap extends ResteasyBootstrap { try { initializeAuthorityInstance(resourceMap, authorityInstance, serviceBinding, tenant, reset); } catch (Exception e) { - logger.log(Level.SEVERE, "Could not initialize authorities and authority terms: " + e.getMessage()); + logger.error("Could not initialize authorities and authority terms: " + e.getMessage()); throw e; } } @@ -234,14 +380,14 @@ public class CSpaceResteasyBootstrap extends ResteasyBootstrap { } if (status == Response.Status.OK.getStatusCode()) { - logger.log(Level.FINE, String.format("Authority of type '%s' with the short ID of '%s' existed already.", - serviceName, authorityInstance.getTitleRef())); + logger.debug("Authority of type '{}' with the short ID of '{}' existed already.", + serviceName, authorityInstance.getTitleRef()); } else if (status == Response.Status.CREATED.getStatusCode()) { - logger.log(Level.FINE, String.format("Created a new authority of type '%s' with the short ID of '%s'.", - serviceName, authorityInstance.getTitleRef())); + logger.debug("Created a new authority of type '{}' with the short ID of '{}'.", + serviceName, authorityInstance.getTitleRef()); } else { - logger.log(Level.WARNING, String.format("Unknown status '%d' encountered when creating or fetching authority of type '%s' with the short ID of '%s'.", - serviceName, authorityInstance.getTitleRef())); + logger.warn("Unknown status '{}' encountered when creating or fetching authority of type '{}' with the short ID of '{}'.", + status, serviceName, authorityInstance.getTitleRef()); } // @@ -289,8 +435,8 @@ public class CSpaceResteasyBootstrap extends ResteasyBootstrap { String xmlPayload = client.createAuthorityItemInstance(termShortId, termDisplayName); try { authorityResource.createAuthorityItem(resourceMap, null, authoritySpecifier, xmlPayload); - logger.log(Level.FINE, String.format("Tenant:%s:Created a new term '%s:%s' in the authority of type '%s' with the short ID of '%s'.", - tenant.getName(), termDisplayName, termShortId, serviceName, authorityInstance.getTitleRef())); + logger.debug("Tenant:{}:Created a new term '{}:{}' in the authority of type '{}' with the short ID of '{}'.", + tenant.getName(), termDisplayName, termShortId, serviceName, authorityInstance.getTitleRef()); } catch (CSWebApplicationException e) { response = e.getResponse(); status = response.getStatus(); diff --git a/services/batch/service/src/main/java/org/collectionspace/services/batch/BatchResource.java b/services/batch/service/src/main/java/org/collectionspace/services/batch/BatchResource.java index ff98d3694..503d62d52 100644 --- a/services/batch/service/src/main/java/org/collectionspace/services/batch/BatchResource.java +++ b/services/batch/service/src/main/java/org/collectionspace/services/batch/BatchResource.java @@ -96,6 +96,7 @@ public class BatchResource extends NuxeoBasedResource { MultivaluedMap queryParams = ctx.getQueryParams(); DocumentHandler handler = createDocumentHandler(ctx); String docType = queryParams.getFirst(IQueryManager.SEARCH_TYPE_DOCTYPE); + String filename = queryParams.getFirst(IQueryManager.SEARCH_TYPE_FILENAME); List modes = queryParams.get(IQueryManager.SEARCH_TYPE_INVOCATION_MODE); String whereClause = null; DocumentFilter documentFilter = null; @@ -108,6 +109,13 @@ public class BatchResource extends NuxeoBasedResource { documentFilter.appendWhereClause(whereClause, IQueryManager.SEARCH_QUALIFIER_AND); } + if (filename != null && !filename.isEmpty()) { + whereClause = QueryManager.createWhereClauseForInvocableByFilename( + common_part, filename); + documentFilter = handler.getDocumentFilter(); + documentFilter.appendWhereClause(whereClause, IQueryManager.SEARCH_QUALIFIER_AND); + } + if (modes != null && !modes.isEmpty()) { whereClause = QueryManager.createWhereClauseForInvocableByMode( common_part, modes); diff --git a/services/client/src/main/java/org/collectionspace/services/client/IQueryManager.java b/services/client/src/main/java/org/collectionspace/services/client/IQueryManager.java index f287539c4..3c23228e4 100644 --- a/services/client/src/main/java/org/collectionspace/services/client/IQueryManager.java +++ b/services/client/src/main/java/org/collectionspace/services/client/IQueryManager.java @@ -35,17 +35,18 @@ public interface IQueryManager { final static String SEARCH_TERM_SEPARATOR = " "; final static String SEARCH_LIKE = " LIKE "; final static String SEARCH_ILIKE = " ILIKE "; - final static String SEARCH_TYPE_KEYWORDS = "keywords"; - final static String SEARCH_TYPE_KEYWORDS_KW = "kw"; - final static String SEARCH_TYPE_KEYWORDS_AS = "as"; - final static String SEARCH_TYPE_PARTIALTERM = "pt"; - final static String SEARCH_TYPE_DOCTYPE = "doctype"; - final static String SEARCH_TYPE_INVOCATION_MODE = "mode"; - final static String SEARCH_TYPE_INVOCATION = "inv"; + final static String SEARCH_TYPE_KEYWORDS = "keywords"; + final static String SEARCH_TYPE_KEYWORDS_KW = "kw"; + final static String SEARCH_TYPE_KEYWORDS_AS = "as"; + final static String SEARCH_TYPE_PARTIALTERM = "pt"; + final static String SEARCH_TYPE_DOCTYPE = "doctype"; + final static String SEARCH_TYPE_FILENAME = "filename"; + final static String SEARCH_TYPE_INVOCATION_MODE = "mode"; + final static String SEARCH_TYPE_INVOCATION = "inv"; final static String SEARCH_QUALIFIER_AND = SEARCH_TERM_SEPARATOR + "AND" + SEARCH_TERM_SEPARATOR; final static String SEARCH_QUALIFIER_OR = SEARCH_TERM_SEPARATOR + "OR" + SEARCH_TERM_SEPARATOR; - final static String DEFAULT_SELECT_CLAUSE = "SELECT * FROM "; - final static String CSID_QUERY_PARAM = "csid"; + final static String DEFAULT_SELECT_CLAUSE = "SELECT * FROM "; + final static String CSID_QUERY_PARAM = "csid"; // @@ -161,6 +162,16 @@ public interface IQueryManager { */ public String createWhereClauseForInvocableByDocType(String schema, String docType); + + /** + * Creates a filtering where clause from filename, for invocables. + * + * @param schema the schema name for this invocable + * @param docType the filename + * @return the where clause + */ + public String createWhereClauseForInvocableByFilename(String schema, String filename); + /** * Creates a filtering where clause from invocation mode, for invocables. * 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 5d29790e8..8071b4936 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 @@ -1,13 +1,25 @@ + xmlns:merge="http://xmlmerge.el4j.elca.ch" + xmlns:tenant="http://collectionspace.org/services/config/tenant"> - - - + + + - - + + + + + report + obj_current_place_details + + + report + tombstone_with_budget + + + + 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 7c33d2cfc..19bf9dc3a 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 @@ -528,61 +528,158 @@ org.collectionspace.services.report.nuxeo.ReportPostInitHandler - - readerRoleName - reader - + + readerRoleName + reader + - - - outputMIME - XML - application/xml - - - outputMIME - HTML - text/html - - - outputMIME - PDF - application/pdf - - - outputMIME - text/csv - - - outputMIME - text/tab-separated-values - - - outputMIME - application/msword - - - outputMIME - application/vnd.openxmlformats-officedocument.wordprocessingml.document - - - outputMIME - application/vnd.ms-excel - - - outputMIME - application/vnd.openxmlformats-officedocument.spreadsheetml.sheet - - - outputMIME - application/vnd.ms-powerpoint - - - outputMIME - application/vnd.openxmlformats-officedocument.presentationml.presentation - - + + + outputMIME + XML + application/xml + + + outputMIME + HTML + text/html + + + outputMIME + PDF + application/pdf + + + outputMIME + text/csv + + + outputMIME + text/tab-separated-values + + + outputMIME + application/msword + + + outputMIME + application/vnd.openxmlformats-officedocument.wordprocessingml.document + + + outputMIME + application/vnd.ms-excel + + + outputMIME + application/vnd.openxmlformats-officedocument.spreadsheetml.sheet + + + outputMIME + application/vnd.ms-powerpoint + + + outputMIME + application/vnd.openxmlformats-officedocument.presentationml.presentation + + + + report + accessions + + + report + acq_basic + + + report + Acq_List_Basic + + + report + box_list + + + report + CC_List_Basic + + + report + coreAcquisition + + + report + coreGroupObject + + + report + coreIntake + + + report + coreLoanIn + + + report + coreLoanOut + + + report + coreObjectExit + + + report + deaccessions + + + report + deed_of_gift + + + report + Exhibition_List_Basic + + + report + Group_List_Basic + + + report + incoming_loan + + + report + incoming_loan_letter + + + report + LoansIn_List_Basic + + + report + LoansOut_List_Basic + + + report + obj_computed_location + + + report + object_valuation + + + report + outgoing_loan_letter + + + report + referral + + + report + systematicInventory + + - + @@ -108,38 +108,38 @@ - - + description="Deploy report files and metadata files"> + includes="*.jrxml,*.xml"/> - + - + + description="Undeploy source (.jrxml) report files and metadata (.xml) files"> - + - + @@ -150,7 +150,7 @@ diff --git a/services/report/3rdparty/jasper-cs-report/src/main/resources/Acq_List_Basic.xml b/services/report/3rdparty/jasper-cs-report/src/main/resources/Acq_List_Basic.xml new file mode 100644 index 000000000..d7d92acfe --- /dev/null +++ b/services/report/3rdparty/jasper-cs-report/src/main/resources/Acq_List_Basic.xml @@ -0,0 +1,16 @@ + + + + Acquisition Basic List + Catalog info for objects related to an acquisition record. Runs on a single record only. + + Acquisition + + true + false + false + false + application/pdf + Acq_List_Basic.jrxml + + diff --git a/services/report/3rdparty/jasper-cs-report/src/main/resources/CC_List_Basic.xml b/services/report/3rdparty/jasper-cs-report/src/main/resources/CC_List_Basic.xml new file mode 100644 index 000000000..2d505a82d --- /dev/null +++ b/services/report/3rdparty/jasper-cs-report/src/main/resources/CC_List_Basic.xml @@ -0,0 +1,16 @@ + + + + Condition Check Basic List + Catalog info for objects related to a condition check record. Runs on a single record only. + + Conditioncheck + + true + false + false + false + application/pdf + CC_List_Basic.jrxml + + diff --git a/services/report/3rdparty/jasper-cs-report/src/main/resources/Exhibition_List_Basic.xml b/services/report/3rdparty/jasper-cs-report/src/main/resources/Exhibition_List_Basic.xml new file mode 100644 index 000000000..33fd5576e --- /dev/null +++ b/services/report/3rdparty/jasper-cs-report/src/main/resources/Exhibition_List_Basic.xml @@ -0,0 +1,16 @@ + + + + Exhibition Basic List + Catalog info for objects related to a exhibition record. Runs on a single record only. + + Exhibition + + true + false + false + false + application/pdf + Exhibition_List_Basic.jrxml + + diff --git a/services/report/3rdparty/jasper-cs-report/src/main/resources/Group_List_Basic.xml b/services/report/3rdparty/jasper-cs-report/src/main/resources/Group_List_Basic.xml new file mode 100644 index 000000000..1a480675b --- /dev/null +++ b/services/report/3rdparty/jasper-cs-report/src/main/resources/Group_List_Basic.xml @@ -0,0 +1,16 @@ + + + + Group Basic List + Catalog info for objects related to a group record. Runs on a group of objects, a single object, or selected objects. + + CollectionObject + + true + true + true + false + application/pdf + Group_List_Basic.jrxml + + diff --git a/services/report/3rdparty/jasper-cs-report/src/main/resources/LoansIn_List_Basic.xml b/services/report/3rdparty/jasper-cs-report/src/main/resources/LoansIn_List_Basic.xml new file mode 100644 index 000000000..a6f488590 --- /dev/null +++ b/services/report/3rdparty/jasper-cs-report/src/main/resources/LoansIn_List_Basic.xml @@ -0,0 +1,16 @@ + + + + Loan In Basic List + Catalog info for objects related to a loan in record. Runs on a single record only. + + Loanin + + true + false + false + false + application/pdf + LoansIn_List_Basic.jrxml + + diff --git a/services/report/3rdparty/jasper-cs-report/src/main/resources/LoansOut_List_Basic.xml b/services/report/3rdparty/jasper-cs-report/src/main/resources/LoansOut_List_Basic.xml new file mode 100644 index 000000000..6f1c66110 --- /dev/null +++ b/services/report/3rdparty/jasper-cs-report/src/main/resources/LoansOut_List_Basic.xml @@ -0,0 +1,16 @@ + + + + Loan Out Basic List + Catalog info for objects related to a loan out record. Runs on a single record only. + + Loanout + + true + false + false + false + application/pdf + LoansOut_List_Basic.jrxml + + diff --git a/services/report/3rdparty/jasper-cs-report/src/main/resources/acq_basic.xml b/services/report/3rdparty/jasper-cs-report/src/main/resources/acq_basic.xml new file mode 100644 index 000000000..0af836cb4 --- /dev/null +++ b/services/report/3rdparty/jasper-cs-report/src/main/resources/acq_basic.xml @@ -0,0 +1,16 @@ + + + + Acquisition Summary + An acquisition summary report. Runs on a single record only. + + Acquisition + + true + false + false + false + application/pdf + acq_basic.jrxml + + diff --git a/services/report/3rdparty/jasper-cs-report/src/main/resources/coreAcquisition.xml b/services/report/3rdparty/jasper-cs-report/src/main/resources/coreAcquisition.xml new file mode 100644 index 000000000..04e6cad85 --- /dev/null +++ b/services/report/3rdparty/jasper-cs-report/src/main/resources/coreAcquisition.xml @@ -0,0 +1,16 @@ + + + + Acquisition Ethnographic Object List + Core acquisition report. Runs on a single record only. + + Acquisition + + true + false + false + false + application/pdf + coreAcquisition.jrxml + + diff --git a/services/report/3rdparty/jasper-cs-report/src/main/resources/coreGroupObject.xml b/services/report/3rdparty/jasper-cs-report/src/main/resources/coreGroupObject.xml new file mode 100644 index 000000000..aff1b7425 --- /dev/null +++ b/services/report/3rdparty/jasper-cs-report/src/main/resources/coreGroupObject.xml @@ -0,0 +1,16 @@ + + + + Group Object Ethnographic Object List + Core group object report. Runs on a single record only. + + Group + + true + false + false + false + application/pdf + coreGroupObject.jrxml + + diff --git a/services/report/3rdparty/jasper-cs-report/src/main/resources/coreIntake.xml b/services/report/3rdparty/jasper-cs-report/src/main/resources/coreIntake.xml new file mode 100644 index 000000000..f81674f3e --- /dev/null +++ b/services/report/3rdparty/jasper-cs-report/src/main/resources/coreIntake.xml @@ -0,0 +1,16 @@ + + + + Intake Ethnographic Object List + Core intake report. Runs on a single record only. + + Intake + + true + false + false + false + application/pdf + coreIntake.jrxml + + diff --git a/services/report/3rdparty/jasper-cs-report/src/main/resources/coreLoanIn.xml b/services/report/3rdparty/jasper-cs-report/src/main/resources/coreLoanIn.xml new file mode 100644 index 000000000..39c917386 --- /dev/null +++ b/services/report/3rdparty/jasper-cs-report/src/main/resources/coreLoanIn.xml @@ -0,0 +1,16 @@ + + + + Loan In Ethnographic Object List + Core loan in report. Runs on a single record only. + + Loanin + + true + false + false + false + application/pdf + coreLoanIn.jrxml + + diff --git a/services/report/3rdparty/jasper-cs-report/src/main/resources/coreLoanOut.xml b/services/report/3rdparty/jasper-cs-report/src/main/resources/coreLoanOut.xml new file mode 100644 index 000000000..5567a43e0 --- /dev/null +++ b/services/report/3rdparty/jasper-cs-report/src/main/resources/coreLoanOut.xml @@ -0,0 +1,16 @@ + + + + Loan Out Ethnographic Object List + Core loan out report. Runs on a single record only. + + Loanout + + true + false + false + false + application/pdf + coreLoanOut.jrxml + + diff --git a/services/report/3rdparty/jasper-cs-report/src/main/resources/coreObjectExit.xml b/services/report/3rdparty/jasper-cs-report/src/main/resources/coreObjectExit.xml new file mode 100644 index 000000000..56e381279 --- /dev/null +++ b/services/report/3rdparty/jasper-cs-report/src/main/resources/coreObjectExit.xml @@ -0,0 +1,16 @@ + + + + Object Exit Ethnographic Object List + Core object exit report. Runs on a single record only. + + ObjectExit + + true + false + false + false + application/pdf + coreObjectExit.jrxml + + diff --git a/services/report/3rdparty/jasper-cs-report/src/main/resources/object_valuation.xml b/services/report/3rdparty/jasper-cs-report/src/main/resources/object_valuation.xml new file mode 100644 index 000000000..8d59920d0 --- /dev/null +++ b/services/report/3rdparty/jasper-cs-report/src/main/resources/object_valuation.xml @@ -0,0 +1,16 @@ + + + + Object Valuation + Returns latest valuation information for selected objects. Runs on selected objects, or all objects. + + CollectionObject + + false + true + false + true + application/vnd.openxmlformats-officedocument.spreadsheetml.sheet + object_valuation.jrxml + + diff --git a/services/report/3rdparty/jasper-cs-report/src/main/resources/systematicInventory.xml b/services/report/3rdparty/jasper-cs-report/src/main/resources/systematicInventory.xml new file mode 100644 index 000000000..ea5b90e22 --- /dev/null +++ b/services/report/3rdparty/jasper-cs-report/src/main/resources/systematicInventory.xml @@ -0,0 +1,16 @@ + + + + Systematic Inventory + Generate a checklist for performing an inventory on a range of storage locations. Runs on all records, using the provided start and end locations. + + Locationitem + + false + false + false + true + application/pdf + systematicInventory.jrxml + + diff --git a/services/report/client/src/main/java/org/collectionspace/services/client/ReportClient.java b/services/report/client/src/main/java/org/collectionspace/services/client/ReportClient.java index 9062e150e..4434075bc 100644 --- a/services/report/client/src/main/java/org/collectionspace/services/client/ReportClient.java +++ b/services/report/client/src/main/java/org/collectionspace/services/client/ReportClient.java @@ -1,4 +1,4 @@ -/** +/** * ReportClient.java * * {Purpose of This Class} @@ -38,63 +38,60 @@ import org.collectionspace.services.report.ReportsCommon; * FIXME: http://issues.collectionspace.org/browse/CSPACE-1684 */ public class ReportClient extends AbstractCommonListPoxServiceClientImpl { - - public static final String SERVICE_NAME = "reports"; - public static final String SERVICE_PATH_COMPONENT = SERVICE_NAME; - public static final String SERVICE_PATH = "/" + SERVICE_PATH_COMPONENT; + public static final String SERVICE_NAME = "reports"; + public static final String SERVICE_PATH_COMPONENT = SERVICE_NAME; + public static final String SERVICE_PATH = "/" + SERVICE_PATH_COMPONENT; public static final String SERVICE_COMMON_PART_NAME = SERVICE_NAME + PART_LABEL_SEPARATOR + PART_COMMON_LABEL; - public static final String PDF_MIME_TYPE = "application/pdf"; - public static final String CSV_MIME_TYPE = "text/csv"; - public static final String TSV_MIME_TYPE = "text/tab-separated-values"; - public static final String MSWORD_MIME_TYPE = "application/msword"; - public static final String OPEN_DOCX_MIME_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"; - public static final String MSEXCEL_MIME_TYPE = "application/vnd.ms-excel"; - public static final String OPEN_XLSX_MIME_TYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; - public static final String MSPPT_MIME_TYPE = "application/vnd.ms-powerpoint"; - public static final String OPEN_PPTX_MIME_TYPE = "application/vnd.openxmlformats-officedocument.presentationml.presentation"; - public static final String DEFAULT_REPORT_OUTPUT_MIME = PDF_MIME_TYPE; - public static final String COMPILED_REPORT_EXTENSION = ".jasper"; - public static final String REPORT_DECSRIPTION_EXTENSION = ".jrxml"; + public static final String PDF_MIME_TYPE = "application/pdf"; + public static final String CSV_MIME_TYPE = "text/csv"; + public static final String TSV_MIME_TYPE = "text/tab-separated-values"; + public static final String MSWORD_MIME_TYPE = "application/msword"; + public static final String OPEN_DOCX_MIME_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"; + public static final String MSEXCEL_MIME_TYPE = "application/vnd.ms-excel"; + public static final String OPEN_XLSX_MIME_TYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; + public static final String MSPPT_MIME_TYPE = "application/vnd.ms-powerpoint"; + public static final String OPEN_PPTX_MIME_TYPE = "application/vnd.openxmlformats-officedocument.presentationml.presentation"; + public static final String DEFAULT_REPORT_OUTPUT_MIME = PDF_MIME_TYPE; + public static final String COMPILED_REPORT_EXTENSION = ".jasper"; + public static final String REPORT_DECSRIPTION_EXTENSION = ".jrxml"; + public static final String REPORT_METADATA_EXTENSION = ".xml"; - public ReportClient() throws Exception { + public ReportClient() throws Exception { super(); } - public ReportClient(String clientPropertiesFilename) throws Exception { + public ReportClient(String clientPropertiesFilename) throws Exception { super(clientPropertiesFilename); } @Override - public String getServiceName() { - return SERVICE_NAME; - } + public String getServiceName() { + return SERVICE_NAME; + } - @Override + @Override public String getServicePathComponent() { - return SERVICE_PATH_COMPONENT; - } + return SERVICE_PATH_COMPONENT; + } @Override public Class getProxyClass() { return ReportProxy.class; } - + /* * Proxied service calls */ - - /** - * @return - * @see org.collectionspace.services.client.ReportProxy#getReport() - */ - public Response readListFiltered( - String docType, String mode) { - return getProxy().readListFiltered(docType, mode); - } - - public Response publishReport(String csid, - InvocationContext invContext) { - return getProxy().publishReport(csid, invContext); - } - + + /** + * @return + * @see org.collectionspace.services.client.ReportProxy#getReport() + */ + public Response readListFiltered(String docType, String mode) { + return getProxy().readListFiltered(docType, mode); + } + + public Response publishReport(String csid, InvocationContext invContext) { + return getProxy().publishReport(csid, invContext); + } } diff --git a/services/report/service/src/main/java/org/collectionspace/services/report/ReportResource.java b/services/report/service/src/main/java/org/collectionspace/services/report/ReportResource.java index 74b2cde66..2092608dd 100644 --- a/services/report/service/src/main/java/org/collectionspace/services/report/ReportResource.java +++ b/services/report/service/src/main/java/org/collectionspace/services/report/ReportResource.java @@ -23,6 +23,7 @@ */ package org.collectionspace.services.report; +import java.io.File; import java.io.InputStream; import java.util.List; @@ -37,7 +38,9 @@ import org.collectionspace.services.client.ReportClient; 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.ServiceMessages; +import org.collectionspace.services.common.api.JEEServerDeployment; import org.collectionspace.services.common.context.ServiceContext; import org.collectionspace.services.common.document.DocumentFilter; import org.collectionspace.services.common.document.DocumentHandler; @@ -68,6 +71,8 @@ import javax.ws.rs.core.Response.Status; public class ReportResource extends NuxeoBasedResource { final Logger logger = LoggerFactory.getLogger(ReportResource.class); + private static String REPORTS_FOLDER = "reports"; + @Override protected String getVersionString() { final String lastChangeRevision = "$LastChangedRevision: 1982 $"; @@ -94,6 +99,7 @@ public class ReportResource extends NuxeoBasedResource { MultivaluedMap queryParams = ctx.getQueryParams(); DocumentHandler handler = createDocumentHandler(ctx); String docType = queryParams.getFirst(IQueryManager.SEARCH_TYPE_DOCTYPE); + String filename = queryParams.getFirst(IQueryManager.SEARCH_TYPE_FILENAME); List modes = queryParams.get(IQueryManager.SEARCH_TYPE_INVOCATION_MODE); String whereClause = null; DocumentFilter documentFilter = null; @@ -104,6 +110,12 @@ public class ReportResource extends NuxeoBasedResource { documentFilter = handler.getDocumentFilter(); documentFilter.appendWhereClause(whereClause, IQueryManager.SEARCH_QUALIFIER_AND); } + if (filename != null && !filename.isEmpty()) { + whereClause = QueryManager.createWhereClauseForInvocableByFilename( + common_part, filename); + documentFilter = handler.getDocumentFilter(); + documentFilter.appendWhereClause(whereClause, IQueryManager.SEARCH_QUALIFIER_AND); + } if (modes != null && !modes.isEmpty()) { whereClause = QueryManager.createWhereClauseForInvocableByMode( common_part, modes); @@ -329,4 +341,29 @@ public class ReportResource extends NuxeoBasedResource { return result; } + private static String getReportBasePath() { + return ( + ServiceMain.getInstance().getServerRootDir() + + File.separator + + JEEServerDeployment.CSPACE_DIR_NAME + + File.separator + + REPORTS_FOLDER + + File.separator + ); + } + + public static File getReportSourceFile(String reportName) { + return new File( + getReportBasePath() + reportName + ReportClient.REPORT_DECSRIPTION_EXTENSION); + } + + public static File getReportCompiledFile(String reportName) { + return new File( + getReportBasePath() + reportName + ReportClient.COMPILED_REPORT_EXTENSION); + } + + public static File getReportMetadataFile(String reportName) { + return new File( + getReportBasePath() + reportName + ReportClient.REPORT_METADATA_EXTENSION); + } } diff --git a/services/report/service/src/main/java/org/collectionspace/services/report/nuxeo/ReportDocumentModelHandler.java b/services/report/service/src/main/java/org/collectionspace/services/report/nuxeo/ReportDocumentModelHandler.java index 867d8d90d..9e8de598a 100644 --- a/services/report/service/src/main/java/org/collectionspace/services/report/nuxeo/ReportDocumentModelHandler.java +++ b/services/report/service/src/main/java/org/collectionspace/services/report/nuxeo/ReportDocumentModelHandler.java @@ -71,6 +71,7 @@ import org.collectionspace.services.report.ResourceActionGroupList; import org.collectionspace.services.report.ReportsCommon.ForRoles; import org.collectionspace.services.report.MIMEType; import org.collectionspace.services.report.MIMETypeItemType; +import org.collectionspace.services.report.ReportResource; import org.collectionspace.services.report.ReportsCommon; import org.collectionspace.services.report.ReportsOuputMimeList; import org.collectionspace.services.client.PoxPayloadIn; @@ -117,7 +118,6 @@ public class ReportDocumentModelHandler extends NuxeoDocumentModelHandler params, String reportFileName, String outputMimeType, StringBuffer outReportFileName) - throws Exception { - Connection conn = null; - InputStream result = null; + private InputStream buildReportResult( + String reportCSID, + HashMap params, + String reportFileName, + String outputMimeType, + StringBuffer outReportFileName + ) throws Exception { + + Connection conn = null; + InputStream result = null; try { - String fileNameBase = Tools.getFilenameBase(reportFileName); - String compiledReportFilename = fileNameBase+ReportClient.COMPILED_REPORT_EXTENSION; - String reportDescriptionFilename = fileNameBase+ReportClient.REPORT_DECSRIPTION_EXTENSION; - - String basePath = ServiceMain.getInstance().getServerRootDir() + - File.separator + JEEServerDeployment.CSPACE_DIR_NAME + - File.separator + REPORTS_FOLDER + - // File.separator + tenantName + - File.separator; // + reportFileName; - - String compiledFilePath = basePath+compiledReportFilename; - File f = new File(compiledFilePath); - if(!f.exists()) { // Need to compile the file - // First verify that there is a source file. - String sourceFilePath = basePath+reportDescriptionFilename; - File f2 = new File(sourceFilePath); - if(!f2.exists()) { // Missing source file - error! - logger.error("Report for csid={} is missing the specified source file: {}", - reportCSID, sourceFilePath); - throw new RuntimeException("Report is missing the specified source file!"); - } + String reportName = Tools.getFilenameBase(reportFileName); + File reportCompiledFile = ReportResource.getReportCompiledFile(reportName); - logger.info("Report for csid={} is not compiled. Compiling first, and saving to: {}", - reportCSID, compiledFilePath); + if (!reportCompiledFile.exists()) { + // Need to compile the file. - JasperDesign design = JRXmlLoader.load(sourceFilePath); + File reportSourceFile = ReportResource.getReportSourceFile(reportName); - design.setScriptletClass("org.collectionspace.services.report.jasperreports.CSpaceReportScriptlet"); + if(!reportSourceFile.exists()) { + logger.error("Report for csid={} is missing source file: {}", + reportCSID, reportSourceFile.getAbsolutePath()); - JasperCompileManager.compileReportToFile(design, compiledFilePath); - } + throw new RuntimeException("Report is missing source file"); + } - conn = getConnection(); + logger.info("Report for csid={} is not compiled. Compiling first, and saving to: {}", + reportCSID, reportCompiledFile.getAbsolutePath()); - if (logger.isTraceEnabled()) { - logger.trace("ReportResource for csid=" + reportCSID - +" output as "+outputMimeType+" using report file: "+compiledFilePath); - } - FileInputStream fileStream = new FileInputStream(compiledFilePath); + JasperDesign design = JRXmlLoader.load(reportSourceFile.getAbsolutePath()); + + design.setScriptletClass("org.collectionspace.services.report.jasperreports.CSpaceReportScriptlet"); + + JasperCompileManager.compileReportToFile(design, reportCompiledFile.getAbsolutePath()); + } + + conn = getConnection(); + + if (logger.isTraceEnabled()) { + logger.trace("ReportResource for csid=" + reportCSID + + " output as " + outputMimeType + " using report file: " + reportCompiledFile.getAbsolutePath()); + } + + FileInputStream fileStream = new FileInputStream(reportCompiledFile); // export report to pdf and build a response with the bytes //JasperExportManager.exportReportToPdf(jasperprint); -- 2.47.3