eXo Platform 3.0

- Prev

## Chapter 3. Developers References

## UI Extensions

### About Activity Plug-in

Since the Social 1.1.0, the activity plug-in feature was introduced that enables the activity composer extension and custom UI component to be used for displaying one activity by its type.

### Create the activity plug-in

At first, you should have an idea about the UI Extension Framework. If you have already worked with the UI Extension Framework, it's really easy to create the activity plug-in. If no, you have chance to work with it visiting UI Extension Framework.

#### Create a custom UI component for displaying the activity based on its type

### Note

("Project Code can be downloadable here")

When an activity is displayed, UIActivityFactory will look for its registered custom activity display by activity's type. If not found, UIDefaultActivity will be called for displaying that activity.

For example, in Social, there is an activity of type "exosocial:spaces" created by SpaceActivityPublisher. If you want to display it with our own UI component instead of default ones.

First, create a sample project:

    mvn archetype:generate

    Choose archetype:
    Choose a number: 76
    Choose version: 1
    Define value for property 'groupId': : org.exoplatform.social.samples
    Define value for property 'artifactId': : exo.social.samples.activity-plugin
    Define value for property 'version': 1.0-SNAPSHOT: 1.0.0-SNAPSHOT
    Define value for property 'package': org.exoplatform.social.samples: org.exoplatform.social.samples.activityPlugin
    Confirm properties configuration:
    groupId: org.exoplatform.social.samples
    artifactId: exo.social.samples.activity-plugin
    version: 1.0.0-SNAPSHOT
    package: org.exoplatform.social.samples.activityPlugin
    Y: y

Edit the pom.xml file as follows.

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
      <modelVersion>4.0.0</modelVersion>

      <parent>
        <groupId>org.exoplatform.social</groupId>
        <artifactId>social-project</artifactId>
        <version>1.1.0-GA</version>
      </parent>

      <groupId>org.exoplatform.social.samples</groupId>
      <artifactId>exo.social.samples.activity-plugin</artifactId>
      <packaging>jar</packaging>
      <version>1.1.0-GA</version>

      <name>exo.social.samples.activity-plugin</name>

      <build>
        <sourceDirectory>src/main/java</sourceDirectory>
        <outputDirectory>target/classes</outputDirectory>
        <resources>
          <resource>
            <directory>src/main/resources</directory>
            <includes>
              <include>**/*.gtmpl</include>
            </includes>
          </resource>
          <resource>
            <directory>src/main/java</directory>
            <includes>
              <include>**/*.xml</include>
            </includes>
          </resource>
        </resources>
      </build>

      <dependencies>

        <dependency>
          <groupId>org.exoplatform.portal</groupId>
          <artifactId>exo.portal.webui.core</artifactId>
          <scope>provided</scope>
        </dependency>

        <dependency>
          <groupId>org.exoplatform.portal</groupId>
          <artifactId>exo.portal.webui.portal</artifactId>
          <scope>provided</scope>
        </dependency>

        <dependency>
          <groupId>org.exoplatform.social</groupId>
          <artifactId>exo.social.component.core</artifactId>
          <scope>provided</scope>
        </dependency>

        <dependency>
          <groupId>org.exoplatform.social</groupId>
          <artifactId>exo.social.component.webui</artifactId>
          <scope>provided</scope>
        </dependency>

        <dependency>
          <groupId>org.exoplatform.social</groupId>
          <artifactId>exo.social.component.service</artifactId>
          <scope>provided</scope>
        </dependency>

      </dependencies>

    </project>

To use the custom UI component for displaying its activity, we need a subclass of `BaseUIActivity`. We call this `UISpaceSimpleActivity`:

    package org.exoplatform.social.samples.activityplugin;

    import org.exoplatform.social.webui.activity.BaseUIActivity;
    import org.exoplatform.webui.config.annotation.ComponentConfig;
    import org.exoplatform.webui.core.lifecycle.UIFormLifecycle;

    @ComponentConfig(
      lifecycle = UIFormLifecycle.class,
      template = "classpath:groovy/social/plugin/space/UISpaceSimpleActivity.gtmpl"
    )
    public class UISpaceSimpleActivity extends BaseUIActivity {

    }

The template `UISpaceSimpleActivity.gtmpl` should be created under `main/resources/groovy/social/plugin/space`:

    <div>This is a space activity ui component displayed for type "exosocial:spaces"</div>

An activity builder is also needed which will be explained later.

    package org.exoplatform.social.samples.activityplugin;

    import org.exoplatform.social.core.activity.model.Activity;
    import org.exoplatform.social.webui.activity.BaseUIActivity;
    import org.exoplatform.social.webui.activity.BaseUIActivityBuilder;

    public class SimpleSpaceUIActivityBuilder extends BaseUIActivityBuilder {

      @Override
      protected void extendUIActivity(BaseUIActivity uiActivity, Activity activity) {
        // TODO Auto-generated method stub

      }

    }

Next, create `configuration.xml` under conf/portal:

    <configuration xmlns="http://www.exoplaform.org/xml/ns/kernel_1_1.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.exoplaform.org/xml/ns/kernel_1_1.xsd http://www.exoplaform.org/xml/ns/kernel_1_1.xsd">
      <external-component-plugins>
        <target-component>org.exoplatform.webui.ext.UIExtensionManager</target-component>
        <component-plugin>
          <name>add.action</name>
          <set-method>registerUIExtensionPlugin</set-method>
          <type>org.exoplatform.webui.ext.UIExtensionPlugin</type>
          <init-params>
            <object-param>
              <name>Simple Space Activity</name>
              <object type="org.exoplatform.social.webui.activity.UIActivityExtension">
                <field name="type"><string>org.exoplatform.social.webui.activity.BaseUIActivity</string></field>
                <field name="name"><string>exosocial:spaces</string></field>
                <field name="component"><string>org.exoplatform.social.samples.activityplugin.UISpaceSimpleActivity</string></field>
                <field name="activityBuiderClass"><string>org.exoplatform.social.samples.activityplugin.SimpleSpaceUIActivityBuilder</string></field>
              </object>
            </object-param>
          </init-params>
        </component-plugin>
      </external-component-plugins>
    </configuration>

Note that `exosocial:spaces` is defined in

    <field name="name"><string>exosocial:spaces</string></field>

, its value must match the activity's type you want to display with your UI component.

Build sample project and copy the jar to tomcat/lib. Run Social, create a space and access it. You can see:

space's activity of type "exosocial:spaces" is displayed by default in Social:

With our custom UI component for displaying activity of type: "exosocial:spaces":

Make the custom UI activity display have the look and feel and function like default one.

When displaying an activity, we should make sure the look and feel of the custom UI component is consistent and match other activities and have the functions of like, comments. So, to create the another UI component to display, we call `UISpaceLookAndFeelActivity`:

    package org.exoplatform.social.samples.activityplugin;

    import org.exoplatform.social.webui.activity.BaseUIActivity;
    import org.exoplatform.webui.config.annotation.ComponentConfig;
    import org.exoplatform.webui.config.annotation.EventConfig;
    import org.exoplatform.webui.core.lifecycle.UIFormLifecycle;

    @ComponentConfig(
      lifecycle = UIFormLifecycle.class,
      template = "classpath:groovy/social/plugin/space/UISpaceLookAndFeelActivity.gtmpl",
      events = {
        @EventConfig(listeners = BaseUIActivity.ToggleDisplayLikesActionListener.class),
        @EventConfig(listeners = BaseUIActivity.ToggleDisplayCommentFormActionListener.class),
        @EventConfig(listeners = BaseUIActivity.LikeActivityActionListener.class),
        @EventConfig(listeners = BaseUIActivity.SetCommentListStatusActionListener.class),
        @EventConfig(listeners = BaseUIActivity.PostCommentActionListener.class),
        @EventConfig(listeners = BaseUIActivity.DeleteActivityActionListener.class, confirm = "UIActivity.msg.Are_You_Sure_To_Delete_This_Activity"),
        @EventConfig(listeners = BaseUIActivity.DeleteCommentActionListener.class, confirm = "UIActivity.msg.Are_You_Sure_To_Delete_This_Comment")
      }
    )
    public class UISpaceLookAndFeelActivity extends BaseUIActivity {

    }

Now, create the `UISpaceLookAndFeelActivity` template by copying the content of UIDefaultActivity.gtmpl to this template file.

You should make needed modifications for this template. We make a small modification here:

    <div class="Content">
      $activityContentTitle (from custom ui component)<br>
    </div>

