From 2e10f43fdf99fbf351019702c703bd9141723456 Mon Sep 17 00:00:00 2001 From: Richard Millet Date: Tue, 29 May 2012 09:20:53 -0700 Subject: [PATCH] CSPACE-5036: Added support for the "rtEither" and "rtObj" query params. Now you can search by subject, object, or both. --- .../test/RelationIntegrationTest.java | 33 ++++- .../client/CollectionSpaceClient.java | 9 ++ .../services/client/IQueryManager.java | 7 +- .../client/java/DocumentModelHandler.java | 119 +++++++++++------- 4 files changed, 122 insertions(+), 46 deletions(-) diff --git a/services/IntegrationTests/src/test/java/org/collectionspace/services/IntegrationTests/test/RelationIntegrationTest.java b/services/IntegrationTests/src/test/java/org/collectionspace/services/IntegrationTests/test/RelationIntegrationTest.java index 523a23ae4..b9e546010 100644 --- a/services/IntegrationTests/src/test/java/org/collectionspace/services/IntegrationTests/test/RelationIntegrationTest.java +++ b/services/IntegrationTests/src/test/java/org/collectionspace/services/IntegrationTests/test/RelationIntegrationTest.java @@ -158,7 +158,7 @@ public class RelationIntegrationTest extends CollectionSpaceIntegrationTest { response.releaseConnection(); } - //Next, create a two Dimension records to relate the collection object to + //Next, create two Dimension records to relate the collection object to multipart = this.createDimensionInstance(createIdentifier()); // Make the call to create and check the response response = dimensionClient.create(multipart); @@ -180,7 +180,17 @@ public class RelationIntegrationTest extends CollectionSpaceIntegrationTest { } finally { response.releaseConnection(); } - + //Next, create a the 3rd Dimension record + multipart = this.createDimensionInstance(createIdentifier()); + // Make the call to create and check the response + response = dimensionClient.create(multipart); + String dimensionCsid3 = null; + try { + Assert.assertEquals(response.getStatus(), Response.Status.CREATED.getStatusCode()); + dimensionCsid3 = extractId(response); + } finally { + response.releaseConnection(); + } // Relate the entities, by creating a new relation object RelationsCommon relation = new RelationsCommon(); @@ -217,6 +227,25 @@ public class RelationIntegrationTest extends CollectionSpaceIntegrationTest { } finally { response.releaseConnection(); } + // Create the 3rd relationship - but invert it this time + relation = new RelationsCommon(); + fillRelation(relation, + dimensionCsid3, DimensionsCommon.class.getSimpleName(), + collectionObjectCsid, CollectionobjectsCommon.class.getSimpleName(), + "collectionobject-dimension"); + // Create the part and fill it with the relation object + multipart = new PoxPayloadOut(RelationClient.SERVICE_PAYLOAD_NAME); + commonPart = multipart.addPart(relationClient.getCommonPartName(), relation); + // Create the relationship + response = relationClient.create(multipart); + @SuppressWarnings("unused") + String relationCsid3 = null; + try { + Assert.assertEquals(response.getStatus(), Response.Status.CREATED.getStatusCode()); + relationCsid3 = extractId(response); + } finally { + response.releaseConnection(); + } // Now lock the dimension record. 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 7652020a1..87c0c1d91 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 @@ -38,6 +38,15 @@ import org.collectionspace.services.common.authorityref.AuthorityRefList; */ public interface CollectionSpaceClient> { + public final static String COLLECTIONSPACE_CORE_SCHEMA = "collectionspace_core"; + public final static String COLLECTIONSPACE_CORE_TENANTID = "tenantId"; + public final static String COLLECTIONSPACE_CORE_URI = "uri"; + public final static String COLLECTIONSPACE_CORE_CREATED_AT = "createdAt"; + public final static String COLLECTIONSPACE_CORE_UPDATED_AT = "updatedAt"; + public final static String COLLECTIONSPACE_CORE_CREATED_BY = "createdBy"; + public final static String COLLECTIONSPACE_CORE_UPDATED_BY = "updatedBy"; + public final static String COLLECTIONSPACE_CORE_WORKFLOWSTATE = "workflowState"; + public static final String AUTH_PROPERTY = "cspace.auth"; public static final String PASSWORD_PROPERTY = "cspace.password"; public static final String SSL_PROPERTY = "cspace.ssl"; 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 384b43b99..54cd1f79e 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 @@ -45,8 +45,9 @@ public interface IQueryManager { // // Query params for CMIS queries on the relationship (Relation) table. // - final static String SEARCH_RELATED_TO_CSID_SUBJECT = "rtSbj"; - final static String SEARCH_RELATED_TO_CSID_OBJECT = "rtObj"; + final static String SEARCH_RELATED_TO_CSID_AS_SUBJECT = "rtSbj"; + final static String SEARCH_RELATED_TO_CSID_AS_OBJECT = "rtObj"; + final static String SEARCH_RELATED_TO_CSID_AS_EITHER = "rtEither"; // // Generic CMIS property mapping constants @@ -58,6 +59,7 @@ public interface IQueryManager { final static String CMIS_NUXEO_ID = CMIS_OBJECT_ID; final static String CMIS_NUXEO_NAME = CMIS_NAME; final static String CMIS_NUXEO_TITLE = "dc:title"; + final static String CMIS_CS_UPDATED_AT = CollectionSpaceClient.COLLECTIONSPACE_CORE_SCHEMA + ":" + CollectionSpaceClient.COLLECTIONSPACE_CORE_UPDATED_AT; // CollectionSpace CMIS property mapping constants final static String CMIS_TARGET_PREFIX = "DOC"; @@ -68,6 +70,7 @@ public interface IQueryManager { final static String CMIS_TARGET_CSID = CMIS_TARGET_PREFIX + "." + CMIS_NUXEO_NAME; final static String CMIS_TARGET_TITLE = CMIS_TARGET_PREFIX + "." + CMIS_NUXEO_TITLE; final static String CMIS_TARGET_NAME = CMIS_TARGET_PREFIX + "." + CMIS_NUXEO_NAME; + final static String CMIS_TARGET_UPDATED_AT = CMIS_TARGET_PREFIX + "." + CMIS_CS_UPDATED_AT; public void execQuery(String queryString); 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 72fa04f48..363d5e7c2 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 @@ -28,6 +28,7 @@ import java.util.List; import javax.ws.rs.core.MultivaluedMap; +import org.collectionspace.services.client.CollectionSpaceClient; import org.collectionspace.services.client.IQueryManager; import org.collectionspace.services.client.PoxPayloadIn; import org.collectionspace.services.client.PoxPayloadOut; @@ -73,16 +74,6 @@ public abstract class DocumentModelHandler private final Logger logger = LoggerFactory.getLogger(DocumentModelHandler.class); private RepositoryInstance repositorySession; - //key=schema, value=documentpart - - public final static String COLLECTIONSPACE_CORE_SCHEMA = "collectionspace_core"; - public final static String COLLECTIONSPACE_CORE_TENANTID = "tenantId"; - public final static String COLLECTIONSPACE_CORE_URI = "uri"; - public final static String COLLECTIONSPACE_CORE_CREATED_AT = "createdAt"; - public final static String COLLECTIONSPACE_CORE_UPDATED_AT = "updatedAt"; - public final static String COLLECTIONSPACE_CORE_CREATED_BY = "createdBy"; - public final static String COLLECTIONSPACE_CORE_UPDATED_BY = "updatedBy"; - public final static String COLLECTIONSPACE_CORE_WORKFLOWSTATE = "workflowState"; /* * Map Nuxeo's life cycle object to our JAX-B based life cycle object @@ -318,13 +309,13 @@ public abstract class DocumentModelHandler // Add the tenant ID value to the new entity // String tenantId = ctx.getTenantId(); - documentModel.setProperty(COLLECTIONSPACE_CORE_SCHEMA, - COLLECTIONSPACE_CORE_TENANTID, tenantId); + documentModel.setProperty(CollectionSpaceClient.COLLECTIONSPACE_CORE_SCHEMA, + CollectionSpaceClient.COLLECTIONSPACE_CORE_TENANTID, tenantId); // // Add the uri value to the new entity // - documentModel.setProperty(COLLECTIONSPACE_CORE_SCHEMA, - COLLECTIONSPACE_CORE_URI, getUri(documentModel)); + documentModel.setProperty(CollectionSpaceClient.COLLECTIONSPACE_CORE_SCHEMA, + CollectionSpaceClient.COLLECTIONSPACE_CORE_URI, getUri(documentModel)); // // Add the CSID to the DublinCore title so we can see the CSID in the default // Nuxeo webapp. @@ -338,17 +329,18 @@ public abstract class DocumentModelHandler documentModel.getName()); } } - documentModel.setProperty(COLLECTIONSPACE_CORE_SCHEMA, - COLLECTIONSPACE_CORE_CREATED_AT, now); - documentModel.setProperty(COLLECTIONSPACE_CORE_SCHEMA, - COLLECTIONSPACE_CORE_CREATED_BY, userId); - } - if(action==Action.CREATE || action==Action.UPDATE) { - documentModel.setProperty(COLLECTIONSPACE_CORE_SCHEMA, - COLLECTIONSPACE_CORE_UPDATED_AT, now); - documentModel.setProperty(COLLECTIONSPACE_CORE_SCHEMA, - COLLECTIONSPACE_CORE_UPDATED_BY, userId); + documentModel.setProperty(CollectionSpaceClient.COLLECTIONSPACE_CORE_SCHEMA, + CollectionSpaceClient.COLLECTIONSPACE_CORE_CREATED_AT, now); + documentModel.setProperty(CollectionSpaceClient.COLLECTIONSPACE_CORE_SCHEMA, + CollectionSpaceClient.COLLECTIONSPACE_CORE_CREATED_BY, userId); } + + if (action == Action.CREATE || action == Action.UPDATE) { + documentModel.setProperty(CollectionSpaceClient.COLLECTIONSPACE_CORE_SCHEMA, + CollectionSpaceClient.COLLECTIONSPACE_CORE_UPDATED_AT, now); + documentModel.setProperty(CollectionSpaceClient.COLLECTIONSPACE_CORE_SCHEMA, + CollectionSpaceClient.COLLECTIONSPACE_CORE_UPDATED_BY, userId); + } } /* @@ -365,42 +357,85 @@ public abstract class DocumentModelHandler // // Look the query params to see if we need to make a CMSIS query. // - String subjectCsid = (String)queryParams.getFirst(IQueryManager.SEARCH_RELATED_TO_CSID_SUBJECT); - if (subjectCsid != null) { + 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; } - /** - * Creates the CMIS query from the service context. Each document handler is responsible for returning a valid CMIS query using the - * information in the current service context -which includes things like the query parameters, etc. - */ + /** + * Creates the CMIS query from the service context. Each document handler is + * responsible for returning (can override) a valid CMIS query using the information in the + * current service context -which includes things like the query parameters, + * etc. + * + * This method implementation supports three mutually exclusive cases. We will build a query + * that can find a document(s) 'A' in a relationship with another document + * 'B' where document 'B' has a CSID equal to the query param passed in and: + * 1. Document 'B' is the subject of the relationship + * 2. Document 'B' is the object of the relationship + * 3. Document 'B' is either the object or the subject of the relationship + */ @Override public String getCMISQuery() { String result = null; if (isCMISQuery() == true) { - MultivaluedMap queryParams = getServiceContext().getQueryParams(); - String subjectCsid = (String)queryParams.getFirst(IQueryManager.SEARCH_RELATED_TO_CSID_SUBJECT); - String docType = this.getServiceContext().getDocumentType(); - - String selectFields = IQueryManager.CMIS_TARGET_NAME + ", " + String docType = this.getServiceContext().getDocumentType(); + String selectFields = IQueryManager.CMIS_TARGET_CSID + ", " + IQueryManager.CMIS_TARGET_TITLE + ", " + RelationClient.CMIS_CSPACE_RELATIONS_TITLE + ", " + + RelationClient.CMIS_CSPACE_RELATIONS_OBJECT_ID + ", " + RelationClient.CMIS_CSPACE_RELATIONS_SUBJECT_ID; String targetTable = docType + " " + IQueryManager.CMIS_TARGET_PREFIX; - String relationTable = RelationClient.SERVICE_DOC_TYPE + " " + IQueryManager.CMIS_RELATIONS_PREFIX; - String relationObjectCsid = RelationClient.CMIS_CSPACE_RELATIONS_OBJECT_ID; - String relationSubjectCsid = RelationClient.CMIS_CSPACE_RELATIONS_SUBJECT_ID; - String targetCsid = IQueryManager.CMIS_TARGET_CSID; + String relTable = RelationClient.SERVICE_DOC_TYPE + " " + IQueryManager.CMIS_RELATIONS_PREFIX; + String relObjectCsidCol = RelationClient.CMIS_CSPACE_RELATIONS_OBJECT_ID; + String relSubjectCsidCol = RelationClient.CMIS_CSPACE_RELATIONS_SUBJECT_ID; + String targetCsidCol = IQueryManager.CMIS_TARGET_CSID; + // + // Build up the query arguments + // + String theOnClause = ""; + String theWhereClause = ""; + MultivaluedMap queryParams = getServiceContext().getQueryParams(); + String asSubjectCsid = (String)queryParams.getFirst(IQueryManager.SEARCH_RELATED_TO_CSID_AS_SUBJECT); + String asObjectCsid = (String)queryParams.getFirst(IQueryManager.SEARCH_RELATED_TO_CSID_AS_OBJECT); + String asEitherCsid = (String)queryParams.getFirst(IQueryManager.SEARCH_RELATED_TO_CSID_AS_EITHER); + + // + // Create the "ON" and "WHERE" query clauses based on the params passed into the HTTP request. + // + // First come, first serve -the first match determines the "ON" and "WHERE" query clauses. + // + if (asSubjectCsid != null && !asSubjectCsid.isEmpty()) { + // Since our query param is the "subject" value, join the tables where the CSID of the document is the other side (the "object") of the relationship. + theOnClause = relObjectCsidCol + " = " + targetCsidCol; + theWhereClause = relSubjectCsidCol + " = " + "'" + asSubjectCsid + "'"; + } else if (asObjectCsid != null && !asObjectCsid.isEmpty()) { + // Since our query param is the "object" value, join the tables where the CSID of the document is the other side (the "subject") of the relationship. + theOnClause = relSubjectCsidCol + " = " + targetCsidCol; + theWhereClause = relObjectCsidCol + " = " + "'" + asObjectCsid + "'"; + } else if (asEitherCsid != null && !asEitherCsid.isEmpty()) { + theOnClause = relObjectCsidCol + " = " + targetCsidCol + + " OR " + relSubjectCsidCol + " = " + targetCsidCol; + theWhereClause = relSubjectCsidCol + " = " + "'" + asEitherCsid + "'" + + " OR " + relObjectCsidCol + " = " + "'" + asEitherCsid + "'"; + } else { + //Since the call to isCMISQuery() return true, we should never get here. + logger.error("Attempt to make CMIS query failed because the HTTP request was missing valid query parameters."); + } + // assemble the query from the string arguments result = "SELECT " + selectFields - + " FROM " + targetTable + " JOIN " + relationTable - + " ON " + relationObjectCsid + " = " + targetCsid - + " WHERE " + relationSubjectCsid + " = " + "'" + subjectCsid + "'"; + + " FROM " + targetTable + " JOIN " + relTable + + " ON " + theOnClause + + " WHERE " + theWhereClause; + // An example: // SELECT D.cmis:name, D.dc:title, R.dc:title, R.relations_common:subjectCsid // FROM Dimension D JOIN Relation R // ON R.relations_common:objectCsid = D.cmis:name -- 2.47.3