/*
 * Copyright (C) 2003-2011 eXo Platform SAS.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package org.exoplatform.social.service.rest;


import org.exoplatform.commons.utils.ListAccess;
import org.exoplatform.container.PortalContainer;
import org.exoplatform.social.common.RealtimeListAccess;
import org.exoplatform.social.core.activity.model.ExoSocialActivity;
import org.exoplatform.social.core.activity.model.ExoSocialActivityImpl;
import org.exoplatform.social.core.identity.model.Identity;
import org.exoplatform.social.core.identity.provider.OrganizationIdentityProvider;
import org.exoplatform.social.core.identity.provider.SpaceIdentityProvider;
import org.exoplatform.social.core.manager.ActivityManager;
import org.exoplatform.social.core.manager.IdentityManager;
import org.exoplatform.social.core.manager.RelationshipManager;
import org.exoplatform.social.core.profile.ProfileFilter;
import org.exoplatform.social.core.space.SpaceException;
import org.exoplatform.social.core.space.impl.DefaultSpaceApplicationHandler;
import org.exoplatform.social.core.space.model.Space;
import org.exoplatform.social.core.space.spi.SpaceService;
import org.exoplatform.social.core.storage.impl.StorageUtils;
import org.exoplatform.social.service.test.AbstractServiceTest;
import org.jmock.core.constraint.Or;

import java.util.Arrays;
import java.util.List;
import java.util.Random;

/**
 * Unit Test for {@link SecurityManager}.
 *
 * @author <a href="http://hoatle.net">hoatle (hoatlevan at gmail dot com)</a>
 * @since Jun 17, 2011
 */
public class SecurityManagerTest extends AbstractServiceTest {

  /**
   * The identities.
   */
  private Identity rootIdentity, johnIdentity, maryIdentity, demoIdentity;

  /**
   * The identity manager.
   */
  private IdentityManager identityManager;
  /**
   * The relationship manager.
   */
  private RelationshipManager relationshipManager;
  /**
   * The activity manager.
   */
  private ActivityManager activityManager;
  /**
   * The space service.
   */
  private SpaceService spaceService;

  @Override
  public void setUp() throws Exception {
    super.setUp();
    identityManager = getContainer().getComponentInstanceOfType(IdentityManager.class);
    relationshipManager = getContainer().getComponentInstanceOfType(RelationshipManager.class);
    activityManager = getContainer().getComponentInstanceOfType(ActivityManager.class);
    spaceService = getContainer().getComponentInstanceOfType(SpaceService.class);

    rootIdentity = new Identity(OrganizationIdentityProvider.NAME, "root");
    johnIdentity = new Identity(OrganizationIdentityProvider.NAME, "john");
    maryIdentity = new Identity(OrganizationIdentityProvider.NAME, "mary");
    demoIdentity = new Identity(OrganizationIdentityProvider.NAME, "demo");

    identityManager.saveIdentity(rootIdentity);
    identityManager.saveIdentity(johnIdentity);
    identityManager.saveIdentity(maryIdentity);
    identityManager.saveIdentity(demoIdentity);

    restartTransaction();
    begin();
    deleteAllRelationships();
    restartTransaction();
  }

  @Override
  protected void tearDown() throws Exception {
    end();
    super.tearDown();
  }

  /**
   * Tests {@link SecurityManager#canAccessActivity(PortalContainer, Identity, ExoSocialActivity)}.
   */
  public void testCanAccessActivityUnknown() {
    createActivities(demoIdentity, demoIdentity, 2);
    RealtimeListAccess<ExoSocialActivity> demoActivitiesListAccess = activityManager.getActivitiesWithListAccess(demoIdentity);
    ExoSocialActivity activity = demoActivitiesListAccess.loadAsList(0, demoActivitiesListAccess.getSize()).get(0);
    assertEquals(true, SecurityManager.canAccessActivity(getContainer(), johnIdentity, activity));
    assertEquals(true, SecurityManager.canAccessActivity(getContainer(), johnIdentity.getRemoteId(), activity));
  }