We need to reconfigure `configuration.xml`:

    <configuration xmlns="http://www.exoplaform.org/xml/ns/kernel_1_1.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.exoplaform.org/xml/ns/kernel_1_1.xsd http://www.exoplaform.org/xml/ns/kernel_1_1.xsd">
      <external-component-plugins>
        <target-component>org.exoplatform.webui.ext.UIExtensionManager</target-component>
        <component-plugin>
          <name>add.action</name>
          <set-method>registerUIExtensionPlugin</set-method>
          <type>org.exoplatform.webui.ext.UIExtensionPlugin</type>
          <init-params>
            <object-param>
              <name>Look And Feel Space Activity</name>
              <object type="org.exoplatform.social.webui.activity.UIActivityExtension">
                <field name="type"><string>org.exoplatform.social.webui.activity.BaseUIActivity</string></field>
                <field name="name"><string>exosocial:spaces</string></field>
                <field name="component"><string>org.exoplatform.social.samples.activityplugin.UISpaceLookAndFeelActivity</string></field>
                <field name="activityBuiderClass"><string>org.exoplatform.social.samples.activityplugin.SimpleSpaceUIActivityBuilder</string></field>
              </object>
            </object-param>
          </init-params>
        </component-plugin>
      </external-component-plugins>
    </configuration>

Rebuild the sample project, copy jar to tomcat/lib. Rerun the server and see the result:

### Note

Currently, we have to copy and paste in the template file. We will have the full control of the UI, but it is not good when there is any change in UIDefaultActivity.

##### What is activity builder?

### Note

to do

#### Create a composer extension for composing activity on the UI composer and display it on activity stream

### Note

to do

## Overridable Components

There are 2 components in Social that can be overridden: Space Application Handler & Space Service

- Space Application Handler

    <component>
        <key>org.exoplatform.social.core.space.spi.SpaceApplicationHandler</key>
        <type>org.exoplatform.social.core.space.impl.DefaultSpaceApplicationHandler</type>
      </component>

- Space Service

    <component>
        <key>org.exoplatform.social.core.space.spi.SpaceService</key>
        <type>org.exoplatform.social.core.space.impl.SpaceServiceImpl</type>
        <init-params>
          <!-- Configure the applications to install in a space -->
          <values-param>
            <name>space.homeNodeApp</name>
            <value>SpaceActivityStreamPortlet</value>
          </values-param>
          <!-- Configure removable application or not <value>Application:removable</value> -->
          <values-param>
            <name>space.apps</name>
            <value>DashboardPortlet:true</value>
            <value>SpaceSettingPortlet:false</value>
            <value>MembersPortlet:true</value>
          </values-param>
        </init-params>
      </component>

## Public Java APIs

### ActivityManager

Method | Param | Return | Description
--- | --- | --- | ---
saveActivity(Identity owner, Activity activity) | `owner` - the owner of activity stream, `activity` - the activity which needs to be saved | Activity | Saves an activity to the stream of a owner. Note that the Activity.userId will be set to the owner identity if not already set.
getActivity(java.lang.String activityId) | `activityId` - the id of activity | Activity | Gets an activity by activity id.
deleteActivity(java.lang.String activityId) | `activityId` - the id of activity | void | Deletes an activity by id.
deleteComment(java.lang.String activityId, java.lang.String commentId) | `activityId` - the id of activity, `commentId` - the id of comment | void | Deletes comment by id.
getActivities(Identity identity) | `identity` | List<Activity> | Gets the latest activities by identity with the default limit of 20 latest activities.
getActivities(Identity identity, long start, long limit) | `identity`, `start` - the offset index , `limit` | List<Activity> | Gets the latest activities by identity, specifying the start offset index and limit.
getActivitiesOfConnections(Identity ownerIdentity) | `ownerIdentity` | List<Activity> | Gets activities of connections from an identity. The activities are sorted by time. The result list is maximum 30 activities by default. (Since 1.1.1).
getActivitiesOfConnections(Identity ownerIdentity, int offset, int limit) | `ownerIdentity, limit, offset` | List<Activity> | Gets activities of connections from an identity by specifying offset and limit. The acivities are returned as a list that is sorted starting from the most recent activity. (Since 1.1.3).
getActivitiesOfUserSpaces(Identity ownerIdentity) | `ownerIdentity` | List<Activity> | Gets the activities from all user's spaces.
getActivityFeed(Identity identity) | `identity` | List<Activity> | Gets the activity feed of an identity. This feed is the combination of all the activities of his own activities, his connections' activities and his spaces' activities which are sorted by time. The latest activity is the first item in the activity list.
saveActivity(Activity activity) | `activity` - the activity which needs to be saved | activity | Saves the activity into the stream for the activity's userId.
saveComment(Activity activity, Activity comment) | `activity`, `comment` | void | Saves new or update comments to an activity comment which is an instance of Activity with mandatory properties: userId, title.
saveLike(Activity activity, Identity identity) | `activity`, `identity` | void | Saves an identity of user who likes the activity.
removeLike(Activity activity, Identity identity) | `activity`, `identity` - the identity of user who unlikes the activity | void | Removes the like activity, if this activity liked, remove, else does nothing.
getComments(Activity activity) | `activity` | comments | Gets an activity's commentList.
recordActivity(Identity owner, java.lang.String type, java.lang.String title, java.lang.String body) | `owner` - the owner of the target stream for this activity, `type` is the type of activity (freeform), `title`, `body` | stored activity | Records an activity.
recordActivity(Identity owner, Activity activity) | `owner`, `activity` | stored activity | Saves an activity.
addProcessor(ActivityProcessor processor, Adds a new processor`` | `processor`, `addProcessorPlugin` | void | Adds a new activity processor.
addProcessorPlugin(BaseActivityProcessorPlugin plugin) | `plugin` | void | Adds a new processor plug-in.
getActivitiesCount(Identity owner) | `owner` | int | Gets the number of activity from a stream owner.

### IdentityManager

Method | Param | Return | Description
--- | --- | --- | ---
registerIdentityProviders(IdentityProviderPlugin plugin) | `plugin` |  | Registers one or more IdentityProvider through an IdentityProviderPlugin
getIdentity(String id) | `id` can be a social GlobalId or a raw identity such as in Identity.getId() | null if nothing is found, or the Identity object | Gets the identity by id and to load his profile.
getIdentity(String id, boolean loadProfile) | `id` can be a social GlobalId or a raw identity such as in Identity.getId(), `loadProfile` - the value is true if the profile is loaded and false if not loaded | null if nothing is found, or the Identity object | Gets the identity by loading id of the profile optionally.
deleteIdentity(Identity identity) | `identity` | void | Deletes an identity.
addIdentityProvider(IdentityProvider<?> idProvider) | `idProvider` is the id of provider | void | Adds the id of provider.
getIdentitiesCount(String providerId) | `providerId` | long | Gets the number of identities.
getOrCreateIdentity(java.lang.String providerId, java.lang.String remoteId) | `providerId` is the id of provider, `remoteId` is the remote id | identity | Gets the identity by a remote id.
getOrCreateIdentity(java.lang.String providerId, java.lang.String remoteId, boolean loadProfile) | `providerId` - referring to the name of the Identity provider, `remoteId` - the identifier that identify the identity in the specific identity provider, `loadProfile` is true when the profile is loaded | null if nothing is found, or the Identity object TODO improves the performance by specifying what needs to be loaded | Returns an Identity object that is specific to a special type. For example, if the type is Linked'In, the identifier will be the URL of profile or if it is a CS contact manager contact, it will be the UID of the contact. A new identity is created if it doesnot exist.
getIdentitiesByProfileFilter(java.lang.String providerId, ProfileFilter profileFilter) throws Exception | `providerId` is the id of provider, `profileFilter` is the filter of provider | the identities by the profile filter | Gets the identities by profile filter.
getIdentitiesByProfileFilter(java.lang.String providerId, ProfileFilter profileFilter, long offset, long limit) throws Exception | `providerId, profileFilter, offset, limit,` | List<Identity> | Gets the identities by profile filter.
getIdentitiesByProfileFilter(ProfileFilter profileFilter) throws Exception | `profileFilter` - the profile filter | the identities by profile filter | Gets the identities by profile filter.
getIdentitiesByProfileFilter(ProfileFilter profileFilter, long offset, long limit) throws Exception | `profileFilter, offset, limit` | List<Identity> | Gets the identities by profile filter.
getIdentitiesFilterByAlphaBet(java.lang.String providerId, ProfileFilter profileFilter) throws Exception | `providerId` is the id of provider, `profileFilter` is the profile filter | the identities filter by alphabet | Gets the identities filter by alpha bet.
getIdentitiesFilterByAlphaBet(String providerId, ProfileFilter profileFilter, long offset, long limit) throws Exception | `providerId, profileFilter, offset, limit` | List<Identity> | Gets the identities filter by alpha bet by specifying offset and limit.
getIdentitiesFilterByAlphaBet(ProfileFilter profileFilter) throws Exception | `profileFilter` - the profile filter | the identities filter by alphabet | Gets the identities filter by alphabet.
getIdentity(java.lang.String providerId, java.lang.String remoteId, boolean loadProfile) | `providerId`, `remoteId`, `loadProfile` | Identity | Gets the identity.
identityExisted(java.lang.String providerId, java.lang.String remoteId) | `providerId`, `remoteId` | boolean | Checks if the identity is already existed or not.
saveIdentity(Identity identity) | `identity` is the identity | void | Saves the identity.
saveProfile(Profile profile) | `profile` | void | Saves a profile.
updateAvatar(Profile p) throws Exception | `p - profile` | void | Updates avatar.
updateBasicInfo(Profile p) throws Exception | `p - profile` | Profile | Updates basic info of a profile.
updateContactSection(Profile p)throws Exception | `p - profile` | void | Updates the contact section of a profile.
updateExperienceSection(Profile p) throws Exception | `p - profile` | void | Updates the experience section of a profile.
updateHeaderSection(Profile p)throws Exception | `p - profile` | void | Updates the header section of profile.
getIdentities(java.lang.String providerId) throws Exception | `providerId` is the id of provider | List<Identity> | Gets the identity.
getIdentities(java.lang.String providerId, boolean loadProfile) | `providerId` is the id of provider, `loadProfile` is the loaded profile. | List<Identity> | Gets the identities.
getConnections(Identity ownerIdentity) throws Exception | `ownerIdentity` | List<Identity> | Gets connections of an identity
getStorage() | `N/A` | IdentityStorage | Gets the storage.
setIdentityStorage(IdentityStorage identityStorage) | `identityStorage` | void | Sets identityStorage.
registerProfileListener(ProfileListener listener)unregisterProfileListener | `listener` | void | Registers a profile listener.
unregisterProfileListener(ProfileListener listener) | `listener` | void | Unregisters a profile listener.
addProfileListener(ProfileListenerPlugin plugin) | `plugin` | void | Registers a profile listener component plug-in.
getIdentityStorage() | `N/A` | IdentityStorage | Gets identity storage.

### RelationshipManager

Method | Param | Return | Description
--- | --- | --- | ---
getRelationshipById(String id) throws Exception | `id` | Relationship | Gets relationship the by id.
invite(Identity currIdentity, Identity requestedIdentity) throws Exception | `currIdentity` - The current identity, `requestedIdentity` - The requested identity | Relationship | Creates a connection invitation between two identities.
confirm(Relationship relationship) throws Exception | `relationship` | void | Marks a relationship as confirmed.
deny(Relationship relationship) throws Exception | `relationship` | void | Denies a relationship.
remove(Relationship relationship) throws Exception | `relationship` | void | Removes a relationship.
ignore(Relationship relationship) throws Exception | `relationship` | void | Marks a relationship as ignored.
getPendingRelationships(Identity identity) throws Exception | `identity` | List<Relationship> | Returns all the pending relationships of the identity, including sent and received relationships of the pending type.
getPendingRelationships(Identity identity, boolean toConfirm) throws Exception | `identity, toConfirm` | List<Relationship> | If toConfirm is true, it returns a list of the pending relationship received, but not confirmed, if toConfirm is false, it returns a list of the relationship sent, but not confirmed yet.
getPendingRelationships(Identity currIdentity, List<Identity> identities, boolean toConfirm) throws Exception | `currIdentity` - the current identity, `identities` - the identities, `toConfirm` - | List<Relationship> | Gets the pending relations in two cases: - If toConfirm is true, it returns a list of the pending relationships received, but not confirmed. - If toConfirm is false, it returns a list of the relationships sent, but not confirmed yet.
getContacts(Identity currIdentity, List<Identity> identities) throws Exception | `currIdentity` - the current identity, `identities` - the identities, | List<Relationship> | Gets contacts that matches the search result.
getContacts(Identity identity) throws Exception | `identity` | List<Relationship> | Gets the contacts of the identity.
getAllRelationships(Identity identity) throws Exception | `identity` | List<Relationship> | Returns all the relationships associated with a given identity.
getRelationshipsByIdentityId(String id) throws Exception | `id` | List<Relationship> | Returns all the relationships associated with a given identityId.
getIdentities(Identity id) throws Exception | `id` | List<Identity> | Returns all the identities associated with a given identity and checks whether the relation has been validated or not.
create(Identity sender, Identity receiver) | `sender, receiver` | Relationship | Creates the relationship.
saveRelationship(Relationship relationship) throws Exception | `relationship` | void | Saves the relationship.
updateRelationshipCached(Relationship relationship) | `relationship` | void | Updates the relationship cached.
findRoute(Identity sender, Identity receiver) throws NotSupportedException | `sender,receiver` | Relationship | Finds a route.
findRelationships(Identity ownerIdentity, Relationship.Type relationshipType) throws Exception | `ownerIdentity, relationshipType` | List<Identity> | Finds all identities having relationshipType with the ownerIdentity.(Since 1.1.2).
getRelationshipStatus(Relationship rel, Identity id) | `rel, id` | Relationship.Type | Gets the relationship type of the relationship with the identity.
getConnectionStatus(Identity fromIdentity, Identity toIdentity) throws Exception | `fromIdentity, toIdentity` | Relationship.Type | Gets the connection type between two identities. (Since 1.1.1).
registerListener(RelationshipListener listener) | `listener` | void | Registers the RelationshipListener.
unregisterListener(RelationshipListener listener) | `listener` | void | Removes the RelationshipListener.
addListenerPlugin(RelationshipListenerPlugin plugin) | `plugin` | void | Adds the plugin.

### SpaceService

Method | Param | Return | Description
--- | --- | --- | ---
getAllSpaces() throws SpaceException | `N/A` | List<Space> - list of spaces in Social | Gets all spaces in Social.
getSpaceByName(String spaceName) throws SpaceException | `spaceName` | Space | Gets a space by its space name.
getSpacesByFirstCharacterOfName(String firstCharacterOfName) throws SpaceException | `firstCharacterOfName` | List<Space> - all spaces which have first character of name matched the input string. | Gets all spaces has the name starting with the input character.
getSpacesBySearchCondition(String condition) throws Exception | `condition` - the input condition | List<Space> - a list of spaces | Gets all spaces which has the name or the description that matches the input condition.
getSpaceByGroupId(String groupId) throws SpaceException, | `groupId` - the group id of the space | Space | Gets a space by its group id.
getSpaceById(String spaceId) throws SpaceException | `spaceId` - Id of that space | Space - space with the id specified | Gets a space by its id.
getSpaceByUrl(String spaceUrl) throws SpaceException | `spaceUrl` - url of space | Space - the space with string url specified | Gets a space by its url.
getSpaces(String userId) throws SpaceException | `userId` - Id of the user | List<Space> - all spaces of a user in which the user is a member | Gets spaces of a user in which that user is a member.
getAccessibleSpaces(String userId) throws SpaceException | `userId` | List<Space> - list of spaces | Gets spaces of a user which that user has the access permission
getEditableSpaces(String userId) throws SpaceException | `userId` | List<Space> - list of spaces | Gets spaces of a user which that user has the edit permission.
getInvitedSpaces(String userId) throws SpaceException | `userId` | List<Space> - spaces list of all user's invited spaces | Gets a user's invited spaces and that user can accept or deny the request.
getPublicSpaces(String userId) throws SpaceException | `userId - Id of user` | List<Space> - spaces list in which the user can request to join | Gets a user's public spaces and that user can request to join.
getPendingSpaces(String userId) throws SpaceException | `userId` | List<Space> - spaces list in which the user can revoke that request | Gets a user's pending spaces and that the user can revoke that request.
createSpace(Space space, String creator) throws SpaceException | `space, creator` | Space - the created space | Creates a new space by creating a new group.This new group will be under /Spaces node.This is shorthand for calling createSpace(space, creator, null).
createSpace(Space space, String creator, String groupId) throws SpaceException | `space, creator, groupId` - if groupId == null: create a new space by creating a new group | Space | Creates a new space from an existing group.
saveSpace(Space space, boolean isNew) throws SpaceException | `space - space is saved, isNew` - true if creating a new space, otherwise, update an existing space. | void | Saves a new space or updates a space.
deleteSpace(Space space) throws SpaceException | `space - the space is deleted` | void | Deletes a space. When deleting a space, all of its page navigations and its group will be deleted.
deleteSpace(String spaceId) throws SpaceException | `spaceId` | void | Deletes a space by its id.
initApp(Space space) throws SpaceException | `space` | void | Initializes default applications in a space. Deprecated, use initApps(Space) instead.
initApps(Space space) throws SpaceException | `space` | void | Initializes default applications in a space. Set space.homeNodeApp from the configuration file to be the root page of that space node. When removing a space, make sure to call deInitApps(Space) and then deleteSpace(Space) or deleteSpace(String)
deInitApps(Space space) throws SpaceException | `space` | void | De-initializes the applications of a space.Make sure to call this method before deleteSpace(Space) or deleteSpace(String). Otherwise, the space is deleted but its pages and navigation still exists.
addMember(Space space, String userId) throws SpaceException |  | void | Adds a user to a space, the user will get the "member" role in a space.
addMember(String spaceId, String userId) throws SpaceException | `spaceId, userId` | void | Adds a user to a space, the user will get the "member" role in a space.
removeMember(Space space, String userId) throws SpaceException | `space, userId` | void | Removes a member from a space. If the member is the only leader of that space, the member removed is not allowed and throws SpaceException with Code = USERONLYLEADER.
removeMember?(String spaceId, String userId) throws SpaceException | `spaceId, userId` | void | Removes a member from a space.
getMembers(Space space) throws SpaceException | `space` | List<String> - a list of the space members | Gets a list of the space members from a space.
getMembers(String spaceId) throws SpaceException | `spaceId` | List<String> - a list of the space members | Gets a list of the space members from a space.
setLeader(Space space, String userId, boolean isLeader) throws SpaceException | `space, userId, isLeader` | void | Sets a member of a space as a manager.
setLeader(String spaceId, String userId, boolean isLeader) throws SpaceException | `spaceId, userId, isLeader` | void | Sets a member of a space as a manager.
isLeader(Space space, String userId) throws SpaceException | `space, userId` | boolean - true if that the user is a leader, otherwise, false | Checks whether a user is a space's leader or not.
isLeader(String spaceId, String userId) throws SpaceException | `spaceId, userId` | boolean - true if that user is a leader, otherwise, false | Checks whether a user is a space's leader or not.
isOnlyLeader(Space space, String userId) throws SpaceException | `space, userId` | boolean - true if that user is the only leader of the space, otherwise, false | Checks whether a user is the only leader of a space or not.
isOnlyLeader(String spaceId, String userId) throws SpaceException | `spaceId, userId` | boolean | Checks whether a user is the only leader of a space or not.
isMember(Space space, String userId) throws SpaceException | `space, userId` | boolean - true if that user is a member, otherwise, false | Checks whether a user is a space's member or not.
isMember(String spaceId, String userId) throws SpaceException | `spaceId, userId,` | boolean - true if that user is a member, otherwise,false | Checks whether a user is a space's member or not.
hasAccessPermission(Space space, String userId) throws SpaceException | `space, userId` | boolean - true If the user is root or the space's member. | Checks if a user can access a space or not.
hasAccessPermission(String spaceId, String userId) throws SpaceException | `spaceId, userId` | boolean - true If the user is root or the space's member | Checks if a user can access a space or not.
hasEditPermission(Space space, String userId) throws SpaceException | `space, userId` | boolen - true If the user is root or the space's manager | Checks if a user can have the edit permission of a space or not.
hasEditPermission(String spaceId, String userId) throws SpaceException | `spaceId, userId` | boolen - true If user is root or the space's manager | Checks if a user can have the edit permission of a space or not.
isInvited(Space space, String userId) throws SpaceException | `space, userId` | boolen - true if that user is in the invited list, otherwise, false | Checks if a user is in the invited list of a space or not.
isInvited(String spaceId, String userId) throws SpaceException | `spaceId, userId` | boolen - true if the user is in the invited list, otherwise, false | Checks if a user is in the invited list of a space or not.
isPending(Space space, String userId) throws SpaceException | `space, userId` | boolen - true if that user is in the pending list, otherwise, false | Checks if a user is in the pending list of a space or not.
installApplication(String spaceId, String appId) throws SpaceException | `spaceId, appId` | void | Installs an application to a space.
installApplication(Space space, String appId) throws SpaceException | `space, appId` | void | Installs an application to a space
activateApplication(Space space, String appId) throws SpaceException | `space, appId` | void | Activates an installed application in a space.
activateApplication(String spaceId, String appId) throws SpaceException | `spaceId, appId` | void | Activates an installed application in a space.
deactivateApplication(Space space, String appId) throws SpaceException | `space, appId` | void | Deactivates an installed application in a space.
deactivateApplication(String spaceId, String appId) throws SpaceException | `spaceId, appId` | void | Deactivates an installed application in a space.
removeApplication(Space space, String appId, String appName) throws SpaceException | `space, appId, appName` | void | Removes an installed application from a space.
removeApplication(String spaceId, String appId, String appName) throws SpaceException | `space, appId, appName` | void | Removes an installed application from a space.
requestJoin(Space space, String userId) throws SpaceException | `space, userid` | void | Requests a user to join a space, adds that user to the pending list of the space.
requestJoin(String spaceId, String userId) throws SpaceException | `spaceId, userid` | void | Requests a user to join a space, adds that user to the pending list of the space.
revokeRequestJoin(Space space, String userId) throws SpaceException | `space, userid` | void | Revokes a join request after users request to join a group and is in the pending status.
revokeRequestJoin(String spaceId, String userId) throws SpaceException | `spaceId, userid` | void | Revokes a request to join a space.
inviteMember(Space space, String userId) throws SpaceException | `space, userid` | void | Invites a userId to become a member of a space.
inviteMember(String spaceId, String userId) throws SpaceException | `spaceId, userid` | void | Invites a userId to a be member of a space.
revokeInvitation(Space space, String userId) throws SpaceException | `space, userid` | void | Revokes an invitation. Removes a user from the invited member list of the space.
revokeInvitation(String spaceId, String userId) throws SpaceException | `spaceId, userid` | void | Revokes an invitation. Removes a user from the invited member list of the space.
acceptInvitation(Space space, String userId) throws SpaceException | `space, userid` | void | Accepts an invitation and moves a user from the invited list to the member list.
acceptInvitation(String spaceId, String userId) throws SpaceException | `spaceId, userid` | void | Accepts an invitation and moves a user from the invited list to the member list.
denyInvitation(Space space, String userId) throws SpaceException | `space, userid` | void | Denies an invitation and removes a user from the invited list.
denyInvitation(String spaceId, String userId) throws SpaceException | `spaceId, userid` | void | Denies an invitation and removes a user from the invited list.
validateRequest(Space space, String userId) throws SpaceException | `space, userid` | void | Validates a request and moves a user from the pending list to the member list.
validateRequest(String spaceId, String userId) throws SpaceException | `spaceId, userid` | void | Validates a request and moves a user from the pending list to the member list.
declineRequest(Space space, String userId) throws SpaceException | `space, userid` | void | Declines a request and removes a user from the pending list.
declineRequest(String spaceId, String userId) throws SpaceException | `spaceId, userid` | void | Declines a request and removes a user from the pending list.
registerSpaceLifeCycleListener(SpaceLifeCycleListener listener | `listener` | void | Registers a space lifecycle listener.
unregisterSpaceLifeCycleListener(SpaceLifeCycleListener listener) | `listener` | void | Unregisters a space lifecycle listener.
setPortletsPrefsRequired(PortletPreferenceRequiredPlugin portletPrefsRequiredPlugin) | `portletPrefsRequiredPlugin` | void | Sets the portlet preferences got from the plug-in configuration.
getPortletsPrefsRequired() | `N/A` | String[] | Gets the portlet preferences required to use in creating the portlet application.
setSpaceApplicationConfigPlugin(SpaceApplicationConfigPlugin spaceApplicationConfigPlugin) | `SpaceApplicationConfigPlugin` | void | Sets configuration plugin for initializing applications when creating a new space. (Since 1.1.3).
getSpaceApplicationConfigPlugin() | `N/A` | SpaceApplicationConfigPlugin | Gets the configuration of applications to be initialized when creating a new space. (Since 1.1.3).

## Public REST APIs

### Activities REST service

Name | Service URL | Location | Description
--- | --- | --- | ---
ActivitiesRestService | {restContextName}/{portalName}/social/activities | Maven groupId: org.exoplatform.social ArtifactId: exo.social.component.service | Provides REST services for activity applications, such as like/unlike, comment, delete activity.

- API:

Name | Service URL Endpoint | Parameters | Expected Values | Description
--- | --- | --- | --- | ---
destroyActivity | {restContextName}/{portalName}/social/activities/destroy/{activityId}.{format} | portalName activityId format | String String String: json or xml | Destroys an activity and returns the json/xml format.
showLikes | {restContextName}/{portalName}/social/activities/{activityId}/likes/show.{format} | portalName activityId format | String String String: json or xml | Shows the list of identityId who likes this activity and returns the json/xml format.
updateLike | {restContextName}/{portalName}/social/activities/{activityId}/likes/update.{format} | portalName activityId format | String String String: json or xml | Updates the list of likes by the json/xml format.
destroyLike | {restContextName}/{portalName}/social/activities/{activityId}/likes/destroy/{identity}.{format} | portalName activityId identityId format | String String String String: json or xml | Destroys like by identityId and returns the json/xml format.
showComments | {restContextName}/{portalName}/social/activities/{activityId}/comments/show.{format} | portalName activityId format | String String String: json or xml | Shows the comment list of an activity by the json/xml format.
updateComment | {restContextName}/{portalName}/social/activities/{activityId}/comments/update.{format} | portalName activityId format | String String String: json or xml | Updates the comment of an acitivity by the json/xml format.
destroyComment | {restContextName}/{portalName}/social/activities/{activityId}/comments/destroy/{commentId}.{format} | portalName activityId commentId format | String String String String: json or xml | Destroys the comment of an identity and returns the json/xml format.

Example:

- http://localhost:9090/rest-socialdemo/social/activities/s08d397dg6/likesdestroy/abc.xml

- http://localhost:9090/rest-socialdemo/social/activities/s08d397dg6/likesdestroy/abc.json

### Apps REST service

Name | Service URL | Location | Description
--- | --- | --- | ---
AppsRestService | {restContextName}/social/apps | Maven groupId: org.exoplatform.social ArtifactId: exo.social.component.service | Provides REST services for showing the application list from the application registry gadget.

- API:

Name | Service URL Endpoint | Parameters | Expected Values | Description
--- | --- | --- | --- | ---
showApps | {restContextName}/social/apps/show.{format} | format | String: json or xml | Shows applications by the json/xml format.

Example:

http://localhost:9090/rest-socialdemo/apps/show.json

### Identity REST service

Name | Service URL | Location | Description
--- | --- | --- | ---
IdentityRestService | {restContextName}/{portalName}/social/identity/{username}/id | Maven groupId: org.exoplatform.social ArtifactId: exo.social.component.service | Gets identityId by the username.

- API:

Name | Service URL Endpoint | Parameters | Expected Values | Description
--- | --- | --- | --- | ---
getId | {restContextName}/{portalName}/social/identity/{username}/id/show.json | username portalname | String String | Gets the identity by username and returns by the json format.

Example:

http://localhost:8080/rest-socialdemo/socialdemo/social/identity/john/id/show.json

### Linkshare REST service

Name | Service URL | Location | Description
--- | --- | --- | ---
LinkshareRestService | {restContextName}/social/linkshare | Maven groupId: org.exoplatform.social ArtifactId: exo.social.component.service | Provides REST service for getting metadata information, such as page title, images, and description from a provided link.

- API:

Name | Service URL Endpoint | Parameters | Expected Values | Description
--- | --- | --- | --- | ---
getLink | {restContextName}/social/linkshare/show.{format} | format | String: json or xml | Gets the provided link metadat by posting a linkShare request as post data.

Example:

http://localhost:9090/rest-socialdemo/social/linkshare/show.json

### People REST Service

Name | Service URL | Location | Description
--- | --- | --- | ---
PeopleRestService | {restContextName}/social/people | Maven groupId: org.exoplatform.social ArtifactId: exo.social.component.service | Provides REST services for serving requests related to people, such as suggesting username, getting people information.

- API:

Name | Service URL Endpoint | Parameters | Expected Values | Description
--- | --- | --- | --- | ---
suggestUsernames | {restContextName}/social/people/suggest.{format} | nameToSearch currentUser typeOfRelation spaceURL portalName format | String String String String String String | Gets and returns a list of users's full names that matches the input string for suggesting.
getPeopleInfo | {restContextName}/social/people/{portalName}/{currentUserName}/getPeopleInfo/{userId}.{format} | portalName currentUserName userId format updatedType | String String String String: json or xml String | Gets and returns information of people that is displayed as users's detailed information on pop-up.

Example:

http://localhost:8080/rest-socialdemo/social/people/suggest.json?nameToSearch=root&currentUser=john&typeOfRelation=pending&portalName=socialdemo

#### Spaces REST service

Name | Service URL | Location | Description
--- | --- | --- | ---
SpacesRestService | {restContextName}/{portalName}/social/spaces | Maven groupId: org.exoplatform.social ArtifactId: exo.social.component.service | Provides REST services for space gadget to display user's spaces and pending spaces

- API:

Name | Service URL Endpoint | Parameters | Expected Values | Description |
showMySpaceList | {restContextName}/social/spaces/mySpaces/show.{format} | portalName format | String String: json or xml | Shows mySpaceList by the json/xml format. |
showPendingSpaceList | {restContextName}/social/spaces/pendingSpaces/show.{format} | portalName format | String String: json or xml | Shows pendingSpaceList by the json/xml format. |
suggestSpacenames | {restContextName}/social/spaces/suggest.{format} | portalName conditionToSearch typeOfRelation currentUser format | String String String String String: json or xml | Returns space's names that match the input string for suggesting. |

Example:

http://localhost:8080/rest-socialdemo/social/spaces/s08d397dg6/mySpaces/show.xml

#### Widget REST service

Name | Service URL | Location | Description
--- | --- | --- | ---
WidgetRestService | {restContextName}/spaces/{containerName} | Maven groupId: org.exoplatform.social ArtifactId: exo.social.extras.widget.rest | Provides REST services for creating spaces or getting spaces'information.

- API:

Name | Service URL Endpoint | Parameters | Expected Values | Description
--- | --- | --- | --- | ---
goToSpace | {restContextName}/spaces/{containerName}/go_to_space | containerName portalName spaceName description | String String (Defauult Value: classic) String String | Creates (if not existing) or accesses a space. Two query parameters needed: `spaceName` and `description`
spaceInfo | {restContextName}/spaces/{containerName}/space_info | containerName portalName spaceName description | String String (Default Value: classic) String | Returns the HTML page for displaying the information of space. Two query parameters needed: `spaceName` and `description`

Example:

http://localhost:8080/rest-socialdemo/spaces/socialdemo/go_to_space?name=Social&description=Social

http://localhost:8080/rest-socialdemo/spaces/socialdemo/space_info?name=Social&description=Social

## Sample code/tutorial

### Activity Stream

eXo Social provides a way to share status updates and activity information for users as well as spaces (aka Activity Streams). With the API, you can customize the activities or publish new ones.

To manipulate activities, you will use the ActivityManager. To get an instance of this class, you will need to use the `PortalContainer`.

#### Create an activity

There are two types of activities : activities for a user and activities for a space. The following examples will show you how to create an activity for each type.

#### Publish an activity for a user

Users have activity streams. The code below shows you how to publish a nex activity into the public activity stream of a user.

    import org.exoplatform.container.PortalContainer;
    import org.exoplatform.social.core.activitystream.ActivityManager;
    import org.exoplatform.social.core.activitystream.model.Activity;
    import org.exoplatform.social.core.identity.IdentityManager;
    import org.exoplatform.social.core.identity.impl.organization.OrganizationIdentityProvider;
    import org.exoplatform.social.core.identity.model.Identity;

      public void createActivityForUser() {
        String username = "zun";
        // Get current container
        PortalContainer container = PortalContainer.getInstance();

        // Get IdentityManager to handle identity operation
        IdentityManager identityManager = (IdentityManager) container.getComponentInstance(IdentityManager.class);

        // Get ActivityManager to handle activity operation
        ActivityManager activityManager = (ActivityManager) container.getComponentInstanceOfType(ActivityManager.class);

        // Get existing user or create a new one
        try {
          Identity userIdentity = identityManager.getOrCreateIdentity(OrganizationIdentityProvider.NAME, username);

          // Create new activity for this user
          Activity activity = new Activity();
          activity.setUserId(userIdentity.getId());
          activity.setTitle("Hello World!");
          // Save activity into JCR using ActivityManager
          activityManager.saveActivity(activity);
        } catch (Exception e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }

#### Publish an activity for a space

Spaces are also social objects and thus, they own an activity stream. The code below shows you how to publish activity into a space's stream

    import org.exoplatform.container.PortalContainer;
    import org.exoplatform.social.core.activitystream.ActivityManager;
    import org.exoplatform.social.core.activitystream.model.Activity;
    import org.exoplatform.social.core.identity.IdentityManager;
    import org.exoplatform.social.core.identity.impl.organization.OrganizationIdentityProvider;
    import org.exoplatform.social.core.identity.model.Identity;
    import org.exoplatform.social.space.Space;
    import org.exoplatform.social.space.SpaceException;
    import org.exoplatform.social.space.SpaceService;
    import org.exoplatform.social.space.impl.SpaceIdentityProvider;

    //...

      public void createActivityForSpace() {
        //make sure a space with name "mySpace" is created.
        String spaceName = "mySpace";
        String username = "zun";
        // Get current container
        PortalContainer container = PortalContainer.getInstance();

        // Get IdentityManager to handle identity operation
        IdentityManager identityManager = (IdentityManager) container.getComponentInstance(IdentityManager.class);

        // Get ActivityManager to handle activity operation
        ActivityManager activityManager = (ActivityManager) container.getComponentInstanceOfType(ActivityManager.class);

        // Get SpaceService to handle space operation
        SpaceService spaceService = (SpaceService) container.getComponentInstanceOfType(SpaceService.class);
        try {
          Space space = spaceService.getSpaceByName(spaceName);
          if (space != null) {
            // Get space identity via SpaceIdentityProvider
            Identity spaceIdentity = identityManager.getOrCreateIdentity(SpaceIdentityProvider.NAME, spaceName);
            // Get identity instance of the user who wants to create activity
            Identity userIdentity = identityManager.getOrCreateIdentity(OrganizationIdentityProvider.NAME, username);
            // Create new activity for this space
            Activity activity =  new Activity();
            activity.setUserId(userIdentity.getId());
            activity.setTitle("An activity for space");
            activityManager.saveActivity(spaceIdentity, activity);
          }
        } catch (SpaceException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        } catch (Exception e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }

#### Useful functions

- ActivityManager#getActivity

- ActivityManager#getActivities

- ActivityManager#saveActivity

- ActivityManager#saveComment

- ActivityManager#saveLike

- ActivityManager#removeLike

- ActivityManager#getComments

##### Configure an activity processor

An Activity processor is used for modifying the content of activities before they are responsed and rendered at client's browser. For example, we will create an activity processor for replacing all the texts representing the smile face ":-)" in the activity title by the smiley icons.

Firstly, we will create the `SmileyProcessor` class by extending the `BaseActivityProcessorPlugin`

    package org.exoplatform.social.core.activitystream;

    public class SmileyProcessor extends BaseActivityProcessorPlugin {
      public SmileyProcessor(InitParams params) {
        super(params);
      }

      String smiley =  "<img src={{{"}}}http://www.tombraider4u.com/pictures/smiley.gif{{{"}}}/>";

      public void processActivity(Activity activity) {
        String title = activity.getTitle();
        activity.setTitle(title.replaceAll(":-
    )", smiley));
      }
    }

And then, we have to register this processor by adding some XML configuration into the project configuration file (configuration.xml)

    <component>
      <key>org.exoplatform.social.core.activitystream.ActivityManager</key>
      <type>org.exoplatform.social.core.activitystream.ActivityManager</type>
      <component-plugins>
        <component-plugin>
          <name>SmileyProcessor</name>
          <set-method>addProcessorPlugin</set-method>
          <type>org.exoplatform.social.core.activitystrea.SmileyProcessor</type>
          <init-params>
            <values-param>
              <name>priority</name>
              <value>1</value>
            </values-param>
          </init-params>
        </component-plugin>
      </component-plugins>
    </component>

"init-params" contains all the key-value data which a processor will use to initialize. At the above config, priority value indicates the order that this processor will be used. So with '1' value, this processor will be used before all remaining processors with lower priority.

#### Publish an rss feed with feedmash

It's really easy to publish an rss feed to a space's activity stream. eXo Social already provides `FeedmashJobPlugin` for publishing rss feeds. As you can see in project `exo.social.extras.feedmash`, there are `JiraFeedConsumer` and `HudsonFeedConsumer` samples to post eXo Social project's feeds (jira and hudson) to a pre-defined space: `exosocial` in a specifiportal container: `socialdemo` as in the configuration file:

    <external-component-plugins>
       <target-component>org.exoplatform.services.scheduler.JobSchedulerService</target-component>
        <component-plugin>
          <name>RepubSocialJiraActivityJob</name>
          <set-method>addPeriodJob</set-method>
          <type>org.exoplatform.social.feedmash.FeedmashJobPlugin</type>
          <description/>
          <init-params>
            <properties-param>
              <name>mash.info</name>
              <property name="feedURL" value="http://jira.exoplatform.org/plugins/servlet/streams?key=SOC"/>
              <property name="categoryMatch" value="resolved|created"/>
              <property name="targetActivityStream" value="space:exosocial"/>
              <property name="portalContainer" value="socialdemo"/>
            </properties-param>
            <properties-param>
              <name>job.info</name>
              <description>save the monitor data  periodically</description>
              <property name="jobName" value="JIRAFeedConsumer"/>
              <property name="groupName" value="Feedmash"/>
              <property name="job" value="org.exoplatform.social.feedmash.JiraFeedConsumer"/>
              <property name="repeatCount" value="0"/>
              <property name="period" value="60000"/>
              <property name="startTime" value="+45"/>
              <property name="endTime" value=""/>
            </properties-param>
          </init-params>
        </component-plugin>
        <component-plugin>
          <name>WatchSocialBuildStatus</name>
          <set-method>addPeriodJob</set-method>
          <type>org.exoplatform.social.feedmash.FeedmashJobPlugin</type>
          <description/>
          <init-params>
            <properties-param>
              <name>mash.info</name>
               <property name="feedURL" value="http://builder.exoplatform.org/hudson/view/social/job/social-trunk-ci/rssAll"/>
               <property name="targetActivityStream" value="space:exosocial"/>
               <property name="portalContainer" value="socialdemo"/>
            </properties-param>
            <properties-param>
              <name>job.info</name>
              <description>save the monitor data  periodically</description>
              <property name="jobName" value="HudsonFeedConsumer"/>
              <property name="groupName" value="Feedmash"/>
              <property name="job" value="org.exoplatform.social.feedmash.HudsonFeedConsumer"/>
              <property name="repeatCount" value="0"/>
              <property name="period" value="60000"/>
              <property name="startTime" value="+100"/>
              <property name="endTime" value=""/>
            </properties-param>
          </init-params>
        </component-plugin>
     </external-component-plugins>

When running eXo Social, login with http://localhost:8080/socialdemo and create a space named "exosocial". Done, all the feeds from jira and hudson for Social project will be automatically published to `exosocial` space.

### People

eXo Social provides a way to add profile informations, relationships and connections between users: People. With the eXo People API, profile informations and relationship can be easily managed and customized.

#### Identity

The identity allows to identity uniquely a social object. Social objects can be persons, groups, applications, or whatever you think deserves social interactions like connecting, publishing an activity stream or holding a profile.

##### IdentityProvider

Creating your Identity Provider allows you to integrate people outside of your portal (for exemple customers) into your social network without having to create a portal account. You can also use this to populate the profile with data coming from other systems. Here is an example :

    class SampleIdentityProvider extends OrganizationIdentityProvider{
      public SampleIdentityProvider(OrganizationService organizationService) {
        super(organizationService);
      }

      @Override
      public void populateProfile(Profile profile, User user) {
        profile.setProperty(Profile.FIRST_NAME, "this is first name");
        profile.setProperty(Profile.LAST_NAME, "this is last name");
        profile.setProperty(Profile.USERNAME, "this is user name");
        profile.setProperty(Profile.URL, "/path/to/profile/");
      }
    }

In this example, we created a SampleIdentityProvider class extending OrganizationIdentityProvider which is the IdentityProvider used to connect to the portal user's base. In this class, we overrided the populateProfile method and added some dummy data in the profile fields.

##### IdentityManager

The IdentityManager is the service used to manipulate the identity operations like creating, getting, deleting or finding a profile. We can get the IdentityManager via the ExoContainer. The following code will show how to get an IdentityManager instance and create a basic identity instance :

    import org.exoplatform.container.ExoContainer;
    import org.exoplatform.container.ExoContainerContext;
    import org.exoplatform.social.core.identity.IdentityManager;
    import org.exoplatform.social.core.identity.impl.organization.OrganizationIdentityProvider;
    import org.exoplatform.social.core.identity.model.Identity;

    //......

    String containerName = "portal";
    String username = "zun";

    //get container to get other registered components
    ExoContainer container = ExoContainerContext.getContainerByName(containerName);

    //get IdentityManager to handle identity operation
    IdentityManager identityManager = (IdentityManager) container.getComponentInstanceOfType(IdentityManager.class);

    //get ActivityManager to handle activity operation
    ActivityManager activityManager = (ActivityManager) container.getComponentInstanceOfType(ActivityManager.class);

    //create new user with name Zun
    Identity userIdentity = identityManager.getOrCreateIdentity(OrganizationIdentityProvider.NAME, username);

#### ProfileListener

The People API provides some notification interfaces which programmers can implement in order to create their own handlers for notifications like notifications() for profile modifications(ProfileListenerPlugin]) or for relationship changes(RelationshipListenerPlugin]). The following example will guide you through implementing one of these interfaces and show you how to configure this plugin.

