From 49566704d022dfa69f3d8bf4a3a401a4504ab0b1 Mon Sep 17 00:00:00 2001 From: remillet Date: Fri, 8 Dec 2017 15:50:01 -0800 Subject: [PATCH] DRYD-120: Added query param 'andReciprocal' to GET list requests on Relations service. See JIRA DRYD-120 comments for details. --- .../services/client/IRelationsManager.java | 29 +++--- .../common/relation/RelationResource.java | 21 +++-- .../common/relation/RelationUtils.java | 1 - .../common/relation/nuxeo/RelationsUtils.java | 93 +++++++------------ .../java/NuxeoDocumentModelHandler.java | 23 +++-- .../ServiceGroupDocumentModelHandler.java | 19 ++-- 6 files changed, 93 insertions(+), 93 deletions(-) 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 723dccd49..9ca08e4ae 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 @@ -16,35 +16,36 @@ public interface IRelationsManager { public final static String CMIS_CSPACE_RELATIONS_PREDICATE = IQueryManager.CMIS_RELATIONS_PREFIX + "." + SERVICE_COMMONPART_NAME + ":relationshipType"; - 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; - - /** The Constant SUBJECT. */ + + /** The Subject related schema/db column names */ static public final String SUBJECT = "subjectCsid"; static public final String SUBJECT_DOCTYPE = "subjectDocumentType"; - - static public final String SUBJECT_REFNAME = "subjectRefName"; + static public final String SUBJECT_REFNAME = "subjectRefName"; + + /** Request query params for Subject related requests */ static public final String SUBJECT_QP = "sbj"; -// static public final String SUBJECT_TYPE = "subjectType"; static public final String SUBJECT_TYPE_QP = SUBJECT_QP + "Type"; - - // A query param for specifying either Subject or Object - static public final String SUBJECT_OR_OBJECT = "sbjOrObj"; - - /** The Constant PREDICATE. */ + + /** The Predicate related schema/db column names */ static public final String PREDICATE = "predicate"; static public final String PREDICATE_QP = "prd"; static public final String RELATIONSHIP_TYPE = "relationshipType"; - - /** The Constant OBJECT. */ + /** The Object related schema/db column names */ static public final String OBJECT = "objectCsid"; static public final String OBJECT_DOCTYPE = "objectDocumentType"; static public final String OBJECT_REFNAME = "objectRefName"; + + /** Request query params for Subject related requests */ static public final String OBJECT_QP = "obj"; -// static public final String OBJECT_TYPE = "objectType"; static public final String OBJECT_TYPE_QP = OBJECT_QP + "Type"; + + // A query param that, if true, will case the Relations service to return the combined results of two queries for LIST requests -reversing the + // suject and object values in the second query. This is useful for finding relations for records when you're not sure if they're the subject + // or object of the relationship. + public static final String RECIPROCAL_QP = "andReciprocal"; } diff --git a/services/common/src/main/java/org/collectionspace/services/common/relation/RelationResource.java b/services/common/src/main/java/org/collectionspace/services/common/relation/RelationResource.java index 53be9d6b8..12dedc2c5 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/relation/RelationResource.java +++ b/services/common/src/main/java/org/collectionspace/services/common/relation/RelationResource.java @@ -32,6 +32,7 @@ import org.collectionspace.services.client.PoxPayloadOut; import org.collectionspace.services.common.CSWebApplicationException; import org.collectionspace.services.common.NuxeoBasedResource; import org.collectionspace.services.common.ServiceMessages; +import org.collectionspace.services.common.api.Tools; import org.collectionspace.services.common.context.ServiceContext; import org.collectionspace.services.common.document.DocumentHandler; import org.collectionspace.services.common.query.QueryManager; @@ -40,16 +41,17 @@ import org.collectionspace.services.common.relation.nuxeo.RelationsUtils; import org.collectionspace.services.relation.RelationsCommon; import org.collectionspace.services.relation.RelationsCommonList; import org.collectionspace.services.relation.RelationsCommonList.RelationListItem; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.List; + import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.DELETE; import javax.ws.rs.Path; -import javax.ws.rs.PathParam; import javax.ws.rs.Produces; -import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Context; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.Response; @@ -95,27 +97,30 @@ public class RelationResource extends NuxeoBasedResource { String predicate = queryParams.getFirst(IRelationsManager.PREDICATE_QP); String objectCsid = queryParams.getFirst(IRelationsManager.OBJECT_QP); String objectType = queryParams.getFirst(IRelationsManager.OBJECT_TYPE_QP); - String subjectOrObject = queryParams.getFirst(IRelationsManager.SUBJECT_OR_OBJECT); + String viceVersaValue = queryParams.getFirst(IRelationsManager.RECIPROCAL_QP); - return this.getRelationList(parentCtx, uriInfo, subjectCsid, subjectType, predicate, objectCsid, objectType, subjectOrObject); + RelationsCommonList resultList = this.getRelationList(parentCtx, uriInfo, subjectCsid, subjectType, predicate, objectCsid, objectType, Tools.isTrue(viceVersaValue)); + + return resultList; } - private RelationsCommonList getRelationList( + + private RelationsCommonList getRelationList( ServiceContext parentCtx, UriInfo uriInfo, String subjectCsid, String subjectType, String predicate, String objectCsid, String objectType, - String subjectOrObject) throws CSWebApplicationException { + boolean viceVersa) throws CSWebApplicationException { try { ServiceContext ctx = createServiceContext(uriInfo); if (parentCtx != null && parentCtx.getCurrentRepositorySession() != null) { // If the parent context has a non-null and open repository session then use it ctx.setCurrentRepositorySession(parentCtx.getCurrentRepositorySession()); } + DocumentHandler handler = createDocumentHandler(ctx); - - String relationClause = RelationsUtils.buildWhereClause(subjectCsid, subjectType, predicate, objectCsid, objectType, subjectOrObject); + String relationClause = RelationsUtils.buildWhereClause(subjectCsid, subjectType, predicate, objectCsid, objectType, viceVersa); handler.getDocumentFilter().appendWhereClause(relationClause, IQueryManager.SEARCH_QUALIFIER_AND); // // Handle keyword clause diff --git a/services/common/src/main/java/org/collectionspace/services/common/relation/RelationUtils.java b/services/common/src/main/java/org/collectionspace/services/common/relation/RelationUtils.java index a0a7af84b..812fda13e 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/relation/RelationUtils.java +++ b/services/common/src/main/java/org/collectionspace/services/common/relation/RelationUtils.java @@ -29,7 +29,6 @@ public class RelationUtils { private static final Logger logger = LoggerFactory.getLogger(RelationUtils.class); private static final int DEFAULT_PAGE_SIZE = 1000; - /* * Performs an NXQL query to find refName references in relationship records. */ diff --git a/services/common/src/main/java/org/collectionspace/services/common/relation/nuxeo/RelationsUtils.java b/services/common/src/main/java/org/collectionspace/services/common/relation/nuxeo/RelationsUtils.java index 30211583d..61edaf01e 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/relation/nuxeo/RelationsUtils.java +++ b/services/common/src/main/java/org/collectionspace/services/common/relation/nuxeo/RelationsUtils.java @@ -50,73 +50,22 @@ public class RelationsUtils { * @param object the object * @return the string */ - public static String buildWhereClause(String subject, String subjectType, + private static String buildWhereClause(String subject, String subjectType, String predicate, - String object, String objectType, - String subjectOrObject) { + String object, String objectType) { String result = null; StringBuilder stringBuilder = new StringBuilder(); - - if (subjectOrObject != null && object != null) { - // Used for GET requests like: cspace-services/collectionobjects?mkRtSbjOrObj=cf5db000-4e65-42d5-8117 - // - // (Example, ((rel.subjectcsid = subject AND rel.objectcsid = target) - // OR - // (rel.subjectcsid = target AND rel.objectcsid = subject)) - // - String target = object; - stringBuilder.append("("); - stringBuilder.append("(" + RelationConstants.NUXEO_SCHEMA_NAME + ":" + - RelationJAXBSchema.SUBJECT_CSID + " = " + "'" + subjectOrObject + "'"); - stringBuilder.append(" AND " + RelationConstants.NUXEO_SCHEMA_NAME + ":" + - RelationJAXBSchema.OBJECT_CSID + " = " + "'" + target + "'" + ")"); - stringBuilder.append(" OR "); - stringBuilder.append("(" + RelationConstants.NUXEO_SCHEMA_NAME + ":" + - RelationJAXBSchema.SUBJECT_CSID + " = " + "'" + target + "'"); - stringBuilder.append(" AND " + RelationConstants.NUXEO_SCHEMA_NAME + ":" + - RelationJAXBSchema.OBJECT_CSID + " = " + "'" + subjectOrObject + "'" + ")"); - stringBuilder.append(")"); - } else if (subjectOrObject != null) { - // Used for GET requests like: cspace-services/relations?sbjOrObj=cf5db000-4e65-42d5-8117 - // - // (subectCsid = ${csid} OR objectCsid = ${csid}) overrides the individual subject or object query params - // (Example, (rel.subjectcsid = subjectOrObject OR rel.objectcsid = subjectOrObject) - // - stringBuilder.append("(" + RelationConstants.NUXEO_SCHEMA_NAME + ":" + - RelationJAXBSchema.SUBJECT_CSID + " = " + "'" + subjectOrObject + "'"); - stringBuilder.append(" OR "); + if (subject != null) { stringBuilder.append(RelationConstants.NUXEO_SCHEMA_NAME + ":" + - RelationJAXBSchema.OBJECT_CSID + " = " + "'" + subjectOrObject + "')"); - } else { - // Used for GET requests like: cspace-services/relations?sbj=cf5db000-4e65-42d5-8117 - // and cspace-services/relations?obj=cf5db000-4e65-42d5-8117 - // - if (subject != null) { - if (stringBuilder.length() > 0) { - stringBuilder.append(IQueryManager.SEARCH_QUALIFIER_AND); - } - - stringBuilder.append(RelationConstants.NUXEO_SCHEMA_NAME + ":" + - RelationJAXBSchema.SUBJECT_CSID + " = " + "'" + subject + "'"); - } - - if (object != null) { - if (stringBuilder.length() > 0) { - stringBuilder.append(IQueryManager.SEARCH_QUALIFIER_AND); - } - stringBuilder.append(RelationConstants.NUXEO_SCHEMA_NAME + ":" + - RelationJAXBSchema.OBJECT_CSID + " = " + "'" + object + "'"); - } + RelationJAXBSchema.SUBJECT_CSID + " = " + "'" + subject + "'"); } - // - // Check for the other possible query params - // if (subjectType != null) { if (stringBuilder.length() > 0) { stringBuilder.append(IQueryManager.SEARCH_QUALIFIER_AND); } + // BUG - this should use the new field RelationJAXBSchema.SUBJECT_DOCTYPE stringBuilder.append(RelationConstants.NUXEO_SCHEMA_NAME + ":" + RelationJAXBSchema.SUBJECT_DOCTYPE + " = " + "'" + subjectType + "'"); } @@ -128,7 +77,15 @@ public class RelationsUtils { stringBuilder.append(RelationConstants.NUXEO_SCHEMA_NAME + ":" + RelationJAXBSchema.RELATIONSHIP_TYPE + " = " + "'" + predicate + "'"); } - + + if (object != null) { + if (stringBuilder.length() > 0) { + stringBuilder.append(IQueryManager.SEARCH_QUALIFIER_AND); + } + stringBuilder.append(RelationConstants.NUXEO_SCHEMA_NAME + ":" + + RelationJAXBSchema.OBJECT_CSID + " = " + "'" + object + "'"); + } + if (objectType != null) { if (stringBuilder.length() > 0) { stringBuilder.append(IQueryManager.SEARCH_QUALIFIER_AND); @@ -144,5 +101,27 @@ public class RelationsUtils { return result; } + + public static String buildWhereClause(String subject, String subjectType, + String predicate, + String object, String objectType, boolean viceVersa) { + String result = null; + + result = buildWhereClause( + subject, subjectType, + predicate, + object, objectType); + + if (viceVersa == true) { + String secondClause = buildWhereClause( + object, objectType, + predicate, + subject, subjectType); + result = String.format("(%s) OR (%s)", result, secondClause); + } + + return result; + } + } diff --git a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/NuxeoDocumentModelHandler.java b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/NuxeoDocumentModelHandler.java index 60d17dfc5..3e8bf0fac 100644 --- a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/NuxeoDocumentModelHandler.java +++ b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/NuxeoDocumentModelHandler.java @@ -225,17 +225,26 @@ public abstract class NuxeoDocumentModelHandler extends RemoteDocumentModelHa AbstractServiceContextImpl ctx = (AbstractServiceContextImpl) getServiceContext(); MultivaluedMap queryParams = getServiceContext().getQueryParams(); String markRtSbj = queryParams.getFirst(IQueryManager.MARK_RELATED_TO_CSID_AS_SUBJECT); - if (markRtSbj != null && markRtSbj.isEmpty()) { + if (Tools.isBlank(markRtSbj)) { markRtSbj = null; } + // + // We may be being asked to mark the record as related independent of whether it is the subject or object of a relationship. + // String markRtSbjOrObj = queryParams.getFirst(IQueryManager.MARK_RELATED_TO_CSID_AS_EITHER); - if (markRtSbjOrObj != null && markRtSbjOrObj.isEmpty()) { + if (Tools.isBlank(markRtSbjOrObj)) { markRtSbjOrObj = null; + } else { + if (Tools.isBlank(markRtSbj) == false) { + logger.warn(String.format("Ignoring query param %s=%s since overriding query param %s=%s exists.", + IQueryManager.MARK_RELATED_TO_CSID_AS_SUBJECT, markRtSbj, IQueryManager.MARK_RELATED_TO_CSID_AS_EITHER, markRtSbjOrObj)); + } + markRtSbj = markRtSbjOrObj; // Mark the record as related independent of whether it is the subject or object of a relationship } try { - if (markRtSbj != null || markRtSbjOrObj != null) { + if (markRtSbj != null) { repoClient = (RepositoryClientImpl) this.getRepositoryClient(ctx); RepositoryClientImpl nuxeoRepoClient = (RepositoryClientImpl) repoClient; repoSession = this.getRepositorySession(); @@ -250,7 +259,7 @@ public abstract class NuxeoDocumentModelHandler extends RemoteDocumentModelHa List resultsFields = getListItemsArray(); // Get additional list result fields defined in the service bindings int baseFields = NUM_STANDARD_LIST_RESULT_FIELDS; int nFields = resultsFields.size() + NUM_STANDARD_LIST_RESULT_FIELDS; - if (markRtSbj != null || markRtSbjOrObj != null) { + if (markRtSbj != null) { nFields++; baseFields++; } @@ -262,7 +271,7 @@ public abstract class NuxeoDocumentModelHandler extends RemoteDocumentModelHa fields[3] = STANDARD_LIST_UPDATED_AT_FIELD; fields[4] = STANDARD_LIST_WORKFLOW_FIELD; - if (markRtSbj != null || markRtSbjOrObj != null) { + if (markRtSbj != null) { fields[5] = STANDARD_LIST_MARK_RT_FIELD; } @@ -283,8 +292,8 @@ public abstract class NuxeoDocumentModelHandler extends RemoteDocumentModelHa // If the mark-related query param was set, check to see if the doc we're processing // is related to the value specified in the mark-related query param. // - if (markRtSbj != null || markRtSbjOrObj != null) { - String relationClause = RelationsUtils.buildWhereClause(markRtSbj, null, null, id, null, markRtSbjOrObj); + if (markRtSbj != null) { + String relationClause = RelationsUtils.buildWhereClause(markRtSbj, null, null, id, null, markRtSbj == markRtSbjOrObj); String whereClause = relationClause + IQueryManager.SEARCH_QUALIFIER_AND + NuxeoUtils.buildWorkflowNotDeletedWhereClause(); QueryContext queryContext = new QueryContext(ctx, whereClause); 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 d3fba7369..cebc0614d 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 @@ -54,6 +54,7 @@ import org.collectionspace.services.common.UriTemplateRegistryKey; import org.collectionspace.services.common.api.RefName; import org.collectionspace.services.common.api.RefNameUtils; import org.collectionspace.services.common.api.RefNameUtils.AuthorityTermInfo; +import org.collectionspace.services.common.api.Tools; import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl; import org.collectionspace.services.common.context.AbstractServiceContextImpl; import org.collectionspace.services.common.context.ServiceBindingUtils; @@ -311,17 +312,23 @@ public class ServiceGroupDocumentModelHandler MultivaluedMap queryParams = getServiceContext().getQueryParams(); String markRtSbj = queryParams.getFirst(IQueryManager.MARK_RELATED_TO_CSID_AS_SUBJECT); - if (markRtSbj != null && markRtSbj.isEmpty()) { + if (Tools.isBlank(markRtSbj)) { markRtSbj = null; } String markRtSbjOrObj = queryParams.getFirst(IQueryManager.MARK_RELATED_TO_CSID_AS_EITHER); - if (markRtSbjOrObj != null && markRtSbjOrObj.isEmpty()) { + if (Tools.isBlank(markRtSbjOrObj)) { markRtSbjOrObj = null; + } else { + if (Tools.isBlank(markRtSbj) == false) { + logger.warn(String.format("Ignoring query param %s='%s' since overriding query param %s='%s' exists.", + IQueryManager.MARK_RELATED_TO_CSID_AS_SUBJECT, markRtSbj, IQueryManager.MARK_RELATED_TO_CSID_AS_EITHER, markRtSbjOrObj)); + } + markRtSbj = markRtSbjOrObj; // Mark the record as related independent of whether it is the subject or object of a relationship } try { - if (markRtSbj != null || markRtSbjOrObj != null) { + if (markRtSbj != null) { repoClient = (RepositoryClientImpl) this.getRepositoryClient(ctx); RepositoryClientImpl nuxeoRepoClient = (RepositoryClientImpl) repoClient; repoSession = this.getRepositorySession(); @@ -340,7 +347,7 @@ public class ServiceGroupDocumentModelHandler fields[5] = DOC_NAME_FIELD; fields[6] = DOC_NUMBER_FIELD; fields[7] = DOC_TYPE_FIELD; - if (markRtSbj != null || markRtSbjOrObj != null) { + if (markRtSbj != null) { fields[8] = STANDARD_LIST_MARK_RT_FIELD; } @@ -364,8 +371,8 @@ public class ServiceGroupDocumentModelHandler // If the mark-related query param was set, check to see if the doc we're processing // is related to the value specified in the mark-related query param. // - if (markRtSbj != null || markRtSbjOrObj != null) { - String relationClause = RelationsUtils.buildWhereClause(markRtSbj, null, null, csid, null, markRtSbjOrObj); + if (markRtSbj != null) { + String relationClause = RelationsUtils.buildWhereClause(markRtSbj, null, null, csid, null, markRtSbj == markRtSbjOrObj); String whereClause = relationClause + IQueryManager.SEARCH_QUALIFIER_AND + NuxeoUtils.buildWorkflowNotDeletedWhereClause(); QueryContext queryContext = new QueryContext(ctx, whereClause); -- 2.47.3