  /**
   * Tests {@link SecurityManager#canAccessActivity(PortalContainer, Identity, ExoSocialActivity)}.
   */
  public void testCanAccessActivityMine() {
    createActivities(demoIdentity, demoIdentity, 2);
    RealtimeListAccess<ExoSocialActivity> demoActivitiesListAccess = activityManager.getActivitiesWithListAccess(demoIdentity);
    ExoSocialActivity activity = demoActivitiesListAccess.loadAsList(0, demoActivitiesListAccess.getSize()).get(0);
    assertEquals(true, SecurityManager.canAccessActivity(getContainer(), demoIdentity, activity));
    assertEquals(true, SecurityManager.canAccessActivity(getContainer(), demoIdentity.getRemoteId(), activity));
  }

  /**
   * Tests {@link SecurityManager#canAccessActivity(PortalContainer, Identity, ExoSocialActivity)}.
   */
  public void testCanAccessActivityNetwork() {
    createActivities(demoIdentity, demoIdentity, 2);
    connectIdentities(demoIdentity, johnIdentity, true);
    RealtimeListAccess<ExoSocialActivity> demoActivitiesListAccess = activityManager.getActivitiesWithListAccess(demoIdentity);
    ExoSocialActivity activity = demoActivitiesListAccess.loadAsList(0, demoActivitiesListAccess.getSize()).get(0);

    // In network stream
    assertEquals(true, SecurityManager.canAccessActivity(getContainer(), johnIdentity, activity));
    assertEquals(true, SecurityManager.canAccessActivity(getContainer(), johnIdentity.getRemoteId(), activity));

    // Out network stream
    assertEquals(true, SecurityManager.canAccessActivity(getContainer(), maryIdentity, activity));
    assertEquals(true, SecurityManager.canAccessActivity(getContainer(), maryIdentity.getRemoteId(), activity));
  }

  /**
   * Tests {@link SecurityManager#canAccessActivity(PortalContainer, Identity, ExoSocialActivity)}.
   */
  public void testCanAccessActivitySpace() throws SpaceException {

    createSpace("space1");

    //
    Space space1 = spaceService.getSpaceByDisplayName("space1");
    Identity spaceIdentity = identityManager.getOrCreateIdentity(SpaceIdentityProvider.NAME, space1.getPrettyName(), false);
    createActivities(spaceIdentity, spaceIdentity, 2);
    
    RealtimeListAccess<ExoSocialActivity> spaceActivitiesListAccess = activityManager.getActivitiesWithListAccess(spaceIdentity);
    ExoSocialActivity activity = spaceActivitiesListAccess.loadAsList(0, 10).get(0);

    assertEquals(true, SecurityManager.canAccessActivity(getContainer(), demoIdentity, activity));
    assertEquals(true, SecurityManager.canAccessActivity(getContainer(), demoIdentity.getRemoteId(), activity));
    assertEquals(true, SecurityManager.canAccessActivity(getContainer(), maryIdentity, activity));
    assertEquals(true, SecurityManager.canAccessActivity(getContainer(), maryIdentity.getRemoteId(), activity));

    assertEquals(false, SecurityManager.canAccessActivity(getContainer(), johnIdentity, activity));
    assertEquals(false, SecurityManager.canAccessActivity(getContainer(), johnIdentity.getRemoteId(), activity));
  }

