libreccm-legacy/ccm-navigation/src/com/arsdigita/navigation/NavigationConfig.java

429 lines
17 KiB
Java
Executable File

/*
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.arsdigita.navigation;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.RequestLocal;
import com.arsdigita.categorization.Category;
import com.arsdigita.categorization.CategoryCollection;
import com.arsdigita.domain.DataObjectNotFoundException;
import com.arsdigita.navigation.ui.category.Menu;
import com.arsdigita.navigation.ui.category.TreeCatProvider;
import com.arsdigita.runtime.AbstractConfig;
import com.arsdigita.util.Assert;
import com.arsdigita.util.StringUtils;
import com.arsdigita.util.UncheckedWrapperException;
import com.arsdigita.util.parameter.Parameter;
import com.arsdigita.util.parameter.BooleanParameter;
import com.arsdigita.util.parameter.IntegerParameter;
import com.arsdigita.util.parameter.StringArrayParameter;
import com.arsdigita.util.parameter.StringParameter;
import com.arsdigita.util.parameter.ClassParameter;
import com.arsdigita.util.parameter.ResourceParameter;
import com.arsdigita.web.Application;
import java.io.InputStream;
// import java.io.IOException;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.lang.reflect.Constructor;
import org.apache.log4j.Logger;
/**
* Configuration record for the navigation app
*
* @author Daniel Berrange
*/
public final class NavigationConfig extends AbstractConfig {
private static final Logger s_log = Logger.getLogger(NavigationConfig.class);
/**
* The cache lifetime for category index pages in seconds. Default 1 hour
*/
private final Parameter m_indexPageCacheLifetime = new IntegerParameter(
"com.arsdigita.navigation.index_page_cache_lifetime",
Parameter.REQUIRED, new Integer(3600));
/**
* Generate full item URLs instead of going via search redirector. Default
* true
*/
private final Parameter m_generateItemURL = new BooleanParameter(
"com.arsdigita.navigation.generate_item_url",
Parameter.REQUIRED, new Boolean(true));
/**
* The default category template.
*/
private final Parameter m_defaultTemplate = new StringParameter(
"com.arsdigita.navigation.default_template",
Parameter.REQUIRED,
"/templates/ccm-navigation/navigation/nav-default.jsp");
/**
* If no template for category, should it get template from parent, or fall
* back on default? Default: true
*/
private final Parameter m_inheritTemplates;
// Removed, use content-section config directly instead!
// ContentSection.getConfig().getDefaultContentSection()
// /** The URL of the default content section. Default: /content/ */
// private final Parameter m_defaultContentSectionURL;
private final Parameter m_relatedItemsContext;
private final Parameter m_defaultModelClass;
private final Parameter m_defaultCatRootPath;
private final Parameter m_relatedItemsFactory;
private final Parameter m_traversalAdapters;
private final Parameter m_categoryMenuShowNephews;
private final Parameter m_categoryMenuShowGrandChildren;
// Quasimodo: Begin
private final Parameter m_categoryMenuShowGrandChildrenMax;
private final Parameter m_categoryMenuShowGrandChildrenMin;
private final Parameter m_categoryMenuShowGrandChildrenLimit;
// Quasimodo: End
private final Parameter m_dateOrderCategories;
private final Parameter m_topLevelDateOrderCategories;
/**
* Class that provides categories included in menu for any categories that
* do not have an alternative provider registered
*/
private final Parameter m_defaultMenuCatProvider;
private static Set s_fixedDateOrderCats = null;
private Category m_defaultCategoryRoot = null;
// maybe 2 lookups in a single request so prevent double overhead
private RequestLocal m_allDateOrderCategories = new RequestLocal() {
public Object initialValue(PageState state) {
return getCurrentDateOrderCategories();
}
};
private NavigationModel m_defaultModel = null;
private TreeCatProvider m_treeCatProvider = null;
public NavigationConfig() {
// not desirable default value (IMHO) but retains existing behaviour
m_inheritTemplates = new BooleanParameter(
"com.arsdigita.navigation.inherit_templates",
Parameter.REQUIRED, new Boolean(true));
m_relatedItemsContext = new StringParameter(
"com.arsdigita.navigation.related_items_context",
Parameter.REQUIRED, "subject");
m_defaultModelClass = new StringParameter(
"com.arsdigita.navigation.default_nav_model",
Parameter.REQUIRED, ApplicationNavigationModel.class.getName());
m_defaultCatRootPath = new StringParameter(
"com.arsdigita.navigation.default_cat_root_path",
Parameter.REQUIRED, "/navigation/");
m_relatedItemsFactory = new ClassParameter(
"com.arsdigita.navigation.related_items_factory",
Parameter.REQUIRED, RelatedItemsQueryFactoryImpl.class);
m_traversalAdapters = new ResourceParameter(
"com.arsdigita.navigation.traversal_adapters",
Parameter.REQUIRED,
"/WEB-INF/resources/navigation-adapters.xml");
m_categoryMenuShowNephews = new BooleanParameter(
"com.arsdigita.navigation.category_menu_show_nephews",
Parameter.OPTIONAL, new Boolean(false));
// Quasimodo: Begin
m_categoryMenuShowGrandChildren = new StringParameter(
"com.arsdigita.navigation.category_menu_show_grand_children",
Parameter.OPTIONAL, "false");
m_categoryMenuShowGrandChildrenMax = new IntegerParameter(
"com.arsdigita.navigation.category_menu_show_grand_children_max",
Parameter.OPTIONAL, new Integer(0));
m_categoryMenuShowGrandChildrenMin = new IntegerParameter(
"com.arsdigita.navigation.category_menu_show_grand_children_min",
Parameter.OPTIONAL, new Integer(1));
m_categoryMenuShowGrandChildrenLimit = new IntegerParameter(
"com.arsdigita.navigation.category_menu_show_grand_children_limit",
Parameter.OPTIONAL, new Integer(1));
// Quasimodo: End
m_dateOrderCategories = new StringArrayParameter(
"com.arsdigita.navigation.date_order_categories",
Parameter.OPTIONAL, new String[0]);
m_topLevelDateOrderCategories = new StringArrayParameter(
"com.arsdigita.navigation.top_level_date_order_categories",
Parameter.OPTIONAL, new String[0]);
m_defaultMenuCatProvider = new ClassParameter(
"com.arsdigita.navigation.default_menu_cat_provider",
Parameter.OPTIONAL, null);
register(m_indexPageCacheLifetime);
register(m_generateItemURL);
register(m_defaultTemplate);
register(m_inheritTemplates);
// Removed, use content-section config directly instead!
// ContentSection.getConfig().getDefaultContentSection()
// register(m_defaultContentSectionURL);
register(m_relatedItemsContext);
register(m_defaultModelClass);
register(m_defaultCatRootPath);
register(m_relatedItemsFactory);
register(m_traversalAdapters);
register(m_categoryMenuShowNephews);
register(m_categoryMenuShowGrandChildren);
// Quasimodo: Begin
register(m_categoryMenuShowGrandChildrenMax);
register(m_categoryMenuShowGrandChildrenMin);
register(m_categoryMenuShowGrandChildrenLimit);
// Quasimodo: End
register(m_dateOrderCategories);
register(m_topLevelDateOrderCategories);
register(m_defaultMenuCatProvider);
loadInfo();
// Quasimodo: Begin
// Checking Paramter
String param = new String((String) get(m_categoryMenuShowGrandChildren));
if (param.equals("false") || param.equals("adaptive") || param.equals(
"true")) {
set(m_categoryMenuShowGrandChildren, param);
} else {
s_log.error(
"com.arsdigita.navigation.category_menu_show_grand_children: "
+ "Invalid setting " + param + ". Falling back to false.");
set(m_categoryMenuShowGrandChildren, "false");
}
// Quasimodo: End
}
public final long getIndexPageCacheLifetime() {
return ((Integer) get(m_indexPageCacheLifetime)).longValue();
}
public final boolean getGenerateItemURL() {
return ((Boolean) get(m_generateItemURL)).booleanValue();
}
public final String getDefaultTemplate() {
return (String) get(m_defaultTemplate);
}
public final boolean inheritTemplates() {
return ((Boolean) get(m_inheritTemplates)).booleanValue();
}
// Removed, use content-section config directly instead!
// ContentSection.getConfig().getDefaultContentSection()
// public final String getDefaultContentSectionURL() {
// return (String)get(m_defaultContentSectionURL);
// }
public final String getRelatedItemsContext() {
return (String) get(m_relatedItemsContext);
}
public final String getDefaultCategoryRootPath() {
return (String) get(m_defaultCatRootPath);
}
public final Class getRelatedItemsFactory() {
return (Class) get(m_relatedItemsFactory);
}
public final synchronized NavigationModel getDefaultModel() {
if (null != m_defaultModel) {
return m_defaultModel;
}
String defaultModelClassName = (String) get(m_defaultModelClass);
try {
Class defaultModelClass = Class.forName(defaultModelClassName);
Constructor cons = defaultModelClass.getConstructor(new Class[]{});
m_defaultModel = (NavigationModel) cons.newInstance(new Object[]{});
} catch (Exception ex) {
throw new UncheckedWrapperException(ex);
}
return m_defaultModel;
}
public final synchronized Category getDefaultCategoryRoot() {
if (null != m_defaultCategoryRoot) {
return m_defaultCategoryRoot;
}
String defaultCatRootPath = (String) get(m_defaultCatRootPath);
Application app = Application.retrieveApplicationForPath(
defaultCatRootPath);
Assert.exists(app, Application.class);
Category m_defaultCategoryRoot = Category.getRootForObject(app);
Assert.exists(m_defaultCategoryRoot, Category.class);
return m_defaultCategoryRoot;
}
InputStream getTraversalAdapters() {
return (InputStream) get(m_traversalAdapters);
}
public final boolean getCategoryMenuShowNephews() {
return ((Boolean) get(m_categoryMenuShowNephews)).booleanValue();
}
// Quasimodo: Begin
public final String getCategoryMenuShowGrandChildren() {
return (String) get(m_categoryMenuShowGrandChildren);
}
public final long getCategoryMenuShowGrandChildrenMax() {
return ((Integer) get(m_categoryMenuShowGrandChildrenMax)).longValue();
}
public final long getCategoryMenuShowGrandChildrenMin() {
return ((Integer) get(m_categoryMenuShowGrandChildrenMin)).longValue();
}
public final long getCategoryMenuShowGrandChildrenLimit() {
return ((Integer) get(m_categoryMenuShowGrandChildrenLimit)).longValue();
}
// Quasimodo: End
/**
* retrieve a collection of categories to order by date. Collection includes
* categories directly specified as date ordered and also all subcategories
* of categories specified as being top level date ordered categories in
* config
*
* @return
*/
public Collection getDateOrderedCategories(PageState state) {
Collection categories = null;
if (state == null) {
categories = getCurrentDateOrderCategories();
} else {
categories = (Collection) m_allDateOrderCategories.get(state);
}
return categories;
}
public boolean isDateOrderedCategory(Category cat, PageState state) {
return getDateOrderedCategories(state).contains(cat.getID().toString());
}
private Collection getCurrentDateOrderCategories() {
if (s_fixedDateOrderCats == null) {
populateFixedDateOrderCats();
}
String[] topLevelCats = (String[]) get(m_topLevelDateOrderCategories);
Set allCats = new HashSet();
allCats.addAll(s_fixedDateOrderCats);
for (int i = 0; i < topLevelCats.length; i++) {
try {
String[] categoryArray = StringUtils.split(topLevelCats[i], ':');
String order = "";
if (categoryArray.length > 1) {
order = ":" + categoryArray[1];
}
Category topLevelCat = new Category(new BigDecimal(
categoryArray[0]));
s_log.debug("retrieved top level category " + topLevelCat);
Set childCats = new HashSet();
CategoryCollection children = topLevelCat.getDescendants();
while (children.next()) {
BigDecimal id = children.getCategory().getID();
childCats.add(id.toString() + order);
}
allCats.addAll(childCats);
} catch (DataObjectNotFoundException e) {
// non existent category id specified in configuration. Output warning to
// logs and continue
s_log.warn("Category with id " + topLevelCats[i]
+ " specified in configuration as a top level date order category, "
+ "but the category does not exist");
} catch (NumberFormatException e) {
// non number specified in configuration. Output warning to
// logs and continue
s_log.warn("Category with id " + topLevelCats[i]
+ " specified in configuration as a top level date order category, "
+ "but this is not a valid number");
}
}
return allCats;
}
// synchronised because set isn't - potential to
// create and cache very odd set if navigation page is accessed
// concurrently first time after server restart
private synchronized void populateFixedDateOrderCats() {
String[] catArray = (String[]) get(m_dateOrderCategories);
s_fixedDateOrderCats = new HashSet();
for (int i = 0; i < catArray.length; i++) {
try {
// don't need to do this, as including invalid or non existent
// ids will not have any adverse effects, but this gives us a chance to
// provide some warning to the users when they find that a category
// they expected to be date ordered isn't because they mistyped etc.
// This only occurs once, first time navigation page is accessed after
// server restart
String[] category = StringUtils.split(catArray[i], ':');
Category cat = new Category(new BigDecimal(category[0]));
} catch (DataObjectNotFoundException e) {
// non existent category id specified in configuration. Output warning to
// logs and continue
s_log.warn("Category with id " + catArray[i]
+ " specified in configuration as a date ordered category, but the category"
+ "does not exist");
} catch (NumberFormatException e) {
// non number specified in configuration. Output warning to
// logs and continue
s_log.warn("Category with id " + catArray[i]
+ " specified in configuration as a date ordered category, "
+ "but this is not a valid number");
}
s_fixedDateOrderCats.add(catArray[i]);
}
}
public final TreeCatProvider getDefaultMenuCatProvider() {
if (null == m_treeCatProvider) {
try {
Class providerClass = (Class) get(m_defaultMenuCatProvider);
if (providerClass == null) {
m_treeCatProvider = new Menu();
} else {
m_treeCatProvider = (TreeCatProvider) providerClass
.newInstance();
}
} catch (Exception ex) {
throw new UncheckedWrapperException(ex);
}
}
return m_treeCatProvider;
}
}