Modifed the menu component of navigation. It is now possible to configure

the properties for showing grand children from the JSP. Settings in the JSP
will override the settings from configuration.


git-svn-id: https://svn.libreccm.org/ccm/trunk@2831 8810af33-2d31-482b-a856-94f89814c4df
master
jensp 2014-09-03 10:49:51 +00:00
parent 4648c842e8
commit cdc551736f
1 changed files with 165 additions and 123 deletions

View File

@ -15,13 +15,13 @@
* License along with this library; if not, write to the Free Software * License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
package com.arsdigita.navigation.ui.category; package com.arsdigita.navigation.ui.category;
import com.arsdigita.categorization.Category; import com.arsdigita.categorization.Category;
import com.arsdigita.categorization.CategoryCollection; import com.arsdigita.categorization.CategoryCollection;
import com.arsdigita.domain.DomainObjectFactory; import com.arsdigita.domain.DomainObjectFactory;
import com.arsdigita.navigation.Navigation; import com.arsdigita.navigation.Navigation;
import com.arsdigita.navigation.NavigationConfig;
import com.arsdigita.persistence.DataCollection; import com.arsdigita.persistence.DataCollection;
import com.arsdigita.persistence.SessionManager; import com.arsdigita.persistence.SessionManager;
import com.arsdigita.xml.Element; import com.arsdigita.xml.Element;
@ -34,111 +34,155 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
/** /**
* CategoryTree component displays children of all categories * CategoryTree component displays children of all categories in the current path.
* in the current path.
* *
* Updated cg - TreeCatProvider interface introduced to * Updated cg - TreeCatProvider interface introduced to provide the categories to be included in the
* provide the categories to be included in the menu. The * menu. The TreeCatProvider returns a collection of all categories that should be included in the
* TreeCatProvider returns a collection of all categories * tree - the AbstractTree organises children under their correct parents. This class provides the
* that should be included in the tree - the AbstractTree * default implementation of TreeCatProvider. A different default provider may be set in config and
* organises children under their correct parents. This class
* provides the default implementation of TreeCatProvider.
* A different default provider may be set in config and
* providers may be registered for specific categories. * providers may be registered for specific categories.
* *
* Note - the final tree will only include categories where there * Note - the final tree will only include categories where there is a complete trail from a
* is a complete trail from a category in the path to the * category in the path to the category output by the provider
* category output by the provider
* *
* an alternative provider - PopulatedSubCategoryTreeCatProvider * an alternative provider - PopulatedSubCategoryTreeCatProvider is included in this package - it
* is included in this package - it avoids access denied errors * avoids access denied errors and blank index pages by restricting the categories under the current
* and blank index pages by restricting the categories under * categories to those that contain at least one item visible to the current user
* the current categories to those that contain at least one item
* visible to the current user
* *
* Note 2 - changes do not affect the configurable display of * Note 2 - changes do not affect the configurable display of nephews & grandchildren as these are
* nephews & grandchildren as these are added to the path list * added to the path list
*/ */
public class Menu extends AbstractTree implements TreeCatProvider { public class Menu extends AbstractTree implements TreeCatProvider {
/** /**
*Text for the additional xml attribute for categorys having more children than supposed to be shown. * Text for the additional xml attribute for categorys having more children than supposed to be
* shown.
*/ */
public static final String MORE_ATTRIB = "showMore"; public static final String MORE_ATTRIB = "showMore";
/** /**
*used to log errors/warnings etc. to catalina-stdout * used to log errors/warnings etc. to catalina-stdout
*/ */
// public static Logger s_log = Logger.getLogger(Menu.class); ?? public or private ?? // public static Logger s_log = Logger.getLogger(Menu.class); ?? public or private ??
private static Logger s_log = Logger.getLogger(Menu.class); private static Logger s_log = Logger.getLogger(Menu.class);
private static Map treeCatProviders = new HashMap(); private static Map treeCatProviders = new HashMap();
public static TreeCatProvider defaultProvider = Navigation.getConfig().getDefaultMenuCatProvider(); public static TreeCatProvider defaultProvider = Navigation.getConfig().
getDefaultMenuCatProvider();
private String showGrandChildren;
private long showGrandChildrenMax;
private long showGrandChildrenMin;
private long showGrandChildrenLimit;
private boolean showNephews;
public Menu() {
super();
final NavigationConfig config = Navigation.getConfig();
showGrandChildren = config.getCategoryMenuShowGrandChildren();
showGrandChildrenMin = config.getCategoryMenuShowGrandChildrenMin();
showGrandChildrenMax = config.getCategoryMenuShowGrandChildrenMax();
showGrandChildrenLimit = config.getCategoryMenuShowGrandChildrenLimit();
showNephews = config.getCategoryMenuShowNephews();
}
/** /**
* enables a different strategy to be used to retrieve categories * enables a different strategy to be used to retrieve categories for a specific category
* for a specific category
*/ */
public static void registerTreeCatProvider(Category cat, TreeCatProvider provider) { public static void registerTreeCatProvider(Category cat, TreeCatProvider provider) {
s_log.debug("registering " s_log.debug("registering "
+ provider.getClass().getName() + provider.getClass().getName()
+ " for category " + " for category "
+ cat.getName()); + cat.getName());
treeCatProviders.put(cat, provider); treeCatProviders.put(cat, provider);
} }
public String getShowGrandChildren() {
public Element generateXML(HttpServletRequest request, return showGrandChildren;
HttpServletResponse response) { }
public void setShowGrandChildren(final String showGrandChildren) {
this.showGrandChildren = showGrandChildren;
}
public long getShowGrandChildrenMax() {
return showGrandChildrenMax;
}
public void setShowGrandChildrenMax(final long showGrandChildrenMax) {
this.showGrandChildrenMax = showGrandChildrenMax;
}
public long getShowGrandChildrenMin() {
return showGrandChildrenMin;
}
public void setShowGrandChildrenMin(final long showGrandChildrenMin) {
this.showGrandChildrenMin = showGrandChildrenMin;
}
public long getShowGrandChildrenLimit() {
return showGrandChildrenLimit;
}
public void setShowGrandChildrenLimit(final long showGrandChildrenLimit) {
this.showGrandChildrenLimit = showGrandChildrenLimit;
}
public boolean isShowNephews() {
return showNephews;
}
public void setShowNephews(final boolean showNephews) {
this.showNephews = showNephews;
}
public Element generateXML(final HttpServletRequest request,
final HttpServletResponse response) {
//stores how deep we are inside the menu structure //stores how deep we are inside the menu structure
Category[] path = getModel().getCategoryPath(); Category[] path = getModel().getCategoryPath();
if (path == null || path.length == 0) { if (path == null || path.length == 0) {
return null; return null;
} }
List catIDs = new ArrayList(); List catIDs = new ArrayList();
List selectedIDsList = new ArrayList(); List selectedIDsList = new ArrayList();
for (int i = 0 ; i < path.length ; i++) { for (int i = 0; i < path.length; i++) {
catIDs.add(path[i].getID()); catIDs.add(path[i].getID());
selectedIDsList.add(path[i].getID()); selectedIDsList.add(path[i].getID());
} }
BigDecimal[] selectedIDs = BigDecimal[] selectedIDs
(BigDecimal[]) selectedIDsList.toArray( = (BigDecimal[]) selectedIDsList.toArray(
new BigDecimal[selectedIDsList.size()]); new BigDecimal[selectedIDsList.size()]);
// Quasimodo: Begin // Quasimodo: Begin
// If show_grand_children is set to "true" or "adaptive" // If show_grand_children is set to "true" or "adaptive"
if (Navigation.getConfig().getCategoryMenuShowGrandChildren().equals("true") || if (showGrandChildren.equals("true") || showGrandChildren.equals("adaptive")) {
Navigation.getConfig().getCategoryMenuShowGrandChildren().equals("adaptive")) {
// should add the children categories as potential parents // should add the children categories as potential parents
if (path.length > 0) { if (path.length > 0) {
// Adaptive Mode // Adaptive Mode
if(Navigation.getConfig().getCategoryMenuShowGrandChildren().equals("adaptive")) { if (showGrandChildren.equals("adaptive")) {
// Show grand children of the first n levels // Show grand children of the first n levels
for(int path_it = 0; for (int path_it = 0;
path_it < path.length && path_it < Navigation.getConfig().getCategoryMenuShowGrandChildrenLimit(); path_it < path.length && path_it < showGrandChildrenLimit;
path_it++) { path_it++) {
// add children of all the catgories along the path until limit is reached // add children of all the catgories along the path until limit is reached
BigDecimal categoryID = path[path_it].getID(); BigDecimal categoryID = path[path_it].getID();
addChildrenOfToList(catIDs, categoryID, categoryID); addChildrenOfToList(catIDs, categoryID, categoryID);
if (Navigation.getConfig().getCategoryMenuShowNephews()) { if (showNephews) {
// should add the sibling categories as potential parents // should add the sibling categories as potential parents
if (path_it > 1) { if (path_it > 1) {
BigDecimal parentID = path[path_it - 1].getID(); BigDecimal parentID = path[path_it - 1].getID();
@ -146,75 +190,75 @@ public class Menu extends AbstractTree implements TreeCatProvider {
} }
} }
} }
} else { } else {
// add children of the current category // add children of the current category
BigDecimal categoryID = path[path.length-1].getID(); BigDecimal categoryID = path[path.length - 1].getID();
addChildrenOfToList(catIDs, categoryID, categoryID); addChildrenOfToList(catIDs, categoryID, categoryID);
} }
} }
} }
// Quasimodo: End // Quasimodo: End
if (Navigation.getConfig().getCategoryMenuShowNephews()) { if (showNephews) {
// should add the sibling categories as potential parents // should add the sibling categories as potential parents
if (path.length > 1) { //> 1 if (path.length > 1) { //> 1
BigDecimal categoryID = path[path.length-1].getID(); BigDecimal categoryID = path[path.length - 1].getID();
BigDecimal parentID = path[path.length-2].getID(); BigDecimal parentID = path[path.length - 2].getID();
addChildrenOfToList(catIDs, categoryID, parentID); addChildrenOfToList(catIDs, categoryID, parentID);
} }
} }
DataCollection treeCats = getTreeCatProvider(path[path.length - 1]).getTreeCats( DataCollection treeCats = getTreeCatProvider(path[path.length - 1]).getTreeCats(
catIDs, catIDs,
selectedIDs); selectedIDs);
treeCats.addPath("parents.link.sortKey"); treeCats.addPath("parents.link.sortKey");
treeCats.addPath("parents.id"); treeCats.addPath("parents.id");
if (s_log.isDebugEnabled()) { if (s_log.isDebugEnabled()) {
while (treeCats.next()) { while (treeCats.next()) {
Category cat = Category cat
(Category) DomainObjectFactory.newInstance( = (Category) DomainObjectFactory.newInstance(
treeCats.getDataObject()); treeCats.getDataObject());
s_log.debug("treecats - " + cat.getID() + " " + cat.getName()); s_log.debug("treecats - " + cat.getID() + " " + cat.getName());
} }
treeCats.rewind(); treeCats.rewind();
for (int i = 0; i < selectedIDs.length; i++) { for (int i = 0; i < selectedIDs.length; i++) {
Category selected = new Category(selectedIDs[i]); Category selected = new Category(selectedIDs[i]);
s_log.debug("selected - " s_log.debug("selected - "
+ selected.getID() + selected.getID()
+ " " + " "
+ selected.getName()); + selected.getName());
} }
} }
Element content = Navigation.newElement("categoryMenu"); Element content = Navigation.newElement("categoryMenu");
exportAttributes(content); exportAttributes(content);
Element rootEl = generateTreeXML(request, Element rootEl = generateTreeXML(request,
response, response,
path[0], path[0],
new CategoryCollection(treeCats), new CategoryCollection(treeCats),
selectedIDs); selectedIDs);
if (rootEl != null) { if (rootEl != null) {
content.addContent(rootEl); content.addContent(rootEl);
} }
return content; return content;
} }
/** /**
* @param category * @param category
*/ */
protected TreeCatProvider getTreeCatProvider(Category category) { protected TreeCatProvider getTreeCatProvider(Category category) {
TreeCatProvider provider = (TreeCatProvider) treeCatProviders.get(category); TreeCatProvider provider = (TreeCatProvider) treeCatProviders.get(category);
s_log.debug(treeCatProviders.size() + " providers registered"); s_log.debug(treeCatProviders.size() + " providers registered");
if (provider == null) { if (provider == null) {
s_log.debug("No provider registered for this category"); s_log.debug("No provider registered for this category");
provider = defaultProvider; provider = defaultProvider;
@ -223,43 +267,42 @@ public class Menu extends AbstractTree implements TreeCatProvider {
} }
return provider; return provider;
} }
/** /**
* retrieve data collection of all categories that are to appear in the menu * retrieve data collection of all categories that are to appear in the menu Default retrieves
* Default retrieves all children of categories included in catList. * all children of categories included in catList.
* *
* @param catIDs * @param catIDs
* @param selectedIDs * @param selectedIDs
* @return * @return
*/ */
public DataCollection getTreeCats(List catIDs, BigDecimal[] selectedIDs) { public DataCollection getTreeCats(List catIDs, BigDecimal[] selectedIDs) {
DataCollection treeCats = DataCollection treeCats
SessionManager.getSession().retrieve( = SessionManager.getSession().retrieve(
Category.BASE_DATA_OBJECT_TYPE); Category.BASE_DATA_OBJECT_TYPE);
// Filter to all children of :ids // Filter to all children of :ids
treeCats.addFilter("parents.id in :ids").set("ids", catIDs); treeCats.addFilter("parents.id in :ids").set("ids", catIDs);
treeCats.addEqualsFilter("parents.link.relationType", Category.CHILD); treeCats.addEqualsFilter("parents.link.relationType", Category.CHILD);
return treeCats; return treeCats;
} }
/** /**
* Adds the IDs for the menu entrys to the menu.. * Adds the IDs for the menu entrys to the menu..
* *
* @param List catIDs * @param List catIDs
* @param BigDecimal categoryID * @param BigDecimal categoryID
* @param BigDecimal parentID ID of the parent menu entry... * @param BigDecimal parentID ID of the parent menu entry... only those entrys will be added who
* only those entrys will be added who have this ID as parent id * have this ID as parent id
*/ */
protected void addChildrenOfToList( protected void addChildrenOfToList(
List catIDs, List catIDs,
BigDecimal categoryID, BigDecimal categoryID,
BigDecimal parentID) { BigDecimal parentID) {
BigDecimal childID; BigDecimal childID;
DataCollection childCats = DataCollection childCats
SessionManager.getSession().retrieve( = SessionManager.getSession().retrieve(
Category.BASE_DATA_OBJECT_TYPE); Category.BASE_DATA_OBJECT_TYPE);
childCats.addFilter("parents.id = :id").set("id", parentID); childCats.addFilter("parents.id = :id").set("id", parentID);
childCats.addEqualsFilter("parents.link.relationType", Category.CHILD); childCats.addEqualsFilter("parents.link.relationType", Category.CHILD);
while (childCats.next()) { while (childCats.next()) {
@ -270,50 +313,49 @@ public class Menu extends AbstractTree implements TreeCatProvider {
} }
} }
} }
// Quasimodo: Begin // Quasimodo: Begin
// Calculating the maxChildCounter for generateNodeXML // Calculating the maxChildCounter for generateNodeXML
// This is needed for the adaptive mode of the Menu class. Calculating the maximum shown children per menu // This is needed for the adaptive mode of the Menu class. Calculating the maximum shown children per menu
protected long calcMaxChildCounter(Category cat, BigDecimal[] selected) { protected long calcMaxChildCounter(Category cat, BigDecimal[] selected) {
// Show all children of a category if: // Show all children of a category if:
// com.arsdigita.navigation.category_menu_show_grand_children is not set to adaptive or // com.arsdigita.navigation.category_menu_show_grand_children is not set to adaptive or
// com.arsdigita.navigation.category_menu_show_nephews is set to true and this category has the same parents as the active category or // com.arsdigita.navigation.category_menu_show_nephews is set to true and this category has the same parents as the active category or
// this category is part of the current path // this category is part of the current path
if(!(Navigation.getConfig().getCategoryMenuShowGrandChildren().equals("adaptive")) || if (!(showGrandChildren.equals("adaptive"))
(Navigation.getConfig().getCategoryMenuShowNephews() && || (showNephews && compareCategoryCollection(
compareCategoryCollection(cat.getParents(), new Category(selected[selected.length - 1]).getParents()) cat.getParents(), new Category(selected[selected.length - 1]).getParents()))
) || || Arrays.asList(selected).contains(cat.getID())) {
Arrays.asList(selected).contains(cat.getID())) {
return new Long(Long.MAX_VALUE).longValue(); return new Long(Long.MAX_VALUE).longValue();
} else { } else {
// Child of active category // Child of active category
if((new Category(selected[selected.length - 1])).isMemberOfSubtree(cat)) { if ((new Category(selected[selected.length - 1])).isMemberOfSubtree(cat)) {
// If com.arsdigita.navigation.category_menu_show_grand_children_max = 0 // If com.arsdigita.navigation.category_menu_show_grand_children_max = 0
if(Navigation.getConfig().getCategoryMenuShowGrandChildrenMax() == 0) { if (showGrandChildrenMax == 0) {
// Show all children // Show all children
return new Long(Long.MAX_VALUE).longValue(); return new Long(Long.MAX_VALUE).longValue();
} else { } else {
// Show com.arsdigita.navigation.category_menu_show_grand_children_max children // Show com.arsdigita.navigation.category_menu_show_grand_children_max children
return Navigation.getConfig().getCategoryMenuShowGrandChildrenMax(); return showGrandChildrenMax;
} }
} else { } else {
// Show com.arsdigita.navigation.category_menu_show_grand_children_min children // Show com.arsdigita.navigation.category_menu_show_grand_children_min children
return Navigation.getConfig().getCategoryMenuShowGrandChildrenMin(); return showGrandChildrenMin;
} }
} }
} }
} }