  /**
   * Tests {@link SecurityManager#canPostActivity(PortalContainer, Identity, Identity)}.
   */
  public void testCanPostActivity() {
    boolean demoPostToDemo = SecurityManager.canPostActivity(getContainer(), demoIdentity, demoIdentity);
    assertTrue("demoPostToDemo must be true", demoPostToDemo);
    boolean demoPostToJohn = SecurityManager.canPostActivity(getContainer(), demoIdentity, johnIdentity);
    assertFalse("demoPostToJohn must be false", demoPostToJohn);
    //demo is connected to mary => they can post activity to each other's activity stream
    relationshipManager.inviteToConnect(demoIdentity, maryIdentity);
    boolean demoPostToMary = SecurityManager.canPostActivity(getContainer(), demoIdentity, maryIdentity);
    boolean maryPostToDemo = SecurityManager.canPostActivity(getContainer(), maryIdentity, demoIdentity);
    assertFalse("demoPostToMary must be false", demoPostToMary);
    assertFalse("maryPostToDemo must be false", maryPostToDemo);
    relationshipManager.confirm(maryIdentity, demoIdentity);
    demoPostToMary = SecurityManager.canPostActivity(getContainer(), demoIdentity, maryIdentity);
    maryPostToDemo = SecurityManager.canPostActivity(getContainer(), maryIdentity, demoIdentity);
    assertTrue("demoPostToMary must be true", demoPostToMary);
    assertTrue("maryPostToDemo must be true", maryPostToDemo);
    //checks user posts to space
    createSpace("space2");
    Identity spaceIdentity = identityManager.getOrCreateIdentity(SpaceIdentityProvider.NAME,
                                                                 "space2",
                                                                 false);
    assertNotNull("spaceIdentity must not be null", spaceIdentity);

    //demo, mary could post activity to this space's activity stream

    boolean demoPostToSpace = SecurityManager.canPostActivity(getContainer(), demoIdentity, spaceIdentity);
    assertTrue("demoPostToSpace must be true", demoPostToSpace);
    boolean maryPostToSpace = SecurityManager.canPostActivity(getContainer(), maryIdentity, spaceIdentity);
    assertTrue("maryPostToSpace must be false", maryPostToSpace);

    //john could not
    boolean johnPostToSpace = SecurityManager.canPostActivity(getContainer(), johnIdentity, spaceIdentity);
    assertFalse("johnPostToSpace must be false", johnPostToSpace);
  }

