/** * Licensed to Apereo under one or more contributor license agreements. See the NOTICE file * distributed with this work for additional information regarding copyright ownership. Apereo * licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use * this file except in compliance with the License. You may obtain a copy of the License at the * following location: * * <p>http://www.apache.org/licenses/LICENSE-2.0 * * <p>Unless required by applicable law or agreed to in writing, software distributed under the * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing permissions and * limitations under the License. */ package org.apereo.portal.portlets.favorites; import static org.apereo.portal.layout.node.IUserLayoutFolderDescription.FAVORITES_TYPE; import static org.apereo.portal.layout.node.IUserLayoutFolderDescription.FAVORITE_COLLECTION_TYPE; import static org.apereo.portal.layout.node.IUserLayoutNodeDescription.LayoutNodeType.FOLDER; import java.util.Enumeration; import java.util.LinkedList; import java.util.List; import org.apache.commons.lang3.Validate; import org.apereo.portal.layout.IUserLayout; import org.apereo.portal.layout.node.IUserLayoutFolderDescription; import org.apereo.portal.layout.node.IUserLayoutNodeDescription; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Utility class supporting Favorites portlet. * * @since 4.1 */ public final class FavoritesUtils { protected static Logger logger = LoggerFactory.getLogger(FavoritesUtils.class); /** * Get the favorite collections of portlets (i.e. suitable folders ("tabs") in the user layout.) * Suitable layout nodes are of type folder with @type attribute favorite_collection. * * @param userLayout * @return non-null List of IUserLayoutDescriptions describing the tabs */ public static List<IUserLayoutNodeDescription> getFavoriteCollections(IUserLayout userLayout) { if (null == userLayout) { throw new IllegalArgumentException( "Cannot get favorites collections from a null userLayout"); } logger.trace("Extracting favorites collections from layout [{}].", userLayout); Enumeration<String> nodeIds = userLayout.getChildIds(userLayout.getRootId()); List<IUserLayoutNodeDescription> results = new LinkedList<IUserLayoutNodeDescription>(); while (nodeIds.hasMoreElements()) { String nodeId = nodeIds.nextElement(); try { IUserLayoutNodeDescription nodeDescription = userLayout.getNodeDescription(nodeId); String parentId = userLayout.getParentId(nodeId); String nodeName = nodeDescription.getName(); IUserLayoutNodeDescription.LayoutNodeType nodeType = nodeDescription.getType(); if (FOLDER.equals(nodeType) && nodeDescription instanceof IUserLayoutFolderDescription) { IUserLayoutFolderDescription folderDescription = (IUserLayoutFolderDescription) nodeDescription; String folderType = folderDescription.getFolderType(); if (FAVORITE_COLLECTION_TYPE.equals(folderType)) { results.add(nodeDescription); logger.trace( "Selected node with id [{}] named [{}] with " + "folderType [{}] and type [{}] as a collection of favorites.", nodeId, nodeName, folderType, nodeType); } else { logger.trace( "Rejected node with id [{}] named [{}] with " + "folderType [{}] and type [{}] as not a collection of favorites.", nodeId, nodeName, folderType, nodeType); } } else { logger.trace( "Rejected non-folder node with id [{}] named [{}] " + "with parentId [{}] and type [{}] as not a collection of favorites.", nodeId, nodeName, parentId, nodeType); } // if something goes wrong in processing a node, exclude it } catch (Exception e) { logger.error( "Error determining whether to include layout node [{}]" + " as a collection of favorites. Excluding.", nodeId, e); } } logger.debug("Extracted favorites collections [{}] from [{}]", results, userLayout); return results; } public static String getFavoriteTabNodeId(IUserLayout userLayout) { @SuppressWarnings("unchecked") Enumeration<String> childrenOfRoot = userLayout.getChildIds(userLayout.getRootId()); while (childrenOfRoot .hasMoreElements()) { //loop over folders that might be the favorites folder String nodeId = childrenOfRoot.nextElement(); try { IUserLayoutNodeDescription nodeDescription = userLayout.getNodeDescription(nodeId); IUserLayoutNodeDescription.LayoutNodeType nodeType = nodeDescription.getType(); if (FOLDER.equals(nodeType) && nodeDescription instanceof IUserLayoutFolderDescription) { IUserLayoutFolderDescription folderDescription = (IUserLayoutFolderDescription) nodeDescription; if (FAVORITES_TYPE.equalsIgnoreCase(folderDescription.getFolderType())) { return folderDescription.getId(); } } } catch (Exception e) { logger.error( "Ignoring on error a node while examining for favorites: node ID is [{}]", nodeId, e); } } logger.warn("Favorite tab was searched for but not found"); return null; //didn't find favorite tab } /** * Get the portlets that are in the folder(s) of type "favorites". * * @param userLayout * @return */ @SuppressWarnings("unchecked") public static List<IUserLayoutNodeDescription> getFavoritePortlets(IUserLayout userLayout) { logger.trace("Extracting favorite portlets from layout [{}]", userLayout); List<IUserLayoutNodeDescription> favorites = new LinkedList<IUserLayoutNodeDescription>(); Enumeration<String> childrenOfRoot = userLayout.getChildIds(userLayout.getRootId()); while (childrenOfRoot .hasMoreElements()) { //loop over folders that might be the favorites folder String nodeId = childrenOfRoot.nextElement(); try { IUserLayoutNodeDescription nodeDescription = userLayout.getNodeDescription(nodeId); String parentId = userLayout.getParentId(nodeId); String nodeName = nodeDescription.getName(); IUserLayoutNodeDescription.LayoutNodeType nodeType = nodeDescription.getType(); if (FOLDER.equals(nodeDescription.getType()) && nodeDescription instanceof IUserLayoutFolderDescription) { IUserLayoutFolderDescription folderDescription = (IUserLayoutFolderDescription) nodeDescription; if (FAVORITES_TYPE.equalsIgnoreCase(folderDescription.getFolderType())) { // TODO: assumes columns structure, but should traverse tree to collect all portlets regardless Enumeration<String> columns = userLayout.getChildIds(nodeId); //loop through columns to gather beloved portlets while (columns.hasMoreElements()) { String column = (String) columns.nextElement(); Enumeration<String> portlets = userLayout.getChildIds(column); while (portlets.hasMoreElements()) { String portlet = (String) portlets.nextElement(); IUserLayoutNodeDescription portletDescription = userLayout.getNodeDescription(portlet); favorites.add(portletDescription); } } } else { logger.trace("Ignoring non-favorites folder node [{}]", nodeDescription); } } else { logger.trace("Ignoring non-folder node [{}]", nodeDescription); } } catch (Exception e) { logger.error( "Ignoring on error a node while examining for favorites: node ID is [{}]", nodeId, e); } } logger.debug("Extracted favorite portlets [{}] from [{}]", favorites, userLayout); return favorites; } /** * True if the layout contains any favorited collections or favorited individual portlets, false * otherwise. * * @param layout non-null user layout that might contain favorite portlets and/or collections * @return true if the layout contains at least one favorited portlet or collection, false * otherwise * @throws IllegalArgumentException if layout is null */ public static boolean hasAnyFavorites(IUserLayout layout) { Validate.notNull(layout, "Cannot determine whether a null layout contains favorites."); // (premature) performance optimization: short circuit returns true if nonzero favorite portlets return (!getFavoritePortlets(layout).isEmpty() || !getFavoriteCollections(layout).isEmpty()); } }