View Javadoc
1       /*
2    * Copyright (C) 2003-2009 eXo Platform SAS.
3    *
4    * This program is free software; you can redistribute it and/or
5    * modify it under the terms of the GNU Affero General Public License
6    * as published by the Free Software Foundation; either version 3
7    * of the License, or (at your option) any later version.
8    *
9    * This program is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   * GNU General Public License for more details.
13   *
14   * You should have received a copy of the GNU General Public License
15   * along with this program; if not, see<http://www.gnu.org/licenses/>.
16   */
17  package org.exoplatform.social.service.rest;
18  
19  import java.lang.reflect.UndeclaredThrowableException;
20  import java.util.ArrayList;
21  import java.util.HashMap;
22  import java.util.List;
23  
24  import javax.ws.rs.Consumes;
25  import javax.ws.rs.GET;
26  import javax.ws.rs.POST;
27  import javax.ws.rs.Path;
28  import javax.ws.rs.PathParam;
29  import javax.ws.rs.QueryParam;
30  import javax.ws.rs.WebApplicationException;
31  import javax.ws.rs.core.Context;
32  import javax.ws.rs.core.MediaType;
33  import javax.ws.rs.core.Response;
34  import javax.ws.rs.core.Response.Status;
35  import javax.ws.rs.core.UriInfo;
36  import javax.xml.bind.annotation.XmlRootElement;
37  
38  import org.exoplatform.commons.utils.ListAccess;
39  import org.exoplatform.container.ExoContainerContext;
40  import org.exoplatform.container.PortalContainer;
41  import org.exoplatform.services.log.ExoLogger;
42  import org.exoplatform.services.log.Log;
43  import org.exoplatform.services.rest.resource.ResourceContainer;
44  import org.exoplatform.services.security.ConversationState;
45  import org.exoplatform.social.common.RealtimeListAccess;
46  import org.exoplatform.social.core.activity.model.ExoSocialActivity;
47  import org.exoplatform.social.core.activity.model.ExoSocialActivityImpl;
48  import org.exoplatform.social.core.identity.model.Identity;
49  import org.exoplatform.social.core.identity.model.Profile;
50  import org.exoplatform.social.core.identity.provider.OrganizationIdentityProvider;
51  import org.exoplatform.social.core.manager.ActivityManager;
52  import org.exoplatform.social.core.manager.IdentityManager;
53  import org.exoplatform.social.core.storage.ActivityStorageException;
54  import org.exoplatform.social.rest.entity.ActivityEntity;
55  import org.exoplatform.social.rest.entity.CommentEntity;
56  import org.exoplatform.social.rest.impl.activity.ActivityRestResourcesV1;
57  import org.exoplatform.social.rest.impl.comment.CommentRestResourcesV1;
58  import org.exoplatform.social.service.rest.api.models.ActivityRestOut;
59  import org.exoplatform.social.service.rest.api.models.ActivityRestOut.Field;
60  import org.exoplatform.social.service.rest.api.models.ActivityStreamRestOut;
61  import org.exoplatform.social.service.rest.api.models.CommentRestOut;
62  import org.exoplatform.social.service.rest.api.models.IdentityRestOut;
63  
64  /**
65   *
66   * Provides services for manipulating activities (like/unlike, comment and delete).
67   * @anchor ActivitiesRestService
68   *
69   */
70  @Path("{portalName}/social/activities")
71  public class ActivitiesRestService implements ResourceContainer {
72  
73    /**
74     * The logger.
75     */
76    private static final Log LOG = ExoLogger.getLogger(ActivitiesRestService.class);
77  
78    private ActivityManager _activityManager;
79    private IdentityManager _identityManager;
80    private String portalName_;
81    /**
82     * constructor
83     */
84    public ActivitiesRestService() {}
85  
86  
87    /**
88     * Destroys an activity by its provided Id.
89     * 
90     * @param uriInfo The requested URI information.
91     * @param portalName The name of current portal.
92     * @param activityId The Id of the target activity which is destroyed.
93     * @param format The format of the returned result, for example, JSON, or XML.
94     * @return The response contains a returned result.
95     * @throws Exception
96     * @LevelAPI Platform
97     * @anchor ActivitiesRestService.destroyActivity
98     * @deprecated Deprecated from 4.3.x. Replaced by a new API {@link ActivityRestResourcesV1#deleteActivityById(UriInfo, String, String)}
99     */
100   @POST
101   @Path("destroy/{activityId}.{format}")
102   public Response destroyActivity(@Context UriInfo uriInfo,
103                                   @PathParam("portalName") String portalName,
104                                   @PathParam("activityId") String activityId,
105                                   @PathParam("format") String format) throws Exception {
106     MediaType mediaType = Util.getMediaType(format);
107     portalName_ = portalName;
108     ActivityManager activityManager = Util.getActivityManager(portalName);
109     ExoSocialActivity activity = activityManager.getActivity(activityId);
110     if (activity == null){
111       LOG.error("No activity is found for this activityId. You should enter a valid and a correct value for the activityId parameter.");
112       return Util.getResponse("No id is found for this activityId. You should enter a valid and a correct value for the activityId parameter.", uriInfo, mediaType, Response.Status.OK);
113     } else {
114       activity = destroyActivity(activityId);
115       return Util.getResponse(activity, uriInfo, mediaType, Response.Status.OK);
116     }
117   }
118 
119   /**
120    * Gets a list of users who like the activity.
121    *
122    * @param uriInfo The requested URI information.
123    * @param portalName The name of the current portal.
124    * @param activityId The Id of the target activity.
125    * @param format The format of the returned result, for example, JSON, or XML.
126    * @return The response contains a returned result.
127    * @throws Exception
128    * @LevelAPI Platform
129    * @anchor ActivitiesRestService.showLikes
130    * @deprecated Deprecated from 4.3.x. Replaced by a new API {@link ActivityRestResourcesV1#getLikesOfActivity(UriInfo, String, int, int, String)}
131    */
132   @GET
133   @Path("{activityId}/likes/show.{format}")
134   public Response showLikes(@Context UriInfo uriInfo,
135                             @PathParam("portalName") String portalName,
136                             @PathParam("activityId") String activityId,
137                             @PathParam("format") String format) throws Exception {
138     MediaType mediaType = Util.getMediaType(format);
139     portalName_ = portalName;
140     LikeList likeList = null;
141     likeList = showLikes(activityId);
142     return Util.getResponse(likeList, uriInfo, mediaType, Response.Status.OK);
143   }
144 
145   /**
146    * Updates the "like" information of the activity.
147    *
148    * @param uriInfo The requested URI information.
149    * @param portalName The name of the current portal.
150    * @param activityId The Id of the target activity.
151    * @param format The format of the returned result, for example, JSON, or XML.
152    * @param like The object containing the information of users who like the activity.
153    * @return The response contains a returned result.
154    * @throws Exception
155    * @LevelAPI Platform
156    * @anchor ActivitiesRestService.updateLike
157    * @deprecated Deprecated from 4.3.x. Replaced by a new API {@link ActivityRestResourcesV1#addLike(UriInfo, String, String)}
158    */
159   @POST
160   @Path("{activityId}/likes/update.{format}")
161   @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
162   public Response updateLike(@Context UriInfo uriInfo,
163                              @PathParam("portalName") String portalName,
164                              @PathParam("activityId") String activityId,
165                              @PathParam("format") String format,
166                              Like like) throws Exception {
167     MediaType mediaType = Util.getMediaType(format);
168     portalName_ = portalName;
169     LikeList likeList = updateLike(activityId, like);
170     return Util.getResponse(likeList, uriInfo, mediaType, Response.Status.OK);
171   }
172 
173   /**
174    * Removes the "like" information of the activity.
175    *
176    * @param uriInfo The requested URI information.
177    * @param portalName The name of the current portal.
178    * @param activityId The Id of the target activity.
179    * @param identityId The information of a user who unlikes the activity.
180    * @param format The format of the returned result, for example, JSON, or XML.
181    * @return The response contains a returned result.
182    * @throws Exception
183    * @LevelAPI Platform
184    * @anchor ActivitiesRestService.destroyLike
185    * @deprecated Deprecated from 4.3.x. Replaced by a new API {@link ActivityRestResourcesV1#deleteLike(UriInfo, String, String, String)}
186    */
187   @POST
188   @Path("{activityId}/likes/destroy/{identityId}.{format}")
189   public Response destroyLike(@Context UriInfo uriInfo,
190                               @PathParam("portalName") String portalName,
191                               @PathParam("activityId") String activityId,
192                               @PathParam("identityId") String identityId,
193                               @PathParam("format") String format) throws Exception{
194     MediaType mediaType = Util.getMediaType(format);
195     portalName_ = portalName;
196     LikeList likeList =  null;
197     likeList = destroyLike(activityId, identityId);
198     return Util.getResponse(likeList, uriInfo, mediaType, Response.Status.OK);
199   }
200 
201   /**
202    * Gets comments on the activity.
203    * 
204    * @param uriInfo The requested URI information.
205    * @param portalName The name of the current portal.
206    * @param activityId The Id of target activity.
207    * @param format The format of the returned result, for example, JSON, or XML.
208    * @return The response contains a returned result.
209    * @throws Exception
210    * @LevelAPI Platform
211    * @anchor ActivitiesRestService.showComments
212    * @deprecated Deprecated from 4.3.x. Replaced by a new API {@link ActivityRestResourcesV1#getCommentsOfActivity(UriInfo, String, int, int, boolean, String)}
213    */
214   @GET
215   @Path("{activityId}/comments/show.{format}")
216   public Response showComments(@Context UriInfo uriInfo,
217                                @PathParam("portalName") String portalName,
218                                @PathParam("activityId") String activityId,
219                                @PathParam("format") String format) throws Exception {
220     MediaType mediaType = Util.getMediaType(format);
221     portalName_ = portalName;
222     CommentList commentList = null;
223     commentList = showComments(activityId);
224     return Util.getResponse(commentList, uriInfo, mediaType, Response.Status.OK);
225   }
226 
227   /**
228    * Gets a limit number of comments on the activity.
229    * 
230    * @param uriInfo The requested URI information.
231    * @param portalName The name of the current portal.
232    * @param activityId The Id of the target activity.
233    * @param format The format of the returned result, for example, JSON, or XML.
234    * @param offset The starting point of the range to get comments. It must be greater than or equal to 0.
235    * @param limit The ending point of the range to get comments.
236    * @return The response contains a returned result.
237    * @throws Exception
238    * @LevelAPI Platform
239    * @anchor ActivitiesRestService.showComments
240    * @deprecated Deprecated from 4.3.x. Replaced by a new API {@link ActivityRestResourcesV1#getCommentsOfActivity(UriInfo, String, int, int, boolean, String)}
241    */
242   @GET
243   @Path("{activityId}/comments.{format}")
244   public Response showComments(@Context UriInfo uriInfo,
245                                @PathParam("portalName") String portalName,
246                                @PathParam("activityId") String activityId,
247                                @PathParam("format") String format,
248                                @QueryParam("offset") Integer offset,
249                                @QueryParam("limit") Integer limit) throws Exception {
250     MediaType mediaType = RestChecker.checkSupportedFormat(format, new String[]{"json"});
251     ActivityManager activityManager = Util.getActivityManager(portalName);
252     ExoSocialActivity activity = activityManager.getActivity(activityId);
253     if (activity == null) {
254       LOG.error("No activity is found for this activityId. You should enter a valid and a correct value for the activityId parameter.");
255       return Util.getResponse("No id is found for this activityId. You should enter a valid and a correct value for the activityId parameter.", uriInfo, mediaType, Response.Status.OK);
256     } else {
257       if(offset == null || limit == null) {
258          offset = 0;
259          limit = 10;
260       }
261       if(offset < 0 || limit < 0) {
262          throw new WebApplicationException(Response.Status.BAD_REQUEST);
263       }
264       try {
265         activity = activityManager.getActivity(activityId);
266         int total;
267         List<CommentRestOut> commentWrapers = null;
268         ListAccess<ExoSocialActivity> comments = activityManager.getCommentsWithListAccess(activity);
269         if(offset > comments.getSize()) {
270           offset = 0;
271           limit = 0;
272         } else if (offset + limit > comments.getSize()) {
273           limit = comments.getSize() - offset;
274         }
275         total = limit;
276         ExoSocialActivity[] commentsLimited = comments.load(offset, total + offset);
277         commentWrapers = new ArrayList<CommentRestOut>(total);
278         for (int i = 0; i < total; i++) {
279           CommentRestOut commentRestOut = new CommentRestOut(commentsLimited[i], portalName);
280           commentRestOut.setPosterIdentity(commentsLimited[i], portalName);
281           commentWrapers.add(commentRestOut);
282         }
283         HashMap<String, Object> resultJson = new HashMap<String, Object>();
284         resultJson.put("totalNumberOfComments", commentWrapers.size());
285         resultJson.put("comments", commentWrapers);
286         return Util.getResponse(resultJson, uriInfo, mediaType, Response.Status.OK);
287       } catch (UndeclaredThrowableException undeclaredThrowableException) {
288          if (undeclaredThrowableException.getCause() instanceof ActivityStorageException) {
289            throw new WebApplicationException(Response.Status.NOT_FOUND);
290          } else {
291            throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
292          }
293       } catch (Exception e) {
294            throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
295      }
296     }
297   }
298   /**
299    * Gets an activity by its Id.
300    *
301    * @param uriInfo  The requested URI information.
302    * @param portalContainerName The associated portal container name.
303    * @param activityId The Id of the target activity.
304    * @param format The format of the returned result, for example: JSON, or XML.
305    * @param showPosterIdentity The identity information of the poster.
306    * @param numberOfComments The number of comments will be returned.
307    * @param showActivityStream Specifies the stream of an activity.
308    * @param numberOfLikes The number of likes will be returned.
309    * @return The response contains a returned result.
310    * @LevelAPI Platform
311    * @anchor ActivitiesRestService.getActivityById
312    * @deprecated Deprecated from 4.3.x. Replaced by a new API {@link ActivityRestResourcesV1#getActivityById(UriInfo, String, String)}
313    */
314   @GET
315   @Path("{activityId}.{format}")
316   public Response getActivityById(@Context UriInfo uriInfo,
317                                   @PathParam("portalName") String portalContainerName,
318                                   @PathParam("activityId") String activityId,
319                                   @PathParam("format") String format,
320                                   @QueryParam("poster_identity") String showPosterIdentity,
321                                   @QueryParam("number_of_comments") int numberOfComments,
322                                   @QueryParam("activity_stream") String showActivityStream,
323                                   @QueryParam("number_of_likes") int numberOfLikes) {
324     
325     MediaType mediaType = RestChecker.checkSupportedFormat(format, new String[]{"json"});
326     ActivityManager activityManager = Util.getActivityManager(portalContainerName);
327     IdentityManager identityManager = Util.getIdentityManager(portalContainerName);
328     
329     ExoSocialActivity activity = null;
330     try {
331       activity = activityManager.getActivity(activityId);
332     } catch (UndeclaredThrowableException undeclaredThrowableException) {
333       if(undeclaredThrowableException.getCause() instanceof ActivityStorageException){
334         throw new WebApplicationException(Response.Status.NOT_FOUND);
335       } else {
336         throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
337       }
338     }
339     
340     if(activity.isComment()) {
341       throw new WebApplicationException(Response.Status.NOT_FOUND);
342     }
343     ActivityRestOut model = new ActivityRestOut();
344     
345     
346     model.setId(activity.getId());
347     model.setTitle(activity.getTitle());
348     model.setPriority(activity.getPriority());
349     model.setAppId(activity.getAppId());
350     model.setType(activity.getType());
351     model.setPostedTime(activity.getPostedTime());
352     model.setLastUpdatedTime(activity.getUpdated().getTime());
353     model.setCreatedAt(Util.convertTimestampToTimeString(activity.getPostedTime()));
354     model.setTitleId(activity.getTitleId());
355     model.setTemplateParams(activity.getTemplateParams());
356     
357     if(activity.getLikeIdentityIds() != null){
358       model.setTotalNumberOfLikes(activity.getLikeIdentityIds().length);
359     } else {
360       model.setTotalNumberOfLikes(null);
361     }
362     
363     if(Util.isLikedByIdentity(identityManager.getOrCreateIdentity(OrganizationIdentityProvider.NAME, Util.getViewerId(uriInfo),
364                                                                   true).getId(),activity)){
365       model.setLiked(true);
366     } else {
367       model.setLiked(false);
368     }
369     
370     RealtimeListAccess<ExoSocialActivity> commentRealtimeListAccess = Util.getActivityManager(portalContainerName).
371                                                                            getCommentsWithListAccess(activity);
372     model.setTotalNumberOfComments(commentRealtimeListAccess.getSize());
373     
374     Identity streamOwnerIdentity = Util.getOwnerIdentityIdFromActivity(portalContainerName, activity);
375     if(streamOwnerIdentity != null){
376       model.put(Field.IDENTITY_ID.toString(),streamOwnerIdentity.getId());
377     }
378     
379     
380     
381     if (isPassed(showPosterIdentity)) {
382       model.setPosterIdentity(new IdentityRestOut(identityManager.getIdentity(activity.getUserId(), false)));
383     }
384     
385     if (isPassed(showActivityStream)) {
386       model.setActivityStream(new ActivityStreamRestOut(activity.getActivityStream(), portalContainerName));
387     }
388     
389     model.setNumberOfComments(numberOfComments, activity, portalContainerName);
390     
391     return Util.getResponse(model, uriInfo, mediaType, Response.Status.OK);
392   }
393   
394   /**
395    * Updates the comment information on the activity.
396    * 
397    * @param uriInfo The requested URI information.
398    * @param portalName The name of the current portal.
399    * @param activityId The Id of the target comment which is updated.
400    * @param format The format of the returned result, for example, JSON, or XML.
401    * @param comment The comment to be updated.
402    * @return response The response contains a returned result.
403    * @throws Exception
404    * @LevelAPI Platform
405    * @anchor ActivitiesRestService.updateComment
406    * @deprecated Deprecated from 4.3.x. Replaced by a new API {@link CommentRestResourcesV1#updateCommentById(UriInfo, String, String, ActivityEntity)}
407    */
408   @POST
409   @Path("{activityId}/comments/update.{format}")
410   @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
411   public Response updateComment(@Context UriInfo uriInfo,
412                                 @PathParam("portalName") String portalName,
413                                 @PathParam("activityId") String activityId,
414                                 @PathParam("format") String format,
415                                 ExoSocialActivityImpl comment) throws Exception {
416     MediaType mediaType = Util.getMediaType(format);
417     portalName_ = portalName;
418     CommentList commentList = null;
419     commentList = updateComment(activityId, comment, uriInfo, portalName);
420     return Util.getResponse(commentList, uriInfo, mediaType, Response.Status.OK);
421   }
422 
423   /**
424    * Add comments to an existing activity.
425    *
426    * @param uriInfo The requested URI information.
427    * @param portalName The associated portal container name.
428    * @param activityId The Id of the activity.
429    * @param format The format of the returned result, for example, JSON, or XML.
430    * @param text The content of the comment.
431    * @return The response contains a returned result.
432    * @LevelAPI Platform
433    * @anchor ActivitiesRestService.createCommentActivityById
434    * @deprecated Deprecated from 4.3.x. Replaced by a new API {@link ActivityRestResourcesV1#postComment(UriInfo, String, String, CommentEntity)}
435    */
436   @GET
437   @Path("{activityId}/comments/create.{format}")
438   public Response createCommentActivityById(@Context UriInfo uriInfo,
439                                            @PathParam("portalName") String portalName,
440                                            @PathParam("activityId") String activityId,
441                                            @PathParam("format") String format,
442                                            @QueryParam("text") String text) {
443     PortalContainer portalContainer = RestChecker.checkValidPortalContainerName(portalName);
444     
445     if(text == null || text.trim().equals("")){
446       throw new WebApplicationException(Response.Status.BAD_REQUEST);
447     }
448       
449     MediaType mediaType = RestChecker.checkSupportedFormat(format, new String[]{"json"});
450 
451     Identity currentIdentity = Util.getIdentityManager(portalName).getOrCreateIdentity(OrganizationIdentityProvider.NAME,
452                                                                                        Util.getViewerId(uriInfo), false);
453     ActivityManager activityManager = Util.getActivityManager(portalName);
454     ExoSocialActivity activity = null;
455     
456     try {
457       activity = activityManager.getActivity(activityId);
458     } catch (UndeclaredThrowableException undeclaredThrowableException){
459       if(undeclaredThrowableException.getCause() instanceof ActivityStorageException){
460         throw new WebApplicationException(Response.Status.NOT_FOUND);
461       } else {
462         throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
463       }
464     }
465     
466     ExoSocialActivity commentActivity = new ExoSocialActivityImpl();
467     commentActivity.setTitle(text);
468     commentActivity.setUserId(currentIdentity.getId());
469     
470     activityManager.saveComment(activity,commentActivity);
471     
472     CommentRestOut commentOut = new CommentRestOut(commentActivity, portalName);
473     
474     return Util.getResponse(commentOut, uriInfo, mediaType, Response.Status.OK);
475   }
476   
477   /**
478    * Removes comments on the activity.
479    * 
480    * @param uriInfo The requested URI information.
481    * @param portalName The name of the current portal.
482    * @param activityId The activity Id.
483    * @param commentId The Id of the target comment which is destroyed.
484    * @param format The format of the returned result, for example, JSON, or XML.
485    * @return response The response contains a returned result.
486    * @throws Exception
487    * @LevelAPI Platform
488    * @anchor ActivitiesRestService.destroyComment
489    * @deprecated Deprecated from 4.3.x. Replaced by a new API {@link CommentRestResourcesV1#deleteCommentById(UriInfo, String, String)}
490    */
491   @POST
492   @Path("{activityId}/comments/destroy/{commentId}.{format}")
493   public Response destroyComment(@Context UriInfo uriInfo,
494                                  @PathParam("portalName") String portalName,
495                                  @PathParam("activityId") String activityId,
496                                  @PathParam("commentId") String commentId,
497                                  @PathParam("format") String format) throws Exception {
498     MediaType mediaType = Util.getMediaType(format);
499     portalName_ = portalName;
500     CommentList commentList = null;
501     commentList = destroyComment(activityId, commentId);
502     return Util.getResponse(commentList, uriInfo, mediaType, Response.Status.OK);
503   }
504 
505   /**
506    * Destroys an activity by activityId.
507    * If any comments of that activity are detected, they will be destroyed, too.
508    * @param activityId
509    * @anchor ActivitiesRestService
510    * @return activity
511    */
512   private ExoSocialActivity destroyActivity(String activityId) {
513     _activityManager = getActivityManager();
514     ExoSocialActivity activity = _activityManager.getActivity(activityId);
515 
516     if (activity == null) {
517       throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
518     }
519     try {
520       _activityManager.deleteActivity(activityId);
521     } catch(Exception ex) {
522       throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
523     }
524     return activity;
525   }
526   
527   /**
528    * Show list of like by activityId.
529    * @param activityId
530    * @return
531    * @throws Exception
532    */
533   private LikeList showLikes(String activityId) {
534     _activityManager = getActivityManager();
535     ExoSocialActivity activity = null;
536     try {
537       activity = _activityManager.getActivity(activityId);
538     } catch (ActivityStorageException e) {
539       throw new WebApplicationException((Response.Status.INTERNAL_SERVER_ERROR));
540     }
541     if (activity == null) {
542       throw new WebApplicationException(Response.Status.NOT_FOUND);
543     }
544 
545     //
546     LikeList likeList = new LikeList();
547     likeList.setActivityId(activityId);
548     likeList.setLikes(getLikes(activity.getLikeIdentityIds()));
549     return likeList;
550   }
551   
552   /**
553    * Update like of an activity.
554    * @param activityId
555    * @param like
556    * @throws Exception
557    */
558   private LikeList updateLike(String activityId, Like like) throws Exception {
559 
560     _activityManager = getActivityManager();
561     _identityManager = getIdentityManager();
562 
563     //
564     ExoSocialActivity activity = _activityManager.getActivity(activityId);
565     if (activity == null) {
566       throw new WebApplicationException(Response.Status.NOT_FOUND);
567     }
568 
569     //
570     String identityId = like.getIdentityId();
571     if (identityId == null) {
572       throw new WebApplicationException(Response.Status.NOT_ACCEPTABLE);
573     }
574     Identity identity = _identityManager.getIdentity(like.getIdentityId(), false);
575 
576     //
577     _activityManager.saveLike(activity, identity);
578 
579     //
580     LikeList likeList = new LikeList();
581     likeList.setActivityId(activityId);
582     likeList.setLikes(getLikes(activity.getLikeIdentityIds()));
583     return likeList;
584   }
585 
586   /**
587    * Destroy like from an activity.
588    * @param activityId
589    * @param identityId
590    */
591   private LikeList destroyLike(String activityId, String identityId) {
592 
593     _activityManager = getActivityManager();
594     ExoSocialActivity activity = null;
595     //
596     try {
597       activity = _activityManager.getActivity(activityId);
598     } catch (ActivityStorageException e) {
599       throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
600     }
601     if (activity == null) {
602       throw new WebApplicationException(Response.Status.NOT_FOUND);
603     }
604 
605     //
606     if (identityId == null) {
607       throw new WebApplicationException(Response.Status.BAD_REQUEST);
608     }
609 
610     try {
611       Identity user = getIdentityManager().getIdentity(identityId, false);
612       _activityManager.deleteLike(activity, user);
613     } catch(Exception ex) {
614       throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
615     }
616 
617     //
618     LikeList likeList = new LikeList();
619     likeList.setActivityId(activityId);
620     likeList.setLikes(getLikes(activity.getLikeIdentityIds()));
621 
622     return likeList;
623   }
624   
625   /**
626    * Show comment list of an activity from its activityId.
627    *
628    * @param activityId
629    * @return commentList
630    * @see CommentList
631    */
632   private CommentList showComments(String activityId) {
633     CommentList commentList = new CommentList();
634     commentList.setActivityId(activityId);
635     _activityManager = getActivityManager();
636     ExoSocialActivity activity = null;
637     try {
638       activity = _activityManager.getActivity(activityId);
639       if (activity == null) {
640         throw new WebApplicationException(Response.Status.NOT_FOUND);
641       }
642       String[] commentIds = activity.getReplyToId();
643       if (commentIds == null) {
644         commentList.setComments(new ArrayList<ExoSocialActivity>());
645       } else {
646         for (String commentId: commentIds) {
647           if (commentId.length() > 0) {
648             commentList.addComment(_activityManager.getActivity(commentId));
649           }
650         }
651       }
652     } catch (ActivityStorageException e) {
653       throw new WebApplicationException(e, Response.Status.INTERNAL_SERVER_ERROR);
654     }
655 
656     return commentList;
657   }
658 
659   /**
660    * Create or update comment to an activity by its activityId.
661    * @param activityId
662    * @param comment
663    * @return commentList
664    * @see CommentList
665    */
666   private CommentList updateComment(String activityId, ExoSocialActivity comment, UriInfo uriInfo, String portalName) {
667     CommentList commentList = new CommentList();
668     commentList.setActivityId(activityId);
669     ExoSocialActivity activity = null;
670     try {
671       activity = _activityManager.getActivity(activityId);
672     } catch (ActivityStorageException e) {
673       throw new WebApplicationException(e, Response.Status.INTERNAL_SERVER_ERROR);
674     }
675     if (activity == null) {
676       throw new WebApplicationException(Response.Status.NOT_FOUND);
677     }
678     _activityManager = getActivityManager();
679 
680     ConversationState state = ConversationState.getCurrent();
681     String userId = null;
682     if (state != null) {
683       userId = state.getIdentity().getUserId();
684     } else {
685       try {
686         userId = Util.getViewerId(uriInfo);
687       } catch (Exception e) {
688         LOG.warn(e.getMessage(), e);
689       }
690     }
691     Identity identity = null;
692     try {
693       identity = getIdentityManager(portalName).getOrCreateIdentity(OrganizationIdentityProvider.NAME, userId);
694     } catch (Exception e1) {
695       LOG.warn(e1.getMessage(), e1);
696     }
697     
698     if (identity == null) {
699       identity = getIdentityManager(portalName).getOrCreateIdentity(OrganizationIdentityProvider.NAME, Util.getViewerId(uriInfo),
700                                                                     false);
701     }
702     
703      //TODO hoatle set current userId from authentication context instead of getting userId from comment
704      if (comment.getUserId() == null) {
705        throw new WebApplicationException(Response.Status.BAD_REQUEST);
706     } else {
707       comment.setUserId(identity.getId());
708     }
709 
710     try {
711       _activityManager.saveComment(activity, comment);
712     } catch (Exception e) {
713       throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
714     }
715     commentList.addComment(comment);
716     return commentList;
717   }
718 
719   /**
720    * Get identityManager.
721    * @return
722    */
723   private IdentityManager getIdentityManager(String portalName) {
724     if (_identityManager == null) {
725       PortalContainer portalContainer = (PortalContainer) ExoContainerContext.getContainerByName(portalName);
726       _identityManager = (IdentityManager) portalContainer.getComponentInstanceOfType(IdentityManager.class);
727     }
728     return _identityManager;
729   }
730 
731 
732   /**
733    * Destroy a comment (by its commentId) from an activity (by its activityId).
734    *
735    * @param activityId
736    * @param commentId
737    * @return commentList
738    * @see CommentList
739    */
740   private CommentList destroyComment(String activityId, String commentId) {
741 
742     CommentList commentList = new CommentList();
743     commentList.setActivityId(activityId);
744 
745     _activityManager = getActivityManager();
746 
747     ExoSocialActivity activity = null;
748     try {
749       activity = _activityManager.getActivity(activityId);
750       ExoSocialActivity comment = _activityManager.getActivity(commentId);
751       if (activity == null || comment == null) {
752         throw new WebApplicationException(Response.Status.NOT_FOUND);
753       }
754       commentList.addComment(comment);
755       _activityManager.deleteComment(activityId, commentId);
756     } catch (ActivityStorageException e) {
757       throw new WebApplicationException(e, Response.Status.INTERNAL_SERVER_ERROR);
758     }
759     return commentList;
760   }
761 
762   /**
763    * LikeList model
764    * @author hoatle
765    */
766   @XmlRootElement
767   static public class LikeList {
768     private String _activityId;
769     private List<Like> _likes;
770     /**
771      * sets activityId
772      * @param activityId
773      */
774     public void setActivityId(String activityId) {
775       _activityId = activityId;
776     }
777     /**
778      * gets activityId
779      * @return
780      */
781     public String getActivityId() {
782       return _activityId;
783     }
784     /**
785      * sets like list
786      * @param likes like list
787      */
788     public void setLikes(List<Like> likes) {
789       _likes = likes;
790     }
791 
792     /**
793      * gets like list
794      * @return like list
795      */
796     public List<Like> getLikes() {
797       return _likes;
798     }
799 
800     /**
801      * adds like to like list
802      * @param like
803      */
804     public void addLike(Like like) {
805       if (_likes == null) {
806         _likes = new ArrayList<Like>();
807       }
808       _likes.add(like);
809     }
810   }
811 
812   /**
813    * CommentList model
814    * @author hoatle
815    *
816    */
817   @XmlRootElement
818   static public class CommentList {
819     private String _activityId;
820     private List<ExoSocialActivity> _comments;
821     /**
822      * sets activityId
823      * @param activityId
824      */
825     public void setActivityId(String activityId) {
826       _activityId = activityId;
827     }
828     /**
829      * gets activityId
830      * @return activityId
831      */
832     public String getActivityId() {
833       return _activityId;
834     }
835     /**
836      * sets comment list
837      * @param comments comment list
838      */
839     public void setComments(List<ExoSocialActivity> comments) {
840       _comments = comments;
841     }
842     /**
843      * gets comment list
844      * @return comments
845      */
846     public List<ExoSocialActivity> getComments() {
847       return _comments;
848     }
849     /**
850      * add comment to comment List
851      * @param activity comment
852      */
853     public void addComment(ExoSocialActivity activity) {
854       if (_comments == null) {
855         _comments = new ArrayList<ExoSocialActivity>();
856       }
857       _comments.add(activity);
858     }
859   }
860 
861   /**
862    * gets activityManager
863    * @return activityManager
864    * @see ActivityManager
865    */
866   private ActivityManager getActivityManager() {
867     if (_activityManager == null) {
868       PortalContainer portalContainer = (PortalContainer) ExoContainerContext.getContainerByName(portalName_);
869       if (portalContainer == null) {
870         throw new WebApplicationException(Status.INTERNAL_SERVER_ERROR);
871       }
872       _activityManager = (ActivityManager) portalContainer.getComponentInstanceOfType(ActivityManager.class);
873     }
874     return _activityManager;
875   }
876 
877   /**
878    * gets identityManger
879    * @return
880    * @see IdentityManager
881    */
882   private IdentityManager getIdentityManager() {
883     if (_identityManager == null) {
884       PortalContainer portalContainer = (PortalContainer) ExoContainerContext.getContainerByName(portalName_);
885       if (portalContainer == null) {
886         throw new WebApplicationException(Status.INTERNAL_SERVER_ERROR);
887       }
888       _identityManager = (IdentityManager) portalContainer.getComponentInstanceOfType(IdentityManager.class);
889     }
890     return _identityManager;
891   }
892 
893   /**
894    * gets like list
895    * @param identityIds
896    * @return
897    */
898   private List<Like> getLikes(String[] identityIds) {
899     Profile profile;
900     Identity identity;
901     Like like;
902     List<Like> likes = new ArrayList<Like>();
903     _identityManager = getIdentityManager();
904     try {
905       for (String identityId : identityIds) {
906         identity = _identityManager.getIdentity(identityId, false);
907         profile = identity.getProfile();
908         like = new Like();
909         like.setIdentityId(identityId);
910         like.setUsername((String) profile.getProperty(Profile.USERNAME));
911         like.setFullName(profile.getFullName());
912         like.setThumbnail(profile.getAvatarUrl());
913         likes.add(like);
914       }
915     } catch (Exception ex) {
916       throw new WebApplicationException(Response.Status.BAD_REQUEST);
917     }
918     return likes;
919   }
920   
921   private boolean isPassed(String value) {
922     return value != null && ("true".equals(value) || "t".equals(value) || "1".equals(value));
923   }
924 }