1 package org.collectionspace.services.batch.nuxeo;
4 import java.net.URISyntaxException;
5 import java.util.ArrayList;
6 import java.util.Arrays;
7 import java.util.Collections;
8 import java.util.HashMap;
11 import javax.ws.rs.core.PathSegment;
12 import javax.ws.rs.core.Response;
13 import javax.ws.rs.core.UriInfo;
14 import org.collectionspace.services.batch.AbstractBatchInvocable;
15 import org.collectionspace.services.client.CollectionObjectClient;
16 import org.collectionspace.services.client.CollectionSpaceClientUtils;
17 import org.collectionspace.services.client.PayloadOutputPart;
18 import org.collectionspace.services.client.PoxPayloadOut;
19 import org.collectionspace.services.common.ResourceBase;
20 import org.collectionspace.services.common.ResourceMap;
21 import org.collectionspace.services.common.api.Tools;
22 import org.collectionspace.services.common.invocable.InvocationResults;
23 import org.dom4j.DocumentException;
24 import org.dom4j.DocumentHelper;
25 import org.dom4j.Element;
26 import org.dom4j.Node;
27 import org.dom4j.XPath;
28 import org.jboss.resteasy.specimpl.UriInfoImpl;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
32 public class UpdateObjectLocationBatchJob extends AbstractBatchInvocable {
34 // FIXME; Get from existing constants and replace these local declarations
35 final static String COLLECTIONOBJECTS_COMMON_SCHEMA_NAME = "collectionobjects_common";
36 final static String OBJECT_NUMBER_FIELD_NAME = "objectNumber";
37 private InvocationResults results = new InvocationResults();
38 final String CLASSNAME = this.getClass().getSimpleName();
39 final Logger logger = LoggerFactory.getLogger(UpdateObjectLocationBatchJob.class);
41 // Initialization tasks
42 public UpdateObjectLocationBatchJob() {
43 setSupportedInvocationModes(Arrays.asList(INVOCATION_MODE_SINGLE, INVOCATION_MODE_LIST));
47 * The main work logic of the batch job. Will be called after setContext.
52 setCompletionStatus(STATUS_MIN_PROGRESS);
55 // FIXME: Placeholder during early development
56 if (logger.isInfoEnabled()) {
57 logger.info("Invoking " + CLASSNAME + " ...");
58 logger.info("Invocation context is: " + getInvocationContext().getMode());
61 if (!requestedInvocationModeIsSupported()) {
62 setInvocationModeNotSupportedResult();
65 List<String> csids = new ArrayList<String>();
66 if (requestIsForInvocationModeSingle()) {
67 String singleCsid = getInvocationContext().getSingleCSID();
68 if (Tools.notBlank(singleCsid)) {
69 csids.add(singleCsid);
71 } else if (requestIsForInvocationModeList()) {
72 List<String> listCsids = (getInvocationContext().getListCSIDs().getCsid());
73 if (listCsids == null || listCsids.isEmpty()) {
74 throw new Exception(CSID_VALUES_NOT_PROVIDED_IN_INVOCATION_CONTEXT_MESSAGE);
76 csids.addAll(listCsids);
77 } else if (requestIsForInvocationModeGroup()) {
78 String groupCsid = getInvocationContext().getGroupCSID();
79 // FIXME: Get individual CSIDs from the group
80 // and add them to the list
83 if (csids.isEmpty()) {
84 throw new Exception(CSID_VALUES_NOT_PROVIDED_IN_INVOCATION_CONTEXT_MESSAGE);
87 // Update the current computed location field for each CollectionObject
88 setResults(updateComputedCurrentLocations(csids));
89 setCompletionStatus(STATUS_COMPLETE);
91 } catch (Exception e) {
92 String errMsg = "Error encountered in " + CLASSNAME + ": " + e.getLocalizedMessage();
93 setErrorResult(errMsg);
98 // Ray's convenience methods from his AbstractBatchJob class for the UC Berkeley Botanical Garden v2.4 implementation.
99 protected PoxPayloadOut findByCsid(String serviceName, String csid) throws URISyntaxException, DocumentException {
100 ResourceBase resource = getResourceMap().get(serviceName);
101 return findByCsid(resource, csid);
104 protected PoxPayloadOut findByCsid(ResourceBase resource, String csid) throws URISyntaxException, DocumentException {
105 byte[] response = resource.get(null, createUriInfo(), csid);
106 PoxPayloadOut payload = new PoxPayloadOut(response);
110 protected UriInfo createUriInfo() throws URISyntaxException {
111 return createUriInfo("");
114 protected UriInfo createUriInfo(String queryString) throws URISyntaxException {
115 URI absolutePath = new URI("");
116 URI baseUri = new URI("");
117 return new UriInfoImpl(absolutePath, baseUri, "", queryString, Collections.<PathSegment>emptyList());
121 * Get a field value from a PoxPayloadOut, given a part name and namespace-qualified xpath
124 protected String getFieldValue(PoxPayloadOut payload, String partLabel, String namespacePrefix, String namespace, String fieldPath) {
126 PayloadOutputPart part = payload.getPart(partLabel);
129 Element element = part.asElement();
130 logger.info(partLabel + " part element =" + element.asXML());
132 Map<String, String> namespaceUris = new HashMap<String, String>();
133 namespaceUris.put(namespacePrefix, namespace);
135 XPath xPath = DocumentHelper.createXPath(fieldPath);
136 xPath.setNamespaceURIs(namespaceUris);
138 Node node = xPath.selectSingleNode(element);
139 // Node node = element.selectSingleNode(fieldPath);
142 value = node.getText();
149 protected List<String> getFieldValues(PoxPayloadOut payload, String partLabel, String fieldPath) {
150 List<String> values = new ArrayList<String>();
151 PayloadOutputPart part = payload.getPart(partLabel);
154 Element element = part.asElement();
155 List<Node> nodes = element.selectNodes(fieldPath);
158 for (Node node : nodes) {
159 values.add(node.getText());
167 private InvocationResults updateComputedCurrentLocations(List<String> csids) {
169 ResourceMap resourcemap = getResourceMap();
170 ResourceBase collectionObjectResource = resourcemap.get(CollectionObjectClient.SERVICE_NAME);
171 PoxPayloadOut collectionObjectPayload;
173 String computedCurrentLocation;
175 // FIXME: Temporary during testing/development
176 final String COMPUTED_CURRENT_LOCATION = "FOO_COMPUTED_CURRENT_LOCATION";
180 // For each CollectionObject record:
181 for (String csid : csids) {
182 // Get the movement records related to this record
183 // Get the latest movement record from among those
184 // Extract its current location value
185 // FIXME: Temporary during testing/development
186 computedCurrentLocation = COMPUTED_CURRENT_LOCATION;
187 // Update the computed current location value in the CollectionObject record
188 collectionObjectPayload = findByCsid(collectionObjectResource, csid);
189 if (Tools.notBlank(collectionObjectPayload.toXML())) {
190 if (logger.isInfoEnabled()) {
191 logger.info("Payload: " + "\n" + collectionObjectPayload);
193 // Silenly fails at various places in dom4j calls (selectSingleNode, selectNode,
194 // createXpath) in any of the methods tried above, without throwing an Exception
196 objectNumber = getFieldValue(collectionObjectPayload,
197 COLLECTIONOBJECTS_COMMON_SCHEMA_NAME,
198 "ns2", "http://collectionspace.org/services/collectionobject",
199 OBJECT_NUMBER_FIELD_NAME);
200 if (logger.isInfoEnabled()) {
201 logger.info("Object number: " + objectNumber);
204 objectNumber = "BAR"; // FIXME
205 if (Tools.notBlank(objectNumber)) {
206 String collectionObjectUpdatePayload =
207 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
208 + "<document name=\"collectionobject\">"
209 + "<ns2:collectionobjects_common xmlns:ns2=\"http://collectionspace.org/services/collectionobject\">"
210 + "<objectNumber>" + objectNumber + "</objectNumber>"
211 + "<computedCurrentLocation>" + computedCurrentLocation + "</computedCurrentLocation>"
212 + "</ns2:collectionobjects_common></document>";
213 if (logger.isInfoEnabled()) {
214 logger.info("Update payload: " + "\n" + collectionObjectUpdatePayload);
216 byte[] response = collectionObjectResource.update(resourcemap, null, csid, collectionObjectUpdatePayload);
218 * if (response.getStatus() != OK_STATUS) {
219 String errMsg = "Error encountered in " + CLASSNAME + ": " + "Updating CollectionObject failed.";
220 setErrorResult(errMsg);
222 results.setUserNote("Computed current location value for CollectionObject " + csid + " set to " + computedCurrentLocation);
230 } catch (Exception e) {
231 String errMsg = "Error encountered in " + CLASSNAME + ": " + e.getLocalizedMessage();
232 setErrorResult(errMsg);
233 getResults().setNumAffected(numAffected);
236 getResults().setNumAffected(numAffected);