From fc5524739af720499a398749067a2bb8bda755f9 Mon Sep 17 00:00:00 2001 From: Richard Millet Date: Tue, 21 Aug 2018 17:06:31 -0700 Subject: [PATCH] DRYD-458: Added update/PUT support for contact payloads send to authority item (person, org). --- .../common/vocabulary/AuthorityResource.java | 2 +- .../AuthorityResourceWithContacts.java | 49 ++++++- ...yItemWithContactsDocumentModelHandler.java | 138 ++++++++++++++++-- .../services/client/PoxPayload.java | 15 ++ .../java/NuxeoDocumentModelHandler.java | 16 ++ 5 files changed, 205 insertions(+), 15 deletions(-) diff --git a/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/AuthorityResource.java b/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/AuthorityResource.java index eaa1a0fcb..7e24bd901 100644 --- a/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/AuthorityResource.java +++ b/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/AuthorityResource.java @@ -697,7 +697,7 @@ public abstract class AuthorityResource } } - private String getCsid(ListItem item) { + protected String getCsid(ListItem item) { String result = null; for (Element ele : item.getAny()) { diff --git a/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/AuthorityResourceWithContacts.java b/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/AuthorityResourceWithContacts.java index 44d14ceaf..7dbf226aa 100644 --- a/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/AuthorityResourceWithContacts.java +++ b/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/AuthorityResourceWithContacts.java @@ -47,8 +47,11 @@ import org.collectionspace.services.common.UriTemplateFactory; import org.collectionspace.services.common.UriTemplateRegistryKey; import org.collectionspace.services.common.vocabulary.AuthorityResource; import org.collectionspace.services.common.context.ServiceContext; +import org.collectionspace.services.common.document.BadRequestException; +import org.collectionspace.services.common.document.DocumentException; 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.contact.ContactResource; import org.collectionspace.services.contact.ContactsCommon; import org.collectionspace.services.contact.ContactJAXBSchema; @@ -176,10 +179,28 @@ public abstract class AuthorityResourceWithContacts @Context UriInfo uriInfo) { AbstractCommonList contactObjectList = new AbstractCommonList(); + contactObjectList = getContactList(null, parentspecifier, itemspecifier, uriInfo); + + return contactObjectList; + } + + public AbstractCommonList getContactList( + ServiceContext existingCtx, + String parentspecifier, + String itemspecifier, + UriInfo uriInfo) { + AbstractCommonList contactObjectList = new AbstractCommonList(); + try { ServiceContext ctx = createServiceContext(getContactServiceName(), uriInfo); - MultivaluedMap queryParams = ctx.getQueryParams(); - + if (existingCtx != null) { + Object repoSession = existingCtx.getCurrentRepositorySession(); + if (repoSession != null) { + ctx.setCurrentRepositorySession(repoSession); + ctx.setProperties(existingCtx.getProperties()); + } + } + String parentcsid = lookupParentCSID(parentspecifier, "getContactList(parent)", "GET_CONTACT_LIST", null); ServiceContext itemCtx = createServiceContext(getItemServiceName()); String itemcsid = lookupItemCSID(itemCtx, itemspecifier, parentcsid, "getContactList(item)", "GET_CONTACT_LIST"); @@ -204,7 +225,7 @@ public abstract class AuthorityResourceWithContacts } return contactObjectList; - } + } /** * Gets the contact. @@ -282,8 +303,30 @@ public abstract class AuthorityResourceWithContacts + ": and item:" + itemspecifier + ": was not found.", csid); } + return result.toXML(); } + + public void updateContact(ServiceContext existingCtx, String parentCsid, String itemCsid, String csid, + PayloadInputPart theUpdate) throws Exception { + PoxPayloadOut result = null; + + String payloadTemplate = "%s"; + String xmlPayload = String.format(payloadTemplate, theUpdate.asXML()); + PoxPayloadIn input = new PoxPayloadIn(xmlPayload); + + ServiceContext ctx = createServiceContext(getContactServiceName(), input); + if (existingCtx != null) { + Object repoSession = existingCtx.getCurrentRepositorySession(); + if (repoSession != null) { + ctx.setCurrentRepositorySession(repoSession); + ctx.setProperties(existingCtx.getProperties()); + } + } + + DocumentHandler handler = createContactDocumentHandler(ctx, parentCsid, itemCsid); + getRepositoryClient(ctx).update(ctx, csid, handler); + } /** * Delete contact. diff --git a/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/nuxeo/AuthorityItemWithContactsDocumentModelHandler.java b/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/nuxeo/AuthorityItemWithContactsDocumentModelHandler.java index 8b5dad99b..c35ce6e08 100644 --- a/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/nuxeo/AuthorityItemWithContactsDocumentModelHandler.java +++ b/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/nuxeo/AuthorityItemWithContactsDocumentModelHandler.java @@ -1,12 +1,19 @@ package org.collectionspace.services.common.vocabulary.nuxeo; +import java.util.List; + import org.collectionspace.services.client.ContactClient; import org.collectionspace.services.client.PayloadInputPart; import org.collectionspace.services.client.PoxPayloadIn; import org.collectionspace.services.client.PoxPayloadOut; +import org.collectionspace.services.common.api.Tools; import org.collectionspace.services.common.context.ServiceContext; +import org.collectionspace.services.common.document.DocumentException; import org.collectionspace.services.common.document.DocumentWrapper; import org.collectionspace.services.common.vocabulary.AuthorityResourceWithContacts; +import org.collectionspace.services.contact.ContactsCommon; +import org.collectionspace.services.jaxb.AbstractCommonList; +import org.collectionspace.services.jaxb.AbstractCommonList.ListItem; import org.nuxeo.ecm.core.api.DocumentModel; public abstract class AuthorityItemWithContactsDocumentModelHandler extends AuthorityItemDocumentModelHandler { @@ -20,30 +27,139 @@ public abstract class AuthorityItemWithContactsDocumentModelHandler ex @Override public void completeCreate(DocumentWrapper wrapDoc) throws Exception { super.completeCreate(wrapDoc); - handleContactPayload(wrapDoc); + handleContactCreate(wrapDoc); + } + + @Override + public void completeUpdate(DocumentWrapper wrapDoc) throws Exception { + super.completeUpdate(wrapDoc); + handleContactUpdate(wrapDoc); } - private void handleContactPayload(DocumentWrapper wrapDoc) throws Exception { - ContactClient contactClient = new ContactClient(); + private void handleContactCreate(DocumentWrapper wrapDoc) throws Exception { ServiceContext ctx = getServiceContext(); + DocumentModel docModel = wrapDoc.getWrappedObject(); + String authorityCsid = this.getInAuthorityCsid(); + String itemCsid = this.getCsid(docModel); PoxPayloadIn input = ctx.getInput(); - PayloadInputPart contactPart = input.getPart(contactClient.getCommonPartName()); - if (contactPart != null) { - DocumentModel docModel = wrapDoc.getWrappedObject(); - String authorityCsid = this.getInAuthorityCsid(); - String itemCsid = this.getCsid(docModel); - createContact(authorityCsid, itemCsid, contactPart); + ContactClient contactClient = new ContactClient(); + // + // There may be multiple contact payloads + // + List contactPartList = input.getParts(contactClient.getCommonPartName()); + for (PayloadInputPart contactPart: contactPartList) { + createContact(authorityCsid, itemCsid, contactPart); } } private void createContact(String authorityCsid, String itemCsid, PayloadInputPart contactPart) throws Exception { - ContactClient contactClient = new ContactClient(); String payloadTemplate = "%s"; String xmlPayload = String.format(payloadTemplate, contactPart.asXML()); PoxPayloadIn input = new PoxPayloadIn(xmlPayload); AuthorityResourceWithContacts contactResource = (AuthorityResourceWithContacts) getServiceContext().getResource(); - contactResource.createContact(getServiceContext(), authorityCsid, itemCsid, input, null); } + + private boolean csidInList(String csid, AbstractCommonList existingContactsList) { + boolean result = false; + + List itemList = existingContactsList.getListItem(); + for (ListItem item: itemList) { + if (getCsid(item).equalsIgnoreCase(csid)) { + result = true; + break; + } + } + + return result; + } + + /* + * Updates the contact list for an authority item. *** warning *** Will not page through all existing contacts, so if the authority + * items has more than a page of contacts (page size is 40 by default), this behavior of this function is + * undefined. + */ + private void handleContactUpdate(DocumentWrapper wrapDoc) throws Exception { + ServiceContext ctx = getServiceContext(); + DocumentModel docModel = wrapDoc.getWrappedObject(); + String authorityCsid = this.getInAuthorityCsid(); + String itemCsid = this.getCsid(docModel); + PoxPayloadIn input = ctx.getInput(); + ContactClient contactClient = new ContactClient(); + + AuthorityResourceWithContacts contactResource = (AuthorityResourceWithContacts) ctx.getResource(); + AbstractCommonList existingContactList = contactResource.getContactList(ctx, authorityCsid, itemCsid, null); + List contactPartList = input.getParts(contactClient.getCommonPartName()); + + // + // If there are no update payloads, then return + // + if (contactPartList.isEmpty()) { + return; + } + + // + // If there are no existing contacts and we're given an update payload then fail with + // an exception + // + if (existingContactList.getTotalItems() == 0 && !contactPartList.isEmpty()) { + throw new DocumentException("There was a request to update a contact that does not exist."); + } + + // + // If there are more update payloads than existing contacts then fail with an exception + // + if (existingContactList.getTotalItems() < contactPartList.size()) { + throw new DocumentException("There are more update payloads than existing contacts."); + } + + // + // If there is only one existing contact and only 1 update payload being sent then + // update the existing contact -assuming the CSID (if any) in the update payload matches + // the CSID of the existing contact + // + if (existingContactList.getTotalItems() == 1 && contactPartList.size() == 1) { + String existingContactCsid = this.getCsid(existingContactList.getListItem().get(0)); + PayloadInputPart contactPart = contactPartList.get(0); + ContactsCommon contactUpdate = (ContactsCommon) contactPart.getBody(); + + if (Tools.isEmpty(contactUpdate.getCsid()) == true) { + // + // Assume the incoming update payload refers to the one (and only) existing contact + // + contactResource.updateContact(ctx, authorityCsid, itemCsid, existingContactCsid, contactPart); + return; + } else { + if (contactUpdate.getCsid().equalsIgnoreCase(existingContactCsid)) { + contactResource.updateContact(ctx, authorityCsid, itemCsid, existingContactCsid, contactPart); + return; + } else { + throw new DocumentException("The CSID's of the contact being requested an update does not match the existing contact CSID."); + } + } + } + + // + // If we've made it this far, it better mean that the number of update payloads is the same as the + // number of existing contacts. If so, all the payloads need to have CSIDs that match a CSID of an existing + // contact + // + if (existingContactList.getTotalItems() == contactPartList.size()) { + for (PayloadInputPart contactPart: contactPartList) { + ContactsCommon contact = (ContactsCommon) contactPart.getBody(); + if (Tools.isEmpty(contact.getCsid()) == false) { + if (csidInList(contact.getCsid(), existingContactList)) { + contactResource.updateContact(ctx, authorityCsid, itemCsid, contact.getCsid(), contactPart); + } + } else { + throw new DocumentException("Contact payload for update did not contain a CSID."); + } + } + } else { + throw new DocumentException("The number of update payloads does not match the number of existing contacts."); + } + + + } } diff --git a/services/client/src/main/java/org/collectionspace/services/client/PoxPayload.java b/services/client/src/main/java/org/collectionspace/services/client/PoxPayload.java index ac51a5a82..be355ba21 100644 --- a/services/client/src/main/java/org/collectionspace/services/client/PoxPayload.java +++ b/services/client/src/main/java/org/collectionspace/services/client/PoxPayload.java @@ -251,6 +251,21 @@ public abstract class PoxPayload { return result; } + public List getParts(String label) { + List result = new ArrayList(); + if (parts != null) { + Iterator it = parts.iterator(); + while (it.hasNext() == true) { + PT part = it.next(); + if (part.getLabel().equalsIgnoreCase(label) == true) { + result.add(part); + } + } + } + + return result; + } + /** * Gets a list of the POX parts. * 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 31188b7c8..202349db5 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 @@ -53,6 +53,7 @@ import org.collectionspace.services.common.relation.nuxeo.RelationsUtils; import org.collectionspace.services.config.service.DocHandlerParams; import org.collectionspace.services.config.service.ListResultField; import org.collectionspace.services.jaxb.AbstractCommonList; +import org.collectionspace.services.jaxb.AbstractCommonList.ListItem; import org.collectionspace.services.nuxeo.client.java.CommonList; import org.collectionspace.services.nuxeo.client.java.RemoteDocumentModelHandlerImpl; import org.collectionspace.services.nuxeo.util.NuxeoUtils; @@ -61,6 +62,7 @@ import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.api.DocumentModelList; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; /** * This class is generified by the marker type T, @@ -109,6 +111,20 @@ public abstract class NuxeoDocumentModelHandler extends RemoteDocumentModelHa this.commonPart = commonPart; } + protected String getCsid(ListItem item) { + String result = null; + + for (Element ele : item.getAny()) { + String elementName = ele.getTagName().toLowerCase(); + if (elementName.equals("csid")) { + result = ele.getTextContent(); + break; + } + } + + return result; + } + /** * The entity type expected from the JAX-RS Response object. By default it is of type String. Child classes * can override this if they need to. -- 2.47.3