From 2f5edddd0862169fc4383740416f26f4987c10e2 Mon Sep 17 00:00:00 2001 From: Patrick Schmitz Date: Wed, 20 Jun 2012 23:43:46 -0700 Subject: [PATCH] CSPACE-5300 Added support to servicegroup service for CMIS queries. Does not properly sort on updatedAt, due to Nuxeo bug (filed). --- .../services/client/IQueryManager.java | 2 + .../services/client/IRelationsManager.java | 2 + .../client/java/DocumentModelHandler.java | 33 +++-- .../client/java/RepositoryJavaClientImpl.java | 114 +++++++++++++++--- .../servicegroup/ServiceGroupResource.java | 17 ++- .../ServiceGroupDocumentModelHandler.java | 26 +--- 6 files changed, 148 insertions(+), 46 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 714559749..accc0cbbb 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 @@ -48,6 +48,8 @@ public interface IQueryManager { 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"; + final static String SEARCH_RELATED_MATCH_OBJ_DOCTYPES = "rtObjDocTypes"; + final static String SELECT_DOC_TYPE_FIELD = "selectDocType"; // // Generic CMIS property mapping constants diff --git a/services/client/src/main/java/org/collectionspace/services/client/IRelationsManager.java b/services/client/src/main/java/org/collectionspace/services/client/IRelationsManager.java index e93948f5f..a2086e0c9 100644 --- a/services/client/src/main/java/org/collectionspace/services/client/IRelationsManager.java +++ b/services/client/src/main/java/org/collectionspace/services/client/IRelationsManager.java @@ -13,6 +13,8 @@ public interface IRelationsManager { + "." + SERVICE_COMMONPART_NAME + ":subjectCsid"; public final static String CMIS_CSPACE_RELATIONS_OBJECT_ID = IQueryManager.CMIS_RELATIONS_PREFIX + "." + SERVICE_COMMONPART_NAME + ":objectCsid"; + public final static String CMIS_CSPACE_RELATIONS_OBJECT_TYPE = IQueryManager.CMIS_RELATIONS_PREFIX + + "." + SERVICE_COMMONPART_NAME + ":objectDocumentType"; public final static String CMIS_CSPACE_RELATIONS_TITLE = IQueryManager.CMIS_RELATIONS_PREFIX + "." + IQueryManager.CMIS_NUXEO_TITLE; 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 c940797e3..38f0d2f21 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 @@ -386,7 +386,22 @@ public abstract class DocumentModelHandler String result = null; if (isCMISQuery() == true) { - String docType = this.getServiceContext().getDocumentType(); + // + // 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); + String matchObjDocTypes = (String)queryParams.getFirst(IQueryManager.SEARCH_RELATED_MATCH_OBJ_DOCTYPES); + String selectDocType = (String)queryParams.getFirst(IQueryManager.SELECT_DOC_TYPE_FIELD); + + String docType = this.getServiceContext().getDocumentType(); + if (selectDocType != null && !selectDocType.isEmpty()) { + docType = selectDocType; + } String selectFields = IQueryManager.CMIS_TARGET_CSID + ", " + IQueryManager.CMIS_TARGET_TITLE + ", " + IRelationsManager.CMIS_CSPACE_RELATIONS_TITLE + ", " @@ -397,15 +412,6 @@ public abstract class DocumentModelHandler String relObjectCsidCol = IRelationsManager.CMIS_CSPACE_RELATIONS_OBJECT_ID; String relSubjectCsidCol = IRelationsManager.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. @@ -430,6 +436,13 @@ public abstract class DocumentModelHandler logger.error("Attempt to make CMIS query failed because the HTTP request was missing valid query parameters."); } + // Now consider a constraint on the object doc types (for search by service group) + if (matchObjDocTypes != null && !matchObjDocTypes.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. + theWhereClause += " AND (" + IRelationsManager.CMIS_CSPACE_RELATIONS_OBJECT_TYPE + + " IN " + matchObjDocTypes + ")"; + } + StringBuilder query = new StringBuilder(); // assemble the query from the string arguments query.append("SELECT "); 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 7bf986185..85b2d21cf 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 @@ -64,6 +64,7 @@ import org.nuxeo.ecm.core.api.repository.RepositoryInstance; // import org.apache.chemistry.opencmis.commons.server.CallContext; import org.apache.chemistry.opencmis.server.impl.CallContextImpl; +import org.apache.chemistry.opencmis.server.support.query.CmisQlExtParser_CmisBaseGrammar.boolean_factor_return; import org.nuxeo.ecm.core.opencmis.impl.server.NuxeoCmisService; import org.nuxeo.ecm.core.opencmis.impl.server.NuxeoRepository; @@ -489,7 +490,7 @@ public class RepositoryJavaClientImpl implements RepositoryClient(docList); } catch (IllegalArgumentException iae) { throw iae; @@ -503,6 +504,73 @@ public class RepositoryJavaClientImpl implements RepositoryClient docTypes) { + StringBuilder sb = new StringBuilder(); + sb.append("("); + boolean first = true; + for(String docType:docTypes) { + if(first) { + first = false; + } else { + sb.append(","); + } + sb.append("'"); + sb.append(docType); + sb.append("'"); + } + sb.append(")"); + return sb.toString(); + } + + public DocumentWrapper findDocs( + ServiceContext ctx, + DocumentHandler handler, + RepositoryInstance repoSession, + List docTypes) + throws DocumentNotFoundException, DocumentException { + DocumentWrapper wrapDoc = null; + + DocumentFilter filter = handler.getDocumentFilter(); + String oldOrderBy = filter.getOrderByClause(); + QueryContext queryContext = new QueryContext(ctx, handler); + + try { + if (docTypes == null || docTypes.size() < 1) { + throw new DocumentNotFoundException( + "The findDocs() method must specify at least one DocumentType."); + } + DocumentModelList docList = null; + if (handler.isCMISQuery() == true) { + // We have to omit the ORDER BY until we can get the "Document" table bug addressed. + // CF Nuxeo JIRA NXP-9562 + String inList = buildInListForDocTypes(docTypes); + ctx.getQueryParams().add(IQueryManager.SEARCH_RELATED_MATCH_OBJ_DOCTYPES, inList); + docList = getFilteredCMIS(repoSession, ctx, handler, queryContext); + } else { + if (isClauseEmpty(oldOrderBy) == true){ + filter.setOrderByClause(DocumentFilter.ORDER_BY_LAST_UPDATED); + } + String query = NuxeoUtils.buildNXQLQuery(docTypes, queryContext); + if (logger.isDebugEnabled()) { + logger.debug("findDocs() NXQL: "+query); + } + docList = repoSession.query(query, null, filter.getPageSize(), filter.getOffset(), true); + } + wrapDoc = new DocumentWrapperImpl(docList); + } catch (IllegalArgumentException iae) { + throw iae; + } catch (Exception e) { + if (logger.isDebugEnabled()) { + logger.debug("Caught exception ", e); + } + throw new DocumentException(e); + } + + return wrapDoc; + } + + + /** * Find a list of documentModels from the Nuxeo repository * @param docTypes a list of DocType names to match @@ -801,8 +869,12 @@ public class RepositoryJavaClientImpl implements RepositoryClient 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); - } + int totalSize = (int)queryResult.size(); + ((DocumentModelListImpl)result).setTotalSize(totalSize); + // Skip the rows before our offset + if(offset>0) { + queryResult.skipTo(offset); + } + int nRows = 0; + 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); + nRows++; + if(nRows >= pageSize) { + logger.debug("Got page full of items - quitting"); + break; + } + } } finally { queryResult.close(); } @@ -841,15 +925,15 @@ public class RepositoryJavaClientImpl implements RepositoryClient docFilter.getPageSize()) { docFilter.setPageSize(totalSize); ((DocumentModelListImpl)result).setTotalSize(totalSize); } } + */ return result; } diff --git a/services/servicegroup/service/src/main/java/org/collectionspace/services/servicegroup/ServiceGroupResource.java b/services/servicegroup/service/src/main/java/org/collectionspace/services/servicegroup/ServiceGroupResource.java index 92169aa25..0a4ccfec9 100644 --- a/services/servicegroup/service/src/main/java/org/collectionspace/services/servicegroup/ServiceGroupResource.java +++ b/services/servicegroup/service/src/main/java/org/collectionspace/services/servicegroup/ServiceGroupResource.java @@ -231,7 +231,22 @@ public class ServiceGroupResource extends AbstractCollectionSpaceResourceImpl { groupsList = new ArrayList(); groupsList.add(serviceGroupName); } - list = handler.getItemsForGroup(ctx, groupsList, keywords); + // set up a keyword search + if (keywords != null && !keywords.isEmpty()) { + String whereClause = QueryManager.createWhereClauseFromKeywords(keywords); + if(Tools.isEmpty(whereClause)) { + if (logger.isDebugEnabled()) { + logger.debug("The WHERE clause is empty for keywords: ["+keywords+"]"); + } + } else { + DocumentFilter documentFilter = handler.getDocumentFilter(); + documentFilter.appendWhereClause(whereClause, IQueryManager.SEARCH_QUALIFIER_AND); + if (logger.isDebugEnabled()) { + logger.debug("The WHERE clause is: " + documentFilter.getWhereClause()); + } + } + } + list = handler.getItemsForGroup(ctx, groupsList); } catch (Exception e) { throw bigReThrow(e, ServiceMessages.READ_FAILED, serviceGroupName); } diff --git a/services/servicegroup/service/src/main/java/org/collectionspace/services/servicegroup/nuxeo/ServiceGroupDocumentModelHandler.java b/services/servicegroup/service/src/main/java/org/collectionspace/services/servicegroup/nuxeo/ServiceGroupDocumentModelHandler.java index 444e439e5..92bcc33d6 100644 --- a/services/servicegroup/service/src/main/java/org/collectionspace/services/servicegroup/nuxeo/ServiceGroupDocumentModelHandler.java +++ b/services/servicegroup/service/src/main/java/org/collectionspace/services/servicegroup/nuxeo/ServiceGroupDocumentModelHandler.java @@ -76,8 +76,7 @@ public class ServiceGroupDocumentModelHandler public AbstractCommonList getItemsForGroup( ServiceContext ctx, - List serviceGroupNames, - String keywords) throws Exception { + List serviceGroupNames) throws Exception { CommonList commonList = new CommonList(); AbstractCommonList list = (AbstractCommonList)commonList; RepositoryInstance repoSession = null; @@ -91,25 +90,9 @@ public class ServiceGroupDocumentModelHandler releaseRepoSession = true; } DocumentFilter myFilter = getDocumentFilter(); - String whereClause = null; - if (keywords != null) { - whereClause = QueryManager.createWhereClauseFromKeywords(keywords); - if(Tools.isEmpty(whereClause)) { - if (logger.isDebugEnabled()) { - logger.debug("The WHERE clause is empty for keywords: ["+keywords+"]"); - } - } else { - myFilter.appendWhereClause(whereClause, IQueryManager.SEARCH_QUALIFIER_AND); - if (logger.isDebugEnabled()) { - logger.debug("The WHERE clause is: " + myFilter.getWhereClause()); - } - } - } // Make sure we pick up workflow state, etc. - whereClause = myFilter.getWhereClause(); int pageSize = myFilter.getPageSize(); int pageNum = myFilter.getStartPage(); - final boolean computeTotal = true; list.setPageNum(pageNum); list.setPageSize(pageSize); @@ -139,12 +122,15 @@ public class ServiceGroupDocumentModelHandler queriedServiceBindings.put(docType, binding); } } + + // This should be "Document" but CMIS is gagging on that right now. + ctx.getQueryParams().add(IQueryManager.SELECT_DOC_TYPE_FIELD, "cmis:document"); // Now we have to issue the search // findDocs qill build a QueryContext, which wants to see a docType for our context ctx.setDocumentType("Document"); - DocumentWrapper docListWrapper = nuxeoRepoClient.findDocs(ctx, repoSession, - docTypes, whereClause, pageSize, pageNum, computeTotal); + DocumentWrapper docListWrapper = + nuxeoRepoClient.findDocs(ctx, this, repoSession, docTypes ); // Now we gather the info for each document into the list and return DocumentModelList docList = docListWrapper.getWrappedObject(); -- 2.47.3