We will create the class ProfileLoggerListener. Its tasks is to log all profile modifications of the systems. The abstract class ProfileListenerPlugin provides us the interface to implement this method.

    import org.exoplatform.services.log.ExoLogger;
    import org.exoplatform.services.log.Log;
    import org.exoplatform.social.core.identity.lifecycle.ProfileListenerPlugin;
    import org.exoplatform.social.core.identity.spi.ProfileLifeCycleEvent;

    public class ProfileLoggerListener extends ProfileListenerPlugin{
      private static final Log logger = ExoLogger.getExoLogger(ProfileLoggerListener.class);
      @Override
      public void avatarUpdated(ProfileLifeCycleEvent event) {
        logger.info("@" + event.getUsername() + " profile has updated his basic profile info.");
      }

      @Override
      public void basicInfoUpdated(ProfileLifeCycleEvent event) {
        logger.info("@" + event.getUsername() + " profile has updated his basic profile info.");
      }

      @Override
      public void contactSectionUpdated(ProfileLifeCycleEvent event) {
        logger.info("@" + event.getUsername() + " profile has updated his contact info.");
      }

      @Override
      public void experienceSectionUpdated(ProfileLifeCycleEvent event) {
        logger.info("@" + event.getUsername() + " profile has an updated experience section.");
      }

      @Override
      public void headerSectionUpdated(ProfileLifeCycleEvent event) {
        logger.info("@" + event.getUsername() + " has updated his header info.");
      }
    }

