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));
39 setCompletionStatus(STATUS_MIN_PROGRESS);
42 String mode = getInvocationContext().getMode();
44 if (!mode.equalsIgnoreCase(INVOCATION_MODE_SINGLE)) {
45 throw new Exception("Unsupported invocation mode: " + mode);
48 String csid = getInvocationContext().getSingleCSID();
50 if (StringUtils.isEmpty(csid)) {
51 throw new Exception("Missing context csid");
54 String docType = getInvocationContext().getDocType();
56 if (docType.equals(CollectionObjectConstants.NUXEO_DOCTYPE)) {
57 setResults(createVoucherFromCataloging(csid));
59 else if (docType.equals(MovementConstants.NUXEO_DOCTYPE)) {
60 setResults(createVoucherFromCurrentLocation(csid));
63 throw new Exception("Unsupported docType: " + docType);
66 setCompletionStatus(STATUS_COMPLETE);
69 setCompletionStatus(STATUS_ERROR);
70 setErrorInfo(new InvocationError(INT_ERROR_STATUS, e.getMessage()));
74 public InvocationResults createVoucherFromCataloging(String collectionObjectCsid) throws ResourceException, URISyntaxException, DocumentException {
75 return createVoucherFromCataloging(collectionObjectCsid, null);
78 public InvocationResults createVoucherFromCataloging(String collectionObjectCsid, String movementCsid) throws ResourceException, URISyntaxException, DocumentException {
79 InvocationResults results = new InvocationResults();
81 PoxPayloadOut collectionObjectPayload = findCollectionObjectByCsid(collectionObjectCsid);
82 String collectionObjectWorkflowState = getFieldValue(collectionObjectPayload, CollectionObjectBotGardenConstants.WORKFLOW_STATE_SCHEMA_NAME,
83 CollectionObjectBotGardenConstants.WORKFLOW_STATE_FIELD_NAME);
85 if (collectionObjectWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_DELETED)) {
86 logger.debug("skipping deleted collectionobject: collectionObjectCsid=" + collectionObjectCsid);
88 results.setNumAffected(0);
89 results.setUserNote("skipped deleted record");
92 Map<String, String> botGardenFields = new HashMap<String, String>();
94 if (movementCsid == null) {
95 movementCsid = findSingleRelatedMovement(collectionObjectCsid);
98 if (movementCsid != null) {
99 PoxPayloadOut movementPayload = findMovementByCsid(movementCsid);
101 if (movementPayload != null) {
102 botGardenFields.put("gardenLocation", getFieldValue(movementPayload, MovementConstants.CURRENT_LOCATION_SCHEMA_NAME, MovementConstants.CURRENT_LOCATION_FIELD_NAME));
106 botGardenFields.put("fieldCollectionNote", getFieldCollectionNote(collectionObjectPayload));
107 botGardenFields.put("annotation", getAnnotation(collectionObjectPayload));
108 botGardenFields.put("labelRequested", LoanoutBotGardenConstants.LABEL_REQUESTED_NO_VALUE);
110 Map<String, String> naturalHistoryFields = new HashMap<String, String>();
111 naturalHistoryFields.put("numLent", "1");
113 String voucherCsid = createVoucher(botGardenFields, naturalHistoryFields);
114 logger.debug("voucher created: voucherCsid=" + voucherCsid);
116 String forwardRelationCsid = createRelation(voucherCsid, LoanoutConstants.NUXEO_DOCTYPE, collectionObjectCsid, CollectionObjectConstants.NUXEO_DOCTYPE, RelationConstants.AFFECTS_TYPE);
117 String backwardRelationCsid = createRelation(collectionObjectCsid, CollectionObjectConstants.NUXEO_DOCTYPE, voucherCsid, LoanoutConstants.NUXEO_DOCTYPE, RelationConstants.AFFECTS_TYPE);
118 logger.debug("relations created: forwardRelationCsid=" + forwardRelationCsid + " backwardRelationCsid=" + backwardRelationCsid);
120 results.setNumAffected(1);
121 results.setPrimaryURICreated("loanout.html?csid=" + voucherCsid);
122 results.setUserNote("Voucher created");
128 private String getFieldCollectionNote(PoxPayloadOut collectionObjectPayload) throws URISyntaxException, DocumentException {
129 String placeNote = "";
130 String reverseFieldCollectionPlace = getReverseFieldCollectionPlace(collectionObjectPayload);
132 if (StringUtils.isNotBlank(reverseFieldCollectionPlace)) {
133 placeNote = reverseFieldCollectionPlace;
136 String taxonomicRange = this.getFieldValue(collectionObjectPayload, CollectionObjectBotGardenConstants.TAXONOMIC_RANGE_SCHEMA_NAME,
137 CollectionObjectBotGardenConstants.TAXONOMIC_RANGE_FIELD_NAME);
139 if (StringUtils.isNotBlank(taxonomicRange)) {
140 placeNote = "Geographic range " + taxonomicRange;
144 String comment = this.getFieldValue(collectionObjectPayload, CollectionObjectBotGardenConstants.COMMENT_SCHEMA_NAME,
145 CollectionObjectBotGardenConstants.COMMENT_FIELD_NAME);
146 String collectionNote = "";
148 if (StringUtils.isNotBlank(placeNote) && StringUtils.isNotBlank(comment)) {
149 collectionNote = placeNote + ": " + comment;
151 else if (StringUtils.isNotBlank(placeNote)) {
152 collectionNote = placeNote;
155 collectionNote = comment;
158 return collectionNote;
161 private String getReverseFieldCollectionPlace(PoxPayloadOut collectionObjectPayload) throws URISyntaxException, DocumentException {
162 String reverseDisplayName = null;
163 String fieldCollectionPlaceRefName = getFieldValue(collectionObjectPayload, CollectionObjectBotGardenConstants.FIELD_COLLECTION_PLACE_SCHEMA_NAME,
164 CollectionObjectBotGardenConstants.FIELD_COLLECTION_PLACE_FIELD_NAME);
166 if (StringUtils.isNotBlank(fieldCollectionPlaceRefName)) {
167 PoxPayloadOut placePayload = null;
170 placePayload = findPlaceByRefName(fieldCollectionPlaceRefName);
172 catch (WebApplicationException e) {
173 logger.error("Error finding place: refName=" + fieldCollectionPlaceRefName, e);
176 if (placePayload != null) {
177 List<String> termTypes = getFieldValues(placePayload, PlaceConstants.TERM_TYPE_SCHEMA_NAME, PlaceConstants.TERM_TYPE_FIELD_NAME);
178 List<String> displayNames = getFieldValues(placePayload, PlaceConstants.DISPLAY_NAME_SCHEMA_NAME, PlaceConstants.DISPLAY_NAME_FIELD_NAME);
180 int index = termTypes.indexOf(PlaceBotGardenConstants.REVERSE_TERM_TYPE);
183 // There's no reverse term. Just use the primary.
185 if (displayNames.size() > 0) {
186 reverseDisplayName = displayNames.get(0);
190 reverseDisplayName = displayNames.get(index);
195 if (reverseDisplayName == null) {
196 reverseDisplayName = "";
199 return reverseDisplayName;
202 private String getAnnotation(PoxPayloadOut collectionObjectPayload) {
203 String annotation = "";
204 String determinationKind = getFieldValue(collectionObjectPayload, CollectionObjectBotGardenConstants.DETERMINATION_KIND_SCHEMA_NAME,
205 CollectionObjectBotGardenConstants.DETERMINATION_KIND_FIELD_NAME);
207 if (determinationKind.equals(CollectionObjectBotGardenConstants.DETERMINATION_KIND_DETERMINATION_VALUE)) {
208 String determinationBy = getDisplayNameFromRefName(getFieldValue(collectionObjectPayload, CollectionObjectBotGardenConstants.DETERMINATION_BY_SCHEMA_NAME,
209 CollectionObjectBotGardenConstants.DETERMINATION_BY_FIELD_NAME));
211 if (StringUtils.isNotBlank(determinationBy)) {
212 annotation += "det. by " + determinationBy;
214 String determinationInstitution = getDisplayNameFromRefName(getFieldValue(collectionObjectPayload, CollectionObjectBotGardenConstants.DETERMINATION_INSTITUTION_SCHEMA_NAME,
215 CollectionObjectBotGardenConstants.DETERMINATION_INSTITUTION_FIELD_NAME));
216 String determinationDate = getFieldValue(collectionObjectPayload, CollectionObjectBotGardenConstants.DETERMINATION_DATE_SCHEMA_NAME,
217 CollectionObjectBotGardenConstants.DETERMINATION_DATE_FIELD_NAME);
219 if (StringUtils.isNotBlank(determinationInstitution)) {
220 annotation += ", " + determinationInstitution;
223 if (StringUtils.isNotBlank(determinationDate)) {
224 annotation += ", " + determinationDate;
232 public InvocationResults createVoucherFromCurrentLocation(String movementCsid) throws ResourceException, URISyntaxException, DocumentException {
233 long numAffected = 0;
234 String primaryUriCreated = null;
236 List<String> collectionObjectCsids = findRelatedCollectionObjects(movementCsid);
238 for (String collectionObjectCsid : collectionObjectCsids) {
239 InvocationResults innerResults = createVoucherFromCataloging(collectionObjectCsid, movementCsid);
241 numAffected = numAffected + innerResults.getNumAffected();
243 if (primaryUriCreated == null) {
244 primaryUriCreated = innerResults.getPrimaryURICreated();
248 InvocationResults results = new InvocationResults();
249 results.setNumAffected(numAffected);
250 results.setPrimaryURICreated(primaryUriCreated);
252 if (collectionObjectCsids.size() == 0) {
253 results.setUserNote("No related cataloging record found");
256 results.setUserNote("Voucher created for " + numAffected + " cataloging " + (numAffected == 1 ? "record" : "records"));
262 private String createVoucher(Map<String, String> botGardenFields, Map<String, String> naturalHistoryFields) throws ResourceException {
263 String voucherCsid = null;
265 String createVoucherPayload =
266 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
267 "<document name=\"loansout\">" +
268 "<ns2:loansout_botgarden xmlns:ns2=\"http://collectionspace.org/services/loanout/local/botgarden\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +
269 getFieldXml(botGardenFields) +
270 "</ns2:loansout_botgarden>" +
271 "<ns2:loansout_naturalhistory xmlns:ns2=\"http://collectionspace.org/services/loanout/domain/naturalhistory\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +
272 getFieldXml(naturalHistoryFields) +
273 "</ns2:loansout_naturalhistory>" +
276 NuxeoBasedResource resource = (NuxeoBasedResource) getResourceMap().get(LoanoutClient.SERVICE_NAME);
277 Response response = resource.create(getResourceMap(), null, createVoucherPayload);
279 if (response.getStatus() == CREATED_STATUS) {
280 voucherCsid = CollectionSpaceClientUtils.extractId(response);
283 throw new ResourceException(response, "Error creating voucher");