  /**
   * Tests {@link SecurityManager#canDeleteActivity(PortalContainer, Identity, ExoSocialActivity)}.
   */
  public void testCanDeleteActivity() {
    createActivities(demoIdentity, demoIdentity, 2);
    
    RealtimeListAccess<ExoSocialActivity> demoActivitiesListAccess = activityManager.getActivitiesWithListAccess(demoIdentity);
    ExoSocialActivity demoActivity = demoActivitiesListAccess.loadAsList(0, demoActivitiesListAccess.getSize()).get(1);
    boolean demoDeleteDemoActivity = SecurityManager.canDeleteActivity(getContainer(), demoIdentity, demoActivity);
    assertTrue("demoDeleteDemoActivity must be true", demoDeleteDemoActivity);

    boolean maryDeleteDemoActivity = SecurityManager.canDeleteActivity(getContainer(), maryIdentity, demoActivity);
    assertFalse("maryDeleteDemoActivity must be false", maryDeleteDemoActivity);


    //demo connects to john
    createActivities(johnIdentity, johnIdentity, 1);
    connectIdentities(demoIdentity, johnIdentity, false);
    RealtimeListAccess<ExoSocialActivity> johnActivitiesListAccess = activityManager.getActivitiesWithListAccess(johnIdentity);
    ExoSocialActivity johnActivity = johnActivitiesListAccess.loadAsList(0, johnActivitiesListAccess.getSize()).get(0);
    boolean demoDeleteJohnActivity = SecurityManager.canDeleteActivity(getContainer(), demoIdentity, johnActivity);
    assertFalse("demoDeleteDemoActivity must be false", demoDeleteJohnActivity);

    connectIdentities(demoIdentity, johnIdentity, true);
    createActivities(demoIdentity, johnIdentity, 1);
    johnActivitiesListAccess = activityManager.getActivitiesWithListAccess(johnIdentity);
    demoActivity = johnActivitiesListAccess.loadAsList(0, johnActivitiesListAccess.getSize()).get(0); //newest
    demoDeleteDemoActivity = SecurityManager.canDeleteActivity(getContainer(), johnIdentity, demoActivity);
    assertTrue("demoDeleteDemoActivity must be true", demoDeleteDemoActivity);
    boolean johnDeleteDemoActivity = SecurityManager.canDeleteActivity(getContainer(), johnIdentity, demoActivity);
    assertTrue("johnDeleteDemoActivity must be true", johnDeleteDemoActivity);

    //demo, mary, john on a space
    createSpace("space3");
    Identity spaceIdentity = identityManager.getOrCreateIdentity(SpaceIdentityProvider.NAME,
            "space3", false);
    createActivities(spaceIdentity, spaceIdentity, 1);
    RealtimeListAccess<ExoSocialActivity> spaceActivitiesListAccess = activityManager.getActivitiesWithListAccess(spaceIdentity);
    ExoSocialActivity spaceActivity = spaceActivitiesListAccess.loadAsList(0, 1).get(0);
    boolean demoDeleteSpaceActivity = SecurityManager.canDeleteActivity(getContainer(), demoIdentity, spaceActivity);
    assertTrue("demoDeleteDemoActivity must be true", demoDeleteSpaceActivity);
    boolean maryDeleteSpaceActivity = SecurityManager.canDeleteActivity(getContainer(), maryIdentity, spaceActivity);
    assertFalse("maryDeleteSpaceActivity must be false", maryDeleteSpaceActivity);
    boolean johnDeleteSpaceActivity = SecurityManager.canDeleteActivity(getContainer(), johnIdentity, spaceActivity);
    assertFalse("johnDeleteSpaceActivity must be false", johnDeleteSpaceActivity);
    createActivities(demoIdentity, spaceIdentity, 1);
    spaceActivitiesListAccess = activityManager.getActivitiesWithListAccess(spaceIdentity);
    ExoSocialActivity demoToSpaceActivity = spaceActivitiesListAccess.loadAsList(0, 10).get(0);
    boolean demoDeleteDemoToSpaceActivity = SecurityManager.canDeleteActivity(getContainer(),
                                                                              demoIdentity, demoToSpaceActivity);
    assertTrue("demoDeleteDemoToSpaceActivity must be true", demoDeleteDemoToSpaceActivity);
    boolean maryDeleteDemoToSpaceActivity = SecurityManager.canDeleteActivity(getContainer(),
                                                                              maryIdentity, demoToSpaceActivity);
    assertFalse("maryDeleteDemoToSpaceActivity must be false", maryDeleteDemoToSpaceActivity);
    boolean johnDeleteDemoToSpaceActivity = SecurityManager.canDeleteActivity(getContainer(),
                                                                              johnIdentity, demoToSpaceActivity);
    assertFalse("johnDeleteDemoToSpaceActivity must be false", johnDeleteDemoToSpaceActivity);
  }


  /**
   * Tests {@link SecurityManager#canCommentToActivity(PortalContainer, Identity, ExoSocialActivity)}.
   */
  public void testCanCommentToActivity() {
    createActivities(demoIdentity, demoIdentity, 1);
    RealtimeListAccess<ExoSocialActivity> demoActivitiesListAccess = activityManager.getActivitiesWithListAccess(demoIdentity);
    ExoSocialActivity demoActivity = demoActivitiesListAccess.loadAsList(0, demoActivitiesListAccess.getSize()).get(0);
    boolean demoCommentToDemoActivity = SecurityManager.canCommentToActivity(getContainer(),
                                                                             demoIdentity, demoActivity);
    assertTrue("demoCommentToDemoActivity must be true", demoCommentToDemoActivity);

    connectIdentities(maryIdentity, demoIdentity, false);
    boolean maryCommentToDemoActivity = SecurityManager.canCommentToActivity(getContainer(),
                                                                             maryIdentity, demoActivity);
    assertFalse("maryCommentToDemoActivity must be false", maryCommentToDemoActivity);
    connectIdentities(maryIdentity, demoIdentity, true);
    maryCommentToDemoActivity = SecurityManager.canCommentToActivity(getContainer(), maryIdentity, demoActivity);
    assertTrue("maryCommentToDemoActivity must be true", maryCommentToDemoActivity);

    createMentionsActivities(johnIdentity, maryIdentity);
    RealtimeListAccess<ExoSocialActivity> johnActivitiesListAccess = activityManager.getActivitiesWithListAccess(johnIdentity);
    ExoSocialActivity johnActivity = johnActivitiesListAccess.loadAsList(0, johnActivitiesListAccess.getSize()).get(0);
    assertTrue(SecurityManager.canCommentToActivity(getContainer(), maryIdentity, johnActivity));
    
    createSpace("space4");
    Identity spaceIdentity = identityManager.getOrCreateIdentity(SpaceIdentityProvider.NAME,
            "space4", false);
    createActivities(spaceIdentity, spaceIdentity, 1);
    RealtimeListAccess<ExoSocialActivity> spaceActivitiesListAccess = activityManager.getActivitiesWithListAccess(spaceIdentity);
    ExoSocialActivity spaceActivity = spaceActivitiesListAccess.loadAsList(0, spaceActivitiesListAccess.getSize()).get(0);
    boolean demoCommentToSpaceActivity = SecurityManager.canCommentToActivity(getContainer(),
                                                                              demoIdentity, spaceActivity);
    assertTrue("demoCommentToSpaceActivity must be true", demoCommentToSpaceActivity);
    boolean maryCommentToSpaceActivity = SecurityManager.canCommentToActivity(getContainer(),
                                                                              maryIdentity, spaceActivity);
    assertTrue("maryCommentToSpaceActivity must be true", maryCommentToSpaceActivity);

    boolean johnCommentToSpaceActivity = SecurityManager.canCommentToActivity(getContainer(),
                                                                              johnIdentity, spaceActivity);
    assertFalse("johnCommentToSpaceActivity must be false", johnCommentToSpaceActivity);

  }