After creating the ProfileLoggerListener class, we have to add some configurations for this class to the configuration.xml :

    <external-component-plugins>
      <target-component>org.exoplatform.social.core.identity.IdentityManager</target-component>
      <component-plugin>
        <name>ProfileLoggerListener</name>
        <set-method>addProfileListener</set-method>
        <type>path.to.ProfileLoggerListener</type>
      </component-plugin>
    </external-component-plugins>

#### Relationships

Similarly, you can apply the above steps to implement the RelationshipListenerPlugin for relationship notifications.

Relationship is the bridge between two identities in eXo Social. There are many types of relationships defined in the Relationship class. With these types, a user can invite another user, confirm invitations or remove relationship.

##### User connection

The following code will show how to invite a user to connect to another :

    import org.exoplatform.container.ExoContainer;
    import org.exoplatform.container.ExoContainerContext;
    import org.exoplatform.social.core.identity.IdentityManager;
    import org.exoplatform.social.core.identity.impl.organization.OrganizationIdentityProvider;
    import org.exoplatform.social.core.identity.model.Identity;
    import org.exoplatform.social.core.relationship.Relationship;
    import org.exoplatform.social.core.relationship.RelationshipManager;

    public void inviteUser() throws Exception {
      String containerName = "portal";
      ExoContainer container = ExoContainerContext.getContainerByName(containerName);

      IdentityManager identityManager = (IdentityManager) container.getComponentInstanceOfType(IdentityManager.class);

      Identity invitedIdentity = identityManager.getOrCreateIdentity(OrganizationIdentityProvider.NAME, "Hoat");
      String invitedUserId = invitedIdentity.getId();

      String currUserId = "Zun";
      Identity currentIdentity = identityManager.getOrCreateIdentity(OrganizationIdentityProvider.NAME,  currUserId);

      RelationshipManager relationshipManager = (RelationshipManager) container.getComponentInstanceOfType(RelationshipManager.class);
      Relationship relationship = relationshipManager.invite( currentIdentity, invitedIdentity);
    }

