]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
ef437856c59cb54635fba99253d3d27d1136ea1c
[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) throws URISyntaxException, DocumentException {
114                 PoxPayloadOut taxonPayload = findTaxonByCsid(taxonCsid);
115                 String taxonRefName = getFieldValue(taxonPayload, TaxonConstants.REFNAME_SCHEMA_NAME, TaxonConstants.REFNAME_FIELD_NAME);
116
117                 RefName.AuthorityItem item = RefName.AuthorityItem.parse(taxonRefName);
118                 String vocabularyShortId = item.getParentShortIdentifier();
119
120                 List<String> collectionObjectCsids = findReferencingCollectionObjects(TaxonomyAuthorityClient.SERVICE_NAME, vocabularyShortId, taxonCsid, 
121                                 CollectionObjectBotGardenConstants.TAXON_SCHEMA_NAME + ":" + TAXON_FIELD_NAME_WITHOUT_PATH);
122                 long numFound = 0;
123                 long numAffected = 0;
124                 
125                 for (String collectionObjectCsid : collectionObjectCsids) {
126                         // Filter out results where the taxon is referenced in the correct field, but isn't the primary value.
127                         
128                         PoxPayloadOut collectionObjectPayload = findCollectionObjectByCsid(collectionObjectCsid);
129                         String primaryTaxonRefName = getFieldValue(collectionObjectPayload, CollectionObjectBotGardenConstants.TAXON_SCHEMA_NAME, 
130                                         CollectionObjectBotGardenConstants.TAXON_FIELD_NAME);
131                                                 
132                         if (primaryTaxonRefName.equals(taxonRefName)) { 
133                                 numFound++;
134                                 
135                                 InvocationResults itemResults = updateRareFlag(collectionObjectPayload);
136                                 numAffected += itemResults.getNumAffected();
137                         }
138                 }
139                 
140                 InvocationResults results = new InvocationResults();
141                 results.setNumAffected(numAffected);
142                 results.setUserNote(numFound + " referencing cataloging " + (numFound == 1 ? "record" : "records") + " found, " + numAffected + " updated");
143                 
144                 return results;
145         }
146         
147         /**
148          * Updates the rare flag of the specified collectionobject.
149          * 
150          * @param collectionObjectCsid  The csid of the collectionobject
151          * @return
152          * @throws URISyntaxException
153          * @throws DocumentException
154          */
155         public InvocationResults updateRareFlag(String collectionObjectCsid) throws URISyntaxException, DocumentException {
156                 PoxPayloadOut collectionObjectPayload = findCollectionObjectByCsid(collectionObjectCsid);
157                 
158                 return updateRareFlag(collectionObjectPayload);
159         }
160         
161         /**
162          * Updates the rare flag of the specified collectionobject. The rare flag is determined by looking at
163          * the taxon record that is referenced by the primary taxonomic determination of the collectionobject.
164          * If the taxon record has a conservation category that is considered rare in its primary plant attributes
165          * group, the rare flag is set to true. Otherwise, it is set to false.
166          * 
167          * @param collectionObjectPayload       The payload representing the collectionobject
168          * @return
169          * @throws URISyntaxException
170          * @throws DocumentException
171          */
172         public InvocationResults updateRareFlag(PoxPayloadOut collectionObjectPayload) throws URISyntaxException, DocumentException {
173                 InvocationResults results = new InvocationResults();
174
175                 String uri = this.getFieldValue(collectionObjectPayload, CollectionObjectBotGardenConstants.URI_SCHEMA_NAME, 
176                                 CollectionObjectBotGardenConstants.URI_FIELD_NAME);
177                 String[] uriParts = uri.split("\\/");
178                 String collectionObjectCsid = uriParts[uriParts.length-1];
179
180                 String workflowState = getFieldValue(collectionObjectPayload, CollectionObjectConstants.WORKFLOW_STATE_SCHEMA_NAME, 
181                                 CollectionObjectConstants.WORKFLOW_STATE_FIELD_NAME);
182                 
183                 if (workflowState.equals(WorkflowClient.WORKFLOWSTATE_DELETED)) {
184                         logger.debug("skipping deleted collectionobject: " + collectionObjectCsid);
185                 }
186                 else {
187                         String taxonRefName = getFieldValue(collectionObjectPayload, CollectionObjectBotGardenConstants.TAXON_SCHEMA_NAME, 
188                                         CollectionObjectBotGardenConstants.TAXON_FIELD_NAME);
189                         String oldIsRare = getFieldValue(collectionObjectPayload, CollectionObjectBotGardenConstants.RARE_FLAG_SCHEMA_NAME, 
190                                         CollectionObjectBotGardenConstants.RARE_FLAG_FIELD_NAME);
191                         
192                         if (oldIsRare == null) {
193                                 oldIsRare = "";
194                         }
195                         
196                         String newIsRare = "false";
197
198                         if (StringUtils.isNotBlank(taxonRefName)) {
199                                 PoxPayloadOut taxonPayload = null;
200                         
201                                 try {
202                                         taxonPayload = findTaxonByRefName(taxonRefName);
203                                 }
204                                 catch (WebApplicationException e) {
205                                         logger.error("Error finding taxon: refName=" + taxonRefName, e);
206                                 }
207                                 
208                                 if (taxonPayload != null) {
209                                         // UCBG-369: Changing this so that it only checks the primary conservation category.
210                                         
211                                         String conservationCategory = getFieldValue(taxonPayload, TaxonBotGardenConstants.CONSERVATION_CATEGORY_SCHEMA_NAME, 
212                                                         TaxonBotGardenConstants.CONSERVATION_CATEGORY_FIELD_NAME);
213
214                                         if (isRare(conservationCategory)) {
215                                                 newIsRare = "true";
216                                         }
217                                 }
218                         }
219                         
220                         if (!newIsRare.equals(oldIsRare)) {
221                                 logger.debug("setting rare flag: collectionObjectCsid=" + collectionObjectCsid + " oldIsRare=" + oldIsRare +" newIsRare=" + newIsRare);
222                                 
223                                 setRareFlag(collectionObjectCsid, newIsRare);
224
225                                 results.setNumAffected(1);
226                                 results.setUserNote("rare flag set to " + newIsRare);
227                         }
228                         else {
229                                 logger.debug("not setting rare flag: collectionObjectCsid=" + collectionObjectCsid + " oldIsRare=" + oldIsRare +" newIsRare=" + newIsRare);
230                                 
231                                 results.setNumAffected(0);
232                                 results.setUserNote("rare flag not changed");
233                         }
234                 }
235                 
236                 return results;
237         }
238         
239         public static boolean isRare(String conservationCategoryRefName) {
240                 boolean isRare = false;
241                 
242                 if (StringUtils.isNotEmpty(conservationCategoryRefName)) {
243                         // The conservation category is non-empty, so it's rare...
244                         isRare = true;
245
246                         // ...unless it's one of the non-rare ones.
247                         
248                         // Check if the display name starts with a prefix that
249                         // indicates that it isn't rare.
250                         
251                         RefName.AuthorityItem item = RefName.AuthorityItem.parse(conservationCategoryRefName);
252                         String displayName = item.getDisplayName();
253                         
254                         for (String prefix : NON_RARE_CONSERVATION_CATEGORY_PREFIXES) {
255                                 if (displayName.startsWith(prefix)) {
256                                         isRare = false;
257                                         break;
258                                 }
259                         }
260                 }
261                 
262                 return isRare;
263         }
264         
265         /**
266          * Updates the rare flags of the specified collectionobjects.
267          * 
268          * @param collectionObjectCsids         The csids of the collectionobjects
269          * @return
270          * @throws URISyntaxException
271          * @throws DocumentException
272          */
273         public InvocationResults updateRareFlags(List<String> collectionObjectCsids) throws URISyntaxException, DocumentException {
274                 int numSubmitted = collectionObjectCsids.size();
275                 long numAffected = 0;
276                 
277                 
278                 for (String collectionObjectCsid : collectionObjectCsids) {
279                         InvocationResults itemResults = updateRareFlag(collectionObjectCsid);
280
281                         numAffected += itemResults.getNumAffected();
282                 }
283                 
284                 InvocationResults results = new InvocationResults();
285                 results.setNumAffected(numAffected);
286                 results.setUserNote("updated " + numAffected + " of " + numSubmitted + " cataloging records");
287                 
288                 return results;
289         }
290
291         /**
292          * Updates the rare flags of all collectionobjects.
293          * 
294          * @return
295          * @throws URISyntaxException
296          * @throws DocumentException
297          */
298         public InvocationResults updateAllRareFlags() throws URISyntaxException, DocumentException {
299                 long numFound = 0;
300                 long numAffected = 0;
301                 
302                 int pageSize = 50;
303                 int pageNum = 0;
304                 List<String> csids = Collections.emptyList();
305                 
306                 do {
307                         csids = findAllCollectionObjects(pageSize, pageNum);
308                         logger.debug("pageNum=" + pageNum + " pageSize=" + pageSize + " result size=" + csids.size());
309                         
310                         InvocationResults pageResults = updateRareFlags(csids);
311                         
312                         numAffected += pageResults.getNumAffected();
313                         numFound += csids.size();
314                         
315                         pageNum++;
316                 }
317                 while (csids.size() == pageSize);
318                 
319                 InvocationResults results = new InvocationResults();
320                 results.setNumAffected(numAffected);
321                 results.setUserNote("updated " + numAffected + " of " + numFound + " cataloging records");
322                 
323                 return null;
324         }
325
326         /**
327          * Sets the rare flag of the specified collectionobject to the specified value.
328          * 
329          * @param collectionObjectCsid  The csid of the collectionobject
330          * @param rareFlag                              The value of the rare flag
331          * @throws URISyntaxException 
332          */
333         private void setRareFlag(String collectionObjectCsid, String rareFlag) throws URISyntaxException {
334                 String updatePayload = 
335                         "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
336                         "<document name=\"collectionobjects\">" +
337                                 "<ns2:collectionobjects_naturalhistory xmlns:ns2=\"http://collectionspace.org/services/collectionobject/domain/naturalhistory\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +
338                                         getFieldXml("rare", rareFlag) +
339                                 "</ns2:collectionobjects_naturalhistory>" +
340                                 "<ns2:collectionobjects_common xmlns:ns2=\"http://collectionspace.org/services/collectionobject\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +
341                                 "</ns2:collectionobjects_common>" +                                     
342                         "</document>";
343                 
344                 NuxeoBasedResource resource = (NuxeoBasedResource) getResourceMap().get(CollectionObjectClient.SERVICE_NAME);
345                 resource.update(getResourceMap(), createUriInfo(), collectionObjectCsid, updatePayload);
346         }
347 }