/* * Copyright (C) 2003-2009 eXo Platform SAS. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation; either version 3 * of the License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see<http://www.gnu.org/licenses/>. */ package org.exoplatform.wcm.webui.category; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.util.ArrayList; import java.util.List; import javax.jcr.Node; import javax.jcr.NodeIterator; import javax.jcr.RepositoryException; import javax.jcr.nodetype.NodeType; import javax.portlet.PortletPreferences; import org.apache.commons.lang.StringUtils; import org.exoplatform.ecm.webui.utils.Utils; import org.exoplatform.portal.webui.container.UIContainer; import org.exoplatform.portal.webui.util.Util; import org.exoplatform.services.cms.link.NodeFinder; import org.exoplatform.services.cms.taxonomy.TaxonomyService; import org.exoplatform.services.ecm.publication.PublicationService; import org.exoplatform.services.log.ExoLogger; import org.exoplatform.services.log.Log; import org.exoplatform.services.wcm.core.NodeLocation; import org.exoplatform.wcm.webui.category.config.UICategoryNavigationConfig; import org.exoplatform.web.application.ApplicationMessage; import org.exoplatform.webui.application.WebuiRequestContext; import org.exoplatform.webui.config.annotation.ComponentConfig; import org.exoplatform.webui.config.annotation.EventConfig; import org.exoplatform.webui.core.UITree; import org.exoplatform.webui.core.lifecycle.Lifecycle; import org.exoplatform.webui.event.Event; import org.exoplatform.webui.event.EventListener; /** * Created by The eXo Platform SAS * Author : eXoPlatform * chuong.phan@exoplatform.com, phan.le.thanh.chuong@gmail.com * Jun 19, 2009 */ @ComponentConfig( lifecycle = Lifecycle.class, template = "app:/groovy/CategoryNavigation/UICategoryNavigationTree.gtmpl", events = { @EventConfig(listeners = UICategoryNavigationTree.QuickEditActionListener.class), @EventConfig(listeners = UICategoryNavigationTree.ChangeNodeActionListener.class) } ) public class UICategoryNavigationTree extends UIContainer { private static final Log LOG = ExoLogger.getLogger(UICategoryNavigationTree.class.getName()); /** The allow publish. */ private boolean allowPublish = false; /** The publication service_. */ private PublicationService publicationService_ = null; /** The templates_. */ private List<String> templates_ = null; /** The accepted node types. */ private String[] acceptedNodeTypes = {}; /** The root tree node. */ protected NodeLocation rootTreeNode; /** The current node. */ protected NodeLocation currentNode; /** * Checks if is allow publish. * * @return true, if is allow publish */ public boolean isAllowPublish() { return allowPublish; } /** * Sets the allow publish. * * @param allowPublish the allow publish * @param publicationService the publication service * @param templates the templates */ public void setAllowPublish(boolean allowPublish, PublicationService publicationService, List<String> templates) { this.allowPublish = allowPublish; publicationService_ = publicationService; templates_ = templates; } /** * Instantiates a new uI node tree builder. * * @throws Exception the exception */ public UICategoryNavigationTree() throws Exception { PortletPreferences portletPreferences = UICategoryNavigationUtils.getPortletPreferences(); String preferenceTreeName = portletPreferences.getValue(UICategoryNavigationConstant.PREFERENCE_TREE_NAME, ""); TaxonomyService taxonomyService = getApplicationComponent(TaxonomyService.class); Node rootTreeNode = null; try { rootTreeNode = taxonomyService.getTaxonomyTree(preferenceTreeName); } catch (RepositoryException e) { if (LOG.isWarnEnabled()) { LOG.warn(e.getMessage()); } } setRootTreeNode(rootTreeNode); setAcceptedNodeTypes(new String[] {"nt:folder", "nt:unstructured", "nt:file", "exo:taxonomy"}); UITree tree = addChild(UICategoryNavigationTreeBase.class, null, null); tree.setBeanLabelField("name"); tree.setBeanIdField("path"); } /** * Gets the root tree node. * * @return the root tree node */ public Node getRootTreeNode() { return NodeLocation.getNodeByLocation(rootTreeNode); } /** * Sets the root tree node. * * @param node the new root tree node * * @throws Exception the exception */ public final void setRootTreeNode(Node node) throws Exception { this.rootTreeNode = NodeLocation.getNodeLocationByNode(node); this.currentNode = NodeLocation.getNodeLocationByNode(node); } /** * Gets the current node. * * @return the current node */ public Node getCurrentNode() { return NodeLocation.getNodeByLocation(currentNode); } /** * Sets the current node. * * @param currentNode the new current node */ public void setCurrentNode(Node currentNode) { this.currentNode = NodeLocation.getNodeLocationByNode(currentNode); } /** * Gets the accepted node types. * * @return the accepted node types */ public String[] getAcceptedNodeTypes() { return acceptedNodeTypes; } /** * Sets the accepted node types. * * @param acceptedNodeTypes the new accepted node types */ public void setAcceptedNodeTypes(String[] acceptedNodeTypes) { this.acceptedNodeTypes = acceptedNodeTypes; } /* (non-Javadoc) * @see org.exoplatform.webui.core.UIComponent#processRender(org.exoplatform.webui.application.WebuiRequestContext) */ public void processRender(WebuiRequestContext context) throws Exception { String parameters = null; try { parameters = URLDecoder.decode(StringUtils.substringAfter(Util.getPortalRequestContext() .getNodePath(), Util.getUIPortal() .getSelectedUserNode() .getURI() + "/"), "UTF-8"); } catch (UnsupportedEncodingException e) { org.exoplatform.wcm.webui.Utils.createPopupMessage(this, "UICategoryNavigationConfig.msg.not-support-encoding", null, ApplicationMessage.ERROR); } PortletPreferences portletPreferences = UICategoryNavigationUtils.getPortletPreferences(); String preferenceTreeName = portletPreferences.getValue(UICategoryNavigationConstant.PREFERENCE_TREE_NAME, ""); TaxonomyService taxonomyService = getApplicationComponent(TaxonomyService.class); Node treeNode = null; try { treeNode = taxonomyService.getTaxonomyTree(preferenceTreeName); } catch (RepositoryException e) { currentNode = null; super.processRender(context); return; } String categoryPath = parameters.substring(parameters.indexOf("/") + 1); if (preferenceTreeName.equals(categoryPath)) categoryPath = ""; currentNode = NodeLocation.getNodeLocationByNode(treeNode.getNode(categoryPath)); super.processRender(context); } /** * Builds the tree. * * @throws Exception the exception */ public void buildTree() throws Exception { NodeIterator sibbling = null; NodeIterator children = null; UICategoryNavigationTreeBase tree = getChild(UICategoryNavigationTreeBase.class); Node selectedNode = NodeLocation.getNodeByLocation(currentNode); tree.setSelected(selectedNode); if (selectedNode == null) { return; } if (Utils.getNodeSymLink(selectedNode).getDepth() > 0) { tree.setParentSelected(selectedNode.getParent()); sibbling = Utils.getNodeSymLink(selectedNode).getNodes(); children = Utils.getNodeSymLink(selectedNode).getNodes(); } else { tree.setParentSelected(selectedNode); sibbling = Utils.getNodeSymLink(selectedNode).getNodes(); children = null; } if (sibbling != null) { tree.setSibbling(filter(sibbling)); } if (children != null) { tree.setChildren(filter(children)); } } /** * Adds the node publish. * * @param listNode the list node * @param node the node * @param publicationService the publication service * * @throws Exception the exception */ private void addNodePublish(List<Node> listNode, Node node, PublicationService publicationService) throws Exception { if (isAllowPublish()) { NodeType nt = node.getPrimaryNodeType(); if (templates_.contains(nt.getName())) { Node nodecheck = publicationService.getNodePublish(node, null); if (nodecheck != null) { listNode.add(nodecheck); } } else { listNode.add(node); } } else { listNode.add(node); } } /** * Filter. * * @param iterator the iterator * * @return the list< node> * * @throws Exception the exception */ private List<Node> filter(final NodeIterator iterator) throws Exception { List<Node> list = new ArrayList<Node>(); if (acceptedNodeTypes.length > 0) { for (; iterator.hasNext();) { Node sibbling = iterator.nextNode(); if (sibbling.isNodeType("exo:hiddenable")) continue; for (String nodetype : acceptedNodeTypes) { if (sibbling.isNodeType(nodetype)) { list.add(sibbling); break; } } } List<Node> listNodeCheck = new ArrayList<Node>(); for (Node node : list) { addNodePublish(listNodeCheck, node, publicationService_); } return listNodeCheck; } for (; iterator.hasNext();) { Node sibbling = iterator.nextNode(); if (sibbling.isNodeType("exo:hiddenable")) continue; list.add(sibbling); } List<Node> listNodeCheck = new ArrayList<Node>(); for (Node node : list) addNodePublish(listNodeCheck, node, publicationService_); return listNodeCheck; } /** * When a node is change in tree. This method will be rerender the children and sibbling nodes of * current node and broadcast change node event to other uicomponent * * @param path the path * @param context the context * * @throws Exception the exception */ public void changeNode(String path, Object context) throws Exception { NodeFinder nodeFinder_ = getApplicationComponent(NodeFinder.class); String rootPath = rootTreeNode.getPath(); if (rootPath.equals(path) || !path.startsWith(rootPath)) { currentNode = rootTreeNode; } else { if (path.startsWith(rootPath)) path = path.substring(rootPath.length()); if (path.startsWith("/")) path = path.substring(1); currentNode = NodeLocation.getNodeLocationByNode(nodeFinder_.getNode(NodeLocation.getNodeByLocation(rootTreeNode), path)); } } /** * The listener interface for receiving changeNodeAction events. The class * that is interested in processing a changeNodeAction event implements this * interface, and the object created with that class is registered with a * component using the component's * <code>addChangeNodeActionListener</code> method. When * the changeNodeAction event occurs, that object's appropriate * method is invoked. */ static public class ChangeNodeActionListener extends EventListener<UITree> { /* (non-Javadoc) * @see org.exoplatform.webui.event.EventListener#execute(org.exoplatform.webui.event.Event) */ public void execute(Event<UITree> event) throws Exception { UICategoryNavigationTree categoryNavigationTree = event.getSource().getParent(); String uri = event.getRequestContext().getRequestParameter(OBJECTID); categoryNavigationTree.changeNode(uri, event.getRequestContext()); event.getRequestContext().addUIComponentToUpdateByAjax(categoryNavigationTree.getParent()); } } /** * The listener interface for receiving quickEditAction events. The class * that is interested in processing a quickEditAction event implements this * interface, and the object created with that class is registered with a * component using the component's * <code>addQuickEditActionListener</code> method. When * the quickEditAction event occurs, that object's appropriate * method is invoked. */ public static class QuickEditActionListener extends EventListener<UICategoryNavigationTree> { /* * (non-Javadoc) * * @see org.exoplatform.webui.event.EventListener#execute(org.exoplatform.webui.event.Event) */ public void execute(Event<UICategoryNavigationTree> event) throws Exception { UICategoryNavigationTree uiContainer = event.getSource(); UICategoryNavigationConfig configForm = uiContainer.createUIComponent(UICategoryNavigationConfig.class, null, null); org.exoplatform.wcm.webui.Utils.createPopupWindow(uiContainer, configForm, UICategoryNavigationPortlet.CONFIG_POPUP_WINDOW, 600); } } }