⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 forumrepository.java

📁 个人认为是最好的Java论坛源码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * 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 + -