📄 forumrepository.java
字号:
/*
* Copyright (c) 2003, Rafael Steil
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* 1) Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
* 2) Redistributions in binary form must reproduce the
* above copyright notice, this list of conditions and
* the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of "Rafael Steil" nor
* the names of its contributors may be used to endorse
* or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
* HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
*
* This file creation date: Apr 23, 2003 / 10:46:05 PM
* The JForum Project
* http://www.jforum.net
*/
package net.jforum.repository;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import net.jforum.SessionFacade;
import net.jforum.cache.CacheEngine;
import net.jforum.cache.Cacheable;
import net.jforum.entities.Category;
import net.jforum.entities.Config;
import net.jforum.entities.Forum;
import net.jforum.entities.LastPostInfo;
import net.jforum.entities.MostUsersEverOnline;
import net.jforum.exceptions.CategoryNotFoundException;
import net.jforum.model.CategoryModel;
import net.jforum.model.ConfigModel;
import net.jforum.model.DataAccessDriver;
import net.jforum.model.ForumModel;
import net.jforum.security.PermissionControl;
import net.jforum.security.SecurityConstants;
import net.jforum.util.CategoryOrderComparator;
import net.jforum.util.preferences.ConfigKeys;
/**
* Repository for the forums of the System.
* This repository acts like a cache system, to avoid repetitive and unnecessary SQL queries
* every time we need some info about the forums.
* To start the repository, call the method <code>start(ForumModel, CategoryModel)</code>
*
* @author Rafael Steil
* @version $Id: ForumRepository.java,v 1.32 2005/02/22 23:39:22 rafaelsteil Exp $
*/
public class ForumRepository implements Cacheable
{
private static CacheEngine cache;
private static final String FQN = "categories";
private static final String CATEGORIES_SET = "categoriesSet";
private static final String RELATION = "relationForums";
private static final String FQN_TOTAL_TOPICS = FQN + "/totalTopics";
private static final String TOTAL_MESSAGES = "totalMessages";
private static final String MOST_USERS_ONLINE = "mostUsersEverOnline";
private static final String LOADED = "loaded";
private static ForumRepository instance;
/**
* @see net.jforum.cache.Cacheable#setCacheEngine(net.jforum.cache.CacheEngine)
*/
public void setCacheEngine(CacheEngine engine)
{
cache = engine;
}
/**
* Starts the repository.
*
* @param fm The <code>ForumModel</code> instance which will be
* used to retrieve information about the forums.
* @param cm The <code>CategoryModel</code> instance which will
* be used to retrieve information about the categories.
* @throws Exception
*/
public synchronized static void start(ForumModel fm,
CategoryModel cm,
ConfigModel configModel) throws Exception
{
if (cache.get(FQN, LOADED) == null) {
instance = new ForumRepository();
instance.loadCategories(cm);
instance.loadForums(fm);
instance.loadMostUsersEverOnline(configModel);
Integer i = (Integer)cache.get(FQN, TOTAL_MESSAGES);
if (i == null) {
cache.add(FQN, TOTAL_MESSAGES, new Integer(0));
}
cache.add(FQN, LOADED, "1");
}
}
/**
* Gets a category by its id.
* A call to @link #getCategory(int, int) is made, using the
* return of <code>SessionFacade.getUserSession().getUserId()</code>
* as argument for the "userId" parameter.
*
* @param categoryId The id of the category to check
* @return <code>null</code> if the category is either not
* found or access is denied.
* @see #getCategory(int, int)
*/
public static Category getCategory(int categoryId)
{
return getCategory(SessionFacade.getUserSession().getUserId(), categoryId);
}
/**
* Gets a category by its id.
*
* @param userId The user id who is requesting the category
* @param categoryId The id of the category to get
* @return <code>null</code> if the category is either not
* found or access is denied.
* @see #getCategory(int)
*/
public static Category getCategory(int userId, int categoryId)
{
if (!isCategoryAccessible(userId, categoryId)) {
return null;
}
return (Category)cache.get(FQN, Integer.toString(categoryId));
}
public static Category getCategory(PermissionControl pc, int categoryId)
{
if (!isCategoryAccessible(pc, categoryId)) {
return null;
}
return (Category)cache.get(FQN, Integer.toString(categoryId));
}
/**
* Check is some category is accessible.
*
* @param userId The user's id who is trying to get the category
* @param categoryId The category's id to check for access rights
* @return <code>true</code> if access to the category is allowed.
*/
public static boolean isCategoryAccessible(int userId, int categoryId)
{
return isCategoryAccessible(SecurityRepository.get(userId), categoryId);
}
/**
* Check if some category is accessible.
*
* @param categoryId The category id to check for access rights
* @return <code>true</code> if access to the category is allowed.
*/
public static boolean isCategoryAccessible(int categoryId)
{
return isCategoryAccessible(SessionFacade.getUserSession().getUserId(), categoryId);
}
/**
* Check is some category is accessible.
*
* @param pc The <code>PermissionControl</code> instance containing
* all security info related to the user.
* @param categoryId the category's id to check for access rights
* @return <code>true</code> if access to the category is allowed.
*/
public static boolean isCategoryAccessible(PermissionControl pc, int categoryId)
{
return pc.canAccess(SecurityConstants.PERM_CATEGORY, Integer.toString(categoryId));
}
/**
* Gets all categories from the cache.
*
* @return <code>List</code> with the categories. Each entry is a <code>Category</code> object.
*/
public static List getAllCategories(int userId)
{
PermissionControl pc = SecurityRepository.get(userId);
List l = new ArrayList();
Iterator iter = ((Set)cache.get(FQN, CATEGORIES_SET)).iterator();
while (iter.hasNext()) {
Category c = (Category)iter.next();
if (isCategoryAccessible(pc, c.getId())) {
l.add(c);
}
}
return l;
}
/**
* Get all categories.
* A call to @link #getAllCategories(int) is made, passing
* the return of <code>SessionFacade.getUserSession().getUserId()</code>
* as the value for the "userId" argument.
*
* @return <code>List</code> with the categories. Each entry is a <code>Category</code> object.
* @see #getAllCategories(int)
*/
public static List getAllCategories()
{
return getAllCategories(SessionFacade.getUserSession().getUserId());
}
private static Category findCategoryByOrder(int order)
{
for (Iterator iter = ((Set)cache.get(FQN, CATEGORIES_SET)).iterator(); iter.hasNext(); ) {
Category c = (Category)iter.next();
if (c.getOrder() == order) {
return c;
}
}
return null;
}
/**
* Updates some category.
* This method only updated the "name" and "order" fields.
*
* @param c The category to update. The method will search for a category
* with the same id and update its data.
*/
public synchronized static void reloadCategory(Category c)
{
Category current = (Category)cache.get(FQN, Integer.toString(c.getId()));
Category currentAtOrder = findCategoryByOrder(c.getOrder());
Set tmpSet = new TreeSet(new CategoryOrderComparator());
tmpSet.addAll((Set)cache.get(FQN, CATEGORIES_SET));
if (currentAtOrder != null) {
tmpSet.remove(currentAtOrder);
cache.remove(FQN, Integer.toString(currentAtOrder.getId()));
}
tmpSet.add(c);
cache.add(FQN, Integer.toString(c.getId()), c);
if (currentAtOrder != null && c.getId() != currentAtOrder.getId()) {
tmpSet.remove(current);
currentAtOrder.setOrder(current.getOrder());
tmpSet.add(currentAtOrder);
cache.add(FQN, Integer.toString(currentAtOrder.getId()), currentAtOrder);
}
cache.add(FQN, CATEGORIES_SET, tmpSet);
}
/**
* Refreshes a category entry in the cache.
*
* @param c The category to refresh
*/
public static void refreshCategory(Category c)
{
cache.add(FQN, Integer.toString(c.getId()), c);
Set s = (Set)cache.get(FQN, CATEGORIES_SET);
cache.add(FQN, CATEGORIES_SET, s);
}
/**
* Remove a category from the cache
* @param c The category to remove. The instance should have the
* category id at least
*/
public synchronized static void removeCategory(Category c)
{
cache.remove(FQN, Integer.toString(c.getId()));
Set s = (Set)cache.get(FQN, CATEGORIES_SET);
s.remove(c);
cache.add(FQN, CATEGORIES_SET, s);
Map m = (Map)cache.get(FQN, RELATION);
for (Iterator iter = m.values().iterator(); iter.hasNext(); ) {
if (Integer.parseInt((String)iter.next()) == c.getId()) {
iter.remove();
}
}
cache.add(FQN, RELATION, m);
}
/**
* Adds a new category to the cache.
* @param c The category instance to insert in the cache.
*/
public synchronized static void addCategory(Category c)
{
String categoryId = Integer.toString(c.getId());
cache.add(FQN, categoryId, c);
Set s = (Set)cache.get(FQN, CATEGORIES_SET);
if (s == null) {
s = new TreeSet(new CategoryOrderComparator());
}
s.add(c);
cache.add(FQN, CATEGORIES_SET, s);
Map relation = (Map)cache.get(FQN, RELATION);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -