root/head/ambra/webapp/src/main/java/org/topazproject/ambra/admin/action/ManageFlagsAction.java @ 7724

Revision 7724, 13.8 KB (checked in by ssterling, 15 months ago)

Added ability to edit the Citation and Body of an Annotation. Changed naming of classes and templates to match the rest of the schema.

Addresses Job Order 8927

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id HeadURL Revision
Line 
1/* $HeadURL::                                                                            $
2 * $Id$
3 *
4 * Copyright (c) 2006-2009 by Topaz, Inc.
5 * http://topazproject.org
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *     http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20package org.topazproject.ambra.admin.action;
21
22import org.springframework.transaction.annotation.Transactional;
23import org.springframework.transaction.interceptor.TransactionAspectSupport;
24import org.springframework.beans.factory.annotation.Required;
25
26import org.topazproject.ambra.annotation.service.AnnotationService;
27import org.topazproject.ambra.annotation.service.Flag;
28import org.topazproject.ambra.annotation.service.ReplyService;
29import org.topazproject.ambra.annotation.service.AnnotationConverter;
30import org.topazproject.ambra.models.FormalCorrection;
31import org.topazproject.ambra.models.MinorCorrection;
32import org.topazproject.ambra.models.Retraction;
33import org.topazproject.ambra.models.Comment;
34import org.topazproject.ambra.models.Reply;
35import org.topazproject.ambra.models.Annotea;
36import org.topazproject.ambra.admin.service.FlagManagementService;
37import org.topazproject.ambra.admin.service.FlaggedCommentRecord;
38import org.topazproject.ambra.rating.service.RatingsService;
39import org.apache.commons.logging.Log;
40import org.apache.commons.logging.LogFactory;
41
42import java.util.Collection;
43
44
45@SuppressWarnings("serial")
46public class ManageFlagsAction extends BaseAdminActionSupport {
47  private static final Log log = LogFactory.getLog(ManageFlagsAction.class);
48
49  private FlagManagementService flagManagementService;
50  private AnnotationService annotationService;
51  private RatingsService ratingsService;
52  private ReplyService replyService;
53  protected AnnotationConverter converter;
54
55  private Collection<FlaggedCommentRecord> flaggedComments;
56
57  // Fields used for processFlags
58  private String[] commentsToUnflag;
59  private String[] commentsToDelete;
60  private String[] convertToFormalCorrection;
61  private String[] convertToMinorCorrection;
62  private String[] convertToRetraction;
63  private String[] convertToNote;
64
65  @Override
66  public String execute() throws Exception {
67    if (setCommonFields())
68      return ERROR;
69    return SUCCESS;  // default action is just to display the template
70  }
71
72  private boolean setCommonFields() {
73    // create a faux journal object for template
74    initJournal();
75    // catch all Exceptions to keep Admin console active (vs. Site Error)
76    try {
77      flaggedComments = flagManagementService.getFlaggedComments();
78    } catch (Exception e) {
79      log.error("Admin console Exception", e);
80      addActionError("Exception: " + e);
81      return true;
82    }
83    return false;
84  }
85
86  /**
87    * Gets the list of annotation flags.
88    *
89    * @return List of flags
90    */
91  public Collection<FlaggedCommentRecord> getFlaggedComments() {
92    return flaggedComments;
93  }
94
95  @Transactional(rollbackFor = { Throwable.class })
96  public String processFlags() {
97    if (commentsToUnflag != null){
98      for (String toUnFlag : commentsToUnflag){
99        if (log.isDebugEnabled()){
100          log.debug("Found comment to unflag: " + toUnFlag);
101        }
102        String[] tokens = toUnFlag.split("_");
103        // token[0] = the target ID
104        // token[1] = the flag ID
105        // token[2] = the targetType (a string identifier)
106        try {
107          deleteFlag(tokens[0], tokens[1]);
108        } catch(Exception e) {
109          String errorMessage = "Failed to delete flag id='" + tokens[1] + "'" +
110          "for annotation id='" + tokens[0] + "'";
111          addActionError(errorMessage + " Exception: " +e.getMessage());
112          log.error(errorMessage, e);
113          TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
114          return ERROR;
115        }
116      }
117    }
118
119    if (commentsToDelete != null) {
120      for (String toDelete : commentsToDelete) {
121        if (log.isDebugEnabled()) {
122          log.debug("Found comment to delete: " + toDelete);
123        }
124        String[] tokens = toDelete.split("_");
125        try {
126          deleteTarget(tokens[0], tokens[1], tokens[2]);
127        } catch (Exception e) {
128          String errorMessage = "Failed to delete annotation id='" + tokens[1] + "'.";
129          addActionError(errorMessage + " Exception: " +e.getMessage());
130          log.error(errorMessage, e);
131          TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
132          return ERROR;
133        }
134      }
135    }
136
137    if (convertToFormalCorrection != null) {
138      for (String paramStr : convertToFormalCorrection) {
139        if (log.isDebugEnabled()) {
140          log.debug("Converting to Formal Correction: "+paramStr);
141        }
142        String[] tokens = paramStr.split("_");
143        try {
144          annotationService.convertAnnotationToType(tokens[1], FormalCorrection.class);
145          deleteFlag(tokens[1], tokens[0]);
146        } catch(Exception e) {
147          String errorMessage = "Failed to convert annotation id='" + tokens[1] +
148                                "' to Formal Correction annotation.";
149          addActionError(errorMessage + " Exception: " +e.getMessage());
150          log.error(errorMessage, e);
151          TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
152          return ERROR;
153        }
154      }
155    }
156
157    if (convertToMinorCorrection != null) {
158      for (String paramStr : convertToMinorCorrection) {
159        if (log.isDebugEnabled()) {
160          log.debug("Converting to Minor Correction: "+paramStr);
161        }
162        String[] tokens = paramStr.split("_");
163        try {
164          annotationService.convertAnnotationToType(tokens[1], MinorCorrection.class);
165          deleteFlag(tokens[1], tokens[0]);
166        } catch(Exception e) {
167          String errorMessage = "Failed to convert annotation id='" + tokens[1] +
168                                "' to Minor Correction annotation.";
169          addActionError(errorMessage + " Exception: " +e.getMessage());
170          log.error(errorMessage, e);
171          TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
172          return ERROR;
173        }
174      }
175    }
176
177    if (convertToRetraction != null) {
178      for (String paramStr : convertToRetraction) {
179        if (log.isDebugEnabled()) {
180          log.debug("Converting to Retraction: "+paramStr);
181        }
182        String[] tokens = paramStr.split("_");
183        try {
184          annotationService.convertAnnotationToType(tokens[1], Retraction.class);
185          deleteFlag(tokens[1], tokens[0]);
186        } catch(Exception e) {
187          String errorMessage = "Failed to convert annotation id='" + tokens[1] +
188                                "' to Retraction annotation.";
189          addActionError(errorMessage + " Exception: " +e.getMessage());
190          log.error(errorMessage, e);
191          TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
192          return ERROR;
193        }
194      }
195    }
196
197    if (convertToNote != null) {
198      for (String paramStr : convertToNote) {
199        if (log.isDebugEnabled()) {
200          log.debug("Converting to Note: "+paramStr);
201        }
202        String[] tokens = paramStr.split("_");
203        try {
204          annotationService.convertAnnotationToType(tokens[1], Comment.class);
205          deleteFlag(tokens[1], tokens[0]);
206        } catch(Exception e) {
207          String errorMessage = "Failed to convert annotation id='" + tokens[1]
208                                 + "' to Note annotation.";
209          addActionError(errorMessage + " Exception: " +e.getMessage());
210          log.error(errorMessage, e);
211          TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
212          return ERROR;
213        }
214      }
215    }
216    if (setCommonFields())
217      return ERROR;
218
219    return SUCCESS;
220  }
221
222  /**
223   * @param root
224   * @param target
225   * @param targetType Type, Class name, of target
226   *
227   * Delete the target. Root is either an id (in which case
228   * target is a reply) or else it is a "" in which case target is an annotation.
229   * In either case:
230   *         remove flags on this target
231   *         get all replies to this target
232   *             for each reply
233   *                 check to see if reply has flags
234   *                     remove each flag
235   *         remove all replies in bulk
236   *         remove target
237   *
238   *  Note that because this may be called from a 'batch' job (i.e multiple
239   *  rows were checked off in process flags UI) it may be that things have
240   *  been deleted by previous actions. So we catch 'non-exsietent-id' exceptions
241   *  which may well get thrown and recover and continue (faster than going across
242   *  teh web service tro see if the ID is valid then going out again to get its object).
243   * @throws Exception
244   */
245  private void deleteTarget(String root, String target, String targetType) throws Exception {
246    Reply[] replies;
247    Flag[] flags = converter.convertAsFlags(
248        annotationService.listAnnotations(target, annotationService.COMMENT_SET), false, false);
249
250    if (log.isDebugEnabled()) {
251      log.debug("Deleting Target" + target + " Root is " + root);
252      log.debug(target + " has " + flags.length + " flags - deleting them");
253    }
254    for (Flag flag: flags) {
255      try {
256        deleteFlag(target, flag.getId());
257      } catch (Exception e) {
258        //keep going through the list even if there is an exception
259        if (log.isWarnEnabled()) {
260          log.warn("Couldn't delete flag: " + flag.getId(), e);
261        }
262      }
263    }
264
265    if (targetType.equals(Annotea.WEB_TYPE_REPLY)) {
266      replies = replyService.listAllReplies(root, target);
267    } else if (
268        targetType.equals(Annotea.WEB_TYPE_COMMENT) ||
269        targetType.equals(Annotea.WEB_TYPE_NOTE) ||
270        targetType.equals(Annotea.WEB_TYPE_MINOR_CORRECTION) ||
271        targetType.equals(Annotea.WEB_TYPE_FORMAL_CORRECTION) ||
272        targetType.equals(Annotea.WEB_TYPE_RETRACTION)) {
273      replies = replyService.listAllReplies(target, target);
274    } else {
275      // Flag type doesn't have Replies
276      replies = new Reply[0];
277    }
278
279    if (log.isDebugEnabled()) {
280      log.debug(target + " has " + replies.length + " replies. Removing their flags");
281    }
282    for (Reply reply : replies) {
283      Flag[] replyFlags = converter.convertAsFlags
284        (annotationService.listAnnotations(reply.getId().toString(), annotationService.COMMENT_SET),
285                                           false, false);
286      if (log.isDebugEnabled()) {
287        log.debug("Reply " + reply.getId() + " has " + replyFlags.length + " flags");
288      }
289      for (Flag flag: replyFlags) {
290        deleteFlag(reply.getId().toString(), flag.getId());
291      }
292    }
293
294    if (targetType.equals(Annotea.WEB_TYPE_REPLY)) {
295      replyService.deleteReplies(target); // Bulk delete
296      //annotationService.deleteReply(target);
297      if (log.isDebugEnabled()) {
298        log.debug("Deleted reply: " + target);
299      }
300    } else if (
301        targetType.equals(Annotea.WEB_TYPE_COMMENT) ||
302        targetType.equals(Annotea.WEB_TYPE_NOTE) ||
303        targetType.equals(Annotea.WEB_TYPE_MINOR_CORRECTION) ||
304        targetType.equals(Annotea.WEB_TYPE_FORMAL_CORRECTION) ||
305        targetType.equals(Annotea.WEB_TYPE_RETRACTION)) {
306      replyService.deleteReplies(target, target);
307      annotationService.deleteAnnotation(target);
308      if (log.isDebugEnabled()) {
309        log.debug("Deleted annotation: " + target);
310      }
311    } else if (targetType.equals(Annotea.WEB_TYPE_RATING)) {
312      ratingsService.deleteRating(target);
313      if (log.isDebugEnabled()) {
314        log.debug("Deleted Rating: " + target);
315      }
316    }
317  }
318
319  /*
320   * TODO: It is redundant (and error prone) to presume the caller of this action has provided the
321   * correct target or targetType. This information should be retrieved from the flag by the
322   * service.
323   */
324  private void deleteFlag(String target, String flag) throws Exception {
325    // Delete flag
326    if (log.isDebugEnabled())
327      log.debug("Deleting flag: " + flag + " on target: " + target);
328    annotationService.deleteAnnotation(flag);
329  }
330
331
332  @Required
333  public void setAnnotationService(AnnotationService annotationService) {
334    this.annotationService = annotationService;
335  }
336
337  @Required
338  public void setReplyService(ReplyService replyService) {
339    this.replyService = replyService;
340  }
341
342  /**
343   * Set the RatingsService.
344   *
345   * For Spring wiring.
346   *
347   * @param ratingsService RatingService.
348   */
349  @Required
350  public void setRatingsService(RatingsService ratingsService) {
351    this.ratingsService = ratingsService;
352  }
353
354  @Required
355  public void setAnnotationConverter(AnnotationConverter converter) {
356    this.converter = converter;
357  }
358
359  /**
360   * Sets the FlagManagementService.
361   *
362   * @param  flagManagementService The flag management service
363   */
364  @Required
365  public void setFlagManagementService(FlagManagementService flagManagementService) {
366    this.flagManagementService = flagManagementService;
367  }
368
369  public void setCommentsToUnflag(String[] comments) {
370    commentsToUnflag = comments;
371  }
372
373  public void setCommentsToDelete(String[] comments) {
374    commentsToDelete = comments;
375  }
376
377  public void setConvertToFormalCorrection(String[] convertToFormalCorrection) {
378    this.convertToFormalCorrection = convertToFormalCorrection;
379  }
380
381  public void setConvertToMinorCorrection(String[] convertToMinorCorrection) {
382    this.convertToMinorCorrection = convertToMinorCorrection;
383  }
384
385  public void setConvertToRetraction(String[] convertToRetraction) {
386    this.convertToRetraction = convertToRetraction;
387  }
388
389  public void setConvertToNote(String[] convertToNote) {
390    this.convertToNote = convertToNote;
391  }
392}
Note: See TracBrowser for help on using the browser.