]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
64989d1adde41c330240a9163e24e56149e72618
[tmp/jakarta-migration.git] /
1 package org.collectionspace.services.listener.botgarden;
2
3 import java.util.ArrayList;
4 import java.util.Arrays;
5 import java.util.HashSet;
6 import java.util.List;
7 import java.util.Map;
8 import java.util.Set;
9
10 import org.apache.commons.lang.StringUtils;
11 import org.apache.commons.logging.Log;
12 import org.apache.commons.logging.LogFactory;
13 import org.collectionspace.services.batch.nuxeo.UpdateAccessCodeBatchJob;
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.ResourceMap;
18 import org.collectionspace.services.common.invocable.InvocationResults;
19 import org.collectionspace.services.common.relation.nuxeo.RelationConstants;
20 import org.collectionspace.services.nuxeo.listener.AbstractCSEventListenerImpl;
21 import org.collectionspace.services.taxonomy.nuxeo.TaxonBotGardenConstants;
22 import org.collectionspace.services.taxonomy.nuxeo.TaxonConstants;
23 import org.jboss.resteasy.spi.ResteasyProviderFactory;
24 import org.nuxeo.ecm.core.api.DocumentModel;
25 import org.nuxeo.ecm.core.api.event.CoreEventConstants;
26 import org.nuxeo.ecm.core.api.event.DocumentEventTypes;
27 import org.nuxeo.ecm.core.event.Event;
28 import org.nuxeo.ecm.core.event.EventContext;
29 import org.nuxeo.ecm.core.event.impl.DocumentEventContext;
30
31 /**
32  * A listener that updates the access code on taxon records when collectionobjects
33  * or taxon records are created or modified.
34  * 
35  * @see org.collectionspace.services.batch.nuxeo.UpdateAccessCodeBatchJob
36  * @author ray
37  *
38  */
39 public class UpdateAccessCodeListener extends AbstractCSEventListenerImpl {
40         final Log logger = LogFactory.getLog(UpdateAccessCodeListener.class);
41
42         public static final String PREVIOUS_DEAD_FLAG_PROPERTY_NAME = "UpdateAccessCodeListener.previousDeadFlag";
43         public static final String PREVIOUS_TAXON_NAMES_PROPERTY_NAME = "UpdateAccessCodeListener.previousTaxonNames";
44         public static final String PREVIOUS_ACCESS_CODE_PROPERTY_NAME = "UpdateAccessCodeListener.previousAccessCode";
45         public static final String DELETED_RELATION_PARENT_CSID_PROPERTY_NAME = "UpdateAccessCodeListener.deletedRelationParentCsid";
46         
47         private static final String[] TAXON_PATH_ELEMENTS = CollectionObjectBotGardenConstants.TAXON_FIELD_NAME.split("/");
48         private static final String TAXONOMIC_IDENT_GROUP_LIST_FIELD_NAME = TAXON_PATH_ELEMENTS[0];
49         private static final String TAXON_FIELD_NAME = TAXON_PATH_ELEMENTS[2];
50
51         @Override
52         public void handleEvent(Event event) {
53                 EventContext ec = event.getContext();
54                 
55                 if (isRegistered(event) && ec instanceof DocumentEventContext) {
56                         DocumentEventContext context = (DocumentEventContext) ec;
57                         DocumentModel doc = context.getSourceDocument();
58
59                         logger.debug("docType=" + doc.getType());
60
61                         if (doc.getType().startsWith(CollectionObjectConstants.NUXEO_DOCTYPE) &&
62                                         !doc.isVersion() && 
63                                         !doc.isProxy() && 
64                                         !doc.getCurrentLifeCycleState().equals(WorkflowClient.WORKFLOWSTATE_DELETED)) {
65                                 
66                                 if (event.getName().equals(DocumentEventTypes.BEFORE_DOC_UPDATE)) {
67                                         // Stash the previous dead flag and taxonomic ident values, so they can be retrieved in the documentModified handler.
68                                         
69                                         DocumentModel previousDoc = (DocumentModel) context.getProperty(CoreEventConstants.PREVIOUS_DOCUMENT_MODEL);
70
71                                         String previousDeadFlag = (String) previousDoc.getProperty(CollectionObjectBotGardenConstants.DEAD_FLAG_SCHEMA_NAME, 
72                                                         CollectionObjectBotGardenConstants.DEAD_FLAG_FIELD_NAME);
73                                         context.setProperty(PREVIOUS_DEAD_FLAG_PROPERTY_NAME, previousDeadFlag);
74                                         
75                                         List<String> previousTaxonNames = getTaxonNames(previousDoc);
76                                         context.setProperty(PREVIOUS_TAXON_NAMES_PROPERTY_NAME, previousTaxonNames.toArray(new String[previousTaxonNames.size()]));
77                                 }
78                                 else {
79                                         boolean deadFlagChanged = false;
80                                         Set<String> deletedTaxonNames = null;
81                                         Set<String> addedTaxonNames = null;
82                                         
83                                         if (event.getName().equals(DocumentEventTypes.DOCUMENT_UPDATED)) {                                              
84                                                 // As an optimization, check if the dead flag of the collectionobject has
85                                                 // changed, or if the taxonomic identification has changed. If so, we need to
86                                                 // update the access codes of referenced taxon records.
87
88                                                 String previousDeadFlag = (String) context.getProperty(PREVIOUS_DEAD_FLAG_PROPERTY_NAME);
89                                                 String currentDeadFlag = (String) doc.getProperty(CollectionObjectBotGardenConstants.DEAD_FLAG_SCHEMA_NAME, 
90                                                                 CollectionObjectBotGardenConstants.DEAD_FLAG_FIELD_NAME);
91
92                                                 if (previousDeadFlag == null) {
93                                                         previousDeadFlag = "";
94                                                 }
95                                                 
96                                                 if (currentDeadFlag == null) {
97                                                         currentDeadFlag = "";
98                                                 }
99                                                                                                 
100                                                 if (previousDeadFlag.equals(currentDeadFlag)) {
101                                                         logger.debug("dead flag not changed: previousDeadFlag=" + previousDeadFlag + " currentDeadFlag=" + currentDeadFlag);
102                                                 }
103                                                 else {
104                                                         logger.debug("dead flag changed: previousDeadFlag=" + previousDeadFlag + " currentDeadFlag=" + currentDeadFlag);
105                                                         deadFlagChanged = true;
106                                                 }
107                                                 
108                                                 List<String> previousTaxonNames = Arrays.asList((String[]) context.getProperty(PREVIOUS_TAXON_NAMES_PROPERTY_NAME));
109                                                 List<String> currentTaxonNames = getTaxonNames(doc);
110                                                 
111                                                 deletedTaxonNames = findDeletedTaxonNames(previousTaxonNames, currentTaxonNames);
112                                                 logger.debug("found deleted taxon names: " + StringUtils.join(deletedTaxonNames, ", "));
113
114                                                 addedTaxonNames = findAddedTaxonNames(previousTaxonNames, currentTaxonNames);
115                                                 logger.debug("found added taxon names: " + StringUtils.join(addedTaxonNames, ", "));                                    
116                                         }
117                                         else if (event.getName().equals(DocumentEventTypes.DOCUMENT_CREATED)) {
118                                                 deadFlagChanged = true;
119                                         }
120                                         
121                                         UpdateAccessCodeBatchJob updater = createUpdater();
122                                         
123                                         if (deadFlagChanged) {
124                                                 String collectionObjectCsid = doc.getName();
125                                                 
126                                                 try {
127                                                         // Pass false for the second parameter to updateReferencedAccessCodes, so that it doesn't
128                                                         // propagate changes up the taxon hierarchy. Propagation is taken care of by this
129                                                         // event handler: As taxon records are modified, this handler executes, and updates the
130                                                         // parent.
131                                                 
132                                                         InvocationResults results = updater.updateReferencedAccessCodes(collectionObjectCsid, false);
133                         
134                                                         logger.debug("updateReferencedAccessCodes complete: numAffected=" + results.getNumAffected() + " userNote=" + results.getUserNote());
135                                                 }
136                                                 catch (Exception e) {
137                                                         logger.error(e.getMessage(), e);
138                                                 }
139                                         }
140                                         else {
141                                                 // If the dead flag didn't change, we still need to recalculate the access codes of
142                                                 // any taxonomic idents that were added.
143                                                 
144                                                 if (addedTaxonNames != null) {
145                                                         for (String addedTaxonName : addedTaxonNames) {
146                                                                 logger.debug("updating added taxon: " + addedTaxonName);
147
148                                                                 try {                                                                   
149                                                                         InvocationResults results = updater.updateAccessCode(addedTaxonName, false);
150                                                 
151                                                                         logger.debug("updateAccessCode complete: numAffected=" + results.getNumAffected() + " userNote=" + results.getUserNote());
152                                                                 }
153                                                                 catch (Exception e) {
154                                                                         logger.error(e.getMessage(), e);
155                                                                 }                                               
156                                                         }                                                       
157                                                 }
158                                         }
159                                         
160                                         if (deletedTaxonNames != null) {
161                                                 // If any taxonomic idents were removed from the collectionobject, they need to have their
162                                                 // access codes recalculated.
163
164                                                 for (String deletedTaxonName : deletedTaxonNames) {
165                                                         logger.debug("updating deleted taxon: " + deletedTaxonName);
166
167                                                         try {                                                                   
168                                                                 InvocationResults results = updater.updateAccessCode(deletedTaxonName, false);
169                                         
170                                                                 logger.debug("updateAccessCode complete: numAffected=" + results.getNumAffected() + " userNote=" + results.getUserNote());
171                                                         }
172                                                         catch (Exception e) {
173                                                                 logger.error(e.getMessage(), e);
174                                                         }                                               
175                                                 }
176                                         }
177                                 }
178                         }
179                         else if (doc.getType().startsWith(TaxonConstants.NUXEO_DOCTYPE) &&
180                                         !doc.isVersion() && 
181                                         !doc.isProxy() && 
182                                         !doc.getCurrentLifeCycleState().equals(WorkflowClient.WORKFLOWSTATE_DELETED)) {
183                                 
184                                 if (event.getName().equals(DocumentEventTypes.BEFORE_DOC_UPDATE)) {                                     
185                                         // Stash the previous access code value, so it can be retrieved in the documentModified handler.
186
187                                         DocumentModel previousDoc = (DocumentModel) context.getProperty(CoreEventConstants.PREVIOUS_DOCUMENT_MODEL);
188                                         String previousAccessCode = (String) previousDoc.getProperty(TaxonBotGardenConstants.ACCESS_CODE_SCHEMA_NAME, TaxonBotGardenConstants.ACCESS_CODE_FIELD_NAME);
189
190                                         context.setProperty(PREVIOUS_ACCESS_CODE_PROPERTY_NAME, previousAccessCode);
191                                 }
192                                 else {
193                                         boolean updateRequired = false;
194
195                                         if (event.getName().equals(DocumentEventTypes.DOCUMENT_UPDATED)) {                              
196                                                 // As an optimization, check if the access code of the taxon has
197                                                 // changed. We only need to update the access code of the parent taxon
198                                                 // record if it has.
199
200                                                 String previousAccessCode = (String) context.getProperty(PREVIOUS_ACCESS_CODE_PROPERTY_NAME);
201                                                 String currentAccessCode = (String) doc.getProperty(TaxonBotGardenConstants.ACCESS_CODE_SCHEMA_NAME, TaxonBotGardenConstants.ACCESS_CODE_FIELD_NAME);
202
203                                                 if (previousAccessCode == null) {
204                                                         previousAccessCode = "";
205                                                 }
206                                                 
207                                                 if (currentAccessCode == null) {
208                                                         currentAccessCode = "";
209                                                 }
210                                                 
211                                                 if (previousAccessCode.equals(currentAccessCode)) {
212                                                         logger.debug("update not required: previousAccessCode=" + previousAccessCode + " currentAccessCode=" + currentAccessCode);
213                                                 }
214                                                 else {
215                                                         logger.debug("update required: previousAccessCode=" + previousAccessCode + " currentAccessCode=" + currentAccessCode);
216                                                         updateRequired = true;
217                                                 }
218                                         }
219                                         else if (event.getName().equals(DocumentEventTypes.DOCUMENT_CREATED)) {
220                                                 updateRequired = true;  
221                                         }
222                                 
223                                         if (updateRequired) {
224                                                 String taxonCsid = doc.getName();
225                                                 
226                                                 try {
227                                                         // Pass false for the second parameter to updateReferencedAccessCodes, so that it doesn't
228                                                         // propagate changes up the taxon hierarchy. Propagation is taken care of by this
229                                                         // event handler: As taxon records are modified, this handler executes, and updates the
230                                                         // parent.
231                                                         
232                                                         InvocationResults results = createUpdater().updateParentAccessCode(taxonCsid, false);
233                         
234                                                         logger.debug("updateParentAccessCode complete: numAffected=" + results.getNumAffected() + " userNote=" + results.getUserNote());
235                                                 }
236                                                 catch (Exception e) {
237                                                         logger.error(e.getMessage(), e);
238                                                 }
239                                         }
240                                 }
241                         }
242                         else if (doc.getType().equals(RelationConstants.NUXEO_DOCTYPE) &&
243                                         !doc.isVersion() && 
244                                         !doc.isProxy()) {
245                                 
246                                 if (event.getName().equals(DocumentEventTypes.DOCUMENT_CREATED)) {
247                                         String subjectDocType = (String) doc.getProperty(RelationConstants.SUBJECT_DOCTYPE_SCHEMA_NAME, RelationConstants.SUBJECT_DOCTYPE_FIELD_NAME);
248                                         String objectDocType = (String) doc.getProperty(RelationConstants.OBJECT_DOCTYPE_SCHEMA_NAME, RelationConstants.OBJECT_DOCTYPE_FIELD_NAME);;
249                                         String relationType = (String) doc.getProperty(RelationConstants.TYPE_SCHEMA_NAME, RelationConstants.TYPE_FIELD_NAME);
250         
251                                         logger.debug("subjectDocType=" + subjectDocType + " objectDocType=" + objectDocType + " relationType=" + relationType);
252         
253                                         if (subjectDocType.equals(TaxonConstants.NUXEO_DOCTYPE) && objectDocType.equals(TaxonConstants.NUXEO_DOCTYPE) && relationType.equals(RelationConstants.BROADER_TYPE)) {
254                                                 String parentTaxonCsid = (String) doc.getProperty(RelationConstants.OBJECT_CSID_SCHEMA_NAME, RelationConstants.OBJECT_CSID_FIELD_NAME);
255                                                 logger.debug("child added, updating parent taxon: parentTaxonCsid=" + parentTaxonCsid);
256                                                 
257                                                 try {                                                   
258                                                         InvocationResults results = createUpdater().updateAccessCode(parentTaxonCsid, false);
259                                                         
260                                                         logger.debug("updateAccessCode complete: numAffected=" + results.getNumAffected() + " userNote=" + results.getUserNote());
261                                                 }
262                                                 catch (Exception e) {
263                                                         logger.error(e.getMessage(), e);
264                                                 }
265                                         }
266                                 }
267                                 else if (event.getName().equals(DocumentEventTypes.ABOUT_TO_REMOVE)) {
268                                         String subjectDocType = (String) doc.getProperty(RelationConstants.SUBJECT_DOCTYPE_SCHEMA_NAME, RelationConstants.SUBJECT_DOCTYPE_FIELD_NAME);
269                                         String objectDocType = (String) doc.getProperty(RelationConstants.OBJECT_DOCTYPE_SCHEMA_NAME, RelationConstants.OBJECT_DOCTYPE_FIELD_NAME);;
270                                         String relationType = (String) doc.getProperty(RelationConstants.TYPE_SCHEMA_NAME, RelationConstants.TYPE_FIELD_NAME);
271         
272                                         logger.debug("subjectDocType=" + subjectDocType + " objectDocType=" + objectDocType + " relationType=" + relationType);
273
274                                         if (subjectDocType.equals(TaxonConstants.NUXEO_DOCTYPE) && objectDocType.equals(TaxonConstants.NUXEO_DOCTYPE) && relationType.equals(RelationConstants.BROADER_TYPE)) {
275                                                 String parentTaxonCsid = (String) doc.getProperty(RelationConstants.OBJECT_CSID_SCHEMA_NAME, RelationConstants.OBJECT_CSID_FIELD_NAME);
276                                                 
277                                                 // Stash the parent taxon csid, so it can be retrieved in the documentRemoved handler.
278                                                 logger.debug("about to delete taxon hierarchy relation: parentTaxonCsid=" + parentTaxonCsid);
279                                                 context.setProperty(DELETED_RELATION_PARENT_CSID_PROPERTY_NAME, parentTaxonCsid);
280                                         }
281                                 }
282                                 else if (event.getName().equals(DocumentEventTypes.DOCUMENT_REMOVED)) {
283                                         String parentTaxonCsid = (String) context.getProperty(DELETED_RELATION_PARENT_CSID_PROPERTY_NAME);
284                                         
285                                         if (StringUtils.isNotEmpty(parentTaxonCsid)) {
286                                                 logger.debug("child removed, updating parent taxon: parentTaxonCsid=" + parentTaxonCsid);
287
288                                                 try {                                                   
289                                                         InvocationResults results = createUpdater().updateAccessCode(parentTaxonCsid, false);
290                                                         
291                                                         logger.debug("updateAccessCode complete: numAffected=" + results.getNumAffected() + " userNote=" + results.getUserNote());
292                                                 }
293                                                 catch (Exception e) {
294                                                         logger.error(e.getMessage(), e);
295                                                 }                                               
296                                         }
297                                 }
298                         }
299                 }
300         }
301         
302         private List<String> getTaxonNames(DocumentModel doc) {
303                 List<Map<String, Object>> taxonomicIdentGroupList = (List<Map<String, Object>>) doc.getProperty(CollectionObjectBotGardenConstants.TAXON_SCHEMA_NAME, 
304                                 TAXONOMIC_IDENT_GROUP_LIST_FIELD_NAME);
305                 List<String> taxonNames = new ArrayList<String>();
306
307                 for (Map<String, Object> taxonomicIdentGroup : taxonomicIdentGroupList) {
308                         String taxonName = (String) taxonomicIdentGroup.get(TAXON_FIELD_NAME);
309
310                         if (StringUtils.isNotEmpty(taxonName)) {
311                                 taxonNames.add(taxonName);
312                         }
313                 }
314
315                 return taxonNames;
316         }
317
318         private Set<String> findDeletedTaxonNames(List<String> previousTaxonNames, List<String> currentTaxonNames) {
319                 Set<String> currentTaxonNameSet = new HashSet<String>(currentTaxonNames);
320                 Set<String> deletedTaxonNameSet = new HashSet<String>();
321                 
322                 for (String previousTaxonName : previousTaxonNames) {
323                         if (!currentTaxonNameSet.contains(previousTaxonName)) {
324                                 deletedTaxonNameSet.add(previousTaxonName);
325                         }
326                 }
327                 
328                 return deletedTaxonNameSet;
329         }
330         
331         private Set<String> findAddedTaxonNames(List<String> previousTaxonNames, List<String> currentTaxonNames) {
332                 Set<String> previousTaxonNameSet = new HashSet<String>(previousTaxonNames);
333                 Set<String> addedTaxonNameSet = new HashSet<String>();
334                 
335                 for (String currentTaxonName : currentTaxonNames) {
336                         if (!previousTaxonNameSet.contains(currentTaxonName)) {
337                                 addedTaxonNameSet.add(currentTaxonName);
338                         }
339                 }
340                 
341                 return addedTaxonNameSet;
342         }
343         
344         private UpdateAccessCodeBatchJob createUpdater() {
345                 ResourceMap resourceMap = ResteasyProviderFactory.getContextData(ResourceMap.class);
346
347                 UpdateAccessCodeBatchJob updater = new UpdateAccessCodeBatchJob();
348                 updater.setResourceMap(resourceMap);
349
350                 return updater;
351         }
352 }