  /**
   * Tests {@link SecurityManager#canDeleteComment(PortalContainer, Identity, ExoSocialActivity)}.
   */
  public void testCanDeleteComment() {
    createActivities(demoIdentity, demoIdentity, 1);
    RealtimeListAccess<ExoSocialActivity> demoActivitiesListAccess = activityManager.getActivitiesWithListAccess(demoIdentity); 
    ExoSocialActivity demoActivity = demoActivitiesListAccess.loadAsList(0, demoActivitiesListAccess.getSize()).get(0);
    createComment(demoActivity, demoIdentity, 1);
    RealtimeListAccess<ExoSocialActivity> demoCommentsListAccess = activityManager.getCommentsWithListAccess(demoActivity);
    ExoSocialActivity demoComment = demoCommentsListAccess.loadAsList(0, demoCommentsListAccess.getSize()).get(0);

    boolean demoDeleteDemoComment = SecurityManager.canDeleteComment(getContainer(), demoIdentity, demoComment);
    assertTrue("demoDeleteDemoComment must be true", demoDeleteDemoComment);

    // BUG #3: TODO FIX THIS
    boolean maryDeleteDemoComment = SecurityManager.canDeleteComment(getContainer(), maryIdentity, demoComment);
    assertFalse("maryDeleteDemoComment must be false", maryDeleteDemoComment);

    connectIdentities(maryIdentity, demoIdentity, true);
    createActivities(maryIdentity, maryIdentity, 1);
    RealtimeListAccess<ExoSocialActivity> maryActivitiesListAccess = activityManager.getActivitiesWithListAccess(maryIdentity);
    ExoSocialActivity maryActivity = maryActivitiesListAccess.loadAsList(0, -1).get(0);
    createComment(maryActivity, demoIdentity, 1);
    createComment(maryActivity, maryIdentity, 1);
    RealtimeListAccess<ExoSocialActivity> maryActivityCommentListAccess = activityManager.getCommentsWithListAccess(maryActivity);
    List<ExoSocialActivity> comments = maryActivityCommentListAccess.loadAsList(0, maryActivityCommentListAccess.getSize());
    assertEquals(2, comments.size());

    //BUG of ActivityManager, FIX IT and change these lines below following its changes.
    /*
    assertTrue("comments.get(0).getPostedTime() > comments.get(1).getPostedTime() must return true",
               comments.get(0).getPostedTime() > comments.get(1).getPostedTime());
    */
    assertTrue("comments.get(0).getPostedTime() < comments.get(1).getPostedTime() must return true",
                comments.get(0).getPostedTime() < comments.get(1).getPostedTime()); // must >
    ExoSocialActivity demoCommentMaryActivity = comments.get(0); // must be 1
    ExoSocialActivity maryCommentMaryActivity = comments.get(1); // must be 0

    boolean demoDeleteMaryCommentMaryActivity = SecurityManager.canDeleteComment(getContainer(),
                                                                                 maryIdentity, maryCommentMaryActivity);

    assertTrue("demoDeleteMaryCommentMaryActivity must be true", demoDeleteMaryCommentMaryActivity);

    boolean johnDeleteDemoCommentMaryActivity = SecurityManager.canDeleteComment(getContainer(),
                                                                                 johnIdentity,
                                                                                 demoCommentMaryActivity);
    assertFalse("johnDeleteDemoCommentMaryActivity must be false", johnDeleteDemoCommentMaryActivity);

    createSpace("space5");
    Identity spaceIdentity = identityManager.getOrCreateIdentity(SpaceIdentityProvider.NAME,
            "space5", false);
    createActivities(spaceIdentity, spaceIdentity, 1);
    RealtimeListAccess<ExoSocialActivity> spaceActivitiesListAccess = activityManager.getActivitiesWithListAccess(spaceIdentity); 
    ExoSocialActivity spaceActivity = spaceActivitiesListAccess.loadAsList(0, spaceActivitiesListAccess.getSize()).get(0);

    createComment(spaceActivity, maryIdentity, 1);
    createComment(spaceActivity, demoIdentity, 1);
    RealtimeListAccess<ExoSocialActivity> spaceActivityCommentsListAccess = activityManager.getCommentsWithListAccess(spaceActivity);
    List<ExoSocialActivity> spaceActivityComments = spaceActivityCommentsListAccess.loadAsList(0, spaceActivityCommentsListAccess.getSize());
    ExoSocialActivity maryCommentSpaceActivity = spaceActivityComments.get(0);// must be demo's comment
    ExoSocialActivity demoCommentSpaceActivity = spaceActivityComments.get(1);// must be mary's comment

    boolean maryDeleteDemoCommentSpaceActivity = SecurityManager.canDeleteComment(getContainer(),
                                                                                  maryIdentity,
                                                                                  demoCommentSpaceActivity);
    assertFalse("maryDeleteDemoCommentSpaceActivity must be false", maryDeleteDemoCommentSpaceActivity);

    boolean demoDeleteMaryCommentSpaceActivity = SecurityManager.canDeleteComment(getContainer(),
                                                                                  maryIdentity,
                                                                                  maryCommentSpaceActivity);
    assertTrue("demoDeleteMaryCommentSpaceActivity must be true", demoDeleteMaryCommentSpaceActivity);

  }


  /**
   * Unit Test for {@link SecurityManager#canAccessActivityStream(PortalContainer, Identity, Identity)}.
   */
  public void testCanAccessActivityStream() {
    assertTrue("SecurityManager.canAccessActivityStream(getContainer(), demoIdentity, johnIdentity) must return true",
               SecurityManager.canAccessActivityStream(getContainer(), demoIdentity, johnIdentity));

    createSpace("space6");
    Identity spaceIdentity = identityManager.getOrCreateIdentity(SpaceIdentityProvider.NAME, "space6", false);


    assertFalse("SecurityManager.canAccessActivityStream(getContainer(), johnIdentity, spaceIdentity) must return false",
                SecurityManager.canAccessActivityStream(getContainer(), johnIdentity, spaceIdentity));

    assertTrue("SecurityManager.canAccessActivityStream(getContainer(), maryIdentity, spaceIdentity) must return true",
               SecurityManager.canAccessActivityStream(getContainer(), maryIdentity, spaceIdentity));

    assertTrue("SecurityManager.canAccessActivityStream(getContainer(), demoIdentity, spaceIdentity) musts return true",
               SecurityManager.canAccessActivityStream(getContainer(), demoIdentity, spaceIdentity));
  }

  /**
   * An identity posts an activity to an identity's activity stream with a number of activities.
   *
   * @param posterIdentity the identity who posts activity
   * @param identityStream the identity who has activity stream to be posted.
   * @param number the number of activities
   */
  private void createActivities(Identity posterIdentity, Identity identityStream, int number) {
    for (int i = 0; i < number; i++) {
      ExoSocialActivity activity = new ExoSocialActivityImpl();
      activity.setType("exosocial:core");
      activity.setTitle("title " + i);
      activity.setUserId(posterIdentity.getId());
      activity.setPosterId(posterIdentity.getId());
      activityManager.saveActivityNoReturn(identityStream, activity);
      activity = activityManager.getActivity(activity.getId());
    }
  }

  private void createMentionsActivities (Identity posterIdentity, Identity mentionedIdentity) {
    ExoSocialActivity activity = new ExoSocialActivityImpl();
    activity.setTitle("hello " + "@" + mentionedIdentity.getRemoteId());
    activity.setUserId(posterIdentity.getId());
    activity.setPosterId(posterIdentity.getId());
    activityManager.saveActivityNoReturn(posterIdentity, activity);
    activity = activityManager.getActivity(activity.getId());
  }
  
  /**
   * Creates a comment to an existing activity.
   *
   * @param existingActivity the existing activity
   * @param posterIdentity the identity who comments
   * @param number the number of comments
   */
  private void createComment(ExoSocialActivity existingActivity, Identity posterIdentity, int number) {
    RealtimeListAccess<ExoSocialActivity> existingActivityCommentListAccess = null;
    for (int i = 0; i < number; i++) {
      ExoSocialActivity comment = new ExoSocialActivityImpl();
      comment.setTitle("comment " + i);
      comment.setUserId(posterIdentity.getId());
      activityManager.saveComment(existingActivity, comment);
      existingActivityCommentListAccess = activityManager.getCommentsWithListAccess(existingActivity);
      comment = existingActivityCommentListAccess.loadAsList(0, existingActivityCommentListAccess.getSize()).get(0);
    }
  }

  /**
   * Gets an instance of the space.
   *
   * @param name name of the space to be created
   */
  private void createSpace(String name) {
    Space space = new Space();
    space.setDisplayName(name);
    space.setPrettyName(space.getDisplayName());
    space.setRegistration(Space.OPEN);
    space.setDescription("add new space " + name);
    space.setType(DefaultSpaceApplicationHandler.NAME);
    space.setVisibility(Space.PUBLIC);
    space.setRegistration(Space.VALIDATION);
    space.setPriority(Space.INTERMEDIATE_PRIORITY);
    space.setGroupId("/spaces/space" + new Random().nextInt());
    String[] managers = new String[]{"demo"};
    String[] members = new String[]{"demo", "mary"};
    String[] invitedUsers = new String[]{"john"};
    String[] pendingUsers = new String[]{"root"};
    space.setInvitedUsers(invitedUsers);
    space.setPendingUsers(pendingUsers);
    space.setManagers(managers);
    space.setMembers(members);
    spaceService.createSpace(space, "demo");
  }

  /**
   * Connects 2 identities, if toConfirm = true, they're connected. If false, in pending connection type.
   *
   * @param senderIdentity the identity who sends connection request
   * @param receiverIdentity the identity who receives connection request
   * @param beConfirmed boolean value
   */
  private void connectIdentities(Identity senderIdentity, Identity receiverIdentity, boolean beConfirmed) {
    relationshipManager.inviteToConnect(senderIdentity, receiverIdentity);
    if (beConfirmed) {
      relationshipManager.confirm(receiverIdentity, senderIdentity);
    }
  }
}
