From ec5b43370e3fd4da57b354e04b3289c62922f5af Mon Sep 17 00:00:00 2001 From: Richard Millet Date: Thu, 24 May 2012 15:03:15 -0700 Subject: [PATCH] CSPACE-5036: Final support for CMIS query to list all items/resources in a relationship with specified subject_csid. Uses 'rtSbj' query param on service list requests. For example, http://localhost:8180/cspace-services/collectionobjects?rtSbj=8d1ab4a3-9319-4793-beda returns a list of collection objects related to the document with csid=8d1ab4a3-9319-4793-beda as the subject. --- .../services/client/IQueryManager.java | 25 ++++++- services/common/pom.xml | 5 ++ .../document/AbstractDocumentHandlerImpl.java | 4 ++ .../common/document/DocumentHandler.java | 2 + .../client/java/DocumentModelHandler.java | 68 +++++++++++++++++++ .../client/java/RepositoryJavaClientImpl.java | 54 +++++++-------- .../nuxeo/DimensionDocumentModelHandler.java | 8 ++- .../services/movement/MovementResource.java | 50 +++++++------- .../nuxeo/MovementDocumentModelHandler.java | 36 ---------- .../services/client/RelationClient.java | 9 +++ 10 files changed, 166 insertions(+), 95 deletions(-) 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 a5a143f12..384b43b99 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,29 @@ public interface IQueryManager { // // Query params for CMIS queries on the relationship (Relation) table. // - final static String SEARCH_RELATED_TO_CSID_SUBJECT = "rt_sbj"; - final static String SEARCH_RELATED_TO_CSID_OBJECT = "rd_obj"; + final static String SEARCH_RELATED_TO_CSID_SUBJECT = "rtSbj"; + final static String SEARCH_RELATED_TO_CSID_OBJECT = "rtObj"; + + // + // Generic CMIS property mapping constants + // + final static String CMIS_OBJECT_ID = "cmis:objectId"; + final static String CMIS_NAME = "cmis:name"; + // + // Nuxeo related CMIS property mapping constants + 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"; + + // CollectionSpace CMIS property mapping constants + final static String CMIS_TARGET_PREFIX = "DOC"; + // Relations CMIS property mapping constants + final static String CMIS_RELATIONS_PREFIX = "REL"; + + final static String CMIS_TARGET_NUXEO_ID = CMIS_TARGET_PREFIX + "." + CMIS_NUXEO_ID; + 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; public void execQuery(String queryString); diff --git a/services/common/pom.xml b/services/common/pom.xml index a892bfeec..ddd7fa93e 100644 --- a/services/common/pom.xml +++ b/services/common/pom.xml @@ -50,6 +50,11 @@ org.collectionspace.services.client ${project.version} + + org.collectionspace.services + org.collectionspace.services.relation.client + ${project.version} + org.collectionspace.services org.collectionspace.services.authentication.jaxb 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 53e556bec..64b4a7fe9 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 @@ -423,4 +423,8 @@ public abstract class AbstractDocumentHandlerImpl // return null; } + + public boolean isCMISQuery() { + return false; + } } diff --git a/services/common/src/main/java/org/collectionspace/services/common/document/DocumentHandler.java b/services/common/src/main/java/org/collectionspace/services/common/document/DocumentHandler.java index f938b2140..b7a6657bb 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/document/DocumentHandler.java +++ b/services/common/src/main/java/org/collectionspace/services/common/document/DocumentHandler.java @@ -335,4 +335,6 @@ public interface DocumentHandler { * information in the current service context -which includes things like the query parameters, etc. */ public String getCMISQuery(); + + public boolean isCMISQuery(); } 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 e9a2d8ebe..72fa04f48 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 @@ -26,8 +26,12 @@ package org.collectionspace.services.nuxeo.client.java; import java.util.Collection; import java.util.List; +import javax.ws.rs.core.MultivaluedMap; + +import org.collectionspace.services.client.IQueryManager; import org.collectionspace.services.client.PoxPayloadIn; import org.collectionspace.services.client.PoxPayloadOut; +import org.collectionspace.services.client.RelationClient; import org.collectionspace.services.common.authorityref.AuthorityRefList; import org.collectionspace.services.common.context.ServiceContext; import org.collectionspace.services.common.datetime.GregorianCalendarDateTimeUtils; @@ -346,4 +350,68 @@ public abstract class DocumentModelHandler COLLECTIONSPACE_CORE_UPDATED_BY, userId); } } + + /* + * If we see the "rtSbj" query param then we need to perform a CMIS query. Currently, we have only one + * CMIS query, but we could add more. If we do, this method should look at the incoming request and corresponding + * query params to determine if we need to do a CMIS query + * (non-Javadoc) + * @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 subjectCsid = (String)queryParams.getFirst(IQueryManager.SEARCH_RELATED_TO_CSID_SUBJECT); + if (subjectCsid != 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. + */ + @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 + ", " + + IQueryManager.CMIS_TARGET_TITLE + ", " + + RelationClient.CMIS_CSPACE_RELATIONS_TITLE + ", " + + 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; + + result = "SELECT " + selectFields + + " FROM " + targetTable + " JOIN " + relationTable + + " ON " + relationObjectCsid + " = " + targetCsid + + " WHERE " + relationSubjectCsid + " = " + "'" + subjectCsid + "'"; + + // 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 + // WHERE R.relations_common:subjectCsid = '737527ec-a560-4776-99de' + + if (logger.isDebugEnabled() == true && result != null) { + logger.debug("The CMIS query for the Movement service is: " + result); + } + } + + return result; + } + } diff --git a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClientImpl.java b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClientImpl.java index aad37e2e4..cd9e3dbbd 100644 --- a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClientImpl.java +++ b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClientImpl.java @@ -27,6 +27,7 @@ import java.util.UUID; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MultivaluedMap; +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; @@ -700,6 +701,8 @@ public class RepositoryJavaClientImpl implements RepositoryClient row : result) { - logger.debug( - // "dc:title is: " + (String)row.get("dc:title") - "" + " Hierarchy Table ID is:" + row.get("cmis:objectId") - + " cmis:name is: " + row.get("cmis:name") - // + " nuxeo:lifecycleState is: " + - // row.get("nuxeo:lifecycleState") - ); - } } catch (ClientException e) { // TODO Auto-generated catch block - e.printStackTrace(); + logger.error("Encounter trouble making the following CMIS query: " + query, e); } + + return result; } /** @@ -769,8 +765,8 @@ public class RepositoryJavaClientImpl implements RepositoryClient 0) || (queryContext.getDocFilter().getPageSize() > 0)) { docList = repoSession.query(query, null, queryContext.getDocFilter().getPageSize(), queryContext.getDocFilter().getOffset(), true); @@ -816,18 +812,22 @@ public class RepositoryJavaClientImpl implements RepositoryClient row : queryResult) { - logger.debug( - // "dc:title is: " + (String)row.get("dc:title") - "" + " Hierarchy Table ID is:" + row.get("cmis:objectId") - + " cmis:name is: " + row.get("cmis:name") - // + " nuxeo:lifecycleState is: " + - // row.get("nuxeo:lifecycleState") - ); - String nuxeoId = (String) row.get("cmis:objectId"); - DocumentModel docModel = NuxeoUtils.getDocumentModel(repoSession, nuxeoId); - result.add(docModel); - } + try { + for (Map row : queryResult) { + logger.debug( + // "dc:title is: " + (String)row.get("dc:title") + "" + " Hierarchy Table ID is:" + row.get(IQueryManager.CMIS_TARGET_NUXEO_ID) + + " cmis:name is: " + row.get(IQueryManager.CMIS_TARGET_NAME) + // + " nuxeo:lifecycleState is: " + + // row.get("nuxeo:lifecycleState") + ); + String nuxeoId = (String) row.get(IQueryManager.CMIS_TARGET_NUXEO_ID); + DocumentModel docModel = NuxeoUtils.getDocumentModel(repoSession, nuxeoId); + result.add(docModel); + } + } finally { + queryResult.close(); + } // profiler.stop(); @@ -836,10 +836,6 @@ public class RepositoryJavaClientImpl implements RepositoryClient queryParams) { - if (isSet(IQueryManager.SEARCH_RELATED_TO_CSID_SUBJECT, queryParams) == false) { - // - // It's not a "related to" query so we can use our normal call to getList and not our CMIS query - // - return super.getList(queryParams); - } else { - // - // We need to use CMIS query method since we'll be doing a join with the Relation table - // - try { - ServiceContext ctx = createServiceContext(queryParams); - DocumentHandler handler = createDocumentHandler(ctx); - String relationToCsid = queryParams.getFirst(IQueryManager.SEARCH_RELATED_TO_CSID_SUBJECT); - - getRepositoryClient(ctx).getFilteredCMIS(ctx, handler); - - AbstractCommonList list = (AbstractCommonList) handler.getCommonPartList(); - return list; - } catch (Exception e) { - throw bigReThrow(e, ServiceMessages.LIST_FAILED); - } - } - } +// @Override +// protected AbstractCommonList getList(MultivaluedMap queryParams) { +// if (isSet(IQueryManager.SEARCH_RELATED_TO_CSID_SUBJECT, queryParams) == false) { +// // +// // It's not a "related to" query so we can use our normal call to getList and not our CMIS query +// // +// return super.getList(queryParams); +// } else { +// // +// // We need to use CMIS query method since we'll be doing a join with the Relation table +// // +// try { +// ServiceContext ctx = createServiceContext(queryParams); +// DocumentHandler handler = createDocumentHandler(ctx); +// String relationToCsid = queryParams.getFirst(IQueryManager.SEARCH_RELATED_TO_CSID_SUBJECT); +// +// getRepositoryClient(ctx).getFilteredCMIS(ctx, handler); +// +// AbstractCommonList list = (AbstractCommonList) handler.getCommonPartList(); +// return list; +// } catch (Exception e) { +// throw bigReThrow(e, ServiceMessages.LIST_FAILED); +// } +// } +// } } diff --git a/services/movement/service/src/main/java/org/collectionspace/services/movement/nuxeo/MovementDocumentModelHandler.java b/services/movement/service/src/main/java/org/collectionspace/services/movement/nuxeo/MovementDocumentModelHandler.java index b21054511..8d0d62fa5 100644 --- a/services/movement/service/src/main/java/org/collectionspace/services/movement/nuxeo/MovementDocumentModelHandler.java +++ b/services/movement/service/src/main/java/org/collectionspace/services/movement/nuxeo/MovementDocumentModelHandler.java @@ -23,10 +23,6 @@ */ package org.collectionspace.services.movement.nuxeo; -import javax.ws.rs.core.MultivaluedMap; - -import org.collectionspace.services.client.IQueryManager; -import org.collectionspace.services.movement.MovementResource; import org.collectionspace.services.movement.MovementsCommon; import org.collectionspace.services.nuxeo.client.java.DocHandlerBase; import org.slf4j.Logger; @@ -42,37 +38,5 @@ public class MovementDocumentModelHandler extends DocHandlerBase { final Logger logger = LoggerFactory.getLogger(MovementDocumentModelHandler.class); - - /** - * 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. - */ - @Override - public String getCMISQuery() { - String result = null; - - String subjectCsid = (String)getServiceContext().getQueryParams().get(IQueryManager.SEARCH_RELATED_TO_CSID_SUBJECT); - - // - // For Debugging purposes only - // - String cmis_movement = System.getenv("CMIS_MOVEMENT"); - - if (cmis_movement != null && !cmis_movement.isEmpty()) { - result = cmis_movement; - } else { - result = "SELECT M.cmis:name, M.dc:title, R.dc:title, R.relations_common:subjectCsid " - + "FROM Movement M JOIN Relation R ON R.relations_common:objectCsid = M.cmis:name " - + "WHERE R.relations_common:subjectCsid = " - + "'" + subjectCsid + "'"; - } - - if (logger.isDebugEnabled() == true) { - logger.debug("The CMIS query for the Movement service is: " + result); - } - - return result; - } - } diff --git a/services/relation/client/src/main/java/org/collectionspace/services/client/RelationClient.java b/services/relation/client/src/main/java/org/collectionspace/services/client/RelationClient.java index 8ace93f91..7949c3345 100644 --- a/services/relation/client/src/main/java/org/collectionspace/services/client/RelationClient.java +++ b/services/relation/client/src/main/java/org/collectionspace/services/client/RelationClient.java @@ -34,6 +34,7 @@ import org.collectionspace.services.relation.RelationsCommonList; * The Class RelationClient. */ public class RelationClient extends AbstractPoxServiceClientImpl { + public static final String SERVICE_DOC_TYPE = "Relation"; // Used for CMIS queries only -should be the same as what's in the tenant bindings public static final String SERVICE_NAME = "relations"; public static final String SERVICE_PATH_COMPONENT = SERVICE_NAME; public static final String SERVICE_PATH = "/" + SERVICE_PATH_COMPONENT; @@ -43,6 +44,14 @@ public class RelationClient extends AbstractPoxServiceClientImpl