package org.exoplatform.forum.service.cache;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import javax.jcr.NodeIterator;
import org.exoplatform.commons.utils.CommonsUtils;
import org.exoplatform.container.component.ComponentPlugin;
import org.exoplatform.forum.common.cache.ServiceContext;
import org.exoplatform.forum.common.cache.model.CacheType;
import org.exoplatform.forum.common.cache.model.CachedData;
import org.exoplatform.forum.common.cache.model.data.SimpleCacheData;
import org.exoplatform.forum.common.cache.model.key.SimpleCacheKey;
import org.exoplatform.forum.common.cache.model.selector.ScopeCacheSelector;
import org.exoplatform.forum.common.conf.RoleRulesPlugin;
import org.exoplatform.forum.common.jcr.KSDataLocation;
import org.exoplatform.forum.common.lifecycle.LifeCycleCompletionService;
import org.exoplatform.forum.service.Category;
import org.exoplatform.forum.service.DataStorage;
import org.exoplatform.forum.service.Forum;
import org.exoplatform.forum.service.ForumAdministration;
import org.exoplatform.forum.service.ForumAttachment;
import org.exoplatform.forum.service.ForumEventQuery;
import org.exoplatform.forum.service.ForumLinkData;
import org.exoplatform.forum.service.ForumPrivateMessage;
import org.exoplatform.forum.service.ForumSearchResult;
import org.exoplatform.forum.service.ForumStatistic;
import org.exoplatform.forum.service.ForumSubscription;
import org.exoplatform.forum.service.InitializeForumPlugin;
import org.exoplatform.forum.service.JCRPageList;
import org.exoplatform.forum.service.LazyPageList;
import org.exoplatform.forum.service.MessageBuilder;
import org.exoplatform.forum.service.Post;
import org.exoplatform.forum.service.PruneSetting;
import org.exoplatform.forum.service.SendMessageInfo;
import org.exoplatform.forum.service.SortSettings;
import org.exoplatform.forum.service.SortSettings.Direction;
import org.exoplatform.forum.service.SortSettings.SortField;
import org.exoplatform.forum.service.Tag;
import org.exoplatform.forum.service.Topic;
import org.exoplatform.forum.service.UserProfile;
import org.exoplatform.forum.service.Utils;
import org.exoplatform.forum.service.Watch;
import org.exoplatform.forum.service.cache.model.data.CategoryData;
import org.exoplatform.forum.service.cache.model.data.ForumData;
import org.exoplatform.forum.service.cache.model.data.LinkData;
import org.exoplatform.forum.service.cache.model.data.ListCategoryData;
import org.exoplatform.forum.service.cache.model.data.ListForumData;
import org.exoplatform.forum.service.cache.model.data.ListLinkData;
import org.exoplatform.forum.service.cache.model.data.ListPostData;
import org.exoplatform.forum.service.cache.model.data.ListTopicData;
import org.exoplatform.forum.service.cache.model.data.ListUserProfileData;
import org.exoplatform.forum.service.cache.model.data.ListWatchData;
import org.exoplatform.forum.service.cache.model.data.LoginUserProfileData;
import org.exoplatform.forum.service.cache.model.data.PostData;
import org.exoplatform.forum.service.cache.model.data.TagData;
import org.exoplatform.forum.service.cache.model.data.TopicData;
import org.exoplatform.forum.service.cache.model.data.UserProfileData;
import org.exoplatform.forum.service.cache.model.data.WatchData;
import org.exoplatform.forum.service.cache.model.key.CategoryKey;
import org.exoplatform.forum.service.cache.model.key.CategoryListKey;
import org.exoplatform.forum.service.cache.model.key.ForumKey;
import org.exoplatform.forum.service.cache.model.key.ForumListKey;
import org.exoplatform.forum.service.cache.model.key.LinkListKey;
import org.exoplatform.forum.service.cache.model.key.ObjectNameKey;
import org.exoplatform.forum.service.cache.model.key.PostKey;
import org.exoplatform.forum.service.cache.model.key.PostListCountKey;
import org.exoplatform.forum.service.cache.model.key.PostListKey;
import org.exoplatform.forum.service.cache.model.key.TopicKey;
import org.exoplatform.forum.service.cache.model.key.TopicListCountKey;
import org.exoplatform.forum.service.cache.model.key.TopicListKey;
import org.exoplatform.forum.service.cache.model.key.UserProfileKey;
import org.exoplatform.forum.service.cache.model.key.UserProfileListCountKey;
import org.exoplatform.forum.service.cache.model.key.UserProfileListKey;
import org.exoplatform.forum.service.cache.model.selector.CategoryIdSelector;
import org.exoplatform.forum.service.cache.model.selector.ForumPathSelector;
import org.exoplatform.forum.service.cache.model.selector.MiscDataSelector;
import org.exoplatform.forum.service.cache.model.selector.PostListCountSelector;
import org.exoplatform.forum.service.cache.model.selector.TopicListCountSelector;
import org.exoplatform.forum.service.cache.model.selector.TopicListSelector;
import org.exoplatform.forum.service.filter.model.CategoryFilter;
import org.exoplatform.forum.service.filter.model.ForumFilter;
import org.exoplatform.forum.service.impl.JCRDataStorage;
import org.exoplatform.forum.service.impl.model.PostFilter;
import org.exoplatform.forum.service.impl.model.TopicFilter;
import org.exoplatform.forum.service.impl.model.UserProfileFilter;
import org.exoplatform.management.annotations.Managed;
import org.exoplatform.management.annotations.ManagedDescription;
import org.exoplatform.services.cache.CacheService;
import org.exoplatform.services.cache.ExoCache;
import org.exoplatform.services.cache.future.FutureExoCache;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.exoplatform.services.organization.User;
import org.picocontainer.Startable;
public class CachedDataStorage implements DataStorage, Startable {
private static final Log LOG = ExoLogger.getLogger(CachedDataStorage.class);
private static final String PRIVATE_MESSAGE_COUNT_KEY = "messageCount";
private static final String SCREEN_NAME_KEY = "screenName";
private static final String FORUM_CAN_VIEW_KEY = "userCanView";
private static final String USER_AVATAR_KEY = "userAvatarKey";
private static final String PROFILE_KEY = "profile";
private static final String WATCH_TYPE = "watchType";
private DataStorage storage;
private CacheService service;
private LifeCycleCompletionService completionService;
//
private ExoCache<CategoryKey, CategoryData> categoryData;
private ExoCache<CategoryListKey, ListCategoryData> categoryList;
private ExoCache<ForumKey, ForumData> forumData;
private ExoCache<ForumListKey, ListForumData> forumList;
private ExoCache<PostKey, PostData> postData;
private ExoCache<PostListKey, ListPostData> postList;
private ExoCache<PostListCountKey, SimpleCacheData<Integer>> postListCount;
private ExoCache<TopicKey, TopicData> topicData;
private ExoCache<TopicListKey, ListTopicData> topicList;
private ExoCache<TopicListCountKey, SimpleCacheData<Integer>> topicListCount;
private ExoCache<UserProfileKey, UserProfileData> userProfileData;
private ExoCache<UserProfileListKey, ListUserProfileData> userProfileList;
private ExoCache<UserProfileListCountKey, SimpleCacheData<Integer>> userProfileListCount;
private ExoCache<UserProfileKey, LoginUserProfileData> loginUserProfile;
private ExoCache<SimpleCacheKey, ListWatchData> watchListData;
private ExoCache<LinkListKey, ListLinkData> linkListData;
private ExoCache<ObjectNameKey, CachedData> objectNameData;
private ExoCache<SimpleCacheKey, SimpleCacheData> miscData;
//
private FutureExoCache<CategoryKey, CategoryData, ServiceContext<CategoryData>> categoryDataFuture;
private FutureExoCache<CategoryListKey, ListCategoryData, ServiceContext<ListCategoryData>> categoryListFuture;
private FutureExoCache<ForumKey, ForumData, ServiceContext<ForumData>> forumDataFuture;
private FutureExoCache<ForumListKey, ListForumData, ServiceContext<ListForumData>> forumListFuture;
private FutureExoCache<PostKey, PostData, ServiceContext<PostData>> postDataFuture;
private FutureExoCache<PostListKey, ListPostData, ServiceContext<ListPostData>> postListFuture;
private FutureExoCache<PostListCountKey, SimpleCacheData<Integer>, ServiceContext<SimpleCacheData<Integer>>> postListCountFuture;
private FutureExoCache<TopicKey, TopicData, ServiceContext<TopicData>> topicDataFuture;
private FutureExoCache<TopicListKey, ListTopicData, ServiceContext<ListTopicData>> topicListFuture;
private FutureExoCache<TopicListCountKey, SimpleCacheData<Integer>, ServiceContext<SimpleCacheData<Integer>>> topicListCountFuture;
private FutureExoCache<UserProfileKey, UserProfileData, ServiceContext<UserProfileData>> userProfileDataFuture;
private FutureExoCache<UserProfileListKey, ListUserProfileData, ServiceContext<ListUserProfileData>> userProfileListFuture;
private FutureExoCache<UserProfileListCountKey, SimpleCacheData<Integer>, ServiceContext<SimpleCacheData<Integer>>> userProfileListCountFuture;
private FutureExoCache<UserProfileKey, LoginUserProfileData, ServiceContext<LoginUserProfileData>> loginUserProfileFuture;
private FutureExoCache<SimpleCacheKey, ListWatchData, ServiceContext<ListWatchData>> watchListDataFuture;
private FutureExoCache<LinkListKey, ListLinkData, ServiceContext<ListLinkData>> linkListDataFuture;
private FutureExoCache<SimpleCacheKey, SimpleCacheData, ServiceContext<SimpleCacheData>> miscDataFuture;
private ForumStatistic statistic;
public CachedDataStorage(CacheService service, JCRDataStorage storage) {
this.storage = storage;
this.service = service;
this.completionService = CommonsUtils.getService(LifeCycleCompletionService.class);
}
private void clearCategoryCache(String id) throws Exception {
categoryData.remove(new CategoryKey(id));
}
private void clearCategoryCache(Category category) throws Exception {
if (category != null) {
clearCategoryCache(category.getId());
clearObjectCache(category, false);
}
}
private void clearForumCache(Forum forum, boolean isPutNewKey) throws Exception {
if (isPutNewKey) {
forumData.put(new ForumKey(forum), new ForumData(forum));
} else {
forumData.remove(new ForumKey(forum));
}
statistic = null;
}
private void clearForumCache(String categoryId, String forumId, boolean isPutNewKey) throws Exception {
Forum forum = getForum(categoryId, forumId);
if (forum != null) {
clearForumCache(forum, isPutNewKey);
}
}
private void clearForumListCache() throws Exception {
forumList.select(new ScopeCacheSelector<ForumListKey, ListForumData>());
}
private void clearPostListCache() throws Exception {
postList.select(new ScopeCacheSelector<PostListKey, ListPostData>());
}
private void clearPostListCountCache(String topicId) throws Exception {
postListCount.select(new PostListCountSelector(topicId));
}
private void clearTopicListCache() throws Exception {
topicList.select(new ScopeCacheSelector<TopicListKey, ListTopicData>());
}
private void clearTopicListCache(String forumId) throws Exception {
topicList.select(new TopicListSelector(forumId));
}
private void clearTopicListCountCache(String forumId) throws Exception {
topicListCount.select(new TopicListCountSelector(forumId));
}
private void clearLinkListCache() throws Exception {
linkListData.select(new ScopeCacheSelector<LinkListKey, ListLinkData>());
}
private void clearMiscDataCache(String type) throws Exception {
miscData.select(new MiscDataSelector(type));
}
private void clearTopicsCache(List<Topic> topics) throws Exception {
for(Topic t : topics) {
clearTopicCache(t);
}
}
private void clearUserProfileListCache() throws Exception {
if (userProfileList != null) {
userProfileList.select(new ScopeCacheSelector<UserProfileListKey, ListUserProfileData>());
}
}
private void clearUserProfileListCountCache() throws Exception {
if (userProfileListCount != null) {
userProfileListCount.select(new ScopeCacheSelector<UserProfileListCountKey, SimpleCacheData<Integer>>());
}
}
private void clearTopicCache(String topicPath) {
try {
Topic topic = getTopicByPath(topicPath, false);
clearTopicCache(topic);
} catch (Exception e) {
LOG.warn("Can not clear topic cache for: " + topicPath);
}
}
private void clearTopicCache(String categoryId, String forumId, String topicId) throws Exception {
String topicPath = new StringBuffer(categoryId).append("/").append(forumId).append("/").append(topicId).toString();
clearTopicCache(topicPath);
}
public void clearTopicCache(Topic topic) throws Exception {
if (topic != null) {
String topicPath = Utils.getSubPath(topic.getPath());
topicData.remove(new TopicKey(topicPath, true));
topicData.remove(new TopicKey(topicPath, false));
topicData.remove(new TopicKey(topicPath.toUpperCase(), false));
objectNameData.remove(new ObjectNameKey(topic.getId(), Utils.TOPIC));
}
}
private void clearPostCache(String categoryId, String forumId, String topicId, String postId) throws Exception {
postData.remove(new PostKey(categoryId, forumId, topicId, postId));
}
private void clearObjectCache(Forum forum, boolean isPutNewKey) throws Exception {
if (forum != null) {
ForumData forumData = new ForumData(forum);
String forumId = forum.getId();
if (isPutNewKey) {
objectNameData.put(new ObjectNameKey(forumId, Utils.FORUM), forumData);
} else {
objectNameData.remove(new ObjectNameKey(forumId, Utils.FORUM));
}
}
}
private void clearObjectCache(Category category, boolean isNew) throws Exception {
if (isNew) {
CategoryData categoryData = new CategoryData(category);
objectNameData.put(new ObjectNameKey(category.getId(), Utils.CATEGORY), categoryData);
} else {
objectNameData.remove(new ObjectNameKey(category.getId(), Utils.CATEGORY));
}
}
private void clearObjectCache(String categoryId, String forumId, boolean isPutNewKey) throws Exception {
clearObjectCache(getForum(categoryId, forumId), isPutNewKey);
}
private void clearUserProfile(String userName) {
if (!Utils.isEmpty(userName)) {
UserProfileKey key = new UserProfileKey(userName);
userProfileData.remove(key);
loginUserProfile.remove(key);
} else {
//clear all
userProfileData.clearCache();
loginUserProfile.clearCache();
}
}
/**
* Refresh user profile caching
* @param profile
* @throws Exception
*/
public void refreshUserProfile(UserProfile profile) throws Exception {
UserProfileKey key = new UserProfileKey(profile.getUserId());
userProfileData.put(key, new UserProfileData(profile));
}
private void clearWatchingItemCache(String watchingItemPath) throws Exception {
String categoryId = Utils.getCategoryId(watchingItemPath);
String forumId = Utils.getForumId(watchingItemPath);
String topicPath = Utils.getTopicPath(watchingItemPath);
// Clear watching item data
if (!Utils.isEmpty(topicPath)) {
clearTopicCache(topicPath);
} else if (!Utils.isEmpty(forumId)) {
clearForumCache(categoryId, forumId, false);
} else if (!Utils.isEmpty(categoryId)) {
clearCategoryCache(categoryId);
}
}
public void start() {
//
this.categoryData = CacheType.CATEGORY_DATA.getFromService(service);
this.categoryList = CacheType.CATEGORY_LIST.getFromService(service);
this.forumData = CacheType.FORUM_DATA.getFromService(service);
this.forumList = CacheType.FORUM_LIST.getFromService(service);
this.postData = CacheType.POST_DATA.getFromService(service);
this.postList = CacheType.POST_LIST.getFromService(service);
this.postListCount = CacheType.POST_LIST_COUNT.getFromService(service);
this.topicData = CacheType.TOPIC_DATA.getFromService(service);
this.topicList = CacheType.TOPIC_LIST.getFromService(service);
this.topicListCount = CacheType.TOPIC_LIST_COUNT.getFromService(service);
this.userProfileData = CacheType.USER_PROFILE_DATA.getFromService(service);
this.userProfileList = CacheType.USER_PROFILE_LIST.getFromService(service);
this.userProfileListCount = CacheType.USER_PROFILE_LIST_COUNT.getFromService(service);
this.loginUserProfile = CacheType.LOGIN_USER_PROFILE.getFromService(service);
this.objectNameData = CacheType.OBJECT_NAME_DATA.getFromService(service);
this.miscData = CacheType.MISC_DATA.getFromService(service);
this.watchListData = CacheType.WATCH_LIST_DATA.getFromService(service);
this.linkListData = CacheType.LINK_LIST_DATA.getFromService(service);
//
this.categoryDataFuture = CacheType.CATEGORY_DATA.createFutureCache(categoryData);
this.categoryListFuture = CacheType.CATEGORY_LIST.createFutureCache(categoryList);
this.forumDataFuture = CacheType.FORUM_DATA.createFutureCache(forumData);
this.forumListFuture = CacheType.FORUM_LIST.createFutureCache(forumList);
this.postDataFuture = CacheType.POST_DATA.createFutureCache(postData);
this.postListFuture = CacheType.POST_LIST.createFutureCache(postList);
this.postListCountFuture = CacheType.POST_LIST_COUNT.createFutureCache(postListCount);
this.topicDataFuture = CacheType.TOPIC_DATA.createFutureCache(topicData);
this.topicListFuture = CacheType.TOPIC_LIST.createFutureCache(topicList);
this.topicListCountFuture = CacheType.TOPIC_LIST_COUNT.createFutureCache(topicListCount);
this.userProfileDataFuture = CacheType.USER_PROFILE_DATA.createFutureCache(userProfileData);
this.userProfileListFuture = CacheType.USER_PROFILE_LIST.createFutureCache(userProfileList);
this.userProfileListCountFuture = CacheType.USER_PROFILE_LIST_COUNT.createFutureCache(userProfileListCount);
this.loginUserProfileFuture = CacheType.LOGIN_USER_PROFILE.createFutureCache(loginUserProfile);
this.watchListDataFuture = CacheType.WATCH_LIST_DATA.createFutureCache(watchListData);
this.linkListDataFuture = CacheType.LINK_LIST_DATA.createFutureCache(linkListData);
this.miscDataFuture = CacheType.MISC_DATA.createFutureCache(miscData);
}
public void stop() {
}
private ListLinkData buildLinkInput(List<ForumLinkData> links) {
List<LinkData> data = new ArrayList<LinkData>();
for (ForumLinkData l : links) {
data.add(new LinkData(l));
}
return new ListLinkData(data);
}
private List<ForumLinkData> buildLinkOutput(ListLinkData data) {
if (data == null) {
return null;
}
List<ForumLinkData> out = new ArrayList<ForumLinkData>();
for (LinkData d : data.getIds()) {
out.add(d.build());
}
return out;
}
private ListWatchData buildWatchInput(List<Watch> watches) {
List<WatchData> data = new ArrayList<WatchData>();
for (Watch w : watches) {
data.add(new WatchData(w));
}
return new ListWatchData(data);
}
private List<Watch> buildWatchOutput(ListWatchData data) {
if (data == null) {
return null;
}
List<Watch> out = new ArrayList<Watch>();
for (WatchData d : data.getIds()) {
out.add(d.build());
}
return out;
}
private ListPostData buildPostInput(List<Post> posts) {
List<PostKey> data = new ArrayList<PostKey>();
PostKey key;
for (Post p : posts) {
key = new PostKey(p);
data.add(key);
}
return new ListPostData(data);
}
private List<Post> buildPostOutput(ListPostData data) {
if (data == null) {
return null;
}
List<Post> out = new ArrayList<Post>();
for (PostKey k : data.getIds()) {
try {
out.add(getPost(k.getCategory(), k.getForum(), k.getTopic(), k.getPost()));
} catch (Exception e) {
LOG.error(e);
}
}
return out;
}
private ListForumData buildForumInput(List<Forum> forums) {
List<ForumKey> keys = new ArrayList<ForumKey>();
for (Forum f : forums) {
keys.add(new ForumKey(f));
}
return new ListForumData(keys);
}
private List<Forum> buildForumOutput(ListForumData data) {
if (data == null) {
return null;
}
List<Forum> out = new ArrayList<Forum>();
for (ForumKey k : data.getIds()) {
out.add(getForum(k.getCategoryId(), k.getForumId()));
}
return out;
}
private ListCategoryData buildCategoryInput(List<Category> categories) {
List<CategoryKey> keys = new ArrayList<CategoryKey>();
for (Category c : categories) {
keys.add(new CategoryKey(c));
}
return new ListCategoryData(keys);
}
private List<Category> buildCategoryOutput(ListCategoryData data) {
if (data == null) {
return null;
}
List<Category> out = new ArrayList<Category>();
for (CategoryKey k : data.getIds()) {
try {
out.add(getCategory(k.getId()));
} catch (Exception e) {
LOG.error(e);
}
}
return out;
}
@ManagedDescription("repository for forum storage")
@Managed
public String getRepository() throws Exception {
return storage.getRepository();
}
@ManagedDescription("workspace for the forum storage")
@Managed
public String getWorkspace() throws Exception {
return storage.getWorkspace();
}
@ManagedDescription("data path for forum storage")
@Managed
public String getPath() throws Exception {
return storage.getPath();
}
public void addPlugin(ComponentPlugin plugin) throws Exception {
storage.addPlugin(plugin);
}
public void addRolePlugin(ComponentPlugin plugin) throws Exception {
storage.addRolePlugin(plugin);
}
public void addInitialDataPlugin(ComponentPlugin plugin) throws Exception {
storage.addInitialDataPlugin(plugin);
}
public void addInitialDefaultDataPlugin(ComponentPlugin plugin) throws Exception {
storage.addInitialDefaultDataPlugin(plugin);
}
public void addDeletedUserCalculateListener() throws Exception {
storage.addDeletedUserCalculateListener();
}
public void initCategoryListener() {
storage.initCategoryListener();
}
public boolean isAdminRole(String userName) throws Exception {
return storage.isAdminRole(userName);
}
public boolean isAdminRoleConfig(String userName) throws Exception {
return storage.isAdminRoleConfig(userName);
}
public void setDefaultAvatar(String userName) {
storage.setDefaultAvatar(userName);
miscData.remove(new SimpleCacheKey(USER_AVATAR_KEY, userName));
}
public ForumAttachment getUserAvatar(final String userName) throws Exception {
SimpleCacheKey key = new SimpleCacheKey(USER_AVATAR_KEY, userName);
//
return (ForumAttachment) miscDataFuture.get(new ServiceContext<SimpleCacheData>() {
public SimpleCacheData<ForumAttachment> execute() {
try {
ForumAttachment got = storage.getUserAvatar(userName);
return new SimpleCacheData<ForumAttachment>(got);
} catch (Exception e) {
return new SimpleCacheData<ForumAttachment>(null);
}
}
}, key).build();
}
public void saveUserAvatar(String userId, ForumAttachment fileAttachment) throws Exception {
storage.saveUserAvatar(userId, fileAttachment);
miscData.remove(new SimpleCacheKey(USER_AVATAR_KEY, userId));
}
public void saveForumAdministration(ForumAdministration forumAdministration) throws Exception {
storage.saveForumAdministration(forumAdministration);
}
public ForumAdministration getForumAdministration() throws Exception {
return storage.getForumAdministration();
}
public SortSettings getForumSortSettings() {
return storage.getForumSortSettings();
}
public SortSettings getTopicSortSettings() throws Exception {
return storage.getTopicSortSettings();
}
public List<Category> getCategories() {
return buildCategoryOutput(
categoryListFuture.get(
new ServiceContext<ListCategoryData>() {
public ListCategoryData execute() {
return buildCategoryInput(storage.getCategories());
}
},
new CategoryListKey(null)
)
);
}
public Category getCategory(final String categoryId) {
return categoryDataFuture.get(
new ServiceContext<CategoryData>() {
public CategoryData execute() {
try {
Category got = storage.getCategory(categoryId);
if (got != null) {
return new CategoryData(got);
}
else {
return CategoryData.NULL;
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
},
new CategoryKey(categoryId)
).build();
}
public Category getCategoryIncludedSpace() {
return storage.getCategoryIncludedSpace();
}
public String[] getPermissionTopicByCategory(String categoryId, String type) throws Exception {
return storage.getPermissionTopicByCategory(categoryId, type);
}
public void saveCategory(Category category, boolean isNew) throws Exception {
storage.saveCategory(category, isNew);
categoryList.select(new ScopeCacheSelector<CategoryListKey, ListCategoryData>());
clearLinkListCache();
clearObjectCache(category, isNew);
//
clearUserProfile(null);
clearCategoryCache(category);
}
public void saveModOfCategory(List<String> moderatorCate, String userId, boolean isAdd) {
storage.saveModOfCategory(moderatorCate, userId, isAdd);
try {
categoryData.select(new CategoryIdSelector(moderatorCate, categoryData));
} catch (Exception e) {
LOG.debug("Can not clear list categories in cached.", e);
}
//
clearUserProfile(null);
}
public void calculateModerator(String nodePath, boolean isNew) throws Exception {
storage.calculateModerator(nodePath, isNew);
clearForumCache(Utils.getCategoryId(nodePath), Utils.getForumId(nodePath), false);
clearForumListCache();
//
clearUserProfile(null);
}
public Category removeCategory(String categoryId) throws Exception {
objectNameData.clearCache();
categoryData.remove(new CategoryKey(categoryId));
categoryList.select(new ScopeCacheSelector<CategoryListKey, ListCategoryData>());
clearLinkListCache();
//
clearUserProfile(null);
return storage.removeCategory(categoryId);
}
@Deprecated
public List<Forum> getForums(final String categoryId, final String strQuery) throws Exception {
return getForums(new ForumFilter(categoryId, false).strQuery(strQuery));
}
@Deprecated
public List<Forum> getForumSummaries(final String categoryId, final String strQuery) throws Exception {
return getForums(new ForumFilter(categoryId, true).strQuery(strQuery));
}
public List<Forum> getForums(final ForumFilter filter) {
SortSettings sort = storage.getForumSortSettings();
SortField orderBy = sort.getField();
Direction orderType = sort.getDirection();
return buildForumOutput(
forumListFuture.get(
new ServiceContext<ListForumData>() {
public ListForumData execute() {
try {
return buildForumInput(storage.getForums(filter));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
},
new ForumListKey(filter, orderBy, orderType)
)
);
}
public List<CategoryFilter> filterForumByName(String filterKey, String userName, int maxSize) throws Exception {
return storage.filterForumByName(filterKey, userName, maxSize);
}
public Forum getForum(final String categoryId, final String forumId) {
ForumData data = forumDataFuture.get(
new ServiceContext<ForumData>() {
public ForumData execute() {
Forum got = storage.getForum(categoryId, forumId);
if (got != null) {
return new ForumData(got);
}
else {
return null;
}
}
},
new ForumKey(categoryId, forumId)
);
return data != null ? data.build() : null;
}
public void modifyForum(Forum forum, int type) throws Exception {
storage.modifyForum(forum, type);
clearForumCache(forum, true);
clearForumListCache();
clearObjectCache(forum, true);
//
clearMiscDataCache(FORUM_CAN_VIEW_KEY);
}
public void saveForum(String categoryId, Forum forum, boolean isNew) throws Exception {
storage.saveForum(categoryId, forum, isNew);
//
clearForumCache(forum, true);
clearForumListCache();
clearLinkListCache();
clearObjectCache(forum, true);
clearCategoryCache(categoryId);
//
clearTopicListCache(forum.getId());
clearTopicListCountCache(forum.getId());
//
clearMiscDataCache(FORUM_CAN_VIEW_KEY);
//
clearUserProfile(null);
}
public void saveModerateOfForums(List<String> forumPaths, String userName, boolean isDelete) throws Exception {
storage.saveModerateOfForums(forumPaths, userName, isDelete);
forumData.select(new ForumPathSelector(forumPaths.toArray(new String[forumPaths.size()]), forumData));
clearForumListCache();
for (String forumPath : forumPaths) {
clearObjectCache(Utils.getCategoryId(forumPath), Utils.getForumId(forumPath), true);
}
//
clearMiscDataCache(FORUM_CAN_VIEW_KEY);
//
clearUserProfile(null);
}
public Forum removeForum(String categoryId, String forumId) throws Exception {
clearForumCache(categoryId, forumId, false);
clearForumListCache();
clearLinkListCache();
clearObjectCache(categoryId, forumId, false);
//
clearMiscDataCache(FORUM_CAN_VIEW_KEY);
return storage.removeForum(categoryId, forumId);
}
public void moveForum(List<Forum> forums, String destCategoryPath) throws Exception {
for (Forum forum : forums) {
clearForumCache(forum, false);
clearObjectCache(forum, false);
}
clearForumListCache();
clearLinkListCache();
//
clearMiscDataCache(FORUM_CAN_VIEW_KEY);
//
clearUserProfile(null);
storage.moveForum(forums, destCategoryPath);
//
topicData.clearCache();
postData.clearCache();
objectNameData.clearCache();
watchListData.clearCache();
forumData.clearCache();
clearForumListCache();
}
public JCRPageList getPageTopic(String categoryId, String forumId, String strQuery, String strOrderBy) throws Exception {
return storage.getPageTopic(categoryId, forumId, strQuery, strOrderBy);
}
public LazyPageList<Topic> getTopicList(String categoryId, String forumId, String xpathConditions, String strOrderBy, int pageSize) throws Exception {
return storage.getTopicList(categoryId, forumId, xpathConditions, strOrderBy, pageSize);
}
@Override
public List<Topic> getTopics(final TopicFilter filter, final int offset, final int limit) throws Exception {
TopicListKey key = new TopicListKey(filter, offset, limit);
ListTopicData data = topicListFuture.get(new ServiceContext<ListTopicData>() {
@Override
public ListTopicData execute() {
try {
return buildTopicInput(storage.getTopics(filter, offset, limit));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}, key);
return buildTopicOutput(data);
}
private ListTopicData buildTopicInput(List<Topic> topics) {
List<TopicKey> data = new ArrayList<TopicKey>();
TopicKey key;
for (Topic p : topics) {
key = new TopicKey(p);
data.add(key);
topicData.put(key, new TopicData(p));
}
return new ListTopicData(data);
}
private List<Topic> buildTopicOutput(ListTopicData data) {
if (data == null) {
return null;
}
List<Topic> out = new ArrayList<Topic>();
for (TopicKey k : data.getIds()) {
try {
out.add(getTopicByPath(k.getTopicPath(), false));
} catch (Exception e) {
LOG.error(e);
}
}
return out;
}
@Override
public int getTopicsCount(final TopicFilter filter) throws Exception {
TopicListCountKey key = new TopicListCountKey(filter.toString(), filter.forumId());
SimpleCacheData<Integer> data = topicListCountFuture.get(new ServiceContext<SimpleCacheData<Integer>>() {
@Override
public SimpleCacheData<Integer> execute() {
try {
return new SimpleCacheData<Integer>(storage.getTopicsCount(filter));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}, key);
return data.build();
}
public List<Topic> getTopics(final String categoryId, final String forumId) throws Exception {
TopicFilter filter = new TopicFilter(categoryId, forumId);
filter.isAdmin(true);
//
TopicListKey key = new TopicListKey(filter, 0, 0);
ListTopicData data = topicListFuture.get(new ServiceContext<ListTopicData>() {
@Override
public ListTopicData execute() {
try {
return buildTopicInput(storage.getTopics(categoryId, forumId));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}, key);
return buildTopicOutput(data);
}
public Topic getTopic(String categoryId, String forumId, String topicId, String userRead) throws Exception {
String topicPath = topicId;
if (!Utils.isEmpty(categoryId)) {
topicPath = new StringBuilder(categoryId).append("/").append(forumId).append("/").append(topicId).toString();
}
//
return getTopicByPath(topicPath, false);
}
public Topic getTopicSummary(final String topicPath) {
TopicData data = topicData.get(new TopicKey(topicPath, false));
if (data != null) {
return getTopicPoll(data.build());
}
//
Topic got = topicDataFuture.get(
new ServiceContext<TopicData>() {
public TopicData execute() {
try {
Topic got = storage.getTopicSummary(topicPath);
if (got != null) {
return new TopicData(got);
} else {
return TopicData.NULL;
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
},
new TopicKey(Utils.getSubPath(topicPath.toUpperCase()), false)
).build();
//
return getTopicPoll(got);
}
public Topic getTopicSummary(String topicPath, boolean isLastPost) throws Exception {
if(isLastPost == false) {
return getTopicSummary(topicPath);
}
return storage.getTopicSummary(topicPath, isLastPost);
}
public Topic getTopicByPath(final String topicPath, final boolean isLastPost) throws Exception {
Topic got = topicDataFuture.get(
new ServiceContext<TopicData>() {
public TopicData execute() {
try {
Topic got = storage.getTopicByPath(topicPath, isLastPost);
if (got != null) {
return new TopicData(got);
} else {
return TopicData.NULL;
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
},
new TopicKey(topicPath, isLastPost)
).build();
//
return getTopicPoll(got);
}
public Topic getTopicUpdate(Topic topic, boolean isSummary) throws Exception {
return storage.getTopicUpdate(topic, isSummary);
}
@Override
public List<Topic> getTopicsByDate(long date, String forumPath, int offset, int limit) throws Exception {
return storage.getTopicsByDate(date, forumPath, offset, limit);
}
public JCRPageList getPageTopicOld(long date, String forumPatch) throws Exception {
return storage.getPageTopicOld(date, forumPatch);
}
public List<Topic> getAllTopicsOld(long date, String forumPatch) throws Exception {
return storage.getAllTopicsOld(date, forumPatch);
}
public long getTotalTopicOld(long date, String forumPatch) {
return storage.getTotalTopicOld(date, forumPatch);
}
public JCRPageList getPageTopicByUser(String userName, boolean isMod, String strOrderBy) throws Exception {
return storage.getPageTopicByUser(userName, isMod, strOrderBy);
}
public List<Topic> getTopicsByUser(final TopicFilter filter, final int offset, final int limit) throws Exception {
TopicListKey key = new TopicListKey(filter, 0, 0);
ListTopicData data = topicListFuture.get(new ServiceContext<ListTopicData>() {
@Override
public ListTopicData execute() {
try {
return buildTopicInput(storage.getTopicsByUser(filter, offset, limit));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}, key);
return buildTopicOutput(data);
}
public void modifyTopic(List<Topic> topics, int type) {
storage.modifyTopic(topics, type);
//
try {
clearTopicsCache(topics);
clearTopicListCache(topics.get(0).getForumId());
clearTopicListCountCache(topics.get(0).getForumId());
} catch (Exception e) {
LOG.error(e.getMessage(), e);
}
//
if(type == Utils.CLOSE || type == Utils.ACTIVE || type == Utils.WAITING || type == Utils.APPROVE) {
for(Topic topic : topics) {
try {
clearForumCache(topic.getCategoryId(), topic.getForumId(), false);
} catch (Exception e) {
LOG.error(e.getMessage(), e);
}
}
}
}
public void saveTopic(String categoryId, String forumId, Topic topic, boolean isNew, boolean isMove, MessageBuilder messageBuilder) throws Exception {
storage.saveTopic(categoryId, forumId, topic, isNew, isMove, messageBuilder);
clearForumCache(categoryId, forumId, false);
clearForumListCache();
clearTopicListCache(forumId);
if(!isNew) {
clearPostCache(categoryId, forumId, topic.getId(), topic.getId().replace(Utils.TOPIC, Utils.POST));
clearTopicCache(topic);
} else {
clearTopicListCountCache(forumId);
clearUserProfile(topic.getOwner());
}
}
public Topic removeTopic(String categoryId, String forumId, String topicId) {
try {
clearForumCache(categoryId, forumId, false);
clearForumListCache();
clearTopicCache(categoryId, forumId, topicId);
//
clearTopicListCountCache(forumId);
clearTopicListCache(forumId);
clearUserProfile(null);
} catch (Exception e) {
LOG.error(e.getMessage(), e);
}
return storage.removeTopic(categoryId, forumId, topicId);
}
public void moveTopic(List<Topic> topics, String destForumPath, String mailContent, String link) throws Exception {
storage.moveTopic(topics, destForumPath, mailContent, link);
if (topics != null && topics.size() > 0) {
forumData.select(new ForumPathSelector(new String[] {Utils.getForumPath(topics.get(0).getPath()), destForumPath}, forumData));
clearForumListCache();
clearTopicListCache();
//
clearTopicListCountCache(topics.get(0).getForumId());
clearTopicListCountCache(Utils.getForumId(destForumPath));
for (Topic topic : topics) {
clearTopicCache(topic);
}
//
clearUserProfile(null);
}
}
public long getLastReadIndex(String path, String isApproved, String isHidden, String userLogin) throws Exception {
return storage.getLastReadIndex(path, isApproved, isHidden, userLogin);
}
public JCRPageList getPosts(String categoryId, String forumId, String topicId, String isApproved, String isHidden, String strQuery, String userLogin) throws Exception {
return storage.getPosts(categoryId, forumId, topicId, isApproved, isHidden, strQuery, userLogin);
}
public long getAvailablePost(String categoryId, String forumId, String topicId, String isApproved, String isHidden, String userLogin) throws Exception {
PostFilter filter = new PostFilter(categoryId, forumId, topicId, isApproved, isHidden, isHidden, userLogin);
return Long.valueOf(storage.getPostsCount(filter));
}
public JCRPageList getPagePostByUser(String userName, String userId, boolean isMod, String strOrderBy) throws Exception {
return storage.getPagePostByUser(userName, userId, isMod, strOrderBy);
}
public Post getPost(final String categoryId, final String forumId, final String topicId, final String postId) throws Exception {
PostKey key = new PostKey(categoryId, forumId, topicId, postId);
return postDataFuture.get(
new ServiceContext<PostData>() {
public PostData execute() {
try {
Post got = storage.getPost(categoryId, forumId, topicId, postId);
if (got == null) {
return PostData.NULL;
} else {
return new PostData(got);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
},
key
).build();
}
public void putPost(Post post) {
PostKey key = new PostKey(post.getCategoryId(), post.getForumId(), post.getTopicId(), post.getId());
postData.put(key, new PostData(post));
}
public Post getPostFromCache(final String categoryId, final String forumId, final String topicId, final String postId) {
PostKey key = new PostKey(categoryId, forumId, topicId, postId);
PostData postCache = postData.get(key);
if (postCache != null && postCache != PostData.NULL) {
return postCache.build();
}
return null;
}
public JCRPageList getListPostsByIP(String ip, String strOrderBy) throws Exception {
return storage.getListPostsByIP(ip, strOrderBy);
}
public void savePost(String categoryId, String forumId, String topicId, Post post, boolean isNew, MessageBuilder messageBuilder) throws Exception {
storage.savePost(categoryId, forumId, topicId, post, isNew, messageBuilder);
clearForumCache(categoryId, forumId, false);
clearForumListCache();
clearTopicCache(categoryId, forumId, topicId);
clearTopicListCache(forumId);
clearPostListCache();
//
if (isNew == false) {
clearPostCache(categoryId, forumId, topicId, post.getId());
} else {
clearUserProfile(post.getOwner());
clearPostListCountCache(topicId);
}
statistic = null;
}
public void modifyPost(List<Post> posts, int type) {
storage.modifyPost(posts, type);
// clear caching
try {
clearPostListCache();
//
Post p = posts.get(0);
String categoryId = p.getCategoryId();
String forumId = p.getForumId();
String topicId = p.getTopicId();
for (Post post : posts) {
clearPostListCountCache(post.getTopicId());
clearPostCache(categoryId, forumId, topicId, post.getId());
}
//
clearTopicCache(Utils.getTopicPath(p.getPath()));
clearTopicListCache(forumId);
clearTopicListCountCache(forumId);
clearForumCache(categoryId, forumId, false);
clearForumListCache();
} catch (Exception e) {
LOG.error(e.getMessage(), e);
}
}
public Post removePost(String categoryId, String forumId, String topicId, String postId) {
try {
Post post = getPost(categoryId, forumId, topicId, postId);
clearUserProfile(post.getOwner());
clearForumCache(categoryId, forumId, false);
clearForumListCache();
clearTopicCache(categoryId, forumId, topicId);
clearPostCache(categoryId, forumId, topicId, postId);
clearPostListCache();
clearPostListCountCache(topicId);
//
statistic = null;
} catch (Exception e) {
LOG.error(e.getMessage(), e);
}
return storage.removePost(categoryId, forumId, topicId, postId);
}
public void addTag(List<Tag> tags, String userName, String topicPath) throws Exception {
storage.addTag(tags, userName, topicPath);
clearTopicCache(topicPath);
}
public void unTag(String tagId, String userName, String topicPath) {
storage.unTag(tagId, userName, topicPath);
clearTopicCache(topicPath);
}
public Tag getTag(String tagId) throws Exception {
return storage.getTag(tagId);
}
public List<String> getTagNameInTopic(String userAndTopicId) throws Exception {
return storage.getTagNameInTopic(userAndTopicId);
}
public List<String> getAllTagName(String keyValue, String userAndTopicId) throws Exception {
return storage.getAllTagName(keyValue, userAndTopicId);
}
public List<Tag> getAllTags() throws Exception {
return storage.getAllTags();
}
public List<Tag> getMyTagInTopic(String[] tagIds) throws Exception {
return storage.getMyTagInTopic(tagIds);
}
public JCRPageList getTopicByMyTag(String userIdAndtagId, String strOrderBy) throws Exception {
return storage.getTopicByMyTag(userIdAndtagId, strOrderBy);
}
public void saveTag(Tag newTag) throws Exception {
storage.saveTag(newTag);
}
public JCRPageList getPageListUserProfile() throws Exception {
return storage.getPageListUserProfile();
}
public JCRPageList searchUserProfile(String userSearch) throws Exception {
return storage.searchUserProfile(userSearch);
}
public UserProfile getDefaultUserProfile(final String userName, final String ip) throws Exception {
UserProfileKey key = new UserProfileKey(userName);
return loginUserProfileFuture.get(
new ServiceContext<LoginUserProfileData>() {
public LoginUserProfileData execute() {
try {
UserProfile got = storage.getDefaultUserProfile(userName, ip);
return new LoginUserProfileData(got);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
},
key
).build();
}
public UserProfile updateUserProfileSetting(UserProfile userProfile) throws Exception {
clearUserProfile(userProfile.getUserId());
return storage.updateUserProfileSetting(userProfile);
}
public String getScreenName(final String userName) throws Exception {
SimpleCacheKey key = new SimpleCacheKey(SCREEN_NAME_KEY, userName);
return (String) miscDataFuture.get(
new ServiceContext<SimpleCacheData>() {
public SimpleCacheData<Comparable> execute() {
try {
String got = storage.getScreenName(userName);
return new SimpleCacheData<Comparable>(got);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
},
key
).build();
}
public UserProfile getUserSettingProfile(String userName) throws Exception {
return storage.getUserSettingProfile(userName);
}
public void saveUserSettingProfile(UserProfile userProfile) throws Exception {
storage.saveUserSettingProfile(userProfile);
miscData.remove(new SimpleCacheKey(SCREEN_NAME_KEY, userProfile.getUserId()));
clearUserProfile(userProfile.getUserId());
}
public UserProfile getLastPostIdRead(UserProfile userProfile, String isOfForum) throws Exception {
return storage.getLastPostIdRead(userProfile, isOfForum);
}
public void saveLastPostIdRead(String userId, String[] lastReadPostOfForum, String[] lastReadPostOfTopic) throws Exception {
//
completionService.addTask(new SaveLastPostIdRead(userId, lastReadPostOfForum, lastReadPostOfTopic));
}
class SaveLastPostIdRead implements Callable<Boolean> {
private String userId;
private String[] lastReadPostOfForum, lastReadPostOfTopic;
public SaveLastPostIdRead(String userId, String[] lastReadPostOfForum, String[] lastReadPostOfTopic) {
this.userId = userId;
this.lastReadPostOfTopic = lastReadPostOfTopic;
this.lastReadPostOfForum = lastReadPostOfForum;
}
@Override
public Boolean call() throws Exception {
storage.saveLastPostIdRead(userId, lastReadPostOfForum, lastReadPostOfTopic);
return true;
}
}
public List<String> getUserModerator(String userName, boolean isModeCate) throws Exception {
return storage.getUserModerator(userName, isModeCate);
}
public void saveUserModerator(String userName, List<String> ids, boolean isModeCate) throws Exception {
storage.saveUserModerator(userName, ids, isModeCate);
}
public UserProfile getUserInfo(String userName) throws Exception {
return storage.getUserInfo(userName);
}
public List<UserProfile> getQuickProfiles(List<String> userList) throws Exception {
return storage.getQuickProfiles(userList);
}
public UserProfile getQuickProfile(final String userName) throws Exception {
UserProfileKey key = new UserProfileKey(userName);
return userProfileDataFuture.get(
new ServiceContext<UserProfileData>() {
public UserProfileData execute() {
try {
UserProfile got = storage.getQuickProfile(userName);
return new UserProfileData(got);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
},
key
).build();
}
public UserProfile getUserInformations(UserProfile userProfile) throws Exception {
return storage.getUserInformations(userProfile);
}
public void saveUserProfile(UserProfile newUserProfile, boolean isOption, boolean isBan) throws Exception {
clearUserProfile(newUserProfile.getUserId());
//
clearUserProfileListCache();
clearUserProfileListCountCache();
storage.saveUserProfile(newUserProfile, isOption, isBan);
}
public UserProfile getUserProfileManagement(String userName) throws Exception {
return storage.getUserProfileManagement(userName);
}
public void saveUserBookmark(String userName, String bookMark, boolean isNew) throws Exception {
storage.saveUserBookmark(userName, bookMark, isNew);
clearUserProfile(userName);
}
public void saveCollapsedCategories(String userName, String categoryId, boolean isAdd) throws Exception {
storage.saveCollapsedCategories(userName, categoryId, isAdd);
}
public void saveReadMessage(String messageId, String userName, String type) throws Exception {
storage.saveReadMessage(messageId, userName, type);
miscData.remove(new SimpleCacheKey(PRIVATE_MESSAGE_COUNT_KEY, userName));
}
public JCRPageList getPrivateMessage(String userName, String type) throws Exception {
return storage.getPrivateMessage(userName, type);
}
public long getNewPrivateMessage(final String userName) throws Exception {
SimpleCacheKey key = new SimpleCacheKey(PRIVATE_MESSAGE_COUNT_KEY, userName);
return (Long) miscDataFuture.get(
new ServiceContext<SimpleCacheData>() {
public SimpleCacheData<Comparable> execute() {
try {
Long got = storage.getNewPrivateMessage(userName);
return new SimpleCacheData<Comparable>(got);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
},
key
).build();
}
public void savePrivateMessage(ForumPrivateMessage privateMessage) throws Exception {
storage.savePrivateMessage(privateMessage);
miscData.remove(new SimpleCacheKey(PRIVATE_MESSAGE_COUNT_KEY, privateMessage.getSendTo()));
}
public void removePrivateMessage(String messageId, String userName, String type) throws Exception {
storage.removePrivateMessage(messageId, userName, type);
miscData.remove(new SimpleCacheKey(PRIVATE_MESSAGE_COUNT_KEY, userName));
}
public ForumSubscription getForumSubscription(String userId) {
return storage.getForumSubscription(userId);
}
public void saveForumSubscription(ForumSubscription forumSubscription, String userId) throws Exception {
storage.saveForumSubscription(forumSubscription, userId);
}
public ForumStatistic getForumStatistic() throws Exception {
if (statistic != null) {
return statistic;
} else {
return statistic = storage.getForumStatistic();
}
}
public void saveForumStatistic(ForumStatistic forumStatistic) throws Exception {
storage.saveForumStatistic(forumStatistic);
}
public Object getObjectNameByPath(final String path) throws Exception {
String type = Utils.getObjectType(path);
String id = Utils.getIdByType(path, type);
ObjectNameKey key = new ObjectNameKey(id, type);
CachedData<?> data = objectNameData.get(key);
//
if (data == null) {
Object got = storage.getObjectNameByPath(path);
return getObjectNameByKey(got, key);
} else {
// check path
Object got = data.build();
String sPath = getPath(got);
if (path.indexOf(sPath) < 0) {
return null;
}
if (got instanceof Topic) {
return getTopicPoll((Topic) got);
}
return got;
}
}
private Object getObjectNameByKey(Object got, ObjectNameKey key) throws Exception {
if (got instanceof Post) {
objectNameData.put(key, new PostData((Post) got));
} else if (got instanceof Topic) {
objectNameData.put(key, new TopicData((Topic) got));
} else if (got instanceof Forum) {
objectNameData.put(key, new ForumData((Forum) got));
} else if (got instanceof Category) {
objectNameData.put(key, new CategoryData((Category) got));
} else if (got instanceof Tag) {
objectNameData.put(key, new TagData((Tag) got));
}
return got;
}
private String getPath(Object got) {
String path = null;
if (got instanceof Post) {
path = ((Post) got).getPath();
} else if (got instanceof Topic) {
path = ((Topic) got).getPath();
} else if (got instanceof Forum) {
path = ((Forum) got).getPath();
} else if (got instanceof Category) {
path = ((Category) got).getPath();
} else if (got instanceof Tag) {
path = ((Tag) got).getId();
}
return Utils.getSubPath(path);
}
public Object getObjectNameById(String id, String type) throws Exception {
ObjectNameKey key = new ObjectNameKey(id, type);
CachedData<?> data = objectNameData.get(key);
//
if (data == null) {
Object got = storage.getObjectNameById(id, type);
return getObjectNameByKey(got, key);
} else {
Object object = data.build();
if (object instanceof Topic) {
return getTopicPoll((Topic) object);
}
return object;
}
}
private Topic getTopicPoll(Topic topic) {
if(topic != null) {
topic.setIsPoll(topicHasPoll(topic.getPath()));
}
return topic;
}
// TODO : need range
public List<ForumLinkData> getAllLink(final String strQueryCate, final String strQueryForum) throws Exception {
LinkListKey key = new LinkListKey(strQueryCate, strQueryForum);
return buildLinkOutput(linkListDataFuture.get(
new ServiceContext<ListLinkData>() {
public ListLinkData execute() {
try {
List<ForumLinkData> got = storage.getAllLink(strQueryCate, strQueryForum);
return buildLinkInput(got);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
},
key
));
}
public List<ForumSearchResult> getQuickSearch(String textQuery, String type_, String pathQuery, String userId, List<String> listCateIds, List<String> listForumIds, List<String> forumIdsOfModerator) throws Exception {
return storage.getQuickSearch(textQuery, type_, pathQuery, userId, listCateIds, listForumIds, forumIdsOfModerator);
}
public List<ForumSearchResult> getAdvancedSearch(ForumEventQuery eventQuery, List<String> listCateIds, List<String> listForumIds) {
return storage.getAdvancedSearch(eventQuery, listCateIds, listForumIds);
}
public void addWatch(int watchType, String path, List<String> values, String currentUser) throws Exception {
storage.addWatch(watchType, path, values, currentUser);
watchListData.remove(new SimpleCacheKey(WATCH_TYPE, currentUser));
clearWatchingItemCache(path);
}
public void removeWatch(int watchType, String path, String values) throws Exception {
storage.removeWatch(watchType, path, values);
watchListData.select(new ScopeCacheSelector<SimpleCacheKey, ListWatchData>());
clearWatchingItemCache(path);
}
public void updateEmailWatch(List<String> listNodeId, String newEmailAdd, String userId) throws Exception {
storage.updateEmailWatch(listNodeId, newEmailAdd, userId);
watchListData.remove(new SimpleCacheKey(WATCH_TYPE, userId));
for (String id : listNodeId) {
if (id.contains(Utils.CATEGORY)) {
categoryData.remove(new CategoryKey(id));
} else if (id.contains(Utils.FORUM)) {
forumData.remove(new ForumKey((Forum) getObjectNameById(id, Utils.FORUM)));
} else if (id.contains(Utils.TOPIC)) {
Topic topic = (Topic) getObjectNameById(id, Utils.TOPIC);
clearTopicCache(topic);
}
}
}
// TODO : need range
public List<Watch> getWatchByUser(final String userId) throws Exception {
SimpleCacheKey key = new SimpleCacheKey(WATCH_TYPE, userId);
return buildWatchOutput(watchListDataFuture.get(
new ServiceContext<ListWatchData>() {
public ListWatchData execute() {
try {
List<Watch> got = storage.getWatchByUser(userId);
return buildWatchInput(got);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
},
key
));
}
public void updateForum(String path) throws Exception {
storage.updateForum(path);
}
public SendMessageInfo getMessageInfo(String name) throws Exception {
return storage.getMessageInfo(name);
}
public Iterator<SendMessageInfo> getPendingMessages() throws Exception {
return storage.getPendingMessages();
}
public List<ForumSearchResult> getJobWattingForModerator(String[] paths) {
return storage.getJobWattingForModerator(paths);
}
public int getJobWattingForModeratorByUser(String userId) throws Exception {
return storage.getJobWattingForModeratorByUser(userId);
}
public NodeIterator search(String queryString) throws Exception {
return storage.search(queryString);
}
public void evaluateActiveUsers(String query) {
storage.evaluateActiveUsers(query);
}
public Object exportXML(String categoryId, String forumId, List<String> objectIds, String nodePath, ByteArrayOutputStream bos, boolean isExportAll) throws Exception {
return storage.exportXML(categoryId, forumId, objectIds, nodePath, bos, isExportAll);
}
public void importXML(String nodePath, ByteArrayInputStream bis, int typeImport) throws Exception {
storage.importXML(nodePath, bis, typeImport);
categoryList.select(new ScopeCacheSelector<CategoryListKey, ListCategoryData>());
forumList.select(new ScopeCacheSelector());
forumData.select(new ScopeCacheSelector());
}
public void updateTopicAccess(String userId, String topicId) {
storage.updateTopicAccess(userId, topicId);
clearUserProfile(userId);
}
public void updateForumAccess(String userId, String forumId) {
storage.updateForumAccess(userId, forumId);
clearUserProfile(userId);
}
public void writeReads() {
storage.writeReads();
}
public List<String> getBookmarks(String userName) throws Exception {
return storage.getBookmarks(userName);
}
public List<String> getBanList() throws Exception {
return storage.getBanList();
}
public boolean isBanIp(String ip) throws Exception {
return storage.isBanIp(ip);
}
public boolean addBanIP(String ip) throws Exception {
return storage.addBanIP(ip);
}
public void removeBan(String ip) throws Exception {
storage.removeBan(ip);
}
public List<String> getForumBanList(String forumId) throws Exception {
return storage.getForumBanList(forumId);
}
public boolean addBanIPForum(String ip, String forumId) throws Exception {
Forum forum = getForum(forumId.split("/")[0], forumId.split("/")[1]);
clearForumCache(forum, false);
clearForumListCache();
clearLinkListCache();
clearObjectCache(forum, false);
return storage.addBanIPForum(ip, forumId);
}
public void removeBanIPForum(String ip, String forumId) throws Exception {
Forum forum = getForum(forumId.split("/")[0], forumId.split("/")[1]);
clearForumCache(forum, false);
clearForumListCache();
clearLinkListCache();
clearObjectCache(forum, false);
storage.removeBanIPForum(ip, forumId);
}
public void updateStatisticCounts(long topicCount, long postCount) throws Exception {
storage.updateStatisticCounts(topicCount, postCount);
}
public PruneSetting getPruneSetting(String forumPath) throws Exception {
return storage.getPruneSetting(forumPath);
}
public List<PruneSetting> getAllPruneSetting() throws Exception {
return storage.getAllPruneSetting();
}
public void savePruneSetting(PruneSetting pruneSetting) throws Exception {
storage.savePruneSetting(pruneSetting);
}
public void runPrune(String forumPath) throws Exception {
storage.runPrune(forumPath);
//
clearRunPrune(forumPath);
}
private void clearRunPrune(String forumPath) throws Exception {
//
String forumId = Utils.getForumId(forumPath);
clearForumCache(Utils.getCategoryId(forumPath), forumId, false);
//
clearTopicListCache(forumId);
clearTopicListCountCache(forumId);
}
public void runPrune(PruneSetting pSetting) throws Exception {
storage.runPrune(pSetting);
//
String forumPath = pSetting.getForumPath();
clearRunPrune(forumPath);
}
public long checkPrune(PruneSetting pSetting) throws Exception {
return storage.checkPrune(pSetting);
}
public boolean populateUserProfile(User user, UserProfile profileTemplate, boolean isNew) throws Exception {
boolean isAdded = storage.populateUserProfile(user, profileTemplate, isNew);
//
if (isAdded) {
//clear list of user profiles
clearUserProfileListCache();
clearUserProfileListCountCache();
}
return isAdded;
}
public boolean deleteUserProfile(String userId) throws Exception {
clearUserProfile(userId);
clearUserProfileListCache();
clearUserProfileListCountCache();
clearAllForumCache();
return storage.deleteUserProfile(userId);
}
private void clearAllForumCache() {
postData.clearCache();
postList.clearCache();
topicData.clearCache();
forumData.clearCache();
forumList.clearCache();
categoryData.clearCache();
categoryList.clearCache();
//
miscData.clearCache();
watchListData.clearCache();
}
public void processEnabledUser(String userName, String email, boolean isEnabled) {
storage.processEnabledUser(userName, email, isEnabled);
//
clearAllForumCache();
//
clearUserProfile(userName);
try {
clearUserProfileListCache();
clearUserProfileListCountCache();
} catch (Exception e) {
LOG.warn("Failed to clear user cached.");
}
}
public void calculateDeletedUser(String userName) throws Exception {
storage.calculateDeletedUser(userName);
//
clearAllForumCache();
}
public void calculateDeletedGroup(String groupId, String groupName) throws Exception {
storage.calculateDeletedGroup(groupId, groupName);
topicData.select(new ScopeCacheSelector<TopicKey, TopicData>());
topicList.select(new ScopeCacheSelector<TopicListKey, ListTopicData>());
forumData.select(new ScopeCacheSelector<ForumKey, ForumData>());
forumList.select(new ScopeCacheSelector<ForumListKey, ListForumData>());
categoryData.select(new ScopeCacheSelector<CategoryKey, CategoryData>());
categoryList.select(new ScopeCacheSelector<CategoryListKey, ListCategoryData>());
}
public void initDataPlugin() throws Exception {
storage.initDataPlugin();
}
public void initDefaultData() throws Exception {
storage.initDefaultData();
}
public List<RoleRulesPlugin> getRulesPlugins() {
return storage.getRulesPlugins();
}
public List<InitializeForumPlugin> getDefaultPlugins() {
return storage.getDefaultPlugins();
}
public void initAutoPruneSchedules() throws Exception {
storage.initAutoPruneSchedules();
}
public void updateLastLoginDate(String userId) throws Exception {
storage.updateLastLoginDate(userId);
}
public String getLatestUser() throws Exception {
return storage.getLatestUser();
}
public List<Post> getNewPosts(int number) throws Exception {
return storage.getNewPosts(number);
}
public List<Post> getRecentPostsForUser(String userName, int number) throws Exception {
return storage.getRecentPostsForUser(userName, number);
}
public Map<String, String> getServerConfig() {
return storage.getServerConfig();
}
public KSDataLocation getDataLocation() {
return storage.getDataLocation();
}
public void setViewCountTopic(String path, String userRead) {
storage.setViewCountTopic(path, userRead);
}
public void writeViews() {
storage.writeViews();
}
public JCRPageList getPostForSplitTopic(String topicPath) throws Exception {
return storage.getPostForSplitTopic(topicPath);
}
public void movePost(String[] postPaths, String destTopicPath, boolean isCreatNewTopic, String mailContent, String link) throws Exception {
storage.movePost(postPaths, destTopicPath, isCreatNewTopic, mailContent, link);
String srcTopicPath = Utils.getTopicPath(postPaths[0]);
//
forumData.select(new ForumPathSelector(new String[] {Utils.getForumPath(srcTopicPath), Utils.getForumPath(destTopicPath)}, forumData));
clearForumListCache();
//
clearTopicCache(srcTopicPath);
clearTopicCache(destTopicPath);
//
clearPostListCache();
clearPostListCountCache(srcTopicPath);
clearPostListCountCache(destTopicPath);
//
clearUserProfile(null);
}
public void mergeTopic(String srcTopicPath, String destTopicPath, String mailContent, String link) throws Exception {
clearTopicCache(Utils.getCategoryId(srcTopicPath), Utils.getForumId(srcTopicPath), Utils.getTopicId(srcTopicPath));
storage.mergeTopic(srcTopicPath, destTopicPath, mailContent, link);
clearPostListCache();
clearPostListCountCache(Utils.getTopicId(destTopicPath));
clearTopicCache(destTopicPath);
clearForumCache(Utils.getCategoryId(destTopicPath), Utils.getForumId(destTopicPath), false);
clearTopicListCache();
clearTopicListCountCache(Utils.getForumId(destTopicPath));
//
clearUserProfile(null);
}
public void splitTopic(Topic newTopic, Post fistPost, List<String> postPathMove, String mailContent, String link) throws Exception {
storage.splitTopic(newTopic, fistPost, postPathMove, mailContent, link);
String oldTopicPath = Utils.getTopicPath(postPathMove.get(0));
clearPostListCache();
clearPostListCountCache(Utils.getTopicId(oldTopicPath));
clearTopicCache(oldTopicPath);
clearForumCache(Utils.getCategoryId(oldTopicPath), Utils.getForumId(oldTopicPath), false);
clearTopicListCache(Utils.getForumId(oldTopicPath));
clearTopicListCountCache(Utils.getForumId(oldTopicPath));
}
public void updateUserProfileInfo(String name) throws Exception {
clearUserProfile(name);
storage.updateUserProfileInfo(name);
}
public InputStream createForumRss(String objectId, String link) throws Exception {
return storage.createForumRss(objectId, link);
}
public InputStream createUserRss(String userId, String link) throws Exception {
return storage.createUserRss(userId, link);
}
public List<Post> getPosts(final PostFilter filter, final int offset, final int limit) throws Exception {
PostListKey key = new PostListKey(filter, offset, limit);
return buildPostOutput(postListFuture.get(
new ServiceContext<ListPostData>() {
public ListPostData execute() {
try {
List<Post> got = storage.getPosts(filter, offset, limit);
return buildPostInput(got);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
},
key
));
}
public int getPostsCount(final PostFilter filter) throws Exception {
PostListCountKey key = new PostListCountKey("postsCount", filter.toString(), filter.getTopicId());
SimpleCacheData<Integer> data = postListCountFuture.get(new ServiceContext<SimpleCacheData<Integer>>() {
public SimpleCacheData<Integer> execute() {
try {
return new SimpleCacheData<Integer>(storage.getPostsCount(filter));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}, key);
return data.build();
}
public void saveActivityIdForOwner(String ownerId, String type, String activityId) {
storage.saveActivityIdForOwner(ownerId, type, activityId);
}
public void saveActivityIdForOwner(String ownerPath, String activityId) {
storage.saveActivityIdForOwner(ownerPath, activityId);
}
public String getActivityIdForOwner(String ownerId, String type) {
return storage.getActivityIdForOwner(ownerId, type);
}
public String getActivityIdForOwner(String ownerPath) {
return storage.getActivityIdForOwner(ownerPath);
}
@Override
public boolean topicHasPoll(String topicPath) {
return storage.topicHasPoll(topicPath);
}
@Override
public List<ForumSearchResult> getUnifiedSearch(String textQuery,
String userId,
Integer offset,
Integer limit,
String sort,
String order) throws Exception {
return storage.getUnifiedSearch(textQuery, userId, offset, limit, sort, order);
}
@Override
public List<String> getForumUserCanView(final List<String> listOfUser, final List<String> listForumIds) throws Exception {
String key = UserProfile.USER_GUEST;
if (listOfUser != null && listOfUser.isEmpty() == false) {
key = listOfUser.toString();
}
if (listForumIds != null && listForumIds.isEmpty() == false) {
key += listForumIds.toString();
}
SimpleCacheKey canViewKey = new SimpleCacheKey(FORUM_CAN_VIEW_KEY, key);
return (List<String>) miscDataFuture.get(
new ServiceContext<SimpleCacheData>() {
public SimpleCacheData<List<String>> execute() {
try {
List<String> got = storage.getForumUserCanView(listOfUser, listForumIds);
return new SimpleCacheData<List<String>>(got);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
},
canViewKey
).build();
}
@Override
public List<UserProfile> searchUserProfileByFilter(final UserProfileFilter userProfileFilter,
final int offset,
final int limit) throws Exception {
UserProfileListKey key = new UserProfileListKey(userProfileFilter, offset, limit);
ListUserProfileData data = userProfileListFuture.get(new ServiceContext<ListUserProfileData>() {
@Override
public ListUserProfileData execute() {
try {
return buildUserProfileInput(storage.searchUserProfileByFilter(userProfileFilter, offset, limit));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}, key);
return buildUserProfileOutput(data);
}
@Override
public int getUserProfileByFilterCount(final UserProfileFilter userProfileFilter) throws Exception {
UserProfileListCountKey key = new UserProfileListCountKey(userProfileFilter);
SimpleCacheData<Integer> data = userProfileListCountFuture.get(new ServiceContext<SimpleCacheData<Integer>>() {
@Override
public SimpleCacheData<Integer> execute() {
try {
return new SimpleCacheData<Integer>(storage.getUserProfileByFilterCount(userProfileFilter));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}, key);
return data.build();
}
private ListUserProfileData buildUserProfileInput(List<UserProfile> userProfiles) {
List<UserProfileKey> listKeys = new ArrayList<UserProfileKey>();
for (UserProfile p : userProfiles) {
UserProfileKey key = new UserProfileKey(p.getUserId());
listKeys.add(key);
}
return new ListUserProfileData(listKeys);
}
private List<UserProfile> buildUserProfileOutput(ListUserProfileData data) {
if (data == null) {
return null;
}
List<UserProfile> out = new ArrayList<UserProfile>();
for (UserProfileKey k : data.getIds()) {
try {
out.add(getQuickProfile(k.getUserId()));
} catch (Exception e) {
LOG.error(e);
}
}
return out;
}
@Override
public void removeCacheUserProfile(String userName) {
clearUserProfile(userName);
}
@Override
public void saveUserPrivateOfCategory(String categoryId, String priInfo) {
storage.saveUserPrivateOfCategory(categoryId, priInfo);
}
}