From 37e26df1d7313b931860cf61bbd4e0c523b45f87 Mon Sep 17 00:00:00 2001 From: Patrick Schmitz Date: Tue, 19 Jul 2011 00:58:21 +0000 Subject: [PATCH] CSPACE-4234, CSPACE-4106 Added support to filter Reports by doctype and invocation mode, and since I was in there, I also fixed the bug with hyphens in search (phrase search is still not right, but at least it reverts to keyword search). --- .../test-data/xmlreplay/xml-replay-master.xml | 1 + .../services/client/IQueryManager.java | 21 ++++ .../common/invocable/InvocableUtils.java | 32 ++++++ .../services/common/query/QueryManager.java | 24 ++++ .../query/nuxeo/QueryManagerNuxeoImpl.java | 54 ++++++++- .../services/client/ReportClient.java | 11 ++ .../services/client/ReportProxy.java | 6 + .../client/test/ReportServiceTest.java | 103 +++++++++++++++++- .../services/report/ReportResource.java | 23 ++++ 9 files changed, 266 insertions(+), 9 deletions(-) create mode 100644 services/common/src/main/java/org/collectionspace/services/common/invocable/InvocableUtils.java diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/xml-replay-master.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/xml-replay-master.xml index 48d1af5f4..d6fb9efac 100755 --- a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/xml-replay-master.xml +++ b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/xml-replay-master.xml @@ -47,6 +47,7 @@ + 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 7775b8363..a117cbe5e 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 @@ -37,6 +37,7 @@ public interface IQueryManager { final static String SEARCH_TYPE_KEYWORDS_KW = "kw"; final static String SEARCH_TYPE_PARTIALTERM = "pt"; final static String SEARCH_TYPE_DOCTYPE = "doctype"; + final static String SEARCH_TYPE_INVCOATION_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; @@ -62,4 +63,24 @@ public interface IQueryManager { */ public String createWhereClauseForPartialMatch(String field, String partialTerm); + /** + * Creates a filtering where clause from docType, for invocables. + * + * @param schema the schema name for this invocable type + * @param docType the docType + * + * @return the string + */ + public String createWhereClauseForInvocableByDocType(String schema, String docType); + + /** + * Creates a filtering where clause from invocation mode, for invocables. + * + * @param schema the schema name for this invocable type + * @param mode the mode + * + * @return the string + */ + public String createWhereClauseForInvocableByMode(String schema, String mode); + } diff --git a/services/common/src/main/java/org/collectionspace/services/common/invocable/InvocableUtils.java b/services/common/src/main/java/org/collectionspace/services/common/invocable/InvocableUtils.java new file mode 100644 index 000000000..3f8d96959 --- /dev/null +++ b/services/common/src/main/java/org/collectionspace/services/common/invocable/InvocableUtils.java @@ -0,0 +1,32 @@ +package org.collectionspace.services.common.invocable; + +import org.collectionspace.services.jaxb.InvocableJAXBSchema; + +public class InvocableUtils { + + /** + * Returns the standard property name for an invocable schema, given + * and invocation mode string. + * @param schema If not null, the returned property name will be qualified with + * this schema name. + * @param invocationMode one of Invocable.INVOCATION_MODE_* + * @return + */ + public static String getPropertyNameForInvocationMode(String schema, String invocationMode) { + String modeProperty = null; + if(Invocable.INVOCATION_MODE_SINGLE.equalsIgnoreCase(invocationMode)) { + modeProperty = InvocableJAXBSchema.SUPPORTS_SINGLE_DOC; + } else if(Invocable.INVOCATION_MODE_LIST.equalsIgnoreCase(invocationMode)) { + modeProperty = InvocableJAXBSchema.SUPPORTS_DOC_LIST; + } else if(Invocable.INVOCATION_MODE_GROUP.equalsIgnoreCase(invocationMode)) { + modeProperty = InvocableJAXBSchema.SUPPORTS_GROUP; + } else if(Invocable.INVOCATION_MODE_NO_CONTEXT.equalsIgnoreCase(invocationMode)) { + modeProperty = InvocableJAXBSchema.SUPPORTS_NO_CONTEXT; + } else { + throw new IllegalArgumentException("QueryManagerNuxeoImpl: unknown Invocation Mode: " + +invocationMode); + } + return (schema!=null)? (schema+":"+modeProperty):modeProperty; + } + +} diff --git a/services/common/src/main/java/org/collectionspace/services/common/query/QueryManager.java b/services/common/src/main/java/org/collectionspace/services/common/query/QueryManager.java index ee76beb48..cf88207f0 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/query/QueryManager.java +++ b/services/common/src/main/java/org/collectionspace/services/common/query/QueryManager.java @@ -59,4 +59,28 @@ public class QueryManager { return queryManager.createWhereClauseForPartialMatch(field, partialTerm); } + /** + * Creates a filtering where clause from docType, for invocables. + * + * @param schema the schema name for this invocable type + * @param docType the docType + * + * @return the string + */ + static public String createWhereClauseForInvocableByDocType(String schema, String docType) { + return queryManager.createWhereClauseForInvocableByDocType(schema, docType); + } + + /** + * Creates a filtering where clause from invocation mode, for invocables. + * + * @param schema the schema name for this invocable type + * @param mode the mode + * + * @return the string + */ + static public String createWhereClauseForInvocableByMode(String schema, String mode) { + return queryManager.createWhereClauseForInvocableByMode(schema, mode); + } + } diff --git a/services/common/src/main/java/org/collectionspace/services/common/query/nuxeo/QueryManagerNuxeoImpl.java b/services/common/src/main/java/org/collectionspace/services/common/query/nuxeo/QueryManagerNuxeoImpl.java index 9d268b0f3..5117e8d90 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/query/nuxeo/QueryManagerNuxeoImpl.java +++ b/services/common/src/main/java/org/collectionspace/services/common/query/nuxeo/QueryManagerNuxeoImpl.java @@ -36,9 +36,11 @@ import org.nuxeo.ecm.core.api.DocumentModelList; import org.nuxeo.ecm.core.api.repository.RepositoryInstance; import org.nuxeo.ecm.core.client.NuxeoClient; +import org.collectionspace.services.jaxb.InvocableJAXBSchema; import org.collectionspace.services.nuxeo.client.java.NuxeoConnector; -import org.collectionspace.services.nuxeo.client.java.RepositoryJavaClientImpl; import org.collectionspace.services.client.IQueryManager; +import org.collectionspace.services.common.invocable.Invocable; +import org.collectionspace.services.common.invocable.InvocableUtils; import org.collectionspace.services.common.storage.DatabaseProductType; import org.collectionspace.services.common.storage.JDBCTools; @@ -55,6 +57,8 @@ public class QueryManagerNuxeoImpl implements IQueryManager { private static Pattern nonWordChars = Pattern.compile("[^\\p{L}\\p{M}\\p{N}_']"); private static Pattern unescapedDblQuotes = Pattern.compile("(? readListFiltered( + String docType, String mode) { + return getProxy().readListFiltered(docType, mode); + } + } diff --git a/services/report/client/src/main/java/org/collectionspace/services/client/ReportProxy.java b/services/report/client/src/main/java/org/collectionspace/services/client/ReportProxy.java index 11a8d1bae..908e78a61 100644 --- a/services/report/client/src/main/java/org/collectionspace/services/client/ReportProxy.java +++ b/services/report/client/src/main/java/org/collectionspace/services/client/ReportProxy.java @@ -54,6 +54,12 @@ public interface ReportProxy extends CollectionSpacePoxProxy @Produces({"application/xml"}) ClientResponse readList(); + @GET + @Produces({"application/xml"}) + ClientResponse readListFiltered( + @QueryParam(IQueryManager.SEARCH_TYPE_DOCTYPE) String docType, + @QueryParam(IQueryManager.SEARCH_TYPE_INVCOATION_MODE) String mode); + @Override @GET @Produces({"application/xml"}) diff --git a/services/report/client/src/test/java/org/collectionspace/services/client/test/ReportServiceTest.java b/services/report/client/src/test/java/org/collectionspace/services/client/test/ReportServiceTest.java index 220a318d3..7f22bd1cd 100644 --- a/services/report/client/src/test/java/org/collectionspace/services/client/test/ReportServiceTest.java +++ b/services/report/client/src/test/java/org/collectionspace/services/client/test/ReportServiceTest.java @@ -62,6 +62,8 @@ public class ReportServiceTest extends AbstractServiceTestImpl { // Instance variables specific to this test. /** The known resource id. */ private String knownResourceId = null; + + private String testDocType = "Acquisition"; /* (non-Javadoc) * @see org.collectionspace.services.client.test.BaseServiceTest#getClientInstance() @@ -292,11 +294,11 @@ public class ReportServiceTest extends AbstractServiceTestImpl { invalidStatusCodeMessage(REQUEST_TYPE, statusCode)); Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE); + List items = + list.getReportListItem(); // Optionally output additional data about list members for debugging. boolean iterateThroughList = false; if (iterateThroughList && logger.isDebugEnabled()) { - List items = - list.getReportListItem(); int i = 0; for (ReportsCommonList.ReportListItem item : items) { logger.debug(testName + ": list-item[" + i + "] csid=" @@ -310,7 +312,87 @@ public class ReportServiceTest extends AbstractServiceTestImpl { i++; } } + } + @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class, + dependsOnMethods = {"readList"}) + public void readListFiltered(String testName) throws Exception { + if (logger.isDebugEnabled()) { + logger.debug(testBanner(testName, CLASS_NAME)); + } + // Perform setup. + setupReadList(); + + // Submit the request to the service and store the response. + ReportClient client = new ReportClient(); + ClientResponse res = client.readListFiltered( + testDocType, "single"); + ReportsCommonList list = res.getEntity(); + int statusCode = res.getStatus(); + + // Check the status code of the response: does it match + // the expected response(s)? + if (logger.isDebugEnabled()) { + logger.debug(testName + ": status = " + statusCode); + } + Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode), + invalidStatusCodeMessage(REQUEST_TYPE, statusCode)); + Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE); + + List items = + list.getReportListItem(); + // We must find the basic one we created + boolean fFoundBaseItem = false; + for (ReportsCommonList.ReportListItem item : items) { + if(knownResourceId.equalsIgnoreCase(item.getCsid())) { + fFoundBaseItem = true; + break; + } + } + if(!fFoundBaseItem) + Assert.fail("readListFiltered failed to return base item"); + + // Now filter for something else, and ensure it is NOT returned + res = client.readListFiltered("Intake", "single"); + list = res.getEntity(); + statusCode = res.getStatus(); + + // Check the status code of the response: does it match + // the expected response(s)? + if (logger.isDebugEnabled()) { + logger.debug(testName + ": status = " + statusCode); + } + Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode), + invalidStatusCodeMessage(REQUEST_TYPE, statusCode)); + Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE); + + items = list.getReportListItem(); + // We must NOT find the basic one we created + for (ReportsCommonList.ReportListItem item : items) { + Assert.assertNotSame(item.getCsid(), knownResourceId, + "readListFiltered(\"Intake\", \"single\") incorrectly returned base item"); + } + + // Now filter for something else, and ensure it is NOT returned + res = client.readListFiltered(testDocType, "group"); + list = res.getEntity(); + statusCode = res.getStatus(); + + // Check the status code of the response: does it match + // the expected response(s)? + if (logger.isDebugEnabled()) { + logger.debug(testName + ": status = " + statusCode); + } + Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode), + invalidStatusCodeMessage(REQUEST_TYPE, statusCode)); + Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE); + + items = list.getReportListItem(); + // We must NOT find the basic one we created + for (ReportsCommonList.ReportListItem item : items) { + Assert.assertNotSame(item.getCsid(), knownResourceId, + "readListFiltered(\""+testDocType+"\", \"group\") incorrectly returned base item"); + } } // --------------------------------------------------------------- @@ -322,7 +404,7 @@ public class ReportServiceTest extends AbstractServiceTestImpl { */ @Override @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class, - dependsOnMethods = {"read"}) + dependsOnMethods = {"read", "readListFiltered"}) public void update(String testName) throws Exception { if (logger.isDebugEnabled()) { @@ -475,7 +557,7 @@ public class ReportServiceTest extends AbstractServiceTestImpl { */ @Override @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class, - dependsOnMethods = {"create", "readList", "testSubmitRequest", "update", "readWorkflow"}) + dependsOnMethods = {"create", "readListFiltered", "testSubmitRequest", "update", "readWorkflow"}) public void delete(String testName) throws Exception { if (logger.isDebugEnabled()) { @@ -581,8 +663,9 @@ public class ReportServiceTest extends AbstractServiceTestImpl { */ private PoxPayloadOut createReportInstance(String identifier) { return createReportInstance( - "name-" + identifier, - "persAuthTermCountsTest.jasper", + "Acquisition Summary", + testDocType, true, false, false, true, + "acq_basic.jasper", "application/pdf"); } @@ -595,10 +678,18 @@ public class ReportServiceTest extends AbstractServiceTestImpl { * @return the multipart output */ private PoxPayloadOut createReportInstance(String name, + String forDocType, + boolean supportsSingle, boolean supportsList, + boolean supportsGroup, boolean supportsNoContext, String filename, String outputMIME) { ReportsCommon reportCommon = new ReportsCommon(); reportCommon.setName(name); + reportCommon.setForDocType(forDocType); + reportCommon.setSupportsSingleDoc(supportsSingle); + reportCommon.setSupportsDocList(supportsList); + reportCommon.setSupportsGroup(supportsGroup); + reportCommon.setSupportsNoContext(supportsNoContext); reportCommon.setFilename(filename); reportCommon.setOutputMIME(outputMIME); reportCommon.setNotes(getUTF8DataFragment()); // For UTF-8 tests 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 c17ee3dcf..f65005d99 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 @@ -31,6 +31,7 @@ import net.sf.jasperreports.engine.JasperPrint; import org.collectionspace.services.jaxb.AbstractCommonList; import org.collectionspace.services.jaxb.InvocableJAXBSchema; import org.collectionspace.services.ReportJAXBSchema; +import org.collectionspace.services.client.IQueryManager; import org.collectionspace.services.client.PoxPayloadIn; import org.collectionspace.services.client.PoxPayloadOut; import org.collectionspace.services.client.ReportClient; @@ -41,6 +42,7 @@ import org.collectionspace.services.common.ServiceMessages; import org.collectionspace.services.common.config.ConfigReader; import org.collectionspace.services.common.context.ServiceContext; import org.collectionspace.services.common.document.BadRequestException; +import org.collectionspace.services.common.document.DocumentFilter; import org.collectionspace.services.common.document.DocumentHandler; import org.collectionspace.services.common.document.DocumentNotFoundException; import org.collectionspace.services.common.document.DocumentWrapper; @@ -48,6 +50,7 @@ import org.collectionspace.services.common.invocable.Invocable; import org.collectionspace.services.common.invocable.InvocationContext; import org.collectionspace.services.common.invocable.InvocationResults; import org.collectionspace.services.common.invocable.Invocable.InvocationError; +import org.collectionspace.services.common.query.QueryManager; import org.collectionspace.services.common.security.UnauthorizedException; import org.jboss.resteasy.spi.ResteasyProviderFactory; import org.nuxeo.ecm.core.api.DocumentModel; @@ -107,6 +110,26 @@ public class ReportResource extends ResourceBase { try { ServiceContext ctx = createServiceContext(queryParams); DocumentHandler handler = createDocumentHandler(ctx); + String docType = queryParams.getFirst(IQueryManager.SEARCH_TYPE_DOCTYPE); + String mode = queryParams.getFirst(IQueryManager.SEARCH_TYPE_INVCOATION_MODE); + String whereClause = null; + DocumentFilter documentFilter = null; + String common_part =ctx.getCommonPartLabel(); + if (docType != null && !docType.isEmpty()) { + whereClause = QueryManager.createWhereClauseForInvocableByDocType( + common_part, docType); + documentFilter = handler.getDocumentFilter(); + documentFilter.appendWhereClause(whereClause, IQueryManager.SEARCH_QUALIFIER_AND); + } + if (mode != null && !mode.isEmpty()) { + whereClause = QueryManager.createWhereClauseForInvocableByMode( + common_part, mode); + documentFilter = handler.getDocumentFilter(); + documentFilter.appendWhereClause(whereClause, IQueryManager.SEARCH_QUALIFIER_AND); + } + if (whereClause !=null && logger.isDebugEnabled()) { + logger.debug("The WHERE clause is: " + documentFilter.getWhereClause()); + } getRepositoryClient(ctx).getFiltered(ctx, handler); AbstractCommonList list = (AbstractCommonList) handler.getCommonPartList(); return list; -- 2.47.3