mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
Initial Subscription Cervice check-in
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@28425 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
<import resource="classpath:alfresco/preference-service-context.xml"/>
|
||||
<import resource="classpath:alfresco/swf-transform-context.xml"/>
|
||||
<import resource="classpath:alfresco/form-services-context.xml"/>
|
||||
<import resource="classpath:alfresco/subscription-service-context.xml" />
|
||||
<import resource="classpath:alfresco/cmis-api-context.xml" />
|
||||
<import resource="classpath:alfresco/opencmis-context.xml" />
|
||||
<import resource="classpath:alfresco/period-type-context.xml" />
|
||||
|
@@ -142,6 +142,7 @@
|
||||
<ref bean="patch.db-V4.0-AclChangeSet" />
|
||||
<ref bean="patch.db-V4.0-NodeAssoc-Ordering" />
|
||||
<ref bean="patch.db-V4.0-Node-Locale" />
|
||||
<ref bean="patch.db-V4.0-SubscriptionTables" />
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
@@ -41,6 +41,13 @@
|
||||
<property name="sqlSessionTemplate" ref="activitiesSqlSessionTemplate"/>
|
||||
</bean>
|
||||
|
||||
<bean id="subscriptionsDAO" class="org.alfresco.repo.domain.subscriptions.ibatis.SubscriptionsDAOImpl">
|
||||
<property name="sqlSessionTemplate" ref="repoSqlSessionTemplate"/>
|
||||
<property name="personService" ref="personService"/>
|
||||
<property name="nodeDAO" ref="nodeDAO"/>
|
||||
<property name="QNameDAO" ref="qnameDAO"/>
|
||||
</bean>
|
||||
|
||||
<bean id="patchDAO" class="org.alfresco.util.bean.HierarchicalBeanLoader">
|
||||
<property name="targetBeanName">
|
||||
<value>patchDAO.#bean.dialect#</value>
|
||||
|
@@ -0,0 +1,28 @@
|
||||
--
|
||||
-- Title: Subscription tables
|
||||
-- Database: MySQL InnoDB
|
||||
-- Since: V4.0 Schema 5011
|
||||
-- Author: Florian Mueller
|
||||
--
|
||||
-- Please contact support@alfresco.com if you need assistance with the upgrade.
|
||||
--
|
||||
|
||||
CREATE TABLE alf_subscriptions (
|
||||
user_node_id BIGINT NOT NULL,
|
||||
node_id BIGINT NOT NULL,
|
||||
PRIMARY KEY (user_node_id, node_id),
|
||||
CONSTRAINT fk_alf_sub_user FOREIGN KEY (user_node_id) REFERENCES alf_node(id) ON DELETE CASCADE,
|
||||
CONSTRAINT fk_alf_sub_node FOREIGN KEY (node_id) REFERENCES alf_node(id) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
--
|
||||
-- Record script finish
|
||||
--
|
||||
DELETE FROM alf_applied_patch WHERE id = 'patch.db-V4.0-SubscriptionTables';
|
||||
INSERT INTO alf_applied_patch
|
||||
(id, description, fixes_from_schema, fixes_to_schema, applied_to_schema, target_schema, applied_on_date, applied_to_server, was_executed, succeeded, report)
|
||||
VALUES
|
||||
(
|
||||
'patch.db-V4.0-SubscriptionTables', 'Manually executed script upgrade V4.0: Subscription Tables',
|
||||
0, 5010, -1, 5011, null, 'UNKNOWN', ${TRUE}, ${TRUE}, 'Script completed'
|
||||
);
|
@@ -0,0 +1,28 @@
|
||||
--
|
||||
-- Title: Subscription tables
|
||||
-- Database: PostgreSQL
|
||||
-- Since: V4.0 Schema 5011
|
||||
-- Author: Florian Mueller
|
||||
--
|
||||
-- Please contact support@alfresco.com if you need assistance with the upgrade.
|
||||
--
|
||||
|
||||
CREATE TABLE alf_subscriptions (
|
||||
user_node_id INT8 NOT NULL,
|
||||
node_id INT8 NOT NULL,
|
||||
PRIMARY KEY (user_node_id, node_id),
|
||||
CONSTRAINT fk_alf_sub_user FOREIGN KEY (user_node_id) REFERENCES alf_node(id) ON DELETE CASCADE,
|
||||
CONSTRAINT fk_alf_sub_node FOREIGN KEY (node_id) REFERENCES alf_node(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
--
|
||||
-- Record script finish
|
||||
--
|
||||
DELETE FROM alf_applied_patch WHERE id = 'patch.db-V4.0-SubscriptionTables';
|
||||
INSERT INTO alf_applied_patch
|
||||
(id, description, fixes_from_schema, fixes_to_schema, applied_to_schema, target_schema, applied_on_date, applied_to_server, was_executed, succeeded, report)
|
||||
VALUES
|
||||
(
|
||||
'patch.db-V4.0-SubscriptionTables', 'Manually executed script upgrade V4.0: Subscription Tables',
|
||||
0, 5010, -1, 5011, null, 'UNKNOWN', ${TRUE}, ${TRUE}, 'Script completed'
|
||||
);
|
@@ -137,6 +137,11 @@ Inbound settings from iBatis
|
||||
<typeAlias alias="TestOne" type="org.alfresco.repo.domain.query.CannedQueryDAOTest$TestOneParams"/>
|
||||
<typeAlias alias="Ids" type="org.alfresco.ibatis.IdsEntity"/>
|
||||
|
||||
<!-- Subscriptions -->
|
||||
|
||||
<typeAlias alias="Subscription" type="org.alfresco.repo.domain.subscriptions.SubscriptionEntity"/>
|
||||
<typeAlias alias="SubscriptionNode" type="org.alfresco.repo.domain.subscriptions.SubscriptionNodeEntity"/>
|
||||
|
||||
</typeAliases>
|
||||
|
||||
<typeHandlers>
|
||||
@@ -168,6 +173,7 @@ Inbound settings from iBatis
|
||||
<mapper resource="alfresco/ibatis/#resource.dialect#/usage-insert-SqlMap.xml"/>
|
||||
<mapper resource="alfresco/ibatis/#resource.dialect#/avm-common-SqlMap.xml"/>
|
||||
<mapper resource="alfresco/ibatis/#resource.dialect#/avm-insert-SqlMap.xml"/>
|
||||
<mapper resource="alfresco/ibatis/#resource.dialect#/subscriptions-common-SqlMap.xml"/>
|
||||
<!-- Canned queries -->
|
||||
<mapper resource="alfresco/ibatis/#resource.dialect#/query-test-common-SqlMap.xml"/>
|
||||
<mapper resource="alfresco/ibatis/#resource.dialect#/query-usages-common-SqlMap.xml"/>
|
||||
|
@@ -0,0 +1,108 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
|
||||
<mapper namespace="alfresco.subscriptions">
|
||||
|
||||
<!-- -->
|
||||
<!-- Result Maps -->
|
||||
<!-- -->
|
||||
|
||||
<resultMap id="result_SubscriptionNode" type="SubscriptionNode">
|
||||
<result property="protocol" column="protocol" jdbcType="VARCHAR" javaType="java.lang.String"/>
|
||||
<result property="identifier" column="identifier" jdbcType="VARCHAR" javaType="java.lang.String"/>
|
||||
<result property="id" column="uuid" jdbcType="VARCHAR" javaType="java.lang.String"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- -->
|
||||
<!-- Parameter Maps -->
|
||||
<!-- -->
|
||||
|
||||
<parameterMap id="pararmeter_Subscription" type="Subscription">
|
||||
<parameter property="userNodeId" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
||||
<parameter property="nodeId" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
||||
</parameterMap>
|
||||
|
||||
<!-- -->
|
||||
<!-- SQL Snippets -->
|
||||
<!-- -->
|
||||
|
||||
<!-- -->
|
||||
<!-- Insert, Delete -->
|
||||
<!-- -->
|
||||
|
||||
<insert id="insert_Subscription" parameterMap="pararmeter_Subscription">
|
||||
insert into alf_subscriptions (user_node_id, node_id)
|
||||
values (?, ?)
|
||||
</insert>
|
||||
|
||||
<delete id="delete_Subscription" parameterMap="pararmeter_Subscription">
|
||||
delete from alf_subscriptions where user_node_id = #{userNodeId} and node_id = #{nodeId}
|
||||
</delete>
|
||||
|
||||
<!-- -->
|
||||
<!-- Statements -->
|
||||
<!-- -->
|
||||
|
||||
<select id="select_Subscriptions" parameterType="map" resultMap="result_SubscriptionNode">
|
||||
select
|
||||
store.protocol as protocol, store.identifier as identifier, node.uuid as uuid
|
||||
from
|
||||
alf_node node
|
||||
join alf_store store on (store.id = node.store_id)
|
||||
join alf_subscriptions sub on (sub.node_id = node.id)
|
||||
where
|
||||
node.node_deleted = #{false} and sub.user_node_id = #{userNodeId}
|
||||
</select>
|
||||
|
||||
<!-- Get the ... -->
|
||||
<select id="select_countSubscriptions" parameterType="map" resultType="long">
|
||||
select
|
||||
count(node_id)
|
||||
from
|
||||
alf_node node join alf_subscriptions sub on (sub.node_id = node.id)
|
||||
where
|
||||
node.node_deleted = #{false} and sub.user_node_id = #{userNodeId}
|
||||
</select>
|
||||
|
||||
<select id="select_hasSubscribed" parameterMap="pararmeter_Subscription" resultType="long">
|
||||
select
|
||||
count(node_id)
|
||||
from
|
||||
alf_node node join alf_subscriptions sub on (sub.node_id = node.id)
|
||||
where
|
||||
node.node_deleted = #{false} and sub.user_node_id = #{userNodeId} and sub.node_id = #{nodeId}
|
||||
</select>
|
||||
|
||||
<select id="select_Following" parameterType="map" resultType="String">
|
||||
select
|
||||
props.string_value as user_id
|
||||
from
|
||||
alf_node node
|
||||
join alf_subscriptions sub on (sub.node_id = node.id)
|
||||
join alf_node_properties props on (props.node_id = node.id)
|
||||
where
|
||||
node.node_deleted = #{false} and props.qname_id=#{userIdQname} and sub.user_node_id = #{userNodeId}
|
||||
</select>
|
||||
|
||||
<select id="select_Followers" parameterType="map" resultType="String">
|
||||
select
|
||||
props.string_value as user_id
|
||||
from
|
||||
alf_node node
|
||||
join alf_subscriptions sub on (sub.user_node_id = node.id)
|
||||
join alf_node_properties props on (props.node_id = node.id)
|
||||
where
|
||||
node.node_deleted = #{false} and props.qname_id=#{userIdQname} and sub.node_id = #{userNodeId}
|
||||
</select>
|
||||
|
||||
<select id="select_countFollowers" parameterType="map" resultType="long">
|
||||
select
|
||||
count(user_node_id)
|
||||
from
|
||||
alf_node node join alf_subscriptions sub on (sub.user_node_id = node.id)
|
||||
where
|
||||
node.node_deleted = #{false} and sub.node_id = #{userNodeId}
|
||||
</select>
|
||||
|
||||
</mapper>
|
@@ -268,6 +268,10 @@
|
||||
<type>d:boolean</type>
|
||||
</property>
|
||||
|
||||
<property name="cm:subscriptionsPrivate">
|
||||
<type>d:boolean</type>
|
||||
</property>
|
||||
|
||||
<!-- system maintained / protected values -->
|
||||
|
||||
<property name="cm:emailFeedId">
|
||||
|
@@ -2871,4 +2871,15 @@
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="patch.db-V4.0-SubscriptionTables" class="org.alfresco.repo.admin.patch.impl.SchemaUpgradeScriptPatch" parent="basePatch">
|
||||
<property name="id"><value>patch.db-V4.0-SubscriptionTables</value></property>
|
||||
<property name="description"><value>patch.schemaUpgradeScript.description</value></property>
|
||||
<property name="fixesFromSchema"><value>0</value></property>
|
||||
<property name="fixesToSchema"><value>5010</value></property>
|
||||
<property name="targetSchema"><value>5011</value></property>
|
||||
<property name="scriptUrl">
|
||||
<value>classpath:alfresco/dbscripts/create/${db.script.dialect}/AlfrescoCreate-SubscriptionTables.sql</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
|
29
config/alfresco/subscription-service-context.xml
Normal file
29
config/alfresco/subscription-service-context.xml
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
|
||||
|
||||
<beans>
|
||||
<!-- Subscription service bean -->
|
||||
<bean id="SubscriptionService" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="proxyInterfaces">
|
||||
<value>org.alfresco.service.cmr.subscriptions.SubscriptionService</value>
|
||||
</property>
|
||||
<property name="target">
|
||||
<ref bean="subscriptionService"/>
|
||||
</property>
|
||||
<property name="interceptorNames">
|
||||
<list>
|
||||
<idref bean="AuditMethodInterceptor"/>
|
||||
<idref bean="exceptionTranslator"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- Subscription implementation bean -->
|
||||
<bean id="subscriptionService" class="org.alfresco.repo.subscriptions.SubscriptionServiceImpl" >
|
||||
<property name="subscriptionsDAO" ref="subscriptionsDAO" />
|
||||
<property name="nodeService" ref="nodeService" />
|
||||
<property name="personService" ref="personService" />
|
||||
<property name="activityService" ref="activityService" />
|
||||
</bean>
|
||||
|
||||
</beans>
|
@@ -86,6 +86,7 @@
|
||||
<property name="nodeService" ref="NodeService"/>
|
||||
<property name="contentService" ref="ContentService"/>
|
||||
<property name="permissionService" ref="PermissionService"/>
|
||||
<property name="subscriptionService" ref="SubscriptionService"/>
|
||||
|
||||
<property name="templateSearchPaths">
|
||||
<list>
|
||||
|
@@ -235,7 +235,7 @@ public class ActivityPostServiceImpl implements ActivityPostService
|
||||
|
||||
private String getCurrentUser()
|
||||
{
|
||||
String userId = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||
String userId = AuthenticationUtil.getRunAsUser();
|
||||
if ((userId != null) && (! userId.equals(AuthenticationUtil.SYSTEM_USER_NAME)) && (! userNamesAreCaseSensitive))
|
||||
{
|
||||
// user names are not case-sensitive
|
||||
|
@@ -32,4 +32,6 @@ public interface ActivityType
|
||||
public final String SITE_GROUP_ADDED = "org.alfresco.site.group-added";
|
||||
public final String SITE_GROUP_REMOVED = "org.alfresco.site.group-removed";
|
||||
public final String SITE_GROUP_ROLE_UPDATE = "org.alfresco.site.group-role-changed";
|
||||
public final String SUBSCRIPTIONS_SUBSCRIBE = "org.alfresco.subscriptions.subscribed";
|
||||
public final String SUBSCRIPTIONS_FOLLOW = "org.alfresco.subscriptions.followed";
|
||||
}
|
||||
|
@@ -64,6 +64,7 @@ public abstract class FeedTaskProcessor
|
||||
{
|
||||
private static final Log logger = LogFactory.getLog(FeedTaskProcessor.class);
|
||||
|
||||
|
||||
public static final String FEED_FORMAT_JSON = "json";
|
||||
public static final String FEED_FORMAT_ATOMENTRY = "atomentry";
|
||||
public static final String FEED_FORMAT_HTML = "html";
|
||||
@@ -117,6 +118,7 @@ public abstract class FeedTaskProcessor
|
||||
|
||||
Map<String, List<String>> activityTemplates = new HashMap<String, List<String>>(10);
|
||||
Map<String, Set<String>> siteConnectedUsers = new TreeMap<String, Set<String>>();
|
||||
Map<String, Set<String>> followers = new TreeMap<String, Set<String>>();
|
||||
Map<String, List<FeedControlEntity>> userFeedControls = new HashMap<String, List<FeedControlEntity>>();
|
||||
Map<String, Template> templateCache = new TreeMap<String, Template>();
|
||||
|
||||
@@ -207,15 +209,6 @@ public abstract class FeedTaskProcessor
|
||||
|
||||
String thisSite = (activityPost.getSiteNetwork() != null ? activityPost.getSiteNetwork() : "");
|
||||
|
||||
if (thisSite.length() == 0)
|
||||
{
|
||||
// note: although we allow posts without site id - we currently require site context to generate feeds for site members (hence skip here with warning)
|
||||
// (also Share currently only posts activities within site context)
|
||||
logger.warn(">>> Skipping activity post " + activityPost.getId() + " since no site");
|
||||
updatePostStatus(activityPost.getId(), ActivityPostEntity.STATUS.PROCESSED);
|
||||
continue;
|
||||
}
|
||||
|
||||
model.put(ActivityFeedEntity.KEY_ACTIVITY_FEED_TYPE, activityPost.getActivityType());
|
||||
model.put(ActivityFeedEntity.KEY_ACTIVITY_FEED_SITE, thisSite);
|
||||
model.put("userId", activityPost.getUserId());
|
||||
@@ -224,25 +217,60 @@ public abstract class FeedTaskProcessor
|
||||
model.put("xmldate", new ISO8601DateFormatMethod());
|
||||
model.put("repoEndPoint", ctx.getRepoEndPoint());
|
||||
|
||||
// Get the members of this site - save hammering the repository by reusing cached site members
|
||||
Set<String> connectedUsers = siteConnectedUsers.get(thisSite);
|
||||
if (connectedUsers == null)
|
||||
// Recipients of this post
|
||||
Set<String> recipients = new HashSet<String>();
|
||||
|
||||
// Add site members to recipient list
|
||||
if (thisSite.length() > 0)
|
||||
{
|
||||
// Get the members of this site - save hammering the repository by reusing cached site members
|
||||
Set<String> connectedUsers = siteConnectedUsers.get(thisSite);
|
||||
if (connectedUsers == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Repository callback to get site members
|
||||
connectedUsers = getSiteMembers(ctx, thisSite);
|
||||
connectedUsers.add(""); // add empty posting userid - to represent site feed !
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
logger.error("Skipping activity post " + activityPost.getId() + " since failed to get site members: " + e);
|
||||
updatePostStatus(activityPost.getId(), ActivityPostEntity.STATUS.ERROR);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Cache them for future use in this same invocation
|
||||
siteConnectedUsers.put(thisSite, connectedUsers);
|
||||
}
|
||||
|
||||
recipients.addAll(connectedUsers);
|
||||
}
|
||||
|
||||
// Add followers to recipient list
|
||||
Set<String> followerUsers = followers.get(activityPost.getUserId());
|
||||
if(followerUsers == null) {
|
||||
try
|
||||
{
|
||||
// Repository callback to get site members
|
||||
connectedUsers = getSiteMembers(ctx, thisSite);
|
||||
connectedUsers.add(""); // add empty posting userid - to represent site feed !
|
||||
followerUsers = getFollowers(activityPost.getUserId());
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
logger.error("Skipping activity post " + activityPost.getId() + " since failed to get site members: " + e);
|
||||
logger.error("Skipping activity post " + activityPost.getId() + " since failed to get followers: " + e);
|
||||
updatePostStatus(activityPost.getId(), ActivityPostEntity.STATUS.ERROR);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Cache them for future use in this same invocation
|
||||
siteConnectedUsers.put(thisSite, connectedUsers);
|
||||
followers.put(activityPost.getUserId(), followerUsers);
|
||||
}
|
||||
recipients.addAll(followerUsers);
|
||||
|
||||
if(recipients.size() == 0) {
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("No recipients for activity post " + activityPost.getId() + ".");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
@@ -251,22 +279,22 @@ public abstract class FeedTaskProcessor
|
||||
|
||||
if (logger.isTraceEnabled())
|
||||
{
|
||||
logger.trace("Process: " + connectedUsers.size() + " candidate connections for activity post " + activityPost.getId());
|
||||
logger.trace("Process: " + recipients.size() + " candidate connections for activity post " + activityPost.getId());
|
||||
}
|
||||
|
||||
int excludedConnections = 0;
|
||||
|
||||
for (String connectedUser : connectedUsers)
|
||||
for (String recipient : recipients)
|
||||
{
|
||||
List<FeedControlEntity> feedControls = null;
|
||||
if (! connectedUser.equals(""))
|
||||
if (! recipient.equals(""))
|
||||
{
|
||||
// Get user's feed controls
|
||||
feedControls = userFeedControls.get(connectedUser);
|
||||
feedControls = userFeedControls.get(recipient);
|
||||
if (feedControls == null)
|
||||
{
|
||||
feedControls = getFeedControls(connectedUser);
|
||||
userFeedControls.put(connectedUser, feedControls);
|
||||
feedControls = getFeedControls(recipient);
|
||||
userFeedControls.put(recipient, feedControls);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,7 +306,7 @@ public abstract class FeedTaskProcessor
|
||||
else
|
||||
{
|
||||
// read permission check
|
||||
if (! canRead(ctx, connectedUser, model))
|
||||
if (! canRead(ctx, recipient, model))
|
||||
{
|
||||
excludedConnections++;
|
||||
continue;
|
||||
@@ -306,7 +334,7 @@ public abstract class FeedTaskProcessor
|
||||
ActivityFeedEntity feed = new ActivityFeedEntity();
|
||||
|
||||
// Generate activity feed summary
|
||||
feed.setFeedUserId(connectedUser);
|
||||
feed.setFeedUserId(recipient);
|
||||
feed.setPostUserId(postingUserId);
|
||||
feed.setActivityType(activityType);
|
||||
|
||||
@@ -356,7 +384,7 @@ public abstract class FeedTaskProcessor
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Processed: " + (connectedUsers.size() - excludedConnections) + " connections for activity post " + activityPost.getId() + " (excluded " + excludedConnections + ")");
|
||||
logger.debug("Processed: " + (recipients.size() - excludedConnections) + " connections for activity post " + activityPost.getId() + " (excluded " + excludedConnections + ")");
|
||||
}
|
||||
}
|
||||
finally
|
||||
@@ -398,7 +426,6 @@ public abstract class FeedTaskProcessor
|
||||
|
||||
public abstract int updatePostStatus(long id, ActivityPostEntity.STATUS status) throws SQLException;
|
||||
|
||||
|
||||
protected String callWebScript(String urlString, String ticket) throws MalformedURLException, URISyntaxException, IOException
|
||||
{
|
||||
URL url = new URL(urlString);
|
||||
@@ -482,6 +509,8 @@ public abstract class FeedTaskProcessor
|
||||
return members;
|
||||
}
|
||||
|
||||
protected abstract Set<String> getFollowers(String userId) throws Exception;
|
||||
|
||||
protected boolean canRead(RepoCtx ctx, final String connectedUser, Map<String, Object> model) throws Exception
|
||||
{
|
||||
throw new UnsupportedOperationException("FeedTaskProcessor: Remote callback for 'canRead' not implemented");
|
||||
|
@@ -26,6 +26,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.query.PagingRequest;
|
||||
import org.alfresco.repo.activities.feed.FeedTaskProcessor;
|
||||
import org.alfresco.repo.activities.feed.RepoCtx;
|
||||
import org.alfresco.repo.activities.post.lookup.PostLookup;
|
||||
@@ -46,6 +47,8 @@ import org.alfresco.service.cmr.security.AccessStatus;
|
||||
import org.alfresco.service.cmr.security.AuthorityType;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.cmr.site.SiteService;
|
||||
import org.alfresco.service.cmr.subscriptions.PagingFollowingResults;
|
||||
import org.alfresco.service.cmr.subscriptions.SubscriptionService;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
@@ -74,6 +77,7 @@ public class LocalFeedTaskProcessor extends FeedTaskProcessor implements Applica
|
||||
private NodeService nodeService;
|
||||
private ContentService contentService;
|
||||
private PermissionService permissionService;
|
||||
private SubscriptionService subscriptionService;
|
||||
|
||||
private String defaultEncoding;
|
||||
private List<String> templateSearchPaths;
|
||||
@@ -115,6 +119,11 @@ public class LocalFeedTaskProcessor extends FeedTaskProcessor implements Applica
|
||||
this.permissionService = permissionService;
|
||||
}
|
||||
|
||||
public void setSubscriptionService(SubscriptionService subscriptionService)
|
||||
{
|
||||
this.subscriptionService = subscriptionService;
|
||||
}
|
||||
|
||||
public void setDefaultEncoding(String defaultEncoding)
|
||||
{
|
||||
this.defaultEncoding = defaultEncoding;
|
||||
@@ -152,7 +161,7 @@ public class LocalFeedTaskProcessor extends FeedTaskProcessor implements Applica
|
||||
|
||||
public void endTransaction() throws SQLException
|
||||
{
|
||||
// NOOP
|
||||
// NOOP
|
||||
}
|
||||
|
||||
public List<ActivityPostEntity> selectPosts(ActivityPostEntity selector) throws SQLException
|
||||
@@ -172,7 +181,7 @@ public class LocalFeedTaskProcessor extends FeedTaskProcessor implements Applica
|
||||
|
||||
public List<FeedControlEntity> selectUserFeedControls(String userId) throws SQLException
|
||||
{
|
||||
return feedControlDAO.selectFeedControls(userId);
|
||||
return feedControlDAO.selectFeedControls(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -199,7 +208,7 @@ public class LocalFeedTaskProcessor extends FeedTaskProcessor implements Applica
|
||||
{
|
||||
for (String userName : mapResult.keySet())
|
||||
{
|
||||
if (! ctx.isUserNamesAreCaseSensitive())
|
||||
if (!ctx.isUserNamesAreCaseSensitive())
|
||||
{
|
||||
userName = userName.toLowerCase();
|
||||
}
|
||||
@@ -229,10 +238,10 @@ public class LocalFeedTaskProcessor extends FeedTaskProcessor implements Applica
|
||||
return true;
|
||||
}
|
||||
|
||||
String nodeRefStr = (String)model.get(PostLookup.JSON_NODEREF);
|
||||
String nodeRefStr = (String) model.get(PostLookup.JSON_NODEREF);
|
||||
if (nodeRefStr == null)
|
||||
{
|
||||
nodeRefStr = (String)model.get(PostLookup.JSON_NODEREF_PARENT);
|
||||
nodeRefStr = (String) model.get(PostLookup.JSON_NODEREF_PARENT);
|
||||
}
|
||||
|
||||
if (nodeRefStr != null)
|
||||
@@ -269,7 +278,7 @@ public class LocalFeedTaskProcessor extends FeedTaskProcessor implements Applica
|
||||
{
|
||||
// TODO: require ghosting - this is temp workaround (we should not rely on archive - may be permanently deleted, ie. not archived or already purged)
|
||||
NodeRef archiveNodeRef = new NodeRef(StoreRef.STORE_REF_ARCHIVE_SPACESSTORE, nodeRef.getId());
|
||||
if (! nodeService.exists(archiveNodeRef))
|
||||
if (!nodeService.exists(archiveNodeRef))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -308,7 +317,7 @@ public class LocalFeedTaskProcessor extends FeedTaskProcessor implements Applica
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("canRead: " + nodeRef + " in "+(System.currentTimeMillis()-start)+" msecs");
|
||||
logger.debug("canRead: " + nodeRef + " in " + (System.currentTimeMillis() - start) + " msecs");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -336,7 +345,7 @@ public class LocalFeedTaskProcessor extends FeedTaskProcessor implements Applica
|
||||
if (idx != -1)
|
||||
{
|
||||
path = subPath.substring(0, idx);
|
||||
templatePattern = subPath.substring(idx+1) + ".ftl";
|
||||
templatePattern = subPath.substring(idx + 1) + ".ftl";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -376,12 +385,12 @@ public class LocalFeedTaskProcessor extends FeedTaskProcessor implements Applica
|
||||
path = "/";
|
||||
}
|
||||
|
||||
if (! path.startsWith("/"))
|
||||
if (!path.startsWith("/"))
|
||||
{
|
||||
path = "/" + path;
|
||||
}
|
||||
|
||||
if (! path.endsWith("/"))
|
||||
if (!path.endsWith("/"))
|
||||
{
|
||||
path = path + "/";
|
||||
}
|
||||
@@ -437,4 +446,21 @@ public class LocalFeedTaskProcessor extends FeedTaskProcessor implements Applica
|
||||
}
|
||||
return documentPaths;
|
||||
}
|
||||
|
||||
protected Set<String> getFollowers(String userId) throws Exception
|
||||
{
|
||||
Set<String> result = new HashSet<String>();
|
||||
|
||||
if (!subscriptionService.isSubscriptionListPrivate(userId))
|
||||
{
|
||||
PagingFollowingResults fr = subscriptionService.getFollowers(userId, new PagingRequest(1000000, null));
|
||||
|
||||
if (fr.getPage() != null)
|
||||
{
|
||||
result.addAll(fr.getPage());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.domain.subscriptions;
|
||||
|
||||
import org.alfresco.query.PagingRequest;
|
||||
import org.alfresco.repo.domain.node.NodeDAO;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.security.PersonService;
|
||||
import org.alfresco.service.cmr.subscriptions.PagingFollowingResults;
|
||||
import org.alfresco.service.cmr.subscriptions.PagingSubscriptionResults;
|
||||
import org.alfresco.service.cmr.subscriptions.SubscriptionItemTypeEnum;
|
||||
|
||||
public abstract class AbstractSubscriptionsDAO implements SubscriptionsDAO
|
||||
{
|
||||
protected NodeDAO nodeDAO;
|
||||
protected PersonService personService;
|
||||
|
||||
public final void setNodeDAO(NodeDAO nodeDAO)
|
||||
{
|
||||
this.nodeDAO = nodeDAO;
|
||||
}
|
||||
|
||||
public final void setPersonService(PersonService personService)
|
||||
{
|
||||
this.personService = personService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract PagingSubscriptionResults selectSubscriptions(String userId, SubscriptionItemTypeEnum type,
|
||||
PagingRequest pagingRequest);
|
||||
|
||||
@Override
|
||||
public abstract int countSubscriptions(String userId, SubscriptionItemTypeEnum type);
|
||||
|
||||
@Override
|
||||
public abstract void insertSubscription(String userId, NodeRef node);
|
||||
|
||||
@Override
|
||||
public abstract void deleteSubscription(String userId, NodeRef node);
|
||||
|
||||
@Override
|
||||
public abstract boolean hasSubscribed(String userId, NodeRef node);
|
||||
|
||||
@Override
|
||||
public abstract PagingFollowingResults selectFollowers(String userId, PagingRequest pagingRequest);
|
||||
|
||||
@Override
|
||||
public abstract int countFollowers(String userId);
|
||||
|
||||
protected NodeRef getUserNodeRef(String userId)
|
||||
{
|
||||
return personService.getPerson(userId, false);
|
||||
}
|
||||
}
|
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.domain.subscriptions;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.alfresco.query.PagingRequest;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.security.PersonService;
|
||||
import org.alfresco.service.cmr.subscriptions.PagingFollowingResults;
|
||||
import org.alfresco.service.cmr.subscriptions.PagingSubscriptionResults;
|
||||
import org.alfresco.service.cmr.subscriptions.SubscriptionItemTypeEnum;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.alfresco.util.ApplicationContextHelper;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
public class SubscriptionDAOTest extends TestCase
|
||||
{
|
||||
private ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
|
||||
private TransactionService transactionService;
|
||||
private RetryingTransactionHelper txnHelper;
|
||||
private PersonService personService;
|
||||
|
||||
private SubscriptionsDAO subscriptionsDAO;
|
||||
|
||||
protected NodeRef getUserNodeRef(final String userId)
|
||||
{
|
||||
final PersonService ps = personService;
|
||||
|
||||
return AuthenticationUtil.runAs(new RunAsWork<NodeRef>()
|
||||
{
|
||||
@Override
|
||||
public NodeRef doWork() throws Exception
|
||||
{
|
||||
return ps.getPerson(userId);
|
||||
}
|
||||
}, AuthenticationUtil.getSystemUserName());
|
||||
}
|
||||
|
||||
protected void insert(final String userId, final NodeRef node) throws Exception
|
||||
{
|
||||
RetryingTransactionCallback<Object> callback = new RetryingTransactionCallback<Object>()
|
||||
{
|
||||
public Object execute() throws Throwable
|
||||
{
|
||||
subscriptionsDAO.insertSubscription(userId, node);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
txnHelper.doInTransaction(callback, false, false);
|
||||
}
|
||||
|
||||
protected void delete(final String userId, final NodeRef node) throws Exception
|
||||
{
|
||||
RetryingTransactionCallback<Object> callback = new RetryingTransactionCallback<Object>()
|
||||
{
|
||||
public Object execute() throws Throwable
|
||||
{
|
||||
subscriptionsDAO.deleteSubscription(userId, node);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
txnHelper.doInTransaction(callback, false, false);
|
||||
}
|
||||
|
||||
protected int count(final String userId) throws Exception
|
||||
{
|
||||
RetryingTransactionCallback<Integer> callback = new RetryingTransactionCallback<Integer>()
|
||||
{
|
||||
public Integer execute() throws Throwable
|
||||
{
|
||||
return subscriptionsDAO.countSubscriptions(userId, SubscriptionItemTypeEnum.USER);
|
||||
}
|
||||
};
|
||||
|
||||
return txnHelper.doInTransaction(callback, false, false);
|
||||
}
|
||||
|
||||
protected boolean hasSubscribed(final String userId, final NodeRef node) throws Exception
|
||||
{
|
||||
RetryingTransactionCallback<Boolean> callback = new RetryingTransactionCallback<Boolean>()
|
||||
{
|
||||
public Boolean execute() throws Throwable
|
||||
{
|
||||
return subscriptionsDAO.hasSubscribed(userId, node);
|
||||
}
|
||||
};
|
||||
|
||||
return txnHelper.doInTransaction(callback, false, false);
|
||||
}
|
||||
|
||||
protected PagingSubscriptionResults select(final String userId) throws Exception
|
||||
{
|
||||
RetryingTransactionCallback<PagingSubscriptionResults> callback = new RetryingTransactionCallback<PagingSubscriptionResults>()
|
||||
{
|
||||
public PagingSubscriptionResults execute() throws Throwable
|
||||
{
|
||||
return subscriptionsDAO.selectSubscriptions(userId, SubscriptionItemTypeEnum.USER, new PagingRequest(
|
||||
100000, null));
|
||||
}
|
||||
};
|
||||
|
||||
return txnHelper.doInTransaction(callback, false, false);
|
||||
}
|
||||
|
||||
protected int countFollowers(final String userId) throws Exception
|
||||
{
|
||||
RetryingTransactionCallback<Integer> callback = new RetryingTransactionCallback<Integer>()
|
||||
{
|
||||
public Integer execute() throws Throwable
|
||||
{
|
||||
return subscriptionsDAO.countFollowers(userId);
|
||||
}
|
||||
};
|
||||
|
||||
return txnHelper.doInTransaction(callback, false, false);
|
||||
}
|
||||
|
||||
protected PagingFollowingResults selectFollowing(final String userId) throws Exception
|
||||
{
|
||||
RetryingTransactionCallback<PagingFollowingResults> callback = new RetryingTransactionCallback<PagingFollowingResults>()
|
||||
{
|
||||
public PagingFollowingResults execute() throws Throwable
|
||||
{
|
||||
return subscriptionsDAO.selectFollowing(userId, new PagingRequest(100000, null));
|
||||
}
|
||||
};
|
||||
|
||||
return txnHelper.doInTransaction(callback, false, false);
|
||||
}
|
||||
|
||||
protected PagingFollowingResults selectFollowers(final String userId) throws Exception
|
||||
{
|
||||
RetryingTransactionCallback<PagingFollowingResults> callback = new RetryingTransactionCallback<PagingFollowingResults>()
|
||||
{
|
||||
public PagingFollowingResults execute() throws Throwable
|
||||
{
|
||||
return subscriptionsDAO.selectFollowers(userId, new PagingRequest(100000, null));
|
||||
}
|
||||
};
|
||||
|
||||
return txnHelper.doInTransaction(callback, false, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
ServiceRegistry serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
|
||||
transactionService = serviceRegistry.getTransactionService();
|
||||
txnHelper = transactionService.getRetryingTransactionHelper();
|
||||
|
||||
personService = serviceRegistry.getPersonService();
|
||||
|
||||
subscriptionsDAO = (SubscriptionsDAO) ctx.getBean("subscriptionsDAO");
|
||||
}
|
||||
|
||||
public void testInsertAndDelete() throws Exception
|
||||
{
|
||||
String userId = "admin";
|
||||
String userId2 = "guest";
|
||||
NodeRef nodeRef = getUserNodeRef(userId2);
|
||||
|
||||
// check subscription first
|
||||
if (hasSubscribed(userId, nodeRef))
|
||||
{
|
||||
delete(userId, nodeRef);
|
||||
}
|
||||
boolean hasSubscribed = hasSubscribed(userId, nodeRef);
|
||||
assertFalse(hasSubscribed);
|
||||
|
||||
// count subscriptions
|
||||
int count = count(userId);
|
||||
assertTrue(count >= 0);
|
||||
|
||||
// insert
|
||||
insert(userId, nodeRef);
|
||||
insert(userId, nodeRef);
|
||||
assertEquals(count + 1, count(userId));
|
||||
assertTrue(hasSubscribed(userId, nodeRef));
|
||||
|
||||
// select
|
||||
PagingSubscriptionResults psr = select(userId);
|
||||
assertNotNull(psr);
|
||||
assertNotNull(psr.getPage());
|
||||
assertTrue(psr.getPage().contains(nodeRef));
|
||||
|
||||
PagingFollowingResults following = selectFollowing(userId);
|
||||
assertNotNull(following);
|
||||
assertNotNull(following.getPage());
|
||||
assertTrue(following.getPage().contains(userId2));
|
||||
|
||||
assertEquals(psr.getPage().size(), following.getPage().size());
|
||||
|
||||
// count followers
|
||||
int followerCount = countFollowers(userId2);
|
||||
assertTrue(followerCount >= 0);
|
||||
|
||||
// select followers
|
||||
PagingFollowingResults followers = selectFollowers(userId2);
|
||||
assertNotNull(followers);
|
||||
assertNotNull(followers.getPage());
|
||||
assertTrue(followers.getPage().contains(userId));
|
||||
|
||||
// delete
|
||||
delete(userId, nodeRef);
|
||||
assertEquals(count, count(userId));
|
||||
assertFalse(hasSubscribed(userId, nodeRef));
|
||||
}
|
||||
}
|
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.domain.subscriptions;
|
||||
|
||||
public class SubscriptionEntity
|
||||
{
|
||||
private Long userNodeId;
|
||||
private Long nodeId;
|
||||
|
||||
public Long getUserNodeId()
|
||||
{
|
||||
return userNodeId;
|
||||
}
|
||||
|
||||
public void setUserNodeId(Long userNodeId)
|
||||
{
|
||||
this.userNodeId = userNodeId;
|
||||
}
|
||||
|
||||
public Long getNodeId()
|
||||
{
|
||||
return nodeId;
|
||||
}
|
||||
|
||||
public void setNodeId(Long nodeId)
|
||||
{
|
||||
this.nodeId = nodeId;
|
||||
}
|
||||
|
||||
public boolean getFalse()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.domain.subscriptions;
|
||||
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
|
||||
public class SubscriptionNodeEntity
|
||||
{
|
||||
private String protocol;
|
||||
private String identifier;
|
||||
private String id;
|
||||
|
||||
public String getProtocol()
|
||||
{
|
||||
return protocol;
|
||||
}
|
||||
|
||||
public void setProtocol(String protocol)
|
||||
{
|
||||
this.protocol = protocol;
|
||||
}
|
||||
|
||||
public String getIdentifier()
|
||||
{
|
||||
return identifier;
|
||||
}
|
||||
|
||||
public void setIdentifier(String identifier)
|
||||
{
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public String getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public NodeRef getNodeRef()
|
||||
{
|
||||
return new NodeRef(protocol, identifier, id);
|
||||
}
|
||||
}
|
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.domain.subscriptions;
|
||||
|
||||
import org.alfresco.query.PagingRequest;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.subscriptions.PagingFollowingResults;
|
||||
import org.alfresco.service.cmr.subscriptions.PagingSubscriptionResults;
|
||||
import org.alfresco.service.cmr.subscriptions.SubscriptionItemTypeEnum;
|
||||
|
||||
public interface SubscriptionsDAO
|
||||
{
|
||||
PagingSubscriptionResults selectSubscriptions(String userId, SubscriptionItemTypeEnum type,
|
||||
PagingRequest pagingRequest);
|
||||
|
||||
int countSubscriptions(String userId, SubscriptionItemTypeEnum type);
|
||||
|
||||
void insertSubscription(String userId, NodeRef node);
|
||||
|
||||
void deleteSubscription(String userId, NodeRef node);
|
||||
|
||||
boolean hasSubscribed(String userId, NodeRef node);
|
||||
|
||||
PagingFollowingResults selectFollowing(String userId, PagingRequest pagingRequest);
|
||||
|
||||
PagingFollowingResults selectFollowers(String userId, PagingRequest pagingRequest);
|
||||
|
||||
int countFollowers(String userId);
|
||||
}
|
@@ -0,0 +1,293 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.domain.subscriptions.ibatis;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.query.PagingRequest;
|
||||
import org.alfresco.repo.domain.qname.QNameDAO;
|
||||
import org.alfresco.repo.domain.subscriptions.AbstractSubscriptionsDAO;
|
||||
import org.alfresco.repo.domain.subscriptions.SubscriptionEntity;
|
||||
import org.alfresco.repo.domain.subscriptions.SubscriptionNodeEntity;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.subscriptions.PagingFollowingResults;
|
||||
import org.alfresco.service.cmr.subscriptions.PagingFollowingResultsImpl;
|
||||
import org.alfresco.service.cmr.subscriptions.PagingSubscriptionResults;
|
||||
import org.alfresco.service.cmr.subscriptions.PagingSubscriptionResultsImpl;
|
||||
import org.alfresco.service.cmr.subscriptions.SubscriptionItemTypeEnum;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.apache.ibatis.session.RowBounds;
|
||||
import org.mybatis.spring.SqlSessionTemplate;
|
||||
|
||||
public class SubscriptionsDAOImpl extends AbstractSubscriptionsDAO
|
||||
{
|
||||
private SqlSessionTemplate template;
|
||||
private QNameDAO qnameDAO;
|
||||
|
||||
public final void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate)
|
||||
{
|
||||
this.template = sqlSessionTemplate;
|
||||
}
|
||||
|
||||
public final void setQNameDAO(QNameDAO qnameDAO)
|
||||
{
|
||||
this.qnameDAO = qnameDAO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PagingSubscriptionResults selectSubscriptions(String userId, SubscriptionItemTypeEnum type,
|
||||
PagingRequest pagingRequest)
|
||||
{
|
||||
if (userId == null)
|
||||
{
|
||||
throw new IllegalArgumentException("User Id may not be null!");
|
||||
}
|
||||
|
||||
if (type == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Type may not be null!");
|
||||
}
|
||||
|
||||
NodeRef userNodeRef = getUserNodeRef(userId);
|
||||
Pair<Long, NodeRef> userPair = nodeDAO.getNodePair(userNodeRef);
|
||||
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
map.put("userNodeId", userPair.getFirst());
|
||||
map.put("false", Boolean.FALSE);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<SubscriptionNodeEntity> nodeList = (List<SubscriptionNodeEntity>) template.selectList(
|
||||
"alfresco.subscriptions.select_Subscriptions", map, new RowBounds(pagingRequest.getSkipCount(),
|
||||
pagingRequest.getMaxItems() + 1));
|
||||
|
||||
boolean hasMore = nodeList.size() > pagingRequest.getMaxItems();
|
||||
|
||||
List<NodeRef> result = new ArrayList<NodeRef>(nodeList.size());
|
||||
for (SubscriptionNodeEntity sne : nodeList)
|
||||
{
|
||||
result.add(sne.getNodeRef());
|
||||
if (result.size() == pagingRequest.getMaxItems())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Integer totalCount = null;
|
||||
if (pagingRequest.getRequestTotalCountMax() > 0)
|
||||
{
|
||||
totalCount = countSubscriptions(userId, type);
|
||||
}
|
||||
|
||||
return new PagingSubscriptionResultsImpl(result, hasMore, totalCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countSubscriptions(String userId, SubscriptionItemTypeEnum type)
|
||||
{
|
||||
if (userId == null)
|
||||
{
|
||||
throw new IllegalArgumentException("User Id may not be null!");
|
||||
}
|
||||
|
||||
if (type == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Type may not be null!");
|
||||
}
|
||||
|
||||
NodeRef userNodeRef = getUserNodeRef(userId);
|
||||
Pair<Long, NodeRef> userPair = nodeDAO.getNodePair(userNodeRef);
|
||||
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
map.put("userNodeId", userPair.getFirst());
|
||||
map.put("false", Boolean.FALSE);
|
||||
|
||||
Number count = (Number) template.selectOne("alfresco.subscriptions.select_countSubscriptions", map);
|
||||
|
||||
return count.intValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertSubscription(String userId, NodeRef node)
|
||||
{
|
||||
if (userId == null)
|
||||
{
|
||||
throw new IllegalArgumentException("User Id may not be null!");
|
||||
}
|
||||
|
||||
if (node == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Node may not be null!");
|
||||
}
|
||||
|
||||
NodeRef userNodeRef = getUserNodeRef(userId);
|
||||
Pair<Long, NodeRef> userPair = nodeDAO.getNodePair(userNodeRef);
|
||||
Pair<Long, NodeRef> nodePair = nodeDAO.getNodePair(node);
|
||||
|
||||
SubscriptionEntity se = new SubscriptionEntity();
|
||||
se.setUserNodeId(userPair.getFirst());
|
||||
se.setNodeId(nodePair.getFirst());
|
||||
|
||||
if (((Number) template.selectOne("alfresco.subscriptions.select_hasSubscribed", se)).intValue() == 0)
|
||||
{
|
||||
template.insert("alfresco.subscriptions.insert_Subscription", se);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteSubscription(String userId, NodeRef node)
|
||||
{
|
||||
if (userId == null)
|
||||
{
|
||||
throw new IllegalArgumentException("User Id may not be null!");
|
||||
}
|
||||
|
||||
if (node == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Node may not be null!");
|
||||
}
|
||||
|
||||
NodeRef userNodeRef = getUserNodeRef(userId);
|
||||
Pair<Long, NodeRef> userPair = nodeDAO.getNodePair(userNodeRef);
|
||||
Pair<Long, NodeRef> nodePair = nodeDAO.getNodePair(node);
|
||||
|
||||
SubscriptionEntity se = new SubscriptionEntity();
|
||||
se.setUserNodeId(userPair.getFirst());
|
||||
se.setNodeId(nodePair.getFirst());
|
||||
|
||||
template.delete("alfresco.subscriptions.delete_Subscription", se);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSubscribed(String userId, NodeRef node)
|
||||
{
|
||||
if (userId == null)
|
||||
{
|
||||
throw new IllegalArgumentException("User Id may not be null!");
|
||||
}
|
||||
|
||||
if (node == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Node may not be null!");
|
||||
}
|
||||
|
||||
NodeRef userNodeRef = getUserNodeRef(userId);
|
||||
Pair<Long, NodeRef> userPair = nodeDAO.getNodePair(userNodeRef);
|
||||
Pair<Long, NodeRef> nodePair = nodeDAO.getNodePair(node);
|
||||
|
||||
SubscriptionEntity se = new SubscriptionEntity();
|
||||
se.setUserNodeId(userPair.getFirst());
|
||||
se.setNodeId(nodePair.getFirst());
|
||||
|
||||
return ((Number) template.selectOne("alfresco.subscriptions.select_hasSubscribed", se)).intValue() == 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PagingFollowingResults selectFollowing(String userId, PagingRequest pagingRequest)
|
||||
{
|
||||
if (userId == null)
|
||||
{
|
||||
throw new IllegalArgumentException("User Id may not be null!");
|
||||
}
|
||||
|
||||
NodeRef userNodeRef = getUserNodeRef(userId);
|
||||
Pair<Long, NodeRef> userPair = nodeDAO.getNodePair(userNodeRef);
|
||||
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
map.put("userIdQname", qnameDAO.getQName(ContentModel.PROP_USERNAME).getFirst());
|
||||
map.put("userNodeId", userPair.getFirst());
|
||||
map.put("false", Boolean.FALSE);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<String> userList = (List<String>) template.selectList("alfresco.subscriptions.select_Following", map,
|
||||
new RowBounds(pagingRequest.getSkipCount(), pagingRequest.getMaxItems() + 1));
|
||||
|
||||
boolean hasMore = userList.size() > pagingRequest.getMaxItems();
|
||||
if (hasMore && userList.size() > 0)
|
||||
{
|
||||
userList.remove(userList.size() - 1);
|
||||
}
|
||||
|
||||
Integer totalCount = null;
|
||||
if (pagingRequest.getRequestTotalCountMax() > 0)
|
||||
{
|
||||
totalCount = countFollowers(userId);
|
||||
}
|
||||
|
||||
return new PagingFollowingResultsImpl(userList, hasMore, totalCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PagingFollowingResults selectFollowers(String userId, PagingRequest pagingRequest)
|
||||
{
|
||||
if (userId == null)
|
||||
{
|
||||
throw new IllegalArgumentException("User Id may not be null!");
|
||||
}
|
||||
|
||||
NodeRef userNodeRef = getUserNodeRef(userId);
|
||||
Pair<Long, NodeRef> userPair = nodeDAO.getNodePair(userNodeRef);
|
||||
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
map.put("userIdQname", qnameDAO.getQName(ContentModel.PROP_USERNAME).getFirst());
|
||||
map.put("userNodeId", userPair.getFirst());
|
||||
map.put("false", Boolean.FALSE);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<String> userList = (List<String>) template.selectList("alfresco.subscriptions.select_Followers", map,
|
||||
new RowBounds(pagingRequest.getSkipCount(), pagingRequest.getMaxItems() + 1));
|
||||
|
||||
boolean hasMore = userList.size() > pagingRequest.getMaxItems();
|
||||
if (hasMore && userList.size() > 0)
|
||||
{
|
||||
userList.remove(userList.size() - 1);
|
||||
}
|
||||
|
||||
Integer totalCount = null;
|
||||
if (pagingRequest.getRequestTotalCountMax() > 0)
|
||||
{
|
||||
totalCount = countFollowers(userId);
|
||||
}
|
||||
|
||||
return new PagingFollowingResultsImpl(userList, hasMore, totalCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countFollowers(String userId)
|
||||
{
|
||||
if (userId == null)
|
||||
{
|
||||
throw new IllegalArgumentException("User Id may not be null!");
|
||||
}
|
||||
|
||||
NodeRef userNodeRef = getUserNodeRef(userId);
|
||||
Pair<Long, NodeRef> userPair = nodeDAO.getNodePair(userNodeRef);
|
||||
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
map.put("userNodeId", userPair.getFirst());
|
||||
map.put("false", Boolean.FALSE);
|
||||
|
||||
Number count = (Number) template.selectOne("alfresco.subscriptions.select_countFollowers", map);
|
||||
|
||||
return count.intValue();
|
||||
}
|
||||
}
|
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.subscriptions;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.activities.feed.FeedGenerator;
|
||||
import org.alfresco.repo.activities.feed.local.LocalFeedTaskProcessor;
|
||||
import org.alfresco.repo.activities.post.lookup.PostLookup;
|
||||
import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.security.PersonService;
|
||||
import org.alfresco.service.cmr.subscriptions.SubscriptionService;
|
||||
import org.alfresco.util.ApplicationContextHelper;
|
||||
import org.alfresco.util.PropertyMap;
|
||||
import org.quartz.Scheduler;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
public class SubscriptionServiceActivitiesTest extends TestCase
|
||||
{
|
||||
// Location of activity type templates (for site activities)
|
||||
// assumes test-resources is on classpath
|
||||
protected static final String TEST_TEMPLATES_LOCATION = "activities";
|
||||
|
||||
protected ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
|
||||
protected SubscriptionService subscriptionService;
|
||||
protected PersonService personService;
|
||||
protected PostLookup postLookup;
|
||||
protected FeedGenerator feedGenerator;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
// Let's shut down the scheduler so that we aren't competing with the
|
||||
// scheduled versions of the post lookup and
|
||||
// feed generator jobs
|
||||
Scheduler scheduler = (Scheduler) ctx.getBean("schedulerFactory");
|
||||
scheduler.shutdown();
|
||||
|
||||
// Get the required services
|
||||
subscriptionService = (SubscriptionService) ctx.getBean("SubscriptionService");
|
||||
personService = (PersonService) ctx.getBean("PersonService");
|
||||
|
||||
ChildApplicationContextFactory activitiesFeed = (ChildApplicationContextFactory) ctx.getBean("ActivitiesFeed");
|
||||
ApplicationContext activitiesFeedCtx = activitiesFeed.getApplicationContext();
|
||||
postLookup = (PostLookup) activitiesFeedCtx.getBean("postLookup");
|
||||
feedGenerator = (FeedGenerator) activitiesFeedCtx.getBean("feedGenerator");
|
||||
|
||||
LocalFeedTaskProcessor feedProcessor = (LocalFeedTaskProcessor) activitiesFeedCtx.getBean("feedTaskProcessor");
|
||||
|
||||
List<String> templateSearchPaths = new ArrayList<String>(1);
|
||||
templateSearchPaths.add(TEST_TEMPLATES_LOCATION);
|
||||
feedProcessor.setTemplateSearchPaths(templateSearchPaths);
|
||||
feedProcessor.setUseRemoteCallbacks(false);
|
||||
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getSystemUserName());
|
||||
}
|
||||
|
||||
protected void deletePerson(String userId)
|
||||
{
|
||||
personService.deletePerson(userId);
|
||||
}
|
||||
|
||||
protected NodeRef createPerson(String userId)
|
||||
{
|
||||
deletePerson(userId);
|
||||
|
||||
PropertyMap properties = new PropertyMap(5);
|
||||
properties.put(ContentModel.PROP_USERNAME, userId);
|
||||
properties.put(ContentModel.PROP_FIRSTNAME, userId);
|
||||
properties.put(ContentModel.PROP_LASTNAME, "Test");
|
||||
properties.put(ContentModel.PROP_EMAIL, userId + "@email.com");
|
||||
|
||||
return personService.createPerson(properties);
|
||||
}
|
||||
|
||||
protected void generateFeed() throws Exception
|
||||
{
|
||||
postLookup.execute();
|
||||
feedGenerator.execute();
|
||||
}
|
||||
|
||||
public void testFollowingActivity() throws Exception
|
||||
{
|
||||
final String userId1 = "bob";
|
||||
final String userId2 = "tom";
|
||||
|
||||
createPerson(userId1);
|
||||
createPerson(userId2);
|
||||
|
||||
AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Object>()
|
||||
{
|
||||
@Override
|
||||
public Object doWork() throws Exception
|
||||
{
|
||||
subscriptionService.follow(userId1, userId2);
|
||||
return null;
|
||||
}
|
||||
}, userId1);
|
||||
|
||||
AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Object>()
|
||||
{
|
||||
@Override
|
||||
public Object doWork() throws Exception
|
||||
{
|
||||
subscriptionService.follow(userId2, userId1);
|
||||
return null;
|
||||
}
|
||||
}, userId2);
|
||||
|
||||
generateFeed();
|
||||
|
||||
deletePerson(userId1);
|
||||
deletePerson(userId2);
|
||||
}
|
||||
}
|
@@ -0,0 +1,386 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.subscriptions;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.query.PagingRequest;
|
||||
import org.alfresco.repo.activities.ActivityType;
|
||||
import org.alfresco.repo.domain.subscriptions.SubscriptionsDAO;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||
import org.alfresco.service.cmr.activities.ActivityService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.security.PersonService;
|
||||
import org.alfresco.service.cmr.subscriptions.PagingFollowingResults;
|
||||
import org.alfresco.service.cmr.subscriptions.PagingFollowingResultsImpl;
|
||||
import org.alfresco.service.cmr.subscriptions.PagingSubscriptionResults;
|
||||
import org.alfresco.service.cmr.subscriptions.PagingSubscriptionResultsImpl;
|
||||
import org.alfresco.service.cmr.subscriptions.PrivateSubscriptionListException;
|
||||
import org.alfresco.service.cmr.subscriptions.SubscriptionItemTypeEnum;
|
||||
import org.alfresco.service.cmr.subscriptions.SubscriptionService;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class SubscriptionServiceImpl implements SubscriptionService
|
||||
{
|
||||
/** Logger */
|
||||
private static Log logger = LogFactory.getLog(SubscriptionServiceImpl.class);
|
||||
|
||||
/** Activity tool */
|
||||
private static final String ACTIVITY_TOOL = "subscriptionService";
|
||||
|
||||
/** Activity values */
|
||||
private static final String SUB_USER = "user";
|
||||
private static final String SUB_USER_TO_FOLLOW = "userToFollow";
|
||||
private static final String SUB_NODE = "node";
|
||||
|
||||
protected SubscriptionsDAO subscriptionsDAO;
|
||||
protected NodeService nodeService;
|
||||
protected PersonService personService;
|
||||
protected ActivityService activityService;
|
||||
|
||||
/**
|
||||
* Sets the subscriptions DAO.
|
||||
*/
|
||||
public void setSubscriptionsDAO(SubscriptionsDAO subscriptionsDAO)
|
||||
{
|
||||
this.subscriptionsDAO = subscriptionsDAO;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the node service.
|
||||
*/
|
||||
public final void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the person service.
|
||||
*/
|
||||
public final void setPersonService(PersonService personService)
|
||||
{
|
||||
this.personService = personService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the activity service.
|
||||
*/
|
||||
public final void setActivityService(ActivityService activictyService)
|
||||
{
|
||||
this.activityService = activictyService;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public PagingSubscriptionResults getSubscriptions(String userId, SubscriptionItemTypeEnum type,
|
||||
PagingRequest pagingRequest)
|
||||
{
|
||||
if (!subscriptionsEnabled())
|
||||
{
|
||||
return new PagingSubscriptionResultsImpl(Collections.EMPTY_LIST, false, 0);
|
||||
}
|
||||
|
||||
checkRead(userId);
|
||||
return subscriptionsDAO.selectSubscriptions(userId, type, pagingRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSubscriptionCount(String userId, SubscriptionItemTypeEnum type)
|
||||
{
|
||||
if (!subscriptionsEnabled())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return subscriptionsDAO.countSubscriptions(userId, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subscribe(String userId, NodeRef node)
|
||||
{
|
||||
if (!subscriptionsEnabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
checkWrite(userId);
|
||||
checkUserNode(node);
|
||||
subscriptionsDAO.insertSubscription(userId, node);
|
||||
|
||||
if (userId.equalsIgnoreCase(AuthenticationUtil.getRunAsUser()))
|
||||
{
|
||||
String activityDataJSON = null;
|
||||
try
|
||||
{
|
||||
JSONObject activityData = new JSONObject();
|
||||
activityData.put(SUB_USER, userId);
|
||||
activityData.put(SUB_NODE, node.toString());
|
||||
activityDataJSON = activityData.toString();
|
||||
} catch (JSONException je)
|
||||
{
|
||||
// log error, subsume exception
|
||||
logger.error("Failed to get activity data: " + je);
|
||||
}
|
||||
|
||||
activityService.postActivity(ActivityType.SUBSCRIPTIONS_SUBSCRIBE, null, ACTIVITY_TOOL, activityDataJSON);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsubscribe(String userId, NodeRef node)
|
||||
{
|
||||
if (!subscriptionsEnabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
checkWrite(userId);
|
||||
subscriptionsDAO.deleteSubscription(userId, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSubscribed(String userId, NodeRef node)
|
||||
{
|
||||
if (!subscriptionsEnabled())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
checkRead(userId);
|
||||
return subscriptionsDAO.hasSubscribed(userId, node);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public PagingFollowingResults getFollowing(String userId, PagingRequest pagingRequest)
|
||||
{
|
||||
if (!subscriptionsEnabled())
|
||||
{
|
||||
return new PagingFollowingResultsImpl(Collections.EMPTY_LIST, false, 0);
|
||||
}
|
||||
|
||||
checkRead(userId);
|
||||
return subscriptionsDAO.selectFollowing(userId, pagingRequest);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public PagingFollowingResults getFollowers(String userId, PagingRequest pagingRequest)
|
||||
{
|
||||
if (!subscriptionsEnabled())
|
||||
{
|
||||
return new PagingFollowingResultsImpl(Collections.EMPTY_LIST, false, 0);
|
||||
}
|
||||
|
||||
if (userId == null)
|
||||
{
|
||||
throw new IllegalArgumentException("User Id may not be null!");
|
||||
}
|
||||
|
||||
return subscriptionsDAO.selectFollowers(userId, pagingRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFollowersCount(String userId)
|
||||
{
|
||||
if (!subscriptionsEnabled())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return subscriptionsDAO.countFollowers(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFollowingCount(String userId)
|
||||
{
|
||||
if (!subscriptionsEnabled())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return getSubscriptionCount(userId, SubscriptionItemTypeEnum.USER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void follow(String userId, String userToFollow)
|
||||
{
|
||||
if (!subscriptionsEnabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
checkWrite(userId);
|
||||
subscriptionsDAO.insertSubscription(userId, getUserNodeRef(userToFollow));
|
||||
|
||||
if (userId.equalsIgnoreCase(AuthenticationUtil.getRunAsUser()))
|
||||
{
|
||||
String activityDataJSON = null;
|
||||
try
|
||||
{
|
||||
JSONObject activityData = new JSONObject();
|
||||
activityData.put(SUB_USER, userId);
|
||||
activityData.put(SUB_USER_TO_FOLLOW, userToFollow);
|
||||
activityDataJSON = activityData.toString();
|
||||
} catch (JSONException je)
|
||||
{
|
||||
// log error, subsume exception
|
||||
logger.error("Failed to get activity data: " + je);
|
||||
}
|
||||
|
||||
activityService.postActivity(ActivityType.SUBSCRIPTIONS_FOLLOW, null, ACTIVITY_TOOL, activityDataJSON);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unfollow(String userId, String userToUnfollow)
|
||||
{
|
||||
if (!subscriptionsEnabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
checkWrite(userId);
|
||||
subscriptionsDAO.deleteSubscription(userId, getUserNodeRef(userToUnfollow));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean follows(String userId, String userToFollow)
|
||||
{
|
||||
if (!subscriptionsEnabled())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
checkRead(userId);
|
||||
return subscriptionsDAO.hasSubscribed(userId, getUserNodeRef(userToFollow));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSubscriptionListPrivate(String userId, boolean isPrivate)
|
||||
{
|
||||
checkWrite(userId);
|
||||
nodeService.setProperty(getUserNodeRef(userId), ContentModel.PROP_SUBSCRIPTIONS_PRIVATE, isPrivate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSubscriptionListPrivate(String userId)
|
||||
{
|
||||
if (userId == null)
|
||||
{
|
||||
throw new IllegalArgumentException("User Id may not be null!");
|
||||
}
|
||||
|
||||
Serializable privateList = nodeService.getProperty(getUserNodeRef(userId),
|
||||
ContentModel.PROP_SUBSCRIPTIONS_PRIVATE);
|
||||
if (privateList == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (privateList instanceof Boolean && !((Boolean) privateList).booleanValue())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean subscriptionsEnabled()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the current user is allowed to get subscription data.
|
||||
*/
|
||||
protected void checkRead(String userId)
|
||||
{
|
||||
if (userId == null)
|
||||
{
|
||||
throw new IllegalArgumentException("User Id may not be null!");
|
||||
}
|
||||
|
||||
String currentUser = AuthenticationUtil.getRunAsUser();
|
||||
if (currentUser == null)
|
||||
{
|
||||
throw new IllegalArgumentException("No current user!");
|
||||
}
|
||||
|
||||
if (currentUser.equalsIgnoreCase(userId) || currentUser.equalsIgnoreCase(AuthenticationUtil.getAdminUserName())
|
||||
|| AuthenticationUtil.isRunAsUserTheSystemUser() || !isSubscriptionListPrivate(userId))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
throw new PrivateSubscriptionListException("subscription_service.err.private-list");
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the current user is allowed to get change data.
|
||||
*/
|
||||
protected void checkWrite(String userId)
|
||||
{
|
||||
if (userId == null)
|
||||
{
|
||||
throw new IllegalArgumentException("User Id may not be null!");
|
||||
}
|
||||
|
||||
String currentUser = AuthenticationUtil.getRunAsUser();
|
||||
if (currentUser == null)
|
||||
{
|
||||
throw new IllegalArgumentException("No current user!");
|
||||
}
|
||||
|
||||
if (currentUser.equalsIgnoreCase(userId) || currentUser.equalsIgnoreCase(AuthenticationUtil.getAdminUserName())
|
||||
|| AuthenticationUtil.isRunAsUserTheSystemUser())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
throw new AccessDeniedException("subscription_service.err.write-denied");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the user node ref from the user id.
|
||||
*/
|
||||
protected NodeRef getUserNodeRef(String userId)
|
||||
{
|
||||
return personService.getPerson(userId, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the node is a user node and throws an exception if it id not.
|
||||
*/
|
||||
protected void checkUserNode(NodeRef nodeRef)
|
||||
{
|
||||
// we only support user-to-user subscriptions in this release
|
||||
if (!ContentModel.TYPE_USER.equals(nodeService.getType(nodeRef)))
|
||||
{
|
||||
throw new IllegalArgumentException("Only user nodes supported!");
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.subscriptions;
|
||||
|
||||
import javax.transaction.Status;
|
||||
import javax.transaction.UserTransaction;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.query.PagingRequest;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.security.PersonService;
|
||||
import org.alfresco.service.cmr.subscriptions.PagingFollowingResults;
|
||||
import org.alfresco.service.cmr.subscriptions.PrivateSubscriptionListException;
|
||||
import org.alfresco.service.cmr.subscriptions.SubscriptionService;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.alfresco.util.ApplicationContextHelper;
|
||||
import org.alfresco.util.PropertyMap;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
public class SubscriptionServiceImplTest extends TestCase
|
||||
{
|
||||
public static final String USER_BOB = "bob";
|
||||
public static final String USER_TOM = "tom";
|
||||
public static final String USER_LISA = "lisa";
|
||||
|
||||
private UserTransaction txn;
|
||||
|
||||
protected ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
|
||||
protected TransactionService transactionService;
|
||||
protected SubscriptionService subscriptionService;
|
||||
protected PersonService personService;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
// Get the required services
|
||||
transactionService = (TransactionService) ctx.getBean("TransactionService");
|
||||
subscriptionService = (SubscriptionService) ctx.getBean("SubscriptionService");
|
||||
personService = (PersonService) ctx.getBean("PersonService");
|
||||
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getSystemUserName());
|
||||
|
||||
txn = transactionService.getNonPropagatingUserTransaction(false);
|
||||
txn.begin();
|
||||
|
||||
createPerson(USER_BOB);
|
||||
createPerson(USER_TOM);
|
||||
createPerson(USER_LISA);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception
|
||||
{
|
||||
deletePerson(USER_BOB);
|
||||
deletePerson(USER_TOM);
|
||||
deletePerson(USER_LISA);
|
||||
|
||||
if (txn != null)
|
||||
{
|
||||
if (txn.getStatus() == Status.STATUS_MARKED_ROLLBACK)
|
||||
{
|
||||
txn.rollback();
|
||||
} else
|
||||
{
|
||||
txn.commit();
|
||||
}
|
||||
txn = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected void deletePerson(String userId)
|
||||
{
|
||||
personService.deletePerson(userId);
|
||||
}
|
||||
|
||||
protected NodeRef createPerson(String userId)
|
||||
{
|
||||
deletePerson(userId);
|
||||
|
||||
PropertyMap properties = new PropertyMap(5);
|
||||
properties.put(ContentModel.PROP_USERNAME, userId);
|
||||
properties.put(ContentModel.PROP_FIRSTNAME, userId);
|
||||
properties.put(ContentModel.PROP_LASTNAME, "Test");
|
||||
properties.put(ContentModel.PROP_EMAIL, userId + "@email.com");
|
||||
|
||||
return personService.createPerson(properties);
|
||||
}
|
||||
|
||||
public void testFollow() throws Exception
|
||||
{
|
||||
String userId1 = USER_BOB;
|
||||
String userId2 = USER_TOM;
|
||||
String userId3 = USER_LISA;
|
||||
|
||||
// check follows first
|
||||
if (subscriptionService.follows(userId1, userId2))
|
||||
{
|
||||
subscriptionService.unfollow(userId1, userId2);
|
||||
}
|
||||
assertFalse(subscriptionService.follows(userId1, userId2));
|
||||
|
||||
// count the people user 1 is following
|
||||
int count = subscriptionService.getFollowingCount(userId1);
|
||||
assertTrue(count >= 0);
|
||||
|
||||
// user 1 follows user 2 -- twice (the second follow request should be
|
||||
// ignored)
|
||||
subscriptionService.follow(userId1, userId2);
|
||||
subscriptionService.follow(userId1, userId2);
|
||||
assertEquals(count + 1, subscriptionService.getFollowingCount(userId1));
|
||||
assertTrue(subscriptionService.follows(userId1, userId2));
|
||||
|
||||
// user 1 follows user 3
|
||||
subscriptionService.follow(userId1, userId3);
|
||||
assertEquals(count + 2, subscriptionService.getFollowingCount(userId1));
|
||||
assertTrue(subscriptionService.follows(userId1, userId3));
|
||||
|
||||
// get following list of user 1
|
||||
PagingFollowingResults following = subscriptionService.getFollowing(userId1, new PagingRequest(100000, null));
|
||||
assertNotNull(following);
|
||||
assertNotNull(following.getPage());
|
||||
assertTrue(following.getPage().contains(userId2));
|
||||
assertTrue(following.getPage().contains(userId3));
|
||||
|
||||
// count followers of user 2
|
||||
int followerCount = subscriptionService.getFollowersCount(userId2);
|
||||
assertTrue(followerCount > 0);
|
||||
|
||||
// get followers of user 2
|
||||
PagingFollowingResults followers = subscriptionService.getFollowers(userId2, new PagingRequest(100000, null));
|
||||
assertNotNull(followers);
|
||||
assertNotNull(followers.getPage());
|
||||
assertTrue(followers.getPage().contains(userId1));
|
||||
|
||||
// unfollow
|
||||
subscriptionService.unfollow(userId1, userId2);
|
||||
assertEquals(count + 1, subscriptionService.getFollowingCount(userId1));
|
||||
assertFalse(subscriptionService.follows(userId1, userId2));
|
||||
assertTrue(subscriptionService.follows(userId1, userId3));
|
||||
|
||||
subscriptionService.unfollow(userId1, userId3);
|
||||
assertEquals(count, subscriptionService.getFollowingCount(userId1));
|
||||
assertFalse(subscriptionService.follows(userId1, userId3));
|
||||
}
|
||||
|
||||
public void testDeletePerson() throws Exception
|
||||
{
|
||||
String userId1 = USER_BOB;
|
||||
String userId2 = "subscription-temp-user";
|
||||
|
||||
createPerson(userId2);
|
||||
|
||||
subscriptionService.follow(userId1, userId2);
|
||||
assertTrue(subscriptionService.follows(userId1, userId2));
|
||||
|
||||
deletePerson(userId2);
|
||||
|
||||
PagingFollowingResults following = subscriptionService.getFollowing(userId1, new PagingRequest(100000, null));
|
||||
assertNotNull(following);
|
||||
assertNotNull(following.getPage());
|
||||
assertFalse(following.getPage().contains(userId2));
|
||||
}
|
||||
|
||||
public void testPrivateList() throws Exception
|
||||
{
|
||||
final String userId1 = USER_BOB;
|
||||
final String userId2 = USER_TOM;
|
||||
|
||||
assertFalse(subscriptionService.isSubscriptionListPrivate(userId1));
|
||||
|
||||
subscriptionService.setSubscriptionListPrivate(userId1, false);
|
||||
assertFalse(subscriptionService.isSubscriptionListPrivate(userId1));
|
||||
|
||||
subscriptionService.setSubscriptionListPrivate(userId1, true);
|
||||
assertTrue(subscriptionService.isSubscriptionListPrivate(userId1));
|
||||
|
||||
subscriptionService.setSubscriptionListPrivate(userId1, false);
|
||||
assertFalse(subscriptionService.isSubscriptionListPrivate(userId1));
|
||||
|
||||
subscriptionService.setSubscriptionListPrivate(userId1, true);
|
||||
assertTrue(subscriptionService.isSubscriptionListPrivate(userId1));
|
||||
|
||||
subscriptionService.follow(userId1, userId2);
|
||||
|
||||
AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Object>()
|
||||
{
|
||||
@Override
|
||||
public Object doWork() throws Exception
|
||||
{
|
||||
assertNotNull(subscriptionService.getFollowing(userId1, new PagingRequest(100000, null)));
|
||||
return null;
|
||||
}
|
||||
}, userId1);
|
||||
|
||||
AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Object>()
|
||||
{
|
||||
@Override
|
||||
public Object doWork() throws Exception
|
||||
{
|
||||
assertNotNull(subscriptionService.getFollowing(userId1, new PagingRequest(100000, null)));
|
||||
return null;
|
||||
}
|
||||
}, AuthenticationUtil.getAdminUserName());
|
||||
|
||||
AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Object>()
|
||||
{
|
||||
@Override
|
||||
public Object doWork() throws Exception
|
||||
{
|
||||
try
|
||||
{
|
||||
subscriptionService.getFollowing(userId1, new PagingRequest(100000, null));
|
||||
fail("Expected PrivateSubscriptionListException!");
|
||||
} catch (PrivateSubscriptionListException psle)
|
||||
{
|
||||
// expected
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}, userId2);
|
||||
}
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.service.cmr.subscriptions;
|
||||
|
||||
import org.alfresco.query.PagingResults;
|
||||
|
||||
/**
|
||||
* Response object for follower or following paging requests.
|
||||
*
|
||||
* @author Florian Mueller
|
||||
* @since 4.0
|
||||
*/
|
||||
public interface PagingFollowingResults extends PagingResults<String>
|
||||
{
|
||||
|
||||
}
|
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.service.cmr.subscriptions;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.util.Pair;
|
||||
|
||||
public class PagingFollowingResultsImpl implements PagingFollowingResults
|
||||
{
|
||||
private List<String> page;
|
||||
private boolean hasMore;
|
||||
private Pair<Integer, Integer> totalCount;
|
||||
|
||||
public PagingFollowingResultsImpl(List<String> page, boolean hasMore, Integer total)
|
||||
{
|
||||
this.page = page;
|
||||
this.hasMore = hasMore;
|
||||
|
||||
if (total != null)
|
||||
{
|
||||
totalCount = new Pair<Integer, Integer>(total, total);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getPage()
|
||||
{
|
||||
return Collections.unmodifiableList(page);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasMoreItems()
|
||||
{
|
||||
return hasMore;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<Integer, Integer> getTotalResultCount()
|
||||
{
|
||||
return totalCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryExecutionId()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean permissionsApplied()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.service.cmr.subscriptions;
|
||||
|
||||
import org.alfresco.query.PagingResults;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
|
||||
/**
|
||||
* Response object for subscription paging requests.
|
||||
*
|
||||
* @author Florian Mueller
|
||||
* @since 4.0
|
||||
*/
|
||||
public interface PagingSubscriptionResults extends PagingResults<NodeRef>
|
||||
{
|
||||
|
||||
}
|
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.service.cmr.subscriptions;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.util.Pair;
|
||||
|
||||
public class PagingSubscriptionResultsImpl implements PagingSubscriptionResults
|
||||
{
|
||||
private List<NodeRef> page;
|
||||
private boolean hasMore;
|
||||
private Pair<Integer, Integer> totalCount;
|
||||
|
||||
public PagingSubscriptionResultsImpl(List<NodeRef> page, boolean hasMore, Integer total)
|
||||
{
|
||||
this.page = page;
|
||||
this.hasMore = hasMore;
|
||||
|
||||
if (total != null)
|
||||
{
|
||||
totalCount = new Pair<Integer, Integer>(total, total);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<NodeRef> getPage()
|
||||
{
|
||||
return Collections.unmodifiableList(page);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasMoreItems()
|
||||
{
|
||||
return hasMore;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<Integer, Integer> getTotalResultCount()
|
||||
{
|
||||
return totalCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryExecutionId()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean permissionsApplied()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.service.cmr.subscriptions;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
|
||||
/**
|
||||
* This exception is thrown if a subscription list is private and the accessing
|
||||
* user is not allowed to see it.
|
||||
*
|
||||
* @author Florian Mueller
|
||||
* @since 4.0
|
||||
*/
|
||||
public class PrivateSubscriptionListException extends AlfrescoRuntimeException
|
||||
{
|
||||
private static final long serialVersionUID = 6971869799749343887L;
|
||||
|
||||
public PrivateSubscriptionListException(String msg)
|
||||
{
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public PrivateSubscriptionListException(String msg, Throwable cause)
|
||||
{
|
||||
super(msg, cause);
|
||||
}
|
||||
}
|
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.service.cmr.subscriptions;
|
||||
|
||||
/**
|
||||
* Subscription types enum.
|
||||
*
|
||||
* @author Florian Mueller
|
||||
* @since 4.0
|
||||
*/
|
||||
public enum SubscriptionItemTypeEnum
|
||||
{
|
||||
USER("user");
|
||||
|
||||
private String value;
|
||||
|
||||
SubscriptionItemTypeEnum(String type)
|
||||
{
|
||||
value = type;
|
||||
}
|
||||
|
||||
public String getValue()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
public static SubscriptionItemTypeEnum fromValue(String v)
|
||||
{
|
||||
for (SubscriptionItemTypeEnum ste : SubscriptionItemTypeEnum.values())
|
||||
{
|
||||
if (ste.value.equals(v))
|
||||
{
|
||||
return ste;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException(v);
|
||||
}
|
||||
}
|
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.service.cmr.subscriptions;
|
||||
|
||||
import org.alfresco.query.PagingRequest;
|
||||
import org.alfresco.service.Auditable;
|
||||
import org.alfresco.service.NotAuditable;
|
||||
import org.alfresco.service.PublicService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
|
||||
/**
|
||||
* Subscription Service.
|
||||
*
|
||||
* @author Florian Mueller
|
||||
* @since 4.0
|
||||
*/
|
||||
@PublicService
|
||||
public interface SubscriptionService
|
||||
{
|
||||
// --- subscription ---
|
||||
|
||||
/**
|
||||
* Returns the nodes a user has subscribed to.
|
||||
*
|
||||
* @param userId
|
||||
* the id of the user
|
||||
* @param type
|
||||
* the type of the nodes
|
||||
* @param pagingRequest
|
||||
* paging details
|
||||
*
|
||||
* @throws PrivateSubscriptionListException
|
||||
* if the subscription list is private and the calling user is
|
||||
* not allowed to see it
|
||||
*/
|
||||
@NotAuditable
|
||||
PagingSubscriptionResults getSubscriptions(String userId, SubscriptionItemTypeEnum type, PagingRequest pagingRequest);
|
||||
|
||||
/**
|
||||
* Returns how many nodes the given user has subscribed to.
|
||||
*
|
||||
* @param userId
|
||||
* the id of the user
|
||||
* @param type
|
||||
* the type of the nodes
|
||||
*/
|
||||
@NotAuditable
|
||||
int getSubscriptionCount(String userId, SubscriptionItemTypeEnum type);
|
||||
|
||||
/**
|
||||
* Subscribes to a node.
|
||||
*
|
||||
* @param userId
|
||||
* id of the user
|
||||
* @param node
|
||||
* the node
|
||||
*/
|
||||
@Auditable(parameters = { "userId", "node" })
|
||||
void subscribe(String userId, NodeRef node);
|
||||
|
||||
/**
|
||||
* Unsubscribes from a node.
|
||||
*
|
||||
* @param userId
|
||||
* id of the user
|
||||
* @param node
|
||||
* the node
|
||||
*/
|
||||
@Auditable(parameters = { "userId", "node" })
|
||||
void unsubscribe(String userId, NodeRef node);
|
||||
|
||||
/**
|
||||
* Returns if the user has subscribed to the given node.
|
||||
*
|
||||
* @param userId
|
||||
* id of the user
|
||||
* @param node
|
||||
* the node
|
||||
*/
|
||||
@NotAuditable
|
||||
boolean hasSubscribed(String userId, NodeRef node);
|
||||
|
||||
// --- follow ---
|
||||
|
||||
/**
|
||||
* Returns a list of users that the given user follows.
|
||||
*
|
||||
* @param userId
|
||||
* id of the user
|
||||
* @param pagingRequest
|
||||
* paging details
|
||||
* @throws PrivateSubscriptionListException
|
||||
* if the subscription list is private and the calling user is
|
||||
* not allowed to see it
|
||||
*/
|
||||
@NotAuditable
|
||||
PagingFollowingResults getFollowing(String userId, PagingRequest pagingRequest);
|
||||
|
||||
/**
|
||||
* Returns a list of users that follow the given user.
|
||||
*
|
||||
* @param userId
|
||||
* id of the user
|
||||
* @param pagingRequest
|
||||
* paging details
|
||||
*/
|
||||
@NotAuditable
|
||||
PagingFollowingResults getFollowers(String userId, PagingRequest pagingRequest);
|
||||
|
||||
/**
|
||||
* Returns how many users the given user follows.
|
||||
*
|
||||
* @param userId
|
||||
* the id of the user
|
||||
* @param type
|
||||
* the type of the nodes
|
||||
*/
|
||||
@NotAuditable
|
||||
int getFollowingCount(String userId);
|
||||
|
||||
/**
|
||||
* Returns how many users follow the given user.
|
||||
*
|
||||
* @param userId
|
||||
* the id of the user
|
||||
* @param type
|
||||
* the type of the nodes
|
||||
*/
|
||||
@NotAuditable
|
||||
int getFollowersCount(String userId);
|
||||
|
||||
/**
|
||||
* Follows another
|
||||
*
|
||||
* @param userId
|
||||
* the id of the user
|
||||
* @param userToFollow
|
||||
* the id of the user to follow
|
||||
*/
|
||||
@Auditable(parameters = { "userId", "userToFollow" })
|
||||
void follow(String userId, String userToFollow);
|
||||
|
||||
@Auditable(parameters = { "userId", "userToUnfollow" })
|
||||
void unfollow(String userId, String userToUnfollow);
|
||||
|
||||
/**
|
||||
* Returns if the user follows to the given other user.
|
||||
*
|
||||
* @param userId
|
||||
* id of the user
|
||||
* @param userToFollow
|
||||
* the id of the other user
|
||||
*/
|
||||
@NotAuditable
|
||||
boolean follows(String userId, String userToFollow);
|
||||
|
||||
// --- privacy settings ---
|
||||
|
||||
/**
|
||||
* Sets or unsets the subscription list of the given user to private.
|
||||
*
|
||||
* @param userId
|
||||
* the id of the user
|
||||
* @param isPrivate
|
||||
* <code>true</code> - set list private,
|
||||
* <code>false<code> - set list public
|
||||
*
|
||||
*/
|
||||
@Auditable(parameters = { "userId", "isPrivate" })
|
||||
void setSubscriptionListPrivate(String userId, boolean isPrivate);
|
||||
|
||||
/**
|
||||
* Returns if the subscription list of the given user is set to private.
|
||||
*
|
||||
* @param userId
|
||||
* the id of the user
|
||||
*/
|
||||
@NotAuditable
|
||||
boolean isSubscriptionListPrivate(String userId);
|
||||
}
|
Reference in New Issue
Block a user