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/preference-service-context.xml"/>
|
||||||
<import resource="classpath:alfresco/swf-transform-context.xml"/>
|
<import resource="classpath:alfresco/swf-transform-context.xml"/>
|
||||||
<import resource="classpath:alfresco/form-services-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/cmis-api-context.xml" />
|
||||||
<import resource="classpath:alfresco/opencmis-context.xml" />
|
<import resource="classpath:alfresco/opencmis-context.xml" />
|
||||||
<import resource="classpath:alfresco/period-type-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-AclChangeSet" />
|
||||||
<ref bean="patch.db-V4.0-NodeAssoc-Ordering" />
|
<ref bean="patch.db-V4.0-NodeAssoc-Ordering" />
|
||||||
<ref bean="patch.db-V4.0-Node-Locale" />
|
<ref bean="patch.db-V4.0-Node-Locale" />
|
||||||
|
<ref bean="patch.db-V4.0-SubscriptionTables" />
|
||||||
</list>
|
</list>
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
@@ -41,6 +41,13 @@
|
|||||||
<property name="sqlSessionTemplate" ref="activitiesSqlSessionTemplate"/>
|
<property name="sqlSessionTemplate" ref="activitiesSqlSessionTemplate"/>
|
||||||
</bean>
|
</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">
|
<bean id="patchDAO" class="org.alfresco.util.bean.HierarchicalBeanLoader">
|
||||||
<property name="targetBeanName">
|
<property name="targetBeanName">
|
||||||
<value>patchDAO.#bean.dialect#</value>
|
<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="TestOne" type="org.alfresco.repo.domain.query.CannedQueryDAOTest$TestOneParams"/>
|
||||||
<typeAlias alias="Ids" type="org.alfresco.ibatis.IdsEntity"/>
|
<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>
|
</typeAliases>
|
||||||
|
|
||||||
<typeHandlers>
|
<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#/usage-insert-SqlMap.xml"/>
|
||||||
<mapper resource="alfresco/ibatis/#resource.dialect#/avm-common-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#/avm-insert-SqlMap.xml"/>
|
||||||
|
<mapper resource="alfresco/ibatis/#resource.dialect#/subscriptions-common-SqlMap.xml"/>
|
||||||
<!-- Canned queries -->
|
<!-- Canned queries -->
|
||||||
<mapper resource="alfresco/ibatis/#resource.dialect#/query-test-common-SqlMap.xml"/>
|
<mapper resource="alfresco/ibatis/#resource.dialect#/query-test-common-SqlMap.xml"/>
|
||||||
<mapper resource="alfresco/ibatis/#resource.dialect#/query-usages-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>
|
<type>d:boolean</type>
|
||||||
</property>
|
</property>
|
||||||
|
|
||||||
|
<property name="cm:subscriptionsPrivate">
|
||||||
|
<type>d:boolean</type>
|
||||||
|
</property>
|
||||||
|
|
||||||
<!-- system maintained / protected values -->
|
<!-- system maintained / protected values -->
|
||||||
|
|
||||||
<property name="cm:emailFeedId">
|
<property name="cm:emailFeedId">
|
||||||
|
@@ -2871,4 +2871,15 @@
|
|||||||
</property>
|
</property>
|
||||||
</bean>
|
</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>
|
</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,7 +86,8 @@
|
|||||||
<property name="nodeService" ref="NodeService"/>
|
<property name="nodeService" ref="NodeService"/>
|
||||||
<property name="contentService" ref="ContentService"/>
|
<property name="contentService" ref="ContentService"/>
|
||||||
<property name="permissionService" ref="PermissionService"/>
|
<property name="permissionService" ref="PermissionService"/>
|
||||||
|
<property name="subscriptionService" ref="SubscriptionService"/>
|
||||||
|
|
||||||
<property name="templateSearchPaths">
|
<property name="templateSearchPaths">
|
||||||
<list>
|
<list>
|
||||||
<value>alfresco/extension/templates/activities</value>
|
<value>alfresco/extension/templates/activities</value>
|
||||||
|
@@ -235,7 +235,7 @@ public class ActivityPostServiceImpl implements ActivityPostService
|
|||||||
|
|
||||||
private String getCurrentUser()
|
private String getCurrentUser()
|
||||||
{
|
{
|
||||||
String userId = AuthenticationUtil.getFullyAuthenticatedUser();
|
String userId = AuthenticationUtil.getRunAsUser();
|
||||||
if ((userId != null) && (! userId.equals(AuthenticationUtil.SYSTEM_USER_NAME)) && (! userNamesAreCaseSensitive))
|
if ((userId != null) && (! userId.equals(AuthenticationUtil.SYSTEM_USER_NAME)) && (! userNamesAreCaseSensitive))
|
||||||
{
|
{
|
||||||
// user names are not case-sensitive
|
// user names are not case-sensitive
|
||||||
|
@@ -19,12 +19,12 @@
|
|||||||
package org.alfresco.repo.activities;
|
package org.alfresco.repo.activities;
|
||||||
|
|
||||||
public interface ActivityType
|
public interface ActivityType
|
||||||
{
|
{
|
||||||
// pre-defined alfresco activity types
|
// pre-defined alfresco activity types
|
||||||
|
|
||||||
// generic fallback (if specific template is missing)
|
// generic fallback (if specific template is missing)
|
||||||
public final String GENERIC_FALLBACK = "org.alfresco.generic";
|
public final String GENERIC_FALLBACK = "org.alfresco.generic";
|
||||||
|
|
||||||
// site membership
|
// site membership
|
||||||
public final String SITE_USER_JOINED = "org.alfresco.site.user-joined";
|
public final String SITE_USER_JOINED = "org.alfresco.site.user-joined";
|
||||||
public final String SITE_USER_REMOVED = "org.alfresco.site.user-left";
|
public final String SITE_USER_REMOVED = "org.alfresco.site.user-left";
|
||||||
@@ -32,4 +32,6 @@ public interface ActivityType
|
|||||||
public final String SITE_GROUP_ADDED = "org.alfresco.site.group-added";
|
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_REMOVED = "org.alfresco.site.group-removed";
|
||||||
public final String SITE_GROUP_ROLE_UPDATE = "org.alfresco.site.group-role-changed";
|
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";
|
||||||
}
|
}
|
||||||
|
@@ -63,6 +63,7 @@ import freemarker.template.TemplateException;
|
|||||||
public abstract class FeedTaskProcessor
|
public abstract class FeedTaskProcessor
|
||||||
{
|
{
|
||||||
private static final Log logger = LogFactory.getLog(FeedTaskProcessor.class);
|
private static final Log logger = LogFactory.getLog(FeedTaskProcessor.class);
|
||||||
|
|
||||||
|
|
||||||
public static final String FEED_FORMAT_JSON = "json";
|
public static final String FEED_FORMAT_JSON = "json";
|
||||||
public static final String FEED_FORMAT_ATOMENTRY = "atomentry";
|
public static final String FEED_FORMAT_ATOMENTRY = "atomentry";
|
||||||
@@ -117,6 +118,7 @@ public abstract class FeedTaskProcessor
|
|||||||
|
|
||||||
Map<String, List<String>> activityTemplates = new HashMap<String, List<String>>(10);
|
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>> 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, List<FeedControlEntity>> userFeedControls = new HashMap<String, List<FeedControlEntity>>();
|
||||||
Map<String, Template> templateCache = new TreeMap<String, Template>();
|
Map<String, Template> templateCache = new TreeMap<String, Template>();
|
||||||
|
|
||||||
@@ -207,15 +209,6 @@ public abstract class FeedTaskProcessor
|
|||||||
|
|
||||||
String thisSite = (activityPost.getSiteNetwork() != null ? activityPost.getSiteNetwork() : "");
|
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_TYPE, activityPost.getActivityType());
|
||||||
model.put(ActivityFeedEntity.KEY_ACTIVITY_FEED_SITE, thisSite);
|
model.put(ActivityFeedEntity.KEY_ACTIVITY_FEED_SITE, thisSite);
|
||||||
model.put("userId", activityPost.getUserId());
|
model.put("userId", activityPost.getUserId());
|
||||||
@@ -224,49 +217,84 @@ public abstract class FeedTaskProcessor
|
|||||||
model.put("xmldate", new ISO8601DateFormatMethod());
|
model.put("xmldate", new ISO8601DateFormatMethod());
|
||||||
model.put("repoEndPoint", ctx.getRepoEndPoint());
|
model.put("repoEndPoint", ctx.getRepoEndPoint());
|
||||||
|
|
||||||
// Get the members of this site - save hammering the repository by reusing cached site members
|
// Recipients of this post
|
||||||
Set<String> connectedUsers = siteConnectedUsers.get(thisSite);
|
Set<String> recipients = new HashSet<String>();
|
||||||
if (connectedUsers == null)
|
|
||||||
{
|
// 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
|
try
|
||||||
{
|
{
|
||||||
// Repository callback to get site members
|
followerUsers = getFollowers(activityPost.getUserId());
|
||||||
connectedUsers = getSiteMembers(ctx, thisSite);
|
|
||||||
connectedUsers.add(""); // add empty posting userid - to represent site feed !
|
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
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);
|
updatePostStatus(activityPost.getId(), ActivityPostEntity.STATUS.ERROR);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache them for future use in this same invocation
|
followers.put(activityPost.getUserId(), followerUsers);
|
||||||
siteConnectedUsers.put(thisSite, connectedUsers);
|
|
||||||
}
|
}
|
||||||
|
recipients.addAll(followerUsers);
|
||||||
|
|
||||||
|
if(recipients.size() == 0) {
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("No recipients for activity post " + activityPost.getId() + ".");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
startTransaction();
|
startTransaction();
|
||||||
|
|
||||||
if (logger.isTraceEnabled())
|
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;
|
int excludedConnections = 0;
|
||||||
|
|
||||||
for (String connectedUser : connectedUsers)
|
for (String recipient : recipients)
|
||||||
{
|
{
|
||||||
List<FeedControlEntity> feedControls = null;
|
List<FeedControlEntity> feedControls = null;
|
||||||
if (! connectedUser.equals(""))
|
if (! recipient.equals(""))
|
||||||
{
|
{
|
||||||
// Get user's feed controls
|
// Get user's feed controls
|
||||||
feedControls = userFeedControls.get(connectedUser);
|
feedControls = userFeedControls.get(recipient);
|
||||||
if (feedControls == null)
|
if (feedControls == null)
|
||||||
{
|
{
|
||||||
feedControls = getFeedControls(connectedUser);
|
feedControls = getFeedControls(recipient);
|
||||||
userFeedControls.put(connectedUser, feedControls);
|
userFeedControls.put(recipient, feedControls);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,7 +306,7 @@ public abstract class FeedTaskProcessor
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// read permission check
|
// read permission check
|
||||||
if (! canRead(ctx, connectedUser, model))
|
if (! canRead(ctx, recipient, model))
|
||||||
{
|
{
|
||||||
excludedConnections++;
|
excludedConnections++;
|
||||||
continue;
|
continue;
|
||||||
@@ -306,7 +334,7 @@ public abstract class FeedTaskProcessor
|
|||||||
ActivityFeedEntity feed = new ActivityFeedEntity();
|
ActivityFeedEntity feed = new ActivityFeedEntity();
|
||||||
|
|
||||||
// Generate activity feed summary
|
// Generate activity feed summary
|
||||||
feed.setFeedUserId(connectedUser);
|
feed.setFeedUserId(recipient);
|
||||||
feed.setPostUserId(postingUserId);
|
feed.setPostUserId(postingUserId);
|
||||||
feed.setActivityType(activityType);
|
feed.setActivityType(activityType);
|
||||||
|
|
||||||
@@ -356,7 +384,7 @@ public abstract class FeedTaskProcessor
|
|||||||
|
|
||||||
if (logger.isDebugEnabled())
|
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
|
finally
|
||||||
@@ -381,24 +409,23 @@ public abstract class FeedTaskProcessor
|
|||||||
logger.info(sb.toString());
|
logger.info(sb.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void startTransaction() throws SQLException;
|
public abstract void startTransaction() throws SQLException;
|
||||||
|
|
||||||
public abstract void commitTransaction() throws SQLException;
|
public abstract void commitTransaction() throws SQLException;
|
||||||
|
|
||||||
public abstract void rollbackTransaction() throws SQLException;
|
public abstract void rollbackTransaction() throws SQLException;
|
||||||
|
|
||||||
public abstract void endTransaction() throws SQLException;
|
public abstract void endTransaction() throws SQLException;
|
||||||
|
|
||||||
public abstract List<ActivityPostEntity> selectPosts(ActivityPostEntity selector) throws SQLException;
|
public abstract List<ActivityPostEntity> selectPosts(ActivityPostEntity selector) throws SQLException;
|
||||||
|
|
||||||
public abstract List<FeedControlEntity> selectUserFeedControls(String userId) throws SQLException;
|
public abstract List<FeedControlEntity> selectUserFeedControls(String userId) throws SQLException;
|
||||||
|
|
||||||
public abstract long insertFeedEntry(ActivityFeedEntity feed) throws SQLException;
|
public abstract long insertFeedEntry(ActivityFeedEntity feed) throws SQLException;
|
||||||
|
|
||||||
public abstract int updatePostStatus(long id, ActivityPostEntity.STATUS status) throws SQLException;
|
public abstract int updatePostStatus(long id, ActivityPostEntity.STATUS status) throws SQLException;
|
||||||
|
|
||||||
|
|
||||||
protected String callWebScript(String urlString, String ticket) throws MalformedURLException, URISyntaxException, IOException
|
protected String callWebScript(String urlString, String ticket) throws MalformedURLException, URISyntaxException, IOException
|
||||||
{
|
{
|
||||||
URL url = new URL(urlString);
|
URL url = new URL(urlString);
|
||||||
@@ -450,7 +477,7 @@ public abstract class FeedTaskProcessor
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Set<String> getSiteMembers(RepoCtx ctx, String siteId) throws Exception
|
protected Set<String> getSiteMembers(RepoCtx ctx, String siteId) throws Exception
|
||||||
{
|
{
|
||||||
Set<String> members = new HashSet<String>();
|
Set<String> members = new HashSet<String>();
|
||||||
@@ -481,12 +508,14 @@ public abstract class FeedTaskProcessor
|
|||||||
|
|
||||||
return members;
|
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
|
protected boolean canRead(RepoCtx ctx, final String connectedUser, Map<String, Object> model) throws Exception
|
||||||
{
|
{
|
||||||
throw new UnsupportedOperationException("FeedTaskProcessor: Remote callback for 'canRead' not implemented");
|
throw new UnsupportedOperationException("FeedTaskProcessor: Remote callback for 'canRead' not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Map<String, List<String>> getActivityTypeTemplates(String repoEndPoint, String ticket, String subPath) throws Exception
|
protected Map<String, List<String>> getActivityTypeTemplates(String repoEndPoint, String ticket, String subPath) throws Exception
|
||||||
{
|
{
|
||||||
StringBuffer sbUrl = new StringBuffer();
|
StringBuffer sbUrl = new StringBuffer();
|
||||||
@@ -516,7 +545,7 @@ public abstract class FeedTaskProcessor
|
|||||||
|
|
||||||
return getActivityTemplates(allTemplateNames);
|
return getActivityTemplates(allTemplateNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Map<String, List<String>> getActivityTemplates(List<String> allTemplateNames)
|
protected Map<String, List<String>> getActivityTemplates(List<String> allTemplateNames)
|
||||||
{
|
{
|
||||||
Map<String, List<String>> activityTemplates = new HashMap<String, List<String>>(10);
|
Map<String, List<String>> activityTemplates = new HashMap<String, List<String>>(10);
|
||||||
@@ -557,21 +586,21 @@ public abstract class FeedTaskProcessor
|
|||||||
|
|
||||||
return activityTemplates;
|
return activityTemplates;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Configuration getFreemarkerConfiguration(RepoCtx ctx)
|
protected Configuration getFreemarkerConfiguration(RepoCtx ctx)
|
||||||
{
|
{
|
||||||
Configuration cfg = new Configuration();
|
Configuration cfg = new Configuration();
|
||||||
cfg.setObjectWrapper(new DefaultObjectWrapper());
|
cfg.setObjectWrapper(new DefaultObjectWrapper());
|
||||||
|
|
||||||
// custom template loader
|
// custom template loader
|
||||||
cfg.setTemplateLoader(new TemplateWebScriptLoader(ctx.getRepoEndPoint(), ctx.getTicket()));
|
cfg.setTemplateLoader(new TemplateWebScriptLoader(ctx.getRepoEndPoint(), ctx.getTicket()));
|
||||||
|
|
||||||
// TODO review i18n
|
// TODO review i18n
|
||||||
cfg.setLocalizedLookup(false);
|
cfg.setLocalizedLookup(false);
|
||||||
|
|
||||||
return cfg;
|
return cfg;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String processFreemarker(Map<String, Template> templateCache, String fmTemplate, Configuration cfg, Map<String, Object> model) throws IOException, TemplateException, Exception
|
protected String processFreemarker(Map<String, Template> templateCache, String fmTemplate, Configuration cfg, Map<String, Object> model) throws IOException, TemplateException, Exception
|
||||||
{
|
{
|
||||||
// Save on lots of modification date checking by caching templates locally
|
// Save on lots of modification date checking by caching templates locally
|
||||||
@@ -587,12 +616,12 @@ public abstract class FeedTaskProcessor
|
|||||||
|
|
||||||
return textWriter.toString();
|
return textWriter.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected List<FeedControlEntity> getFeedControls(String connectedUser) throws SQLException
|
protected List<FeedControlEntity> getFeedControls(String connectedUser) throws SQLException
|
||||||
{
|
{
|
||||||
return selectUserFeedControls(connectedUser);
|
return selectUserFeedControls(connectedUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean acceptActivity(ActivityPostEntity activityPost, List<FeedControlEntity> feedControls)
|
protected boolean acceptActivity(ActivityPostEntity activityPost, List<FeedControlEntity> feedControls)
|
||||||
{
|
{
|
||||||
if (feedControls == null)
|
if (feedControls == null)
|
||||||
@@ -632,7 +661,7 @@ public abstract class FeedTaskProcessor
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void addMissingFormats(String activityType, List<String> fmTemplates, List<String> templatesToAdd)
|
protected void addMissingFormats(String activityType, List<String> fmTemplates, List<String> templatesToAdd)
|
||||||
{
|
{
|
||||||
for (String templateToAdd : templatesToAdd)
|
for (String templateToAdd : templatesToAdd)
|
||||||
@@ -666,7 +695,7 @@ public abstract class FeedTaskProcessor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getTemplateSubPath(String activityType)
|
protected String getTemplateSubPath(String activityType)
|
||||||
{
|
{
|
||||||
return (! activityType.startsWith("/") ? "/" : "") + activityType.replace(".", "/");
|
return (! activityType.startsWith("/") ? "/" : "") + activityType.replace(".", "/");
|
||||||
|
@@ -26,6 +26,7 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.alfresco.query.PagingRequest;
|
||||||
import org.alfresco.repo.activities.feed.FeedTaskProcessor;
|
import org.alfresco.repo.activities.feed.FeedTaskProcessor;
|
||||||
import org.alfresco.repo.activities.feed.RepoCtx;
|
import org.alfresco.repo.activities.feed.RepoCtx;
|
||||||
import org.alfresco.repo.activities.post.lookup.PostLookup;
|
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.AuthorityType;
|
||||||
import org.alfresco.service.cmr.security.PermissionService;
|
import org.alfresco.service.cmr.security.PermissionService;
|
||||||
import org.alfresco.service.cmr.site.SiteService;
|
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.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.springframework.beans.BeansException;
|
import org.springframework.beans.BeansException;
|
||||||
@@ -64,117 +67,123 @@ import freemarker.template.DefaultObjectWrapper;
|
|||||||
public class LocalFeedTaskProcessor extends FeedTaskProcessor implements ApplicationContextAware
|
public class LocalFeedTaskProcessor extends FeedTaskProcessor implements ApplicationContextAware
|
||||||
{
|
{
|
||||||
private static final Log logger = LogFactory.getLog(LocalFeedTaskProcessor.class);
|
private static final Log logger = LogFactory.getLog(LocalFeedTaskProcessor.class);
|
||||||
|
|
||||||
private ActivityPostDAO postDAO;
|
private ActivityPostDAO postDAO;
|
||||||
private ActivityFeedDAO feedDAO;
|
private ActivityFeedDAO feedDAO;
|
||||||
private FeedControlDAO feedControlDAO;
|
private FeedControlDAO feedControlDAO;
|
||||||
|
|
||||||
// can call locally (instead of remote repo callback)
|
// can call locally (instead of remote repo callback)
|
||||||
private SiteService siteService;
|
private SiteService siteService;
|
||||||
private NodeService nodeService;
|
private NodeService nodeService;
|
||||||
private ContentService contentService;
|
private ContentService contentService;
|
||||||
private PermissionService permissionService;
|
private PermissionService permissionService;
|
||||||
|
private SubscriptionService subscriptionService;
|
||||||
|
|
||||||
private String defaultEncoding;
|
private String defaultEncoding;
|
||||||
private List<String> templateSearchPaths;
|
private List<String> templateSearchPaths;
|
||||||
private boolean useRemoteCallbacks;
|
private boolean useRemoteCallbacks;
|
||||||
private ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
|
private ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
|
||||||
|
|
||||||
public void setPostDAO(ActivityPostDAO postDAO)
|
public void setPostDAO(ActivityPostDAO postDAO)
|
||||||
{
|
{
|
||||||
this.postDAO = postDAO;
|
this.postDAO = postDAO;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFeedDAO(ActivityFeedDAO feedDAO)
|
public void setFeedDAO(ActivityFeedDAO feedDAO)
|
||||||
{
|
{
|
||||||
this.feedDAO = feedDAO;
|
this.feedDAO = feedDAO;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFeedControlDAO(FeedControlDAO feedControlDAO)
|
public void setFeedControlDAO(FeedControlDAO feedControlDAO)
|
||||||
{
|
{
|
||||||
this.feedControlDAO = feedControlDAO;
|
this.feedControlDAO = feedControlDAO;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSiteService(SiteService siteService)
|
public void setSiteService(SiteService siteService)
|
||||||
{
|
{
|
||||||
this.siteService = siteService;
|
this.siteService = siteService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNodeService(NodeService nodeService)
|
public void setNodeService(NodeService nodeService)
|
||||||
{
|
{
|
||||||
this.nodeService = nodeService;
|
this.nodeService = nodeService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setContentService(ContentService contentService)
|
public void setContentService(ContentService contentService)
|
||||||
{
|
{
|
||||||
this.contentService = contentService;
|
this.contentService = contentService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPermissionService(PermissionService permissionService)
|
public void setPermissionService(PermissionService permissionService)
|
||||||
{
|
{
|
||||||
this.permissionService = permissionService;
|
this.permissionService = permissionService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setSubscriptionService(SubscriptionService subscriptionService)
|
||||||
|
{
|
||||||
|
this.subscriptionService = subscriptionService;
|
||||||
|
}
|
||||||
|
|
||||||
public void setDefaultEncoding(String defaultEncoding)
|
public void setDefaultEncoding(String defaultEncoding)
|
||||||
{
|
{
|
||||||
this.defaultEncoding = defaultEncoding;
|
this.defaultEncoding = defaultEncoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTemplateSearchPaths(List<String> templateSearchPaths)
|
public void setTemplateSearchPaths(List<String> templateSearchPaths)
|
||||||
{
|
{
|
||||||
this.templateSearchPaths = templateSearchPaths;
|
this.templateSearchPaths = templateSearchPaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUseRemoteCallbacks(boolean useRemoteCallbacks)
|
public void setUseRemoteCallbacks(boolean useRemoteCallbacks)
|
||||||
{
|
{
|
||||||
this.useRemoteCallbacks = useRemoteCallbacks;
|
this.useRemoteCallbacks = useRemoteCallbacks;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
|
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
|
||||||
{
|
{
|
||||||
this.resolver = applicationContext;
|
this.resolver = applicationContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startTransaction() throws SQLException
|
public void startTransaction() throws SQLException
|
||||||
{
|
{
|
||||||
// NOOP
|
// NOOP
|
||||||
}
|
}
|
||||||
|
|
||||||
public void commitTransaction() throws SQLException
|
public void commitTransaction() throws SQLException
|
||||||
{
|
{
|
||||||
// NOOP
|
// NOOP
|
||||||
}
|
}
|
||||||
|
|
||||||
public void rollbackTransaction() throws SQLException
|
public void rollbackTransaction() throws SQLException
|
||||||
{
|
{
|
||||||
// NOOP
|
// NOOP
|
||||||
}
|
}
|
||||||
|
|
||||||
public void endTransaction() throws SQLException
|
public void endTransaction() throws SQLException
|
||||||
{
|
{
|
||||||
// NOOP
|
// NOOP
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ActivityPostEntity> selectPosts(ActivityPostEntity selector) throws SQLException
|
public List<ActivityPostEntity> selectPosts(ActivityPostEntity selector) throws SQLException
|
||||||
{
|
{
|
||||||
return postDAO.selectPosts(selector);
|
return postDAO.selectPosts(selector);
|
||||||
}
|
}
|
||||||
|
|
||||||
public long insertFeedEntry(ActivityFeedEntity feed) throws SQLException
|
public long insertFeedEntry(ActivityFeedEntity feed) throws SQLException
|
||||||
{
|
{
|
||||||
return feedDAO.insertFeedEntry(feed);
|
return feedDAO.insertFeedEntry(feed);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int updatePostStatus(long id, ActivityPostEntity.STATUS status) throws SQLException
|
public int updatePostStatus(long id, ActivityPostEntity.STATUS status) throws SQLException
|
||||||
{
|
{
|
||||||
return postDAO.updatePostStatus(id, status);
|
return postDAO.updatePostStatus(id, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<FeedControlEntity> selectUserFeedControls(String userId) throws SQLException
|
public List<FeedControlEntity> selectUserFeedControls(String userId) throws SQLException
|
||||||
{
|
{
|
||||||
return feedControlDAO.selectFeedControls(userId);
|
return feedControlDAO.selectFeedControls(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Set<String> getSiteMembers(final RepoCtx ctx, final String siteId) throws Exception
|
protected Set<String> getSiteMembers(final RepoCtx ctx, final String siteId) throws Exception
|
||||||
{
|
{
|
||||||
@@ -182,7 +191,7 @@ public class LocalFeedTaskProcessor extends FeedTaskProcessor implements Applica
|
|||||||
{
|
{
|
||||||
// as per 3.0, 3.1
|
// as per 3.0, 3.1
|
||||||
return super.getSiteMembers(ctx, siteId);
|
return super.getSiteMembers(ctx, siteId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// optimise for non-remote implementation - override remote repo callback (to "List Site Memberships" web script) with embedded call
|
// optimise for non-remote implementation - override remote repo callback (to "List Site Memberships" web script) with embedded call
|
||||||
@@ -194,12 +203,12 @@ public class LocalFeedTaskProcessor extends FeedTaskProcessor implements Applica
|
|||||||
if ((siteId != null) && (siteId.length() != 0))
|
if ((siteId != null) && (siteId.length() != 0))
|
||||||
{
|
{
|
||||||
Map<String, String> mapResult = siteService.listMembers(siteId, null, null, 0, true);
|
Map<String, String> mapResult = siteService.listMembers(siteId, null, null, 0, true);
|
||||||
|
|
||||||
if ((mapResult != null) && (mapResult.size() != 0))
|
if ((mapResult != null) && (mapResult.size() != 0))
|
||||||
{
|
{
|
||||||
for (String userName : mapResult.keySet())
|
for (String userName : mapResult.keySet())
|
||||||
{
|
{
|
||||||
if (! ctx.isUserNamesAreCaseSensitive())
|
if (!ctx.isUserNamesAreCaseSensitive())
|
||||||
{
|
{
|
||||||
userName = userName.toLowerCase();
|
userName = userName.toLowerCase();
|
||||||
}
|
}
|
||||||
@@ -207,13 +216,13 @@ public class LocalFeedTaskProcessor extends FeedTaskProcessor implements Applica
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return members;
|
return members;
|
||||||
}
|
}
|
||||||
}, AuthenticationUtil.getSystemUserName());
|
}, AuthenticationUtil.getSystemUserName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean canRead(RepoCtx ctx, final String connectedUser, Map<String, Object> model) throws Exception
|
protected boolean canRead(RepoCtx ctx, final String connectedUser, Map<String, Object> model) throws Exception
|
||||||
{
|
{
|
||||||
if (useRemoteCallbacks)
|
if (useRemoteCallbacks)
|
||||||
@@ -228,17 +237,17 @@ public class LocalFeedTaskProcessor extends FeedTaskProcessor implements Applica
|
|||||||
// if permission service not configured then fallback (ie. no read permission check)
|
// if permission service not configured then fallback (ie. no read permission check)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
String nodeRefStr = (String)model.get(PostLookup.JSON_NODEREF);
|
String nodeRefStr = (String) model.get(PostLookup.JSON_NODEREF);
|
||||||
if (nodeRefStr == null)
|
if (nodeRefStr == null)
|
||||||
{
|
{
|
||||||
nodeRefStr = (String)model.get(PostLookup.JSON_NODEREF_PARENT);
|
nodeRefStr = (String) model.get(PostLookup.JSON_NODEREF_PARENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nodeRefStr != null)
|
if (nodeRefStr != null)
|
||||||
{
|
{
|
||||||
final NodeRef nodeRef = new NodeRef(nodeRefStr);
|
final NodeRef nodeRef = new NodeRef(nodeRefStr);
|
||||||
|
|
||||||
return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Boolean>()
|
return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Boolean>()
|
||||||
{
|
{
|
||||||
public Boolean doWork() throws Exception
|
public Boolean doWork() throws Exception
|
||||||
@@ -247,16 +256,16 @@ public class LocalFeedTaskProcessor extends FeedTaskProcessor implements Applica
|
|||||||
}
|
}
|
||||||
}, AuthenticationUtil.getSystemUserName());
|
}, AuthenticationUtil.getSystemUserName());
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean canReadImpl(final String connectedUser, final NodeRef nodeRef) throws Exception
|
private boolean canReadImpl(final String connectedUser, final NodeRef nodeRef) throws Exception
|
||||||
{
|
{
|
||||||
// check for read permission
|
// check for read permission
|
||||||
long start = System.currentTimeMillis();
|
long start = System.currentTimeMillis();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// note: deleted node does not exist (hence no permission, although default permission check would return true which is problematic)
|
// note: deleted node does not exist (hence no permission, although default permission check would return true which is problematic)
|
||||||
@@ -264,34 +273,34 @@ public class LocalFeedTaskProcessor extends FeedTaskProcessor implements Applica
|
|||||||
if (nodeService.exists(nodeRef))
|
if (nodeService.exists(nodeRef))
|
||||||
{
|
{
|
||||||
checkNodeRef = nodeRef;
|
checkNodeRef = nodeRef;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// TODO: require ghosting - this is temp workaround (we should not rely on archive - may be permanently deleted, ie. not archived or already purged)
|
// 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());
|
NodeRef archiveNodeRef = new NodeRef(StoreRef.STORE_REF_ARCHIVE_SPACESSTORE, nodeRef.getId());
|
||||||
if (! nodeService.exists(archiveNodeRef))
|
if (!nodeService.exists(archiveNodeRef))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
checkNodeRef = archiveNodeRef;
|
checkNodeRef = archiveNodeRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connectedUser.equals(""))
|
if (connectedUser.equals(""))
|
||||||
{
|
{
|
||||||
// site feed (public site)
|
// site feed (public site)
|
||||||
Set<AccessPermission> perms = permissionService.getAllSetPermissions(checkNodeRef);
|
Set<AccessPermission> perms = permissionService.getAllSetPermissions(checkNodeRef);
|
||||||
for (AccessPermission perm : perms)
|
for (AccessPermission perm : perms)
|
||||||
{
|
{
|
||||||
if (perm.getAuthority().equals(PermissionService.ALL_AUTHORITIES) &&
|
if (perm.getAuthority().equals(PermissionService.ALL_AUTHORITIES) &&
|
||||||
perm.getAuthorityType().equals(AuthorityType.EVERYONE) &&
|
perm.getAuthorityType().equals(AuthorityType.EVERYONE) &&
|
||||||
perm.getPermission().equals(PermissionService.READ_PERMISSIONS) &&
|
perm.getPermission().equals(PermissionService.READ_PERMISSIONS) &&
|
||||||
perm.getAccessStatus().equals(AccessStatus.ALLOWED))
|
perm.getAccessStatus().equals(AccessStatus.ALLOWED))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// user feed
|
// user feed
|
||||||
@@ -308,11 +317,11 @@ public class LocalFeedTaskProcessor extends FeedTaskProcessor implements Applica
|
|||||||
{
|
{
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
{
|
{
|
||||||
logger.debug("canRead: " + nodeRef + " in "+(System.currentTimeMillis()-start)+" msecs");
|
logger.debug("canRead: " + nodeRef + " in " + (System.currentTimeMillis() - start) + " msecs");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Map<String, List<String>> getActivityTypeTemplates(String repoEndPoint, String ticket, String subPath) throws Exception
|
protected Map<String, List<String>> getActivityTypeTemplates(String repoEndPoint, String ticket, String subPath) throws Exception
|
||||||
{
|
{
|
||||||
@@ -320,32 +329,32 @@ public class LocalFeedTaskProcessor extends FeedTaskProcessor implements Applica
|
|||||||
{
|
{
|
||||||
// as per 3.0, 3.1
|
// as per 3.0, 3.1
|
||||||
return super.getActivityTypeTemplates(repoEndPoint, ticket, subPath);
|
return super.getActivityTypeTemplates(repoEndPoint, ticket, subPath);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// optimisation - override remote repo callback (to "Activities Templates" web script) with local/embedded call
|
// optimisation - override remote repo callback (to "Activities Templates" web script) with local/embedded call
|
||||||
|
|
||||||
String path = "/";
|
String path = "/";
|
||||||
String templatePattern = "*.ftl";
|
String templatePattern = "*.ftl";
|
||||||
|
|
||||||
if ((subPath != null) && (subPath.length() > 0))
|
if ((subPath != null) && (subPath.length() > 0))
|
||||||
{
|
{
|
||||||
subPath = subPath + "*";
|
subPath = subPath + "*";
|
||||||
|
|
||||||
int idx = subPath.lastIndexOf("/");
|
int idx = subPath.lastIndexOf("/");
|
||||||
if (idx != -1)
|
if (idx != -1)
|
||||||
{
|
{
|
||||||
path = subPath.substring(0, idx);
|
path = subPath.substring(0, idx);
|
||||||
templatePattern = subPath.substring(idx+1) + ".ftl";
|
templatePattern = subPath.substring(idx + 1) + ".ftl";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> allTemplateNames = getDocumentPaths(path, false, templatePattern);
|
List<String> allTemplateNames = getDocumentPaths(path, false, templatePattern);
|
||||||
|
|
||||||
return getActivityTemplates(allTemplateNames);
|
return getActivityTemplates(allTemplateNames);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Configuration getFreemarkerConfiguration(RepoCtx ctx)
|
protected Configuration getFreemarkerConfiguration(RepoCtx ctx)
|
||||||
{
|
{
|
||||||
@@ -353,21 +362,21 @@ public class LocalFeedTaskProcessor extends FeedTaskProcessor implements Applica
|
|||||||
{
|
{
|
||||||
// as per 3.0, 3.1
|
// as per 3.0, 3.1
|
||||||
return super.getFreemarkerConfiguration(ctx);
|
return super.getFreemarkerConfiguration(ctx);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Configuration cfg = new Configuration();
|
Configuration cfg = new Configuration();
|
||||||
cfg.setObjectWrapper(new DefaultObjectWrapper());
|
cfg.setObjectWrapper(new DefaultObjectWrapper());
|
||||||
|
|
||||||
cfg.setTemplateLoader(new ClassPathRepoTemplateLoader(nodeService, contentService, defaultEncoding));
|
cfg.setTemplateLoader(new ClassPathRepoTemplateLoader(nodeService, contentService, defaultEncoding));
|
||||||
|
|
||||||
// TODO review i18n
|
// TODO review i18n
|
||||||
cfg.setLocalizedLookup(false);
|
cfg.setLocalizedLookup(false);
|
||||||
|
|
||||||
return cfg;
|
return cfg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper to get template document paths
|
// Helper to get template document paths
|
||||||
private List<String> getDocumentPaths(String path, boolean includeSubPaths, String documentPattern)
|
private List<String> getDocumentPaths(String path, boolean includeSubPaths, String documentPattern)
|
||||||
{
|
{
|
||||||
@@ -375,24 +384,24 @@ public class LocalFeedTaskProcessor extends FeedTaskProcessor implements Applica
|
|||||||
{
|
{
|
||||||
path = "/";
|
path = "/";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! path.startsWith("/"))
|
if (!path.startsWith("/"))
|
||||||
{
|
{
|
||||||
path = "/" + path;
|
path = "/" + path;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! path.endsWith("/"))
|
if (!path.endsWith("/"))
|
||||||
{
|
{
|
||||||
path = path + "/";
|
path = path + "/";
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((documentPattern == null) || (documentPattern.length() == 0))
|
if ((documentPattern == null) || (documentPattern.length() == 0))
|
||||||
{
|
{
|
||||||
documentPattern = "*";
|
documentPattern = "*";
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> documentPaths = new ArrayList<String>(0);
|
List<String> documentPaths = new ArrayList<String>(0);
|
||||||
|
|
||||||
for (String classPath : templateSearchPaths)
|
for (String classPath : templateSearchPaths)
|
||||||
{
|
{
|
||||||
final StringBuilder pattern = new StringBuilder(128);
|
final StringBuilder pattern = new StringBuilder(128);
|
||||||
@@ -400,20 +409,20 @@ public class LocalFeedTaskProcessor extends FeedTaskProcessor implements Applica
|
|||||||
.append(path)
|
.append(path)
|
||||||
.append((includeSubPaths ? "**/" : ""))
|
.append((includeSubPaths ? "**/" : ""))
|
||||||
.append(documentPattern);
|
.append(documentPattern);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
documentPaths.addAll(getPaths(pattern.toString(), classPath));
|
documentPaths.addAll(getPaths(pattern.toString(), classPath));
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
// Note: Ignore: no documents found
|
// Note: Ignore: no documents found
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return documentPaths;
|
return documentPaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper to return a list of resource document paths based on a search pattern.
|
// Helper to return a list of resource document paths based on a search pattern.
|
||||||
private List<String> getPaths(String pattern, String classPath) throws IOException
|
private List<String> getPaths(String pattern, String classPath) throws IOException
|
||||||
{
|
{
|
||||||
@@ -422,7 +431,7 @@ public class LocalFeedTaskProcessor extends FeedTaskProcessor implements Applica
|
|||||||
for (Resource resource : resources)
|
for (Resource resource : resources)
|
||||||
{
|
{
|
||||||
String resourcePath = resource.getURL().toExternalForm();
|
String resourcePath = resource.getURL().toExternalForm();
|
||||||
|
|
||||||
int idx = resourcePath.lastIndexOf(classPath);
|
int idx = resourcePath.lastIndexOf(classPath);
|
||||||
if (idx != -1)
|
if (idx != -1)
|
||||||
{
|
{
|
||||||
@@ -437,4 +446,21 @@ public class LocalFeedTaskProcessor extends FeedTaskProcessor implements Applica
|
|||||||
}
|
}
|
||||||
return documentPaths;
|
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