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

335 lines
12 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.categorization.Category;
import com.arsdigita.kernel.ACSObject;
import com.arsdigita.kernel.Kernel;
import com.arsdigita.kernel.Party;
import com.arsdigita.kernel.permissions.PermissionService;
import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
import com.arsdigita.persistence.DataCollection;
import com.arsdigita.persistence.Filter;
import com.arsdigita.persistence.SessionManager;
import com.arsdigita.persistence.metadata.ObjectType;
import com.arsdigita.persistence.metadata.Property;
import com.arsdigita.util.Assert;
import com.arsdigita.util.LockableImpl;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import org.apache.log4j.Logger;
/**
* A class for building up a definition of parameters to
* later use for a DataCollection of ACSObjects.
*/
public class DataCollectionDefinition extends LockableImpl {
private static Logger s_log = Logger.getLogger(
DataCollectionDefinition.class);
private String m_objectType = ACSObject.BASE_DATA_OBJECT_TYPE;
private String m_specificObjectType = null;
private boolean m_filterCategory = true;
private boolean m_descendCategories = false;
private boolean m_excludeIndexObjects = true;
private boolean m_checkPermissions = false;
private boolean m_blackListTypes = false;
private ArrayList m_ordering = new ArrayList();
private ArrayList m_excludedTypes = new ArrayList();
private ArrayList m_properties = new ArrayList();
private String m_dateAttribute = null;
public final void setObjectType(String objectType) {
Assert.isUnlocked(this);
m_objectType = objectType;
validateObjectType(objectType);
}
public final void setSpecificObjectType(String specificObjectType) {
Assert.isUnlocked(this);
if (specificObjectType != null) {
validateObjectType(specificObjectType);
}
m_specificObjectType = specificObjectType;
}
public final void excludeSpecificObjectType(String specificObjectType) {
Assert.isUnlocked(this);
m_excludedTypes.add(specificObjectType);
}
public void setDateAttribute(DataCollectionRenderer renderer) {
// Stop here, if the set object type is invalid a.k.a. not installed
if(this.hasInvalidObjectType()) {
return;
}
ObjectType type = SessionManager.getMetadataRoot().getObjectType(
m_objectType);
s_log.debug("set date attribute for collection of " + type.
getQualifiedName());
if (s_log.isDebugEnabled()) {
Iterator properties = type.getProperties();
while (properties.hasNext()) {
Property prop = (Property) properties.next();
s_log.debug("object has property " + prop.getName()
+ " of class " + prop.getJavaClass().getName());
}
}
Iterator it = (renderer.getAttributes().iterator());
while (it.hasNext()) {
String attribute = (String) it.next();
s_log.debug("renderer is rendering attribute: " + attribute);
Property property = type.getProperty(attribute);
s_log.debug("property of object: " + property);
if (property != null) {
s_log.debug("Property class is " + property.getJavaClass().
getName());
}
if (property != null && property.getJavaClass().getName().equals(Date.class.
getName())) {
m_dateAttribute = attribute;
// if more than one date attribute is specified for the type included in this
// definition, then we cannot determine in the code which is to be used as the
// basis for ordering in XSL - therefore return the first encountered date.
// User can control which of the dates is used as basis for sorting by specifying
// that date attribute first in the navigation jsp
break;
}
}
}
private final void validateObjectType(String objectType) {
ObjectType type = SessionManager.getMetadataRoot().getObjectType(
objectType);
// WTF: I don't need an exception if the requested objecttype doesn't exists
// That will only ruin your website
//Assert.exists(type, ObjectType.class);
if(type == null) {
m_objectType = "";
} else {
validateObjectType(type);
}
}
public boolean hasInvalidObjectType() {
return m_objectType.isEmpty();
}
protected void validateObjectType(ObjectType type) {
// Nada
}
public final void setFilterCategory(boolean filterCategory) {
Assert.isUnlocked(this);
m_filterCategory = filterCategory;
}
public final boolean getDescendCategories() {
return m_descendCategories;
}
public final void setDescendCategories(boolean descendCategories) {
Assert.isUnlocked(this);
m_descendCategories = descendCategories;
}
public final void setExcludeIndexObjects(boolean excludeIndexObjects) {
Assert.isUnlocked(this);
m_excludeIndexObjects = excludeIndexObjects;
}
public final void setCheckPermissions(boolean checkPermissions) {
Assert.isUnlocked(this);
m_checkPermissions = checkPermissions;
}
/**
* Activates a filter for content types which are blacklisted
* in the AtoZ module.
*/
public void setBlackListTypes(boolean blackListTypes) {
Assert.isUnlocked(this);
m_blackListTypes = blackListTypes;
}
public final void addOrder(String order) {
Assert.isUnlocked(this);
if(s_log.isDebugEnabled()) {
s_log.debug(String.format("Adding order '%s' to current list of "
+ "order attributes: ", order));
for(Object orderAttr : m_ordering) {
s_log.debug(String.format("\t%s", orderAttr));
}
}
m_ordering.add(order);
}
public final void addProperty(DataCollectionProperty property) {
Assert.isUnlocked(this);
m_properties.add(property);
}
/**
* Get a collection of objects from the database defined by model or
* null if the requested object type is invalid
*
* @param model
* @return data collection or null
*/
public final DataCollection getDataCollection(NavigationModel model) {
Assert.isLocked(this);
// Stop here, if the set object type is invalid a.k.a. not installed
if(this.hasInvalidObjectType()) {
return null;
}
DataCollection objects = SessionManager.getSession().retrieve(
m_objectType);
applyFilters(objects, model);
Iterator properties = m_properties.iterator();
while (properties.hasNext()) {
DataCollectionProperty property = (DataCollectionProperty) properties.
next();
property.addProperty(objects);
}
if (model.getCategory() != null) {
// for date ordered categories, if pagination occurs, we need to ensure
// that primary ordering is the date attribute included in the renderer
// if there is one
if (s_log.isDebugEnabled()) {
s_log.debug("Category is " + model.getCategory().getID() + ": " + model.
getCategory().getName());
s_log.debug("getting data collection. Is category date ordered? "
+ Navigation.getConfig().isDateOrderedCategory(model.
getCategory(), PageState.getPageState())
+ " date attribute has been set to "
+ m_dateAttribute);
}
if (Navigation.getConfig().isDateOrderedCategory(model.getCategory(), PageState.
getPageState()) && m_dateAttribute != null) {
objects.addOrder(m_dateAttribute + " desc");
}
}
if (m_ordering.size() > 0) {
Iterator orders = m_ordering.iterator();
while (orders.hasNext()) {
objects.addOrder((String) orders.next());
}
} else {
objects.addOrder("id desc");
}
return objects;
}
/** Can be overridden to extract differently the category to inspect. */
protected Category getCategory(NavigationModel model) {
return model.getCategory();
}
protected void applyFilters(DataCollection objects,
NavigationModel model) {
if (m_specificObjectType != null) {
objects.addEqualsFilter(ACSObject.OBJECT_TYPE, m_specificObjectType);
}
Iterator excludedTypes = m_excludedTypes.iterator();
while (excludedTypes.hasNext()) {
String excludedType = excludedTypes.next().toString();
objects.addFilter(ACSObject.OBJECT_TYPE + " != '" + excludedType
+ "'");
}
if (m_blackListTypes) {
objects.addNotInSubqueryFilter(ACSObject.OBJECT_TYPE,
"com.arsdigita.navigation.blackListTypes");
}
Category cat = getCategory(model);
if (m_filterCategory && cat != null) {
if (m_descendCategories) {
Filter children = objects.addInSubqueryFilter(
getCategorizedObjectPath("id"),
"com.arsdigita.categorization.objectIDsInSubtree");
children.set("categoryID", cat.getID());
if (m_excludeIndexObjects) {
Filter moreChildren =
objects.addNotInSubqueryFilter(
getCategorizedObjectPath("id"),
"com.arsdigita.categorization.liveIndexItemsInSubtree");
moreChildren.set("categoryID", cat.getID());
}
} else {
objects.addEqualsFilter(
getCategorizedObjectPath("categories.id"),
cat.getID());
if (m_excludeIndexObjects) {
Filter moreChildren =
objects.addNotInSubqueryFilter(
getCategorizedObjectPath("id"),
"com.arsdigita.categorization.liveIndexItemsInCategory");
moreChildren.set("categoryID", cat.getID());
}
}
}
if (m_checkPermissions) {
// allow subclasses to override the permission check
checkPermissions(objects);
}
}
protected void checkPermissions(DataCollection objects) {
Party party = Kernel.getContext().getParty();
if (party == null) {
party = Kernel.getPublicUser();
}
PermissionService.filterObjects(
objects,
PrivilegeDescriptor.READ,
party.getOID());
}
protected String getCategorizedObjectPath(String fragment) {
return fragment;
}
}