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