##### RelationshipListener

Let's take a look at relationship Listener(RelationshipListenerPlugin). The following example will show you how to implement one of these interfaces and how to configure this plugin. The following step is similar to the Profile notifications implementation.

    import org.exoplatform.social.core.relationship.Relationship;
    import org.exoplatform.social.core.relationship.lifecycle.RelationshipListenerPlugin;
    import org.exoplatform.social.relationship.spi.RelationshipEvent;

    public class RelationshipLoggerListener extends RelationshipListenerPlugin{
      private static final Log logger = ExoLogger.getExoLogger(RelationshipLoggerListener.class);

      @Override
      public void confirmed(RelationshipEvent event) {
        String[] names = getUserNamesFromEvent(event);
        logger.info(names[0] +" confirmed the invitation of "+ names[1]);
      }

      @Override
      public void ignored(RelationshipEvent event) {
        String[] names = getUserNamesFromEvent(event);
        logger.info(names[0] +" ignored the invitation of "+ names[1]);
      }

      @Override
      public void removed(RelationshipEvent event) {
        String[] names = getUserNamesFromEvent(event);
        logger.info(names[0] +" removed the relationship with "+ names[1]);
      }

      private String[] getUserNamesFromEvent(RelationshipEvent event){
        Relationship relationship = event.getPayload();

        Identity id1 = relationship.getIdentity1();
        Identity id2 = relationship.getIdentity2();

        String user1 = "@" + id1.getRemoteId();
        String user2 = "@" + id2.getRemoteId();

        return new String[]{user1, user2 };
      }
    }

After creating the RelationshipLoggerListener class, we have to add some configurations for this class to the configuration.xml :

    <external-component-plugins>
      <target-component>org.exoplatform.social.core.relationship.RelationshipManager</target-component>
      <component-plugin>
        <name>RelationshipLoggerListener</name>
        <set-method>addListenerPlugin</set-method>
        <type>classpath.of.your.RelationshipLoggerListener</type>
      </component-plugin>
    </external-component-plugins>

### Spaces

eXo Social provides a way to create groups and to share data and applications: the space. A space has it's own activity stream in which applications or members can publish information. In each space, members share applications and an openSocial dashboard.

To manipulate the spaces, you will use the SpaceService. To get an instance of this class, you will need to get current PortalContainer instance.

#### Spaces Management

##### Create a space

The following example shows how to create a space:

    package org.exoplatform.social.sample;

    import org.exoplatform.container.PortalContainer;
    import org.exoplatform.social.application.impl.DefaultSpaceApplicationHandler;
    import org.exoplatform.social.space.Space;
    import org.exoplatform.social.space.SpaceException;
    import org.exoplatform.social.space.SpaceService;

    public class SpaceCreationSample {

      public void createSpace() throws SpaceException {
        String spaceName = "mySpace";
        String creator = "jeremi";
        PortalContainer container = PortalContainer.getInstance();
        SpaceService spaceService = (SpaceService) container.getComponentInstanceOfType(SpaceService.class);
        // We verify if there is no space already created
        Space space = spaceService.getSpaceByName(spaceName);
        if (space == null) {
          space = new Space();
          space.setName(spaceName);
          space.setRegistration(Space.OPEN);
          space.setDescription("space description");
          //DefaultSpaceApplicationHander is the default implementation of SpaceApplicationHandler. You can create your own by extending SpaceApplicationHandler. The default type is "classic" (DefaultSpaceApplicationHandler.NAME = clasic)
          space.setType(DefaultSpaceApplicationHandler.NAME);
          //We create the space
          space = spaceService.createSpace(space, creator);
          //We initialize the applications
          spaceService.initApp(space);

        }
      }
    }

#### Space's applications management

##### Add an application to a space

We can add a portlet or gadget applications into spaces. Once added, all members of the space can use that application. The following code shows how to add an application into a space :

    public void addApplicationToSpace() throws SpaceException {
      //Your portlet name
      String appId = "AnyGadgetOrAnyPortletName";
      String spaceId = "zunSpace";

      //get container to get other registered components
      PortalContainer container = PortalContainer.getInstance();

      //get space service for installing operations
      SpaceService spaceService = (SpaceService) container.getComponentInstanceOfType(SpaceService.class);

      //install application for the space
      spaceService.installApplication(spaceId, appId);

      //we must activate installed application to be able to use it
      spaceService.activateApplication(spaceId, appId);
    }

### Note

appId is the portlet or gadget name as defined in portlet.xml or gadget.xml in the web-app. With eXo Social, we can find it in social-portlet.war and social.war.

#### Members Management

The SpaceService allows you to manage the spaces' members.Here is how you would add a now member to a space:

    String spaceName = "mySpace";

    PortalContainer container = PortalContainer.getInstance();
    SpaceService spaceService = (SpaceService) container.getComponentInstanceOfType(SpaceService.class);

    Space space = service.getSpaceByName(spaceName);
    if (space != null) {
        spaceService.addMember(space, "mary");
    }

#### Listener to a space lifecycle

To receive notifications of what is happening in spaces, you need to extend SpaceListenerPlugin and register it. Every method takes a SpaceLifeCycleEvent object as parameter that contain the information about the event and it's context.

The events available are:

- spaceCreated: this event is called right after space is created successfully with its applications.

- spaceRemoved: this event is called right after a space is removed: application's removed, its group and group navigation is removed

- applicationAdded: this event is called right after an application is added (installed) to a space

- applicationActivated: this event is called right after an application is activated.

- applicationDeactivated: this event is called right after an application is deactivated.

- applicationRemoved: this event is called right after an application is removed from a space.

- joined: this event is called right after a user joins a space.

- left: this event is called right after a space member leaves its space.

- grantedLead: this event is called right after a user is grated space's manager role.

- revokedLead: this event is called right after a space's manager is revoked his role to be a space member.

    import org.exoplatform.social.space.lifecycle.SpaceListenerPlugin;

    public class MySpaceListenerPlugin extends SpaceListenerPlugin {
    ...
    }

As an example, see the SpaceActivityPublisher that publishes an activity based on an event that happened in a space.

To register your listener, hook it to the SpaceService like this :

    <external-component-plugins>
      <target-component>org.exoplatform.social.space.SpaceService</target-component>
      <component-plugin>
        <name>SpaceActivityPublisher</name>
        <set-method>addSpaceListener</set-method>
        <type>org.mycompany.MySpaceListenerPlugin</type>
      </component-plugin>
    </external-component-plugins>

### Open Social

eXo Social is implementing the OpenSocial standard. So you can integrate OpenSocial Gadget in your dashboard and use the RPC or REST API to access to the social data. With the support for the OpenSocial standard, eXo Social provides a framework for developers to build gadgets that can display and mash-up activity information for contacts, social networks, applications and services.

#### Gadget

Gadgets are web-based software components based on HTML, CSS, and JavaScript. They allow developers to easily write useful web applications that work anywhere on the web without modification. To know more, we suggest some links for detail information :

Gadgets Specification

OpenSocial Core Gadget Specification 10

After getting acquainted with Gadget concept, we enter into the detail on how to create an opensocial gadget. However, the tutorials are done greatly in Opensocial official site so we refer you to read these tutorials at that website

We only note that in Opensocial gadgets only work in the dashboard in eXo Social.

##### Supported APIs

As we have said above, eXo Social is implementing the OpenSocial standard. So every eXo Social implementations apply the Opensocial Specification generally or Apache Shindig specifically. Therefore, eXo Social uses and extends Apache Shindig APIs to compatible with the common Opensocial APIs which is supported by other big social networks like Ning, Hi5, Orkut ...

To get more detail about Supported APIs, we refer you to read Opensocial Specs

#### REST/RPC API

If your eXo social server is running on http://localhost:8080/ the address of the API will be:

REST API: http://localhost:8080/social/social/rest

RPC API: http://localhost:8080/social/social/rpc

To learn what you can do with this APIs, have a look at the specification. If you are developing in Java, you can use the opensocial-java-client

##### Configure the security

If you are using opensocial, there is good chance you are going to need to configure the oAuth authentication. To do this, you need to edit the configuration to add you oAuth key.

Edit the file: gatein/conf/portal/portal/configuration.xml and add this component:

            <component>
                    <key>org.exoplatform.social.opensocial.oauth.ServiceProviderStore</key>
                    <type>org.exoplatform.social.opensocial.oauth.ServiceProviderStore</type>

                    <init-params>
                            <properties-param>
                                    <name>grails-book-flow</name>
                                    <description>consmer key and secret for sample oauth provider. </description>
                                    <property name="consumerKey" value="YOUR_KEY_HERE" />

                                    <property name="sharedSecret" value="YOUR_SECRET_KEY_HERE" />
                            </properties-param>

                    </init-params>
            </component>

The consumerKey and sharedSecret are the key that need to be shared with the application that is doing the request.

##### Publish an activity into a space

eXo Social added this functionality that is not available in the standard opensocial API. You can publish activities into a space using the opensocial API.

To do this, instead of publishing your activity to the group @self as usual, publish it to the group "space:spaceID" or "space:spaceName".

Using the opensocial java library and groovy, your code will look like this:

          def client = getOpenSocialClient()

          //we create our new activity
          Activity activity = new Activity()
          activity.title = "BookFlow Purchase"
          activity.body = "xx puchased the book xxx"

          //We prepare the request that will create the activity
          Request request = ActivitiesService.createActivity(activity);
          //We specify that the creation of this new activity is for the space bookflow
          request.groupId = "space:bookflow";

          client.send(request);

As you can see in this example, we set the groupId to "space:bookflow", bookflow being the name of our space.

###### Tutorial

- See Grails + eXo Social tutorial.

### Space widget tutorial

The eXo Social widget enables developers to add capabilities of eXo Social to external applications. Since the widget is hosted on your eXo Social server, it can display personalized information. An activity stream of the most recent user actions will display to the group's members.

There are two options of the eXo Social widget that provide different levels of integration and information.

The basic version of this widget is an iFrame. The more advanced version is a button you can insert in a page; this will display a small pop-up with information about the space.

#### Basic version

To insert the basic version, you need to have an iFrame to insert on your site.

    <iframe  scrolling="no" height="180" frameborder="no" width="220" src="http://URL_OF_YOUR_EXO_INSTALLATION.COM/rest/private/spaces/portal/space_info?spaceName=NAME_OF_YOUR_SPACE&description=DESCRIPTION_OF_THE_SPACE"></iframe>

To install this version in your application, replace all the uppercase text below:

- URLOFYOUREXOINSTALLATION.COM - this is the URL of your eXo Social installation. If you are testing on your local computer, the URL may be localhost:8080_

- NAMEOFYOURSPACE - this is the title of your space in eXo Social. In the URL, it is necessary to avoid special characters. For the space name, you can only use alphanumeric characters and "", ".", "-" or ". "

- DESCRIPTIONOFTHESPACE - this will be displayed in the list of spaces.

#### Advanced version

To install an advanced version of the widget, you need to insert a code snippet in your page. This includes some HTMLs plus some JavaScripts. The necessary CSS will be added dynamically.

Next, insert the following code at the position you want the button to be displayed:

    <div class="exoSpacesContainer"><a href="javascript:void(0);" id="exoSpacesLink" class="exoSpacesLink" target="_blank">Space</a></div>
    <script src="/socialWidgetResources/javascript/space.js"></script>
    <script>spaces.createPopup("exoSpacesLink", "MyAppName - my social object", "my cool description");</script>

The important function here is:

    spaces.createPopup(link, spaceName, description)

- link: link is the ID or the HTMLElement where the pop-up will be placed. If you copy and paste the code snippet provided above, you donot need to change this value.

- spaceName: This is the name of space. It is also used to identify the space. We recommend you use the following format: "MyAppName - my social object"

- description: This is the description of your space that will be displayed within eXo Spaces. It is used when a new space is created.

#### Configure

- serverURL (Default: "http://127.0.0.1:8080"): The address of your eXo installation. To change it, use spaces.setServerURL(...);

- spaceServicePath (Default: "/rest/private/spaces/"): The path to the spaces service. It is rare you have to change it; but if needed, use spaces.setSpaceServicePath(...);

- portalName (Default: "socialdemo"): The name of portal you are using. To change it, use spaces.setPortalName(...);

If you want to change any part of this configuration, the best way is to change before creating the pop-up. For example:

    <div class="exoSpacesContainer"><a href="#" id="exoSpacesLink" class="exoSpacesLink" target="_blank">Space</a></div>
    <script src="/socialWidgetResources/javascript/space.js"></script>
    <script>
      spaces.setServerURL("http://192.168.2.100:8080");
      spaces.createPopup("exoSpacesLink", "My cool new space", "my cool description");
    </script>

You can see an example of integration at: http://localhost:8080/socialWidgetResources/test.html

## Public Javascript APIs

All references for Opensocial Javascript APIs can be viewed here

- Prev
- Up
- Home