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

159 lines
5.4 KiB
Java
Executable File

/* copyright (C) 2007 Chris Gilbert. 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 java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import org.apache.log4j.Logger;
import com.arsdigita.categorization.CategorizedCollection;
import com.arsdigita.categorization.Category;
import com.arsdigita.kernel.ACSObject;
import com.arsdigita.util.StringUtils;
import com.arsdigita.web.Web;
/**
* Navigation model that looks for a path held in a cookie.
*
* Cookie is maintained by NavigationFileResolver, so it is
* updated each time user changes navigation category
*
* If there is no path, or it is invalid for the current item
* an alternative path is retrieved. Subclasses may
* override getAlternativePath to implement their own logic
* for retrieving an alternative.
*
* Validation of the cookie depends on the categorised object.
* Subclasses should ensure that loadObject is implemented
* and optionally getCategorisedObject
*
* @author chris.gilbert@westsussex.gov.uk
*
*/
public class CookieNavigationModel extends GenericNavigationModel {
private static final Logger s_log =
Logger.getLogger(CookieNavigationModel.class);
protected Category[] loadCategoryPath() {
return loadCategoryPath(true);
}
/**
*
* @param validate ignore validation rules if false. This can be useful
* if implementation of getAlternativePath decides to accept the cookie
* path after all - it can then invoke loadCategoryPath (false)
*
* @return
*/
protected Category[] loadCategoryPath(boolean validateCategory) {
Category[] catArray = null;
HttpServletRequest request = Web.getRequest();
Cookie[] cookies = request.getCookies();
List catList = null;
if (cookies != null) {
for (int i = 0; i < cookies.length; i++) {
s_log.debug("cookie found - " + cookies[i].getName()
+ " with value "
+ cookies[i].getValue());
if (cookies[i].getName().equals(NavigationFileResolver.PATH_COOKIE_NAME)) {
catList = new ArrayList();
String[] path = StringUtils.split(cookies[i].getValue(),
NavigationFileResolver.PATH_COOKIE_SEPARATOR);
// validity test 1 - is cookie from this site
if (!path[0].equals(Web.getConfig().getSiteName())) {
// cookie has been set by a different Aplaws site.
// treat this as if there is no cookie.
s_log.debug("cookie was set by " + path[0]);
return getAlternativePath(false);
}
if (validateCategory) {
// validity test 2 - is current object assigned to current category
ACSObject catObj = getCategorisedObject();
if (catObj != null) {
Category cat = new Category(new BigDecimal(path[path.length - 1]));
CategorizedCollection assignedObjects =
cat.getObjects(ACSObject.BASE_DATA_OBJECT_TYPE);
assignedObjects.addEqualsFilter(ACSObject.ID, catObj.getID());
if (assignedObjects.size() == 0) {
s_log.debug("object is not categorised under final category in path");
return getAlternativePath(true);
}
}
// no object available, so we can't check if the path is valid by this method
// just assume it is valid
}
for (int j = 2; j < path.length; j++) {
Category cat = new Category(new BigDecimal(path[j]));
catList.add(cat);
s_log.debug("adding to path in request attribute " + cat.getName());
}
}
}
}
if (catList == null) {
s_log.debug("no cookie found");
return getAlternativePath(false);
}
s_log.debug("categories in list: " + catList.size());
return (Category[]) catList.toArray(new Category[(int) catList.size()]);
}
/**
*
* Invoked if the path specified in the cookie is not valid.
* Default is to return the navigation root. Subclasses may override
* to provide a more useful alternative.
*
*/
protected Category[] getAlternativePath(boolean cookieExists) {
s_log.debug("no category, delegating to parent impl");
return super.loadCategoryPath();
}
/**
* Current object is used to validate the path obtained from the cookie.
*
* Default implementation returns the object specified in loadObject method.
* For CookieNavigationModel this is null. Subclasses should provide a valid
* implementation of loadObject and optionally override getCategorisedObject
* (if the categorised object is not the same as the current object)
*
*
*/
protected ACSObject getCategorisedObject() {
// default is to retrieve the current object, but this is not always the case
// eg in CMS the content bundle is categorised, but the specific item is the loaded object
return getObject();
}
}