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