UITreeTaxonomyBuilder.java
/*
* Copyright (C) 2003-2008 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.ecm.webui.tree;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
import javax.jcr.nodetype.NodeType;
import org.exoplatform.ecm.webui.comparator.NodeTitleComparator;
import org.exoplatform.ecm.webui.tree.selectone.UIOneTaxonomySelector;
import org.exoplatform.ecm.webui.utils.Utils;
import org.exoplatform.portal.webui.container.UIContainer;
import org.exoplatform.services.cms.link.NodeFinder;
import org.exoplatform.services.ecm.publication.PublicationService;
import org.exoplatform.services.wcm.core.NodeLocation;
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.UIBreadcumbs;
import org.exoplatform.webui.core.UITree;
import org.exoplatform.webui.core.UIBreadcumbs.LocalPath;
import org.exoplatform.webui.event.Event;
import org.exoplatform.webui.event.EventListener;
/**
* Created by The eXo Platform SAS.
*
* @author : Hoa.Pham hoa.pham@exoplatform.com Jun 23, 2008
*/
@ComponentConfig(
events = @EventConfig(listeners = UITreeTaxonomyBuilder.ChangeNodeActionListener.class)
)
public class UITreeTaxonomyBuilder extends UIContainer {
private boolean allowPublish = false;
private PublicationService publicationService_ = null;
private List<String> templates_ = null;
private String[] acceptedNodeTypes = {};
private String[] defaultExceptedNodeTypes = {};
/** The root tree node. */
protected NodeLocation rootTreeNode;
/** The current node. */
protected NodeLocation currentNode;
public boolean isAllowPublish() {
return allowPublish;
}
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 UITreeTaxonomyBuilder() throws Exception {
UITree tree = addChild(UINodeTree.class, null, "TaxonomyTreeBuilder") ;
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);
UINodeTree uiNodeTree = getChild(UINodeTree.class);
uiNodeTree.setRootPath(node.getPath());
uiNodeTree.setTaxonomyLocalize(true);
broadcastOnChange(node,null);
}
/**
* 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;
}
/**
* Gets the default excepted node types.
*
* @return the default excepted node types
*/
public String[] getDefaultExceptedNodeTypes() { return defaultExceptedNodeTypes; }
/**
* Sets the default excepted node types.
*
* @param defaultExceptedNodeTypes the new excepted node types
*/
public void setDefaultExceptedNodeTypes(String[] defaultExceptedNodeTypes) {
this.defaultExceptedNodeTypes = defaultExceptedNodeTypes;
}
public boolean isExceptedNodeType(Node node) throws RepositoryException {
if(defaultExceptedNodeTypes.length > 0) {
for(String nodeType: defaultExceptedNodeTypes) {
if(node.isNodeType(nodeType)) return true;
}
}
return false;
}
public void buildTree() throws Exception {
NodeIterator sibbling = null ;
NodeIterator children = null ;
UINodeTree tree = getChild(UINodeTree.class);
Node selectedNode = getNodeByPathBreadcumbs();
if ((tree != null) && (selectedNode != null)) {
tree.setSelected(selectedNode);
if (Utils.getNodeSymLink(selectedNode).getDepth() > 0) {
if (!selectedNode.getPath().equals(rootTreeNode.getPath()))
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(filfer(sibbling));
}
if (children != null) {
tree.setChildren(filfer(children));
}
}
}
private Node getNodeByPathBreadcumbs() throws PathNotFoundException, RepositoryException {
UIOneTaxonomySelector uiOneTaxonomySelector = (UIOneTaxonomySelector) getParent();
UIBreadcumbs uiBreadcumbs = uiOneTaxonomySelector.getChildById("BreadcumbOneTaxonomy");
List<LocalPath> listLocalPath = uiBreadcumbs.getPath();
StringBuilder buffer = new StringBuilder(1024);
String rootPath = "";
if (rootTreeNode != null) rootPath = rootTreeNode.getPath();
for (LocalPath iterLocalPath : listLocalPath) {
buffer.append("/").append(iterLocalPath.getId());
}
String path = buffer.toString();
if (rootPath.endsWith(path)) rootPath = rootPath.substring(0, rootPath.length() - path.length());
path = path.replaceAll("/+", "/");
if (!path.startsWith(rootPath)) {
StringBuffer sb = new StringBuffer();
sb.append(rootPath).append(path);
path = sb.toString();
}
if (path.endsWith("/")) path = path.substring(0, path.length() - 1);
if (path.length() == 0) path = "/";
if (buffer.length() == 0) return NodeLocation.getNodeByLocation(currentNode);
NodeFinder nodeFinder_ = getApplicationComponent(NodeFinder.class);
return (Node)nodeFinder_.getItem(uiOneTaxonomySelector.getWorkspaceName(), path);
}
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);
}
}
private List<Node> filfer(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;
}
}
}
Collections.sort(list, new NodeTitleComparator(NodeTitleComparator.ASCENDING_ORDER));
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") || isExceptedNodeType(sibbling)) continue;
list.add(sibbling);
}
Collections.sort(list, new NodeTitleComparator(NodeTitleComparator.ASCENDING_ORDER));
List<Node> listNodeCheck = new ArrayList<Node>();
for (Node node : list) addNodePublish(listNodeCheck, node, publicationService_);
return listNodeCheck;
}
/* (non-Javadoc)
* @see org.exoplatform.webui.core.UIComponent#processRender(org.exoplatform.webui.application.WebuiRequestContext)
*/
public void processRender(WebuiRequestContext context) throws Exception {
Writer writer = context.getWriter() ;
writer.write("<div class=\"explorerTree\">") ;
buildTree() ;
super.renderChildren() ;
writer.write("</div>") ;
}
/**
* 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 request context
* @throws Exception the exception
*/
public void changeNode(String path, Object context) throws Exception {
if (path == null) return;
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));
}
broadcastOnChange(NodeLocation.getNodeByLocation(currentNode),context);
}
/**
* Broadcast on change.
*
* @param node the node
* @param context the request context
* @throws Exception the exception
*/
public void broadcastOnChange(Node node, Object context) throws Exception {
UIBaseNodeTreeSelector nodeTreeSelector = getAncestorOfType(UIBaseNodeTreeSelector.class);
nodeTreeSelector.onChange(node, context);
}
/**
* 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 {
UITreeTaxonomyBuilder builder = event.getSource().getParent();
String uri = event.getRequestContext().getRequestParameter(OBJECTID);
builder.changeNode(uri,event.getRequestContext());
UIBaseNodeTreeSelector nodeTreeSelector = builder.getAncestorOfType(UIBaseNodeTreeSelector.class);
event.getRequestContext().addUIComponentToUpdateByAjax(nodeTreeSelector);
}
}
}