From 12c3613d9a74e87dcb2faba6bab3256dae34ccb8 Mon Sep 17 00:00:00 2001 From: Aron Roberts Date: Thu, 10 Jan 2013 14:35:09 -0800 Subject: [PATCH] CSPACE-5728: Internal refactoring to split a large method into multiple, smaller and more focused methods. --- .../nuxeo/UpdateObjectLocationBatchJob.java | 369 ++++++++++-------- 1 file changed, 205 insertions(+), 164 deletions(-) diff --git a/services/batch/service/src/main/java/org/collectionspace/services/batch/nuxeo/UpdateObjectLocationBatchJob.java b/services/batch/service/src/main/java/org/collectionspace/services/batch/nuxeo/UpdateObjectLocationBatchJob.java index 60be464f3..fed02d2a7 100644 --- a/services/batch/service/src/main/java/org/collectionspace/services/batch/nuxeo/UpdateObjectLocationBatchJob.java +++ b/services/batch/service/src/main/java/org/collectionspace/services/batch/nuxeo/UpdateObjectLocationBatchJob.java @@ -10,7 +10,6 @@ import java.util.HashSet; import java.util.List; import java.util.Set; import javax.ws.rs.core.PathSegment; -import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; import org.collectionspace.services.batch.AbstractBatchInvocable; import org.collectionspace.services.client.AbstractCommonListUtils; @@ -58,7 +57,6 @@ public class UpdateObjectLocationBatchJob extends AbstractBatchInvocable { COLLECTIONOBJECTS_COMMON_NAMESPACE_URI); private final static String NONDELETED_QUERY_COMPONENT = "&" + WorkflowClient.WORKFLOW_QUERY_NONDELETED + "=false"; - private PoxPayloadOut payloadOut; private final String CLASSNAME = this.getClass().getSimpleName(); private final Logger logger = LoggerFactory.getLogger(this.getClass()); @@ -78,6 +76,9 @@ public class UpdateObjectLocationBatchJob extends AbstractBatchInvocable { try { List csids = new ArrayList(); + + // Build a list of CollectionObject records to process via this + // batch job, depending on the invocation mode requested. if (requestIsForInvocationModeSingle()) { String singleCsid = getInvocationContext().getSingleCSID(); if (Tools.isBlank(singleCsid)) { @@ -101,7 +102,7 @@ public class UpdateObjectLocationBatchJob extends AbstractBatchInvocable { // FIXME: Add code to invoke batch job on every active CollectionObject } - // Update the computed current location field for each CollectionObject + // Update the value of the computed current location field for each CollectionObject setResults(updateComputedCurrentLocations(csids)); setCompletionStatus(STATUS_COMPLETE); @@ -112,6 +113,206 @@ public class UpdateObjectLocationBatchJob extends AbstractBatchInvocable { } + private InvocationResults updateComputedCurrentLocations(List csids) { + + ResourceMap resourcemap = getResourceMap(); + ResourceBase collectionObjectResource = resourcemap.get(CollectionObjectClient.SERVICE_NAME); + ResourceBase movementResource = resourcemap.get(MovementClient.SERVICE_NAME); + String computedCurrentLocation; + PoxPayloadOut payloadOut; + int numAffected = 0; + + try { + + // For each CollectionObject record + for (String collectionObjectCsid : csids) { + + // Skip over soft-deleted CollectionObject records + if (isRecordDeleted(collectionObjectResource, collectionObjectCsid)) { + if (logger.isTraceEnabled()) { + logger.trace("Skipping soft-deleted CollectionObject record with CSID " + collectionObjectCsid); + } + continue; + } + + // Get the Movement records related to this record + AbstractCommonList relatedMovements = getRelatedMovements(movementResource, collectionObjectCsid); + + // Skip over CollectionObject records that have no related Movement records + if (relatedMovements.getListItem().isEmpty()) { + continue; + } + + // Based on data in its related Movement records, compute the + // current location of this CollectionObject + computedCurrentLocation = computeCurrentLocation(relatedMovements); + + // Skip over CollectionObject records where no computed current + // location value can be obtained from related Movement records. + // + // FIXME: Clarify: it ever necessary to 'unset' a computed + // current location value, by setting it to a null or empty value, + // if that value is no longer obtainable from related Movement records? + if (Tools.isBlank(computedCurrentLocation)) { + continue; + } + + // Update the value of the computed current location field + // in the CollectionObject record + numAffected = updateComputedCurrentLocationValue(collectionObjectResource, + collectionObjectCsid, computedCurrentLocation, resourcemap, numAffected); + } + + } catch (Exception e) { + String errMsg = "Error encountered in " + CLASSNAME + ": " + e.getLocalizedMessage() + " "; + errMsg = errMsg + "Successfully updated " + numAffected + " CollectionObject record(s) prior to error."; + logger.error(errMsg); + setErrorResult(errMsg); + getResults().setNumAffected(numAffected); + return getResults(); + } + + logger.info("Updated computedCurrentLocation values in " + numAffected + " CollectionObject record(s)."); + getResults().setNumAffected(numAffected); + return getResults(); + } + + private AbstractCommonList getRelatedMovements(ResourceBase movementResource, String csid) + throws URISyntaxException, DocumentException { + + // Get movement records related to a record, specified by its CSID, + // where the record is the object of the relation + // FIXME: Get query string(s) from constant(s), where appropriate + String queryString = "rtObj=" + csid + NONDELETED_QUERY_COMPONENT; + UriInfo uriInfo = createRelatedRecordsUriInfo(queryString); + AbstractCommonList relatedMovements = movementResource.getList(uriInfo); + if (logger.isTraceEnabled()) { + logger.trace("Identified " + relatedMovements.getTotalItems() + + " Movement record(s) related to the object CollectionObject record " + csid); + } + + // Get movement records related to a record, specified by its CSID, + // where the record is the subject of the relation + // FIXME: Get query string(s) from constant(s), where appropriate + queryString = "rtSbj=" + csid + NONDELETED_QUERY_COMPONENT; + uriInfo = createRelatedRecordsUriInfo(queryString); + AbstractCommonList reverseRelatedMovements = movementResource.getList(uriInfo); + if (logger.isTraceEnabled()) { + logger.trace("Identified " + reverseRelatedMovements.getTotalItems() + + " Movement record(s) related to the subject CollectionObject record " + csid); + } + + // If the second list contains any related movement records, + // merge it into the first list + if (reverseRelatedMovements.getListItem().size() > 0) { + relatedMovements.getListItem().addAll(reverseRelatedMovements.getListItem()); + } + + if (logger.isTraceEnabled()) { + logger.trace("Identified a total of " + relatedMovements.getListItem().size() + + " Movement record(s) related to the subject CollectionObject record " + csid); + } + + return relatedMovements; + } + + private String computeCurrentLocation(AbstractCommonList relatedMovements) { + String computedCurrentLocation; + String movementCsid; + Set alreadyProcessedMovementCsids = new HashSet(); + computedCurrentLocation = ""; + String currentLocation; + String locationDate; + String mostRecentLocationDate = ""; + for (AbstractCommonList.ListItem movementRecord : relatedMovements.getListItem()) { + movementCsid = AbstractCommonListUtils.ListItemGetElementValue(movementRecord, CSID_ELEMENT_NAME); + if (Tools.isBlank(movementCsid)) { + continue; + } + // Avoid processing any related Movement record more than once, + // regardless of the directionality of its relation(s) to this + // CollectionObject record. + if (alreadyProcessedMovementCsids.contains(movementCsid)) { + continue; + } else { + alreadyProcessedMovementCsids.add(movementCsid); + } + locationDate = AbstractCommonListUtils.ListItemGetElementValue(movementRecord, LOCATION_DATE_ELEMENT_NAME); + if (Tools.isBlank(locationDate)) { + continue; + } + currentLocation = AbstractCommonListUtils.ListItemGetElementValue(movementRecord, CURRENT_LOCATION_ELEMENT_NAME); + if (Tools.isBlank(currentLocation)) { + continue; + } + if (logger.isTraceEnabled()) { + logger.trace("Location date value = " + locationDate); + logger.trace("Current location value = " + currentLocation); + } + // If this record's location date value is more recent than that of other + // Movement records processed so far, set the computed current location + // to its current location value. + // + // Assumes that all values for this element/field will be consistent ISO 8601 + // date/time representations, each of which can be ordered via string comparison. + // + // If this is *not* the case, we can instead parse and convert these values + // to date/time objects. + if (locationDate.compareTo(mostRecentLocationDate) > 0) { + mostRecentLocationDate = locationDate; + // FIXME: Add optional validation here that the currentLocation value + // parses successfully as an item refName. (We might make that validation + // dependent on the value of a parameter passed in during batch job invocation.) + computedCurrentLocation = currentLocation; + } + + } + return computedCurrentLocation; + } + + private int updateComputedCurrentLocationValue(ResourceBase collectionObjectResource, + String collectionObjectCsid, String computedCurrentLocation, ResourceMap resourcemap, int numAffected) + throws DocumentException, URISyntaxException { + PoxPayloadOut collectionObjectPayload; + String objectNumber; + + collectionObjectPayload = findByCsid(collectionObjectResource, collectionObjectCsid); + if (Tools.notBlank(collectionObjectPayload.toXML())) { + if (logger.isTraceEnabled()) { + logger.trace("Payload: " + "\n" + collectionObjectPayload); + } + objectNumber = getFieldElementValue(collectionObjectPayload, + COLLECTIONOBJECTS_COMMON_SCHEMA_NAME, COLLECTIONOBJECTS_COMMON_NAMESPACE, + OBJECT_NUMBER_ELEMENT_NAME); + if (logger.isTraceEnabled()) { + logger.trace("Object number: " + objectNumber); + } + if (Tools.notBlank(objectNumber)) { + String collectionObjectUpdatePayload = + "" + + "" + + " " + + " " + objectNumber + "" + + " " + computedCurrentLocation + "" + + " " + + ""; + if (logger.isTraceEnabled()) { + logger.trace("Update payload: " + "\n" + collectionObjectUpdatePayload); + } + byte[] response = collectionObjectResource.update(resourcemap, null, collectionObjectCsid, + collectionObjectUpdatePayload); + numAffected++; + if (logger.isTraceEnabled()) { + logger.trace("Computed current location value for CollectionObject " + collectionObjectCsid + + " was set to " + computedCurrentLocation); + } + } + + } + return numAffected; + } + // ################################################################# // Ray's convenience methods from his AbstractBatchJob class for the // UC Berkeley Botanical Garden v2.4 implementation. @@ -176,7 +377,7 @@ public class UpdateObjectLocationBatchJob extends AbstractBatchInvocable { boolean isDeleted = false; byte[] workflowResponse = resource.getWorkflow(createUriInfo(), collectionObjectCsid); if (workflowResponse != null) { - payloadOut = new PoxPayloadOut(workflowResponse); + PoxPayloadOut payloadOut = new PoxPayloadOut(workflowResponse); String workflowState = getFieldElementValue(payloadOut, WORKFLOW_COMMON_SCHEMA_NAME, WORKFLOW_COMMON_NAMESPACE, LIFECYCLE_STATE_ELEMENT_NAME); @@ -186,164 +387,4 @@ public class UpdateObjectLocationBatchJob extends AbstractBatchInvocable { } return isDeleted; } - - private InvocationResults updateComputedCurrentLocations(List csids) { - - ResourceMap resourcemap = getResourceMap(); - ResourceBase collectionObjectResource = resourcemap.get(CollectionObjectClient.SERVICE_NAME); - ResourceBase movementResource = resourcemap.get(MovementClient.SERVICE_NAME); - PoxPayloadOut collectionObjectPayload; - String computedCurrentLocation; - String objectNumber; - String movementCsid; - PoxPayloadOut payloadOut; - String queryString; - int numAffected = 0; - - try { - - // For each CollectionObject record - for (String collectionObjectCsid : csids) { - - // Skip over soft-deleted CollectionObject records - if (isRecordDeleted(collectionObjectResource, collectionObjectCsid)) { - if (logger.isTraceEnabled()) { - logger.trace("Skipping soft-deleted CollectionObject record with CSID " + collectionObjectCsid); - } - continue; - } - - // Get the movement records related to this record - - // Get movement records related to this record where the CollectionObject - // record is the subject of the relation - // FIXME: Get query string(s) from constant(s), where appropriate - queryString = "rtObj=" + collectionObjectCsid + NONDELETED_QUERY_COMPONENT; - UriInfo uriInfo = createRelatedRecordsUriInfo(queryString); - - AbstractCommonList relatedMovements = movementResource.getList(uriInfo); - if (logger.isTraceEnabled()) { - logger.trace("Identified " + relatedMovements.getTotalItems() - + " Movement record(s) related to the object CollectionObject record " + collectionObjectCsid); - } - - // Get movement records related to this record where the CollectionObject - // record is the object of the relation - // FIXME: Get query string(s) from constant(s), where appropriate - queryString = "rtSbj=" + collectionObjectCsid + NONDELETED_QUERY_COMPONENT; - uriInfo = createRelatedRecordsUriInfo(queryString); - - AbstractCommonList reverseRelatedMovements = movementResource.getList(uriInfo); - if (logger.isTraceEnabled()) { - logger.trace("Identified " + reverseRelatedMovements.getTotalItems() - + " Movement record(s) related to the subject CollectionObject record " + collectionObjectCsid); - } - - if ((relatedMovements.getTotalItems() == 0) && reverseRelatedMovements.getTotalItems() == 0) { - continue; - } - - // Merge the two lists of related movement records - relatedMovements.getListItem().addAll(reverseRelatedMovements.getListItem()); - - if (logger.isTraceEnabled()) { - logger.trace("Identified a total of " + relatedMovements.getListItem().size() - + " Movement record(s) related to the subject CollectionObject record " + collectionObjectCsid); - } - - // Get the latest movement record from among those, and extract - // its current location value - Set alreadyProcessedMovementCsids = new HashSet(); - computedCurrentLocation = ""; - String currentLocation; - String locationDate; - String mostRecentLocationDate = ""; - for (AbstractCommonList.ListItem movementRecord : relatedMovements.getListItem()) { - movementCsid = AbstractCommonListUtils.ListItemGetElementValue(movementRecord, CSID_ELEMENT_NAME); - if (Tools.isBlank(movementCsid)) { - continue; - } - // Avoid processing any related Movement record more than once, - // regardless of the directionality of its relation(s) to this - // CollectionObject record. - if (alreadyProcessedMovementCsids.contains(movementCsid)) { - continue; - } else { - alreadyProcessedMovementCsids.add(movementCsid); - } - locationDate = AbstractCommonListUtils.ListItemGetElementValue(movementRecord, LOCATION_DATE_ELEMENT_NAME); - if (Tools.isBlank(locationDate)) { - continue; - } - currentLocation = AbstractCommonListUtils.ListItemGetElementValue(movementRecord, CURRENT_LOCATION_ELEMENT_NAME); - if (Tools.isBlank(currentLocation)) { - continue; - } - if (logger.isTraceEnabled()) { - logger.trace("Location date value = " + locationDate); - logger.trace("Current location value = " + currentLocation); - } - // Assumes that all values for this element/field will be consistent ISO 8601 - // date/time representations, each of which can be ordered via string comparison. - // - // If this is *not* the case, we can instead parse and convert these values - // to date/time objects. - if (locationDate.compareTo(mostRecentLocationDate) > 0) { - mostRecentLocationDate = locationDate; - // FIXME: Add optional validation here that the currentLocation value - // parses successfully as an item refName - computedCurrentLocation = currentLocation; - } - - } - - // Update the computed current location value in the CollectionObject record - collectionObjectPayload = findByCsid(collectionObjectResource, collectionObjectCsid); - if (Tools.notBlank(collectionObjectPayload.toXML())) { - if (logger.isTraceEnabled()) { - logger.trace("Payload: " + "\n" + collectionObjectPayload); - } - objectNumber = getFieldElementValue(collectionObjectPayload, - COLLECTIONOBJECTS_COMMON_SCHEMA_NAME, COLLECTIONOBJECTS_COMMON_NAMESPACE, - OBJECT_NUMBER_ELEMENT_NAME); - if (logger.isTraceEnabled()) { - logger.trace("Object number: " + objectNumber); - } - if (Tools.notBlank(objectNumber)) { - String collectionObjectUpdatePayload = - "" - + "" - + " " - + " " + objectNumber + "" - + " " + computedCurrentLocation + "" - + " " - + ""; - if (logger.isTraceEnabled()) { - logger.trace("Update payload: " + "\n" + collectionObjectUpdatePayload); - } - byte[] response = collectionObjectResource.update(resourcemap, null, collectionObjectCsid, - collectionObjectUpdatePayload); - numAffected++; - if (logger.isTraceEnabled()) { - logger.trace("Computed current location value for CollectionObject " + collectionObjectCsid - + " was set to " + computedCurrentLocation); - } - } - - } - } - } catch (Exception e) { - String errMsg = "Error encountered in " + CLASSNAME + ": " + e.getLocalizedMessage() + " "; - errMsg = errMsg + "Successfully updated " + numAffected + " CollectionObject record(s) prior to error."; - logger.error(errMsg); - setErrorResult(errMsg); - getResults().setNumAffected(numAffected); - return getResults(); - } - - logger.info("Updated computedCurrentLocation values in " + numAffected + " CollectionObject record(s)."); - getResults().setNumAffected(numAffected); - return getResults(); - } } -- 2.47.3