]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
c91f32f11c4e6198ba8288c9e531ac7468297d38
[tmp/jakarta-migration.git] /
1 package org.collectionspace.services.batch.nuxeo;
2
3 import java.net.URISyntaxException;
4 import java.util.Arrays;
5 import java.util.Collections;
6 import java.util.List;
7
8 import javax.ws.rs.WebApplicationException;
9
10 import org.apache.commons.lang.StringUtils;
11 import org.collectionspace.services.client.CollectionObjectClient;
12 import org.collectionspace.services.client.PoxPayloadOut;
13 import org.collectionspace.services.client.TaxonomyAuthorityClient;
14 import org.collectionspace.services.client.workflow.WorkflowClient;
15 import org.collectionspace.services.collectionobject.nuxeo.CollectionObjectBotGardenConstants;
16 import org.collectionspace.services.collectionobject.nuxeo.CollectionObjectConstants;
17 import org.collectionspace.services.common.NuxeoBasedResource;
18 import org.collectionspace.services.common.api.RefName;
19 import org.collectionspace.services.common.invocable.InvocationContext.ListCSIDs;
20 import org.collectionspace.services.common.invocable.InvocationResults;
21 import org.collectionspace.services.taxonomy.nuxeo.TaxonBotGardenConstants;
22 import org.collectionspace.services.taxonomy.nuxeo.TaxonConstants;
23 import org.dom4j.DocumentException;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
26
27 public class UpdateRareFlagBatchJob extends AbstractBatchJob {
28         final Logger logger = LoggerFactory.getLogger(UpdateRareFlagBatchJob.class);
29         
30         // All conservation categories are considered rare, except for ones that start with the following prefixes.
31         public static final List<String> NON_RARE_CONSERVATION_CATEGORY_PREFIXES = Arrays.asList("none", "DD ", "LC ", "LR (lc) ");
32
33         private static final String[] TAXON_FIELD_NAME_PARTS = CollectionObjectBotGardenConstants.TAXON_FIELD_NAME.split("\\/");
34         private static final String TAXON_FIELD_NAME_WITHOUT_PATH = TAXON_FIELD_NAME_PARTS[TAXON_FIELD_NAME_PARTS.length - 1];
35         
36         public UpdateRareFlagBatchJob() {
37                 this.setSupportedInvocationModes(Arrays.asList(INVOCATION_MODE_SINGLE, INVOCATION_MODE_LIST, INVOCATION_MODE_NO_CONTEXT));
38         }
39
40         @Override
41         public void run() {
42                 setCompletionStatus(STATUS_MIN_PROGRESS);
43                 
44                 try {
45                         String mode = getInvocationContext().getMode();
46                         
47                         if (mode.equals(INVOCATION_MODE_SINGLE)) {
48                                 /*
49                                  * In a single document context, the single csid must specify a collectionobject or a
50                                  * taxonomy record. If it's a collectionobject, the rare flag for the specified
51                                  * collectionobject will be updated. If it's a taxonomy record, the rare flag will be
52                                  * updated for each collectionobject with a primary determination that refers to the
53                                  * specified taxonomy record.
54                                  */
55                                 
56                                 String csid = getInvocationContext().getSingleCSID();
57                                 
58                                 if (StringUtils.isEmpty(csid)) {
59                                         throw new Exception("Missing context csid");
60                                 }
61                                 
62                                 String docType = getInvocationContext().getDocType();
63                                 
64                                 if (docType.equals(CollectionObjectConstants.NUXEO_DOCTYPE)) {
65                                         setResults(updateRareFlag(csid));
66                                 }
67                                 else if (docType.equals(TaxonConstants.NUXEO_DOCTYPE)) {
68                                         setResults(updateReferencingRareFlags(csid));
69                                 }
70                                 else {
71                                         throw new Exception("Unsupported document type: " + docType);
72                                 }
73                         }
74                         else if (mode.equals(INVOCATION_MODE_LIST)) {
75                                 /*
76                                  * In a list context, the csids must specify collectionobjects. The rare flag for
77                                  * each collectionobject will be updated.
78                                  */
79                                 ListCSIDs csids = getInvocationContext().getListCSIDs();
80                                 
81                                 setResults(updateRareFlags(csids.getCsid()));
82                         }
83                         else if (mode.equals(INVOCATION_MODE_NO_CONTEXT)) {
84                                 /*
85                                  * If there is no context, the rare flag will be updated for all (non-deleted)
86                                  * collectionobjects.
87                                  */
88                                 
89                                 setResults(updateAllRareFlags());
90                         }
91                         else {
92                                 throw new Exception("Unsupported invocation mode: " + mode);
93                         }
94                         
95                         setCompletionStatus(STATUS_COMPLETE);
96                 }
97                 catch(Exception e) {
98                         setCompletionStatus(STATUS_ERROR);
99                         setErrorInfo(new InvocationError(INT_ERROR_STATUS, e.getMessage()));
100                 }
101         }
102         
103         /**
104          * Updates the rare flags of collectionobjects that refer to the specified taxon record.
105          * A collectionobject is considered to refer to the taxon record if the refname of its
106          * primary taxonomic identification is the refname of the taxon record.
107          * 
108          * @param taxonCsid             The csid of the taxon record
109          * @return
110          * @throws URISyntaxException
111          * @throws DocumentException
112          */
113         public InvocationResults updateReferencingRareFlags(String taxonCsid, String vocabularyCsid) throws URISyntaxException, DocumentException, Exception {
114                 PoxPayloadOut taxonPayload = vocabularyCsid == null
115                                 ? findTaxonByCsid(taxonCsid)
116                                 : findTaxonByCsid(taxonCsid, vocabularyCsid);
117                 String taxonRefName = getFieldValue(taxonPayload, TaxonConstants.REFNAME_SCHEMA_NAME, TaxonConstants.REFNAME_FIELD_NAME);
118
119                 RefName.AuthorityItem item = RefName.AuthorityItem.parse(taxonRefName);
120                 String vocabularyShortId = item.getParentShortIdentifier();
121
122                 List<String> collectionObjectCsids = findReferencingCollectionObjects(TaxonomyAuthorityClient.SERVICE_NAME, vocabularyShortId, taxonCsid, 
123                                 CollectionObjectBotGardenConstants.TAXON_SCHEMA_NAME + ":" + TAXON_FIELD_NAME_WITHOUT_PATH);
124                 long numFound = 0;
125                 long numAffected = 0;
126                 
127                 for (String collectionObjectCsid : collectionObjectCsids) {
128                         // Filter out results where the taxon is referenced in the correct field, but isn't the primary value.
129                         
130                         PoxPayloadOut collectionObjectPayload = findCollectionObjectByCsid(collectionObjectCsid);
131                         String primaryTaxonRefName = getFieldValue(collectionObjectPayload, CollectionObjectBotGardenConstants.TAXON_SCHEMA_NAME, 
132                                         CollectionObjectBotGardenConstants.TAXON_FIELD_NAME);
133                                                 
134                         if (primaryTaxonRefName.equals(taxonRefName)) { 
135                                 numFound++;
136                                 
137                                 InvocationResults itemResults = updateRareFlag(collectionObjectPayload);
138                                 numAffected += itemResults.getNumAffected();
139                         }
140                 }
141                 
142                 InvocationResults results = new InvocationResults();
143                 results.setNumAffected(numAffected);
144                 results.setUserNote(numFound + " referencing cataloging " + (numFound == 1 ? "record" : "records") + " found, " + numAffected + " updated");
145                 
146                 return results;
147         }
148         
149         public InvocationResults updateReferencingRareFlags(String taxonCsid) throws URISyntaxException, DocumentException, Exception {
150                 return updateReferencingRareFlags(taxonCsid, null);
151         }
152
153         /**
154          * Updates the rare flag of the specified collectionobject.
155          * 
156          * @param collectionObjectCsid  The csid of the collectionobject
157          * @return
158          * @throws URISyntaxException
159          * @throws DocumentException
160          */
161         public InvocationResults updateRareFlag(String collectionObjectCsid) throws URISyntaxException, DocumentException, Exception {
162                 PoxPayloadOut collectionObjectPayload = findCollectionObjectByCsid(collectionObjectCsid);
163                 
164                 return updateRareFlag(collectionObjectPayload);
165         }
166         
167         /**
168          * Updates the rare flag of the specified collectionobject. The rare flag is determined by looking at
169          * the taxon record that is referenced by the primary taxonomic determination of the collectionobject.
170          * If the taxon record has a conservation category that is considered rare in its primary plant attributes
171          * group, the rare flag is set to true. Otherwise, it is set to false.
172          * 
173          * @param collectionObjectPayload       The payload representing the collectionobject
174          * @return
175          * @throws URISyntaxException
176          * @throws DocumentException
177          */
178         public InvocationResults updateRareFlag(PoxPayloadOut collectionObjectPayload) throws URISyntaxException, DocumentException, Exception {
179                 InvocationResults results = new InvocationResults();
180
181                 String uri = this.getFieldValue(collectionObjectPayload, CollectionObjectBotGardenConstants.URI_SCHEMA_NAME, 
182                                 CollectionObjectBotGardenConstants.URI_FIELD_NAME);
183                 String[] uriParts = uri.split("\\/");
184                 String collectionObjectCsid = uriParts[uriParts.length-1];
185
186                 String workflowState = getFieldValue(collectionObjectPayload, CollectionObjectConstants.WORKFLOW_STATE_SCHEMA_NAME, 
187                                 CollectionObjectConstants.WORKFLOW_STATE_FIELD_NAME);
188                 
189                 if (workflowState.equals(WorkflowClient.WORKFLOWSTATE_DELETED)) {
190                         logger.debug("skipping deleted collectionobject: " + collectionObjectCsid);
191                 }
192                 else {
193                         String taxonRefName = getFieldValue(collectionObjectPayload, CollectionObjectBotGardenConstants.TAXON_SCHEMA_NAME, 
194                                         CollectionObjectBotGardenConstants.TAXON_FIELD_NAME);
195                         String oldIsRare = getFieldValue(collectionObjectPayload, CollectionObjectBotGardenConstants.RARE_FLAG_SCHEMA_NAME, 
196                                         CollectionObjectBotGardenConstants.RARE_FLAG_FIELD_NAME);
197                         
198                         if (oldIsRare == null) {
199                                 oldIsRare = "";
200                         }
201                         
202                         String newIsRare = "false";
203
204                         if (StringUtils.isNotBlank(taxonRefName)) {
205                                 PoxPayloadOut taxonPayload = null;
206                         
207                                 try {
208                                         taxonPayload = findTaxonByRefName(taxonRefName);
209                                 }
210                                 catch (WebApplicationException e) {
211                                         logger.error("Error finding taxon: refName=" + taxonRefName, e);
212                                 }
213                                 
214                                 if (taxonPayload != null) {
215                                         // UCBG-369: Changing this so that it only checks the primary conservation category.
216                                         
217                                         String conservationCategory = getFieldValue(taxonPayload, TaxonBotGardenConstants.CONSERVATION_CATEGORY_SCHEMA_NAME, 
218                                                         TaxonBotGardenConstants.CONSERVATION_CATEGORY_FIELD_NAME);
219
220                                         if (isRare(conservationCategory)) {
221                                                 newIsRare = "true";
222                                         }
223                                 }
224                         }
225                         
226                         if (!newIsRare.equals(oldIsRare)) {
227                                 logger.debug("setting rare flag: collectionObjectCsid=" + collectionObjectCsid + " oldIsRare=" + oldIsRare +" newIsRare=" + newIsRare);
228                                 
229                                 setRareFlag(collectionObjectCsid, newIsRare);
230
231                                 results.setNumAffected(1);
232                                 results.setUserNote("rare flag set to " + newIsRare);
233                         }
234                         else {
235                                 logger.debug("not setting rare flag: collectionObjectCsid=" + collectionObjectCsid + " oldIsRare=" + oldIsRare +" newIsRare=" + newIsRare);
236                                 
237                                 results.setNumAffected(0);
238                                 results.setUserNote("rare flag not changed");
239                         }
240                 }
241                 
242                 return results;
243         }
244         
245         public static boolean isRare(String conservationCategoryRefName) {
246                 boolean isRare = false;
247                 
248                 if (StringUtils.isNotEmpty(conservationCategoryRefName)) {
249                         // The conservation category is non-empty, so it's rare...
250                         isRare = true;
251
252                         // ...unless it's one of the non-rare ones.
253                         
254                         // Check if the display name starts with a prefix that
255                         // indicates that it isn't rare.
256                         
257                         RefName.AuthorityItem item = RefName.AuthorityItem.parse(conservationCategoryRefName);
258                         String displayName = item.getDisplayName();
259                         
260                         for (String prefix : NON_RARE_CONSERVATION_CATEGORY_PREFIXES) {
261                                 if (displayName.startsWith(prefix)) {
262                                         isRare = false;
263                                         break;
264                                 }
265                         }
266                 }
267                 
268                 return isRare;
269         }
270         
271         /**
272          * Updates the rare flags of the specified collectionobjects.
273          * 
274          * @param collectionObjectCsids         The csids of the collectionobjects
275          * @return
276          * @throws URISyntaxException
277          * @throws DocumentException
278          */
279         public InvocationResults updateRareFlags(List<String> collectionObjectCsids) throws URISyntaxException, DocumentException, Exception {
280                 int numSubmitted = collectionObjectCsids.size();
281                 long numAffected = 0;
282                 
283                 
284                 for (String collectionObjectCsid : collectionObjectCsids) {
285                         InvocationResults itemResults = updateRareFlag(collectionObjectCsid);
286
287                         numAffected += itemResults.getNumAffected();
288                 }
289                 
290                 InvocationResults results = new InvocationResults();
291                 results.setNumAffected(numAffected);
292                 results.setUserNote("updated " + numAffected + " of " + numSubmitted + " cataloging records");
293                 
294                 return results;
295         }
296
297         /**
298          * Updates the rare flags of all collectionobjects.
299          * 
300          * @return
301          * @throws URISyntaxException
302          * @throws DocumentException
303          */
304         public InvocationResults updateAllRareFlags() throws URISyntaxException, DocumentException, Exception {
305                 long numFound = 0;
306                 long numAffected = 0;
307                 
308                 int pageSize = 50;
309                 int pageNum = 0;
310                 List<String> csids = Collections.emptyList();
311                 
312                 do {
313                         csids = findAllCollectionObjects(pageSize, pageNum);
314                         logger.debug("pageNum=" + pageNum + " pageSize=" + pageSize + " result size=" + csids.size());
315                         
316                         InvocationResults pageResults = updateRareFlags(csids);
317                         
318                         numAffected += pageResults.getNumAffected();
319                         numFound += csids.size();
320                         
321                         pageNum++;
322                 }
323                 while (csids.size() == pageSize);
324                 
325                 InvocationResults results = new InvocationResults();
326                 results.setNumAffected(numAffected);
327                 results.setUserNote("updated " + numAffected + " of " + numFound + " cataloging records");
328                 
329                 return null;
330         }
331
332         /**
333          * Sets the rare flag of the specified collectionobject to the specified value.
334          * 
335          * @param collectionObjectCsid  The csid of the collectionobject
336          * @param rareFlag                              The value of the rare flag
337          * @throws URISyntaxException 
338          */
339         private void setRareFlag(String collectionObjectCsid, String rareFlag) throws URISyntaxException {
340                 String updatePayload = 
341                         "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
342                         "<document name=\"collectionobjects\">" +
343                                 "<ns2:collectionobjects_naturalhistory xmlns:ns2=\"http://collectionspace.org/services/collectionobject/domain/naturalhistory\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +
344                                         getFieldXml("rare", rareFlag) +
345                                 "</ns2:collectionobjects_naturalhistory>" +
346                                 "<ns2:collectionobjects_common xmlns:ns2=\"http://collectionspace.org/services/collectionobject\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +
347                                 "</ns2:collectionobjects_common>" +                                     
348                         "</document>";
349                 
350                 NuxeoBasedResource resource = (NuxeoBasedResource) getResourceMap().get(CollectionObjectClient.SERVICE_NAME);
351                 resource.update(getServiceContext(), getResourceMap(), createUriInfo(), collectionObjectCsid, updatePayload);
352         }
353 }