Java tutorial
/* * The contents of this file are subject to the Mozilla Public License Version 1.1 * (the "License"); you may not use this file except in compliance with the License. * You may obtain a copy of the License at <http://www.mozilla.org/MPL/>. * * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT * WARRANTY OF ANY KIND, either express or implied. See the License for the specific * language governing rights and limitations under the License. * * The Original Code is the Venice Web Communities System. * * The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>, * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are * Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. * * Contributor(s): */ package com.silverwrist.venice.community; import java.util.*; import org.apache.commons.collections.*; import org.apache.log4j.Logger; import org.w3c.dom.*; import com.silverwrist.util.xml.*; import com.silverwrist.dynamo.except.*; import com.silverwrist.dynamo.iface.*; import com.silverwrist.dynamo.util.*; import com.silverwrist.venice.SearchMode; import com.silverwrist.venice.iface.VeniceCategory; public class CategoryManager implements NamedObject, ComponentInitialize, ComponentShutdown, CategoryService { /*-------------------------------------------------------------------------------- * Static data members *-------------------------------------------------------------------------------- */ private static Logger logger = Logger.getLogger(CategoryManager.class); /*-------------------------------------------------------------------------------- * Attributes *-------------------------------------------------------------------------------- */ private String m_name; // this object's name private CategoryOps m_ops; // database operations private ReferenceMap m_categories; // cached category values /*-------------------------------------------------------------------------------- * Constructor *-------------------------------------------------------------------------------- */ public CategoryManager() { m_categories = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.SOFT); } // end constructor /*-------------------------------------------------------------------------------- * Internal operations *-------------------------------------------------------------------------------- */ private final List convertList(List base) throws DatabaseException { if (base.isEmpty()) return Collections.EMPTY_LIST; ArrayList rc = new ArrayList(base.size()); synchronized (this) { // convert the tuples list ont a full category list Iterator it = base.iterator(); while (it.hasNext()) { // get the tuple from the list and convert it CategoryTuple tuple = (CategoryTuple) (it.next()); Integer key = new Integer(tuple.getCategoryID()); VeniceCategory cat = (VeniceCategory) (m_categories.get(key)); if (cat == null) { // need to create a new category object and add it if (tuple.getParentCategoryID() < 0) cat = new CategoryImpl(this, tuple.getCategoryID(), tuple.getSymlink(), tuple.getName()); else cat = new CategoryImpl(lookup(tuple.getParentCategoryID()), tuple.getCategoryID(), tuple.getSymlink(), tuple.getName()); m_categories.put(key, cat); } // end if rc.add(cat); } // end while } // end synchronized block return Collections.unmodifiableList(rc); } // end convertList /*-------------------------------------------------------------------------------- * Implementations from interface NamedObject *-------------------------------------------------------------------------------- */ public String getName() { return m_name; } // end getName /*-------------------------------------------------------------------------------- * Implementations from interface ComponentInitialize *-------------------------------------------------------------------------------- */ /** * Initialize the component. * * @param config_root Pointer to the section of the Dynamo XML configuration file that configures this * particular component. This is to be considered "read-only" by the component. * @param services An implementation of {@link com.silverwrist.dynamo.iface.ServiceProvider ServiceProvider} * which provides initialization services to the component. This will include an implementation * of {@link com.silverwrist.dynamo.iface.ObjectProvider ObjectProvider} which may be used to * get information about other objects previously initialized by the application. * @exception com.silverwrist.dynamo.except.ConfigException If an error is encountered in the component * configuration. */ public void initialize(Element config_root, ServiceProvider services) throws ConfigException { logger.info("CategoryManager initializing"); XMLLoader loader = XMLLoader.get(); String name_pool = null; try { // verify the right node name loader.verifyNodeName(config_root, "object"); // get the object's name m_name = loader.getAttribute(config_root, "name"); // get the name of the database pool DOMElementHelper config_root_h = new DOMElementHelper(config_root); Element foo = loader.getSubElement(config_root_h, "database"); name_pool = loader.getAttribute(foo, "connection"); } // end try catch (XMLLoadException e) { // error loading XML config data logger.fatal("XML loader exception in CategoryManager", e); throw new ConfigException(e); } // end catch // Get the database connection pool. DBConnectionPool pool = GetObjectUtils.getDatabaseConnection(services, name_pool); // Get the operations object. m_ops = CategoryOps.get(pool); } // end initialize /*-------------------------------------------------------------------------------- * Implementations from interface ComponentShutdown *-------------------------------------------------------------------------------- */ public void shutdown() { m_categories.clear(); m_ops.dispose(); m_ops = null; } // end shutdown /*-------------------------------------------------------------------------------- * Implementations from interface CategoryService *-------------------------------------------------------------------------------- */ public boolean isValidCategoryID(int catid) { if (catid == -1) return true; // valid by definition; it means "Top" if (m_categories.containsKey(new Integer(catid))) return true; // already present in our category map, it must be OK try { // call down to the database return m_ops.verifyCategoryID(catid); } // end try catch (DatabaseException e) { // don't throw this exception! logger.warn("CategoryManager.isValidCategoryID(): database failure", e); } // end catch return false; // default return } // end isValidCategoryID public List getRootCategoryList() throws DatabaseException { return getCategorySublist(-1); } // end getRootCategoryList public VeniceCategory getCategory(int catid) throws DatabaseException { return (VeniceCategory) lookup(catid); } // end getCategory public List searchForCategories(SearchMode mode, String term, int offset, int count) throws DatabaseException { return convertList(m_ops.search(mode, term, offset, count)); } // end searchForCategories public int getSearchCategoryCount(SearchMode mode, String term) throws DatabaseException { return m_ops.getSearchCount(mode, term); } // end getSearchCategoryCount /*-------------------------------------------------------------------------------- * External operations *-------------------------------------------------------------------------------- */ synchronized CategoryImpl lookup(int catid) throws DatabaseException { Integer key = new Integer(catid); CategoryImpl rc = (CategoryImpl) (m_categories.get(key)); if (rc != null) return rc; if (catid < 0) { // for "TOP" category, handle specially rc = new CategoryImpl(this); m_categories.put(key, rc); return rc; } // end if // look up the tuple for this category CategoryTuple tuple = m_ops.getCategory(catid); if (tuple == null) { // category not found! DatabaseException de = new DatabaseException(CategoryManager.class, "CommunityMessages", "cat.notfound"); de.setParameter(0, String.valueOf(catid)); throw de; } // end if if (tuple.getParentCategoryID() < 0) rc = new CategoryImpl(this, tuple.getCategoryID(), tuple.getSymlink(), tuple.getName()); else // recurse to look up the parent, and so on rc = new CategoryImpl(lookup(tuple.getParentCategoryID()), tuple.getCategoryID(), tuple.getSymlink(), tuple.getName()); m_categories.put(key, rc); return rc; } // end lookup List getCategorySublist(int parentid) throws DatabaseException { return convertList(m_ops.getCategoriesList(parentid)); } // end getCategorySublist synchronized VeniceCategory canonicalize(CategoryImpl obj) { Integer key = new Integer(obj.getCategoryID()); VeniceCategory rc = (VeniceCategory) (m_categories.get(key)); if (rc == null) { // it wasn't in our refmap - it is now! m_categories.put(key, obj); rc = obj; } // end if else // dispose of the unneeded second copy obj.dispose(); return rc; } // end canonicalize } // end class CategoryManager