1 package org.collectionspace.services.batch.nuxeo;
3 import java.net.URISyntaxException;
4 import java.util.Arrays;
5 import java.util.HashMap;
9 import javax.ws.rs.WebApplicationException;
10 import javax.ws.rs.core.Response;
12 import org.apache.commons.lang.StringUtils;
13 import org.collectionspace.services.client.CollectionSpaceClientUtils;
14 import org.collectionspace.services.client.LoanoutClient;
15 import org.collectionspace.services.client.PoxPayloadOut;
16 import org.collectionspace.services.client.workflow.WorkflowClient;
17 import org.collectionspace.services.collectionobject.nuxeo.CollectionObjectBotGardenConstants;
18 import org.collectionspace.services.collectionobject.nuxeo.CollectionObjectConstants;
19 import org.collectionspace.services.common.NuxeoBasedResource;
20 import org.collectionspace.services.common.invocable.InvocationResults;
21 import org.collectionspace.services.common.relation.nuxeo.RelationConstants;
22 import org.collectionspace.services.loanout.nuxeo.LoanoutBotGardenConstants;
23 import org.collectionspace.services.loanout.nuxeo.LoanoutConstants;
24 import org.collectionspace.services.movement.nuxeo.MovementConstants;
25 import org.collectionspace.services.place.nuxeo.PlaceBotGardenConstants;
26 import org.collectionspace.services.place.nuxeo.PlaceConstants;
27 import org.dom4j.DocumentException;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
31 public class CreateVoucherBatchJob extends AbstractBatchJob {
32 final Logger logger = LoggerFactory.getLogger(CreateVoucherBatchJob.class);
34 public CreateVoucherBatchJob() {
35 setSupportedInvocationModes(Arrays.asList(INVOCATION_MODE_SINGLE));
40 setCompletionStatus(STATUS_MIN_PROGRESS);
43 String mode = getInvocationContext().getMode();
45 if (!mode.equalsIgnoreCase(INVOCATION_MODE_SINGLE)) {
46 throw new Exception("Unsupported invocation mode: " + mode);
49 String csid = getInvocationContext().getSingleCSID();
51 if (StringUtils.isEmpty(csid)) {
52 throw new Exception("Missing context csid");
55 String docType = getInvocationContext().getDocType();
57 if (docType.equals(CollectionObjectConstants.NUXEO_DOCTYPE)) {
58 setResults(createVoucherFromCataloging(csid));
60 else if (docType.equals(MovementConstants.NUXEO_DOCTYPE)) {
61 setResults(createVoucherFromCurrentLocation(csid));
64 throw new Exception("Unsupported docType: " + docType);
67 setCompletionStatus(STATUS_COMPLETE);
70 setCompletionStatus(STATUS_ERROR);
71 setErrorInfo(new InvocationError(INT_ERROR_STATUS, e.getMessage()));
75 public InvocationResults createVoucherFromCataloging(String collectionObjectCsid) throws Exception {
76 return createVoucherFromCataloging(collectionObjectCsid, null);
79 public InvocationResults createVoucherFromCataloging(String collectionObjectCsid, String movementCsid) throws Exception {
80 InvocationResults results = new InvocationResults();
82 PoxPayloadOut collectionObjectPayload = findCollectionObjectByCsid(collectionObjectCsid);
83 String collectionObjectWorkflowState = getFieldValue(collectionObjectPayload, CollectionObjectBotGardenConstants.WORKFLOW_STATE_SCHEMA_NAME,
84 CollectionObjectBotGardenConstants.WORKFLOW_STATE_FIELD_NAME);
86 if (collectionObjectWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_DELETED)) {
87 logger.debug("skipping deleted collectionobject: collectionObjectCsid=" + collectionObjectCsid);
89 results.setNumAffected(0);
90 results.setUserNote("skipped deleted record");
93 Map<String, String> botGardenFields = new HashMap<String, String>();
95 if (movementCsid == null) {
96 movementCsid = findSingleRelatedMovement(collectionObjectCsid);
99 if (movementCsid != null) {
100 PoxPayloadOut movementPayload = findMovementByCsid(movementCsid);
102 if (movementPayload != null) {
103 botGardenFields.put("gardenLocation", getFieldValue(movementPayload, MovementConstants.CURRENT_LOCATION_SCHEMA_NAME, MovementConstants.CURRENT_LOCATION_FIELD_NAME));
107 botGardenFields.put("fieldCollectionNote", getFieldCollectionNote(collectionObjectPayload));
108 botGardenFields.put("annotation", getAnnotation(collectionObjectPayload));
109 botGardenFields.put("labelRequested", LoanoutBotGardenConstants.LABEL_REQUESTED_NO_VALUE);
111 Map<String, String> naturalHistoryFields = new HashMap<String, String>();
112 naturalHistoryFields.put("numLent", "1");
114 String voucherCsid = createVoucher(botGardenFields, naturalHistoryFields);
115 logger.debug("voucher created: voucherCsid=" + voucherCsid);
117 String forwardRelationCsid = createRelation(voucherCsid, LoanoutConstants.NUXEO_DOCTYPE, collectionObjectCsid, CollectionObjectConstants.NUXEO_DOCTYPE, RelationConstants.AFFECTS_TYPE);
118 String backwardRelationCsid = createRelation(collectionObjectCsid, CollectionObjectConstants.NUXEO_DOCTYPE, voucherCsid, LoanoutConstants.NUXEO_DOCTYPE, RelationConstants.AFFECTS_TYPE);
119 logger.debug("relations created: forwardRelationCsid=" + forwardRelationCsid + " backwardRelationCsid=" + backwardRelationCsid);
121 results.setNumAffected(1);
122 results.setPrimaryURICreated("/loansout/" + voucherCsid);
123 results.setUserNote("Voucher created");
129 private String getFieldCollectionNote(PoxPayloadOut collectionObjectPayload) throws Exception {
130 String placeNote = "";
131 String reverseFieldCollectionPlace = getReverseFieldCollectionPlace(collectionObjectPayload);
133 if (StringUtils.isNotBlank(reverseFieldCollectionPlace)) {
134 placeNote = reverseFieldCollectionPlace;
137 String taxonomicRange = this.getFieldValue(collectionObjectPayload, CollectionObjectBotGardenConstants.TAXONOMIC_RANGE_SCHEMA_NAME,
138 CollectionObjectBotGardenConstants.TAXONOMIC_RANGE_FIELD_NAME);
140 if (StringUtils.isNotBlank(taxonomicRange)) {
141 placeNote = "Geographic range " + taxonomicRange;
145 String comment = this.getFieldValue(collectionObjectPayload, CollectionObjectBotGardenConstants.COMMENT_SCHEMA_NAME,
146 CollectionObjectBotGardenConstants.COMMENT_FIELD_NAME);
147 String collectionNote = "";
149 if (StringUtils.isNotBlank(placeNote) && StringUtils.isNotBlank(comment)) {
150 collectionNote = placeNote + ": " + comment;
152 else if (StringUtils.isNotBlank(placeNote)) {
153 collectionNote = placeNote;
156 collectionNote = comment;
159 return collectionNote;
162 private String getReverseFieldCollectionPlace(PoxPayloadOut collectionObjectPayload) throws Exception {
163 String reverseDisplayName = null;
164 String fieldCollectionPlaceRefName = getFieldValue(collectionObjectPayload, CollectionObjectBotGardenConstants.FIELD_COLLECTION_PLACE_SCHEMA_NAME,
165 CollectionObjectBotGardenConstants.FIELD_COLLECTION_PLACE_FIELD_NAME);
167 if (StringUtils.isNotBlank(fieldCollectionPlaceRefName)) {
168 PoxPayloadOut placePayload = null;
171 placePayload = findPlaceByRefName(fieldCollectionPlaceRefName);
173 catch (WebApplicationException e) {
174 logger.error("Error finding place: refName=" + fieldCollectionPlaceRefName, e);
177 if (placePayload != null) {
178 List<String> termTypes = getFieldValues(placePayload, PlaceConstants.TERM_TYPE_SCHEMA_NAME, PlaceConstants.TERM_TYPE_FIELD_NAME);
179 List<String> displayNames = getFieldValues(placePayload, PlaceConstants.DISPLAY_NAME_SCHEMA_NAME, PlaceConstants.DISPLAY_NAME_FIELD_NAME);
181 int index = termTypes.indexOf(PlaceBotGardenConstants.REVERSE_TERM_TYPE);
184 // There's no reverse term. Just use the primary.
186 if (displayNames.size() > 0) {
187 reverseDisplayName = displayNames.get(0);
191 reverseDisplayName = displayNames.get(index);
196 if (reverseDisplayName == null) {
197 reverseDisplayName = "";
200 return reverseDisplayName;
203 private String getAnnotation(PoxPayloadOut collectionObjectPayload) {
204 String annotation = "";
205 String determinationKind = getFieldValue(collectionObjectPayload, CollectionObjectBotGardenConstants.DETERMINATION_KIND_SCHEMA_NAME,
206 CollectionObjectBotGardenConstants.DETERMINATION_KIND_FIELD_NAME);
208 if (determinationKind.equals(CollectionObjectBotGardenConstants.DETERMINATION_KIND_DETERMINATION_VALUE)) {
209 String determinationBy = getDisplayNameFromRefName(getFieldValue(collectionObjectPayload, CollectionObjectBotGardenConstants.DETERMINATION_BY_SCHEMA_NAME,
210 CollectionObjectBotGardenConstants.DETERMINATION_BY_FIELD_NAME));
212 if (StringUtils.isNotBlank(determinationBy)) {
213 annotation += "det. by " + determinationBy;
215 String determinationInstitution = getDisplayNameFromRefName(getFieldValue(collectionObjectPayload, CollectionObjectBotGardenConstants.DETERMINATION_INSTITUTION_SCHEMA_NAME,
216 CollectionObjectBotGardenConstants.DETERMINATION_INSTITUTION_FIELD_NAME));
217 String determinationDate = getFieldValue(collectionObjectPayload, CollectionObjectBotGardenConstants.DETERMINATION_DATE_SCHEMA_NAME,
218 CollectionObjectBotGardenConstants.DETERMINATION_DATE_FIELD_NAME);
220 if (StringUtils.isNotBlank(determinationInstitution)) {
221 annotation += ", " + determinationInstitution;
224 if (StringUtils.isNotBlank(determinationDate)) {
225 annotation += ", " + determinationDate;
233 public InvocationResults createVoucherFromCurrentLocation(String movementCsid) throws Exception {
234 long numAffected = 0;
235 String primaryUriCreated = null;
237 List<String> collectionObjectCsids = findRelatedCollectionObjects(movementCsid);
239 for (String collectionObjectCsid : collectionObjectCsids) {
240 InvocationResults innerResults = createVoucherFromCataloging(collectionObjectCsid, movementCsid);
242 numAffected = numAffected + innerResults.getNumAffected();
244 if (primaryUriCreated == null) {
245 primaryUriCreated = innerResults.getPrimaryURICreated();
249 InvocationResults results = new InvocationResults();
250 results.setNumAffected(numAffected);
251 results.setPrimaryURICreated(primaryUriCreated);
253 if (collectionObjectCsids.size() == 0) {
254 results.setUserNote("No related cataloging record found");
257 results.setUserNote("Voucher created for " + numAffected + " cataloging " + (numAffected == 1 ? "record" : "records"));
263 private String createVoucher(Map<String, String> botGardenFields, Map<String, String> naturalHistoryFields) throws ResourceException {
264 String voucherCsid = null;
266 String createVoucherPayload =
267 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
268 "<document name=\"loansout\">" +
269 "<ns2:loansout_botgarden xmlns:ns2=\"http://collectionspace.org/services/loanout/local/botgarden\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +
270 getFieldXml(botGardenFields) +
271 "</ns2:loansout_botgarden>" +
272 "<ns2:loansout_naturalhistory xmlns:ns2=\"http://collectionspace.org/services/loanout/domain/naturalhistory\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +
273 getFieldXml(naturalHistoryFields) +
274 "</ns2:loansout_naturalhistory>" +
277 NuxeoBasedResource resource = (NuxeoBasedResource) getResourceMap().get(LoanoutClient.SERVICE_NAME);
278 Response response = resource.create(getServiceContext(), getResourceMap(), null, createVoucherPayload);
280 if (response.getStatus() == CREATED_STATUS) {
281 voucherCsid = CollectionSpaceClientUtils.extractId(response);
284 throw new ResourceException(response, "Error creating voucher");