View Javadoc
1   /*
2    * Copyright (C) 2003-2008 eXo Platform SAS.
3    *
4    * This program is free software; you can redistribute it and/or
5    * modify it under the terms of the GNU Affero General Public License
6    * as published by the Free Software Foundation; either version 3
7    * of the License, or (at your option) any later version.
8    *
9    * This program is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   * GNU General Public License for more details.
13   *
14   * You should have received a copy of the GNU General Public License
15   * along with this program; if not, see<http://www.gnu.org/licenses/>.
16   */
17  package org.exoplatform.ecm.webui.tree;
18  
19  import java.io.Writer;
20  import java.util.ArrayList;
21  import java.util.Collections;
22  import java.util.List;
23  
24  import javax.jcr.Node;
25  import javax.jcr.NodeIterator;
26  import javax.jcr.PathNotFoundException;
27  import javax.jcr.RepositoryException;
28  import javax.jcr.nodetype.NodeType;
29  
30  import org.exoplatform.ecm.webui.comparator.NodeTitleComparator;
31  import org.exoplatform.ecm.webui.tree.selectone.UIOneNodePathSelector;
32  import org.exoplatform.ecm.webui.utils.Utils;
33  import org.exoplatform.portal.webui.container.UIContainer;
34  import org.exoplatform.services.cms.link.NodeFinder;
35  import org.exoplatform.services.ecm.publication.PublicationService;
36  import org.exoplatform.services.wcm.core.NodeLocation;
37  import org.exoplatform.webui.application.WebuiRequestContext;
38  import org.exoplatform.webui.config.annotation.ComponentConfig;
39  import org.exoplatform.webui.config.annotation.EventConfig;
40  import org.exoplatform.webui.core.UIBreadcumbs;
41  import org.exoplatform.webui.core.UITree;
42  import org.exoplatform.webui.core.UIBreadcumbs.LocalPath;
43  import org.exoplatform.webui.event.Event;
44  import org.exoplatform.webui.event.EventListener;
45  
46  /**
47   * Created by The eXo Platform SAS.
48   *
49   * @author : Hoa.Pham hoa.pham@exoplatform.com Jun 23, 2008
50   */
51  
52  @ComponentConfig(
53      events = @EventConfig(listeners = UINodeTreeBuilder.ChangeNodeActionListener.class)
54  )
55  public class UINodeTreeBuilder extends UIContainer {
56    private boolean allowPublish = false;
57    private PublicationService publicationService_ = null;
58    private List<String> templates_ = null;
59  
60    private String[] acceptedNodeTypes = {};
61  
62    private String[] defaultExceptedNodeTypes = {};
63  
64    /** The root tree node. */
65    protected NodeLocation rootTreeNode;
66  
67    /** The current node. */
68    protected NodeLocation currentNode;
69  
70    public boolean isAllowPublish() {
71      return allowPublish;
72    }
73  
74    public void setAllowPublish(boolean allowPublish, PublicationService publicationService, List<String> templates) {
75      this.allowPublish = allowPublish;
76      publicationService_ = publicationService;
77      templates_ = templates;
78    }
79  
80    /**
81     * Instantiates a new uI node tree builder.
82     *
83     * @throws Exception the exception
84     */
85    public UINodeTreeBuilder() throws Exception {
86      UITree tree = addChild(UINodeTree.class, null, UINodeTree.class.getSimpleName()+hashCode()) ;
87      tree.setBeanLabelField("name") ;
88      tree.setBeanIdField("path") ;
89    }
90  
91    /**
92     * Gets the root tree node.
93     *
94     * @return the root tree node
95     */
96    public Node getRootTreeNode() { 
97      return NodeLocation.getNodeByLocation(rootTreeNode); 
98    }
99  
100   /**
101    * Sets the root tree node.
102    *
103    * @param node the new root tree node
104    * @throws Exception the exception
105    */
106   public final void setRootTreeNode(Node node) throws Exception {
107     this.rootTreeNode = NodeLocation.getNodeLocationByNode(node);
108     this.currentNode = NodeLocation.getNodeLocationByNode(node);
109     broadcastOnChange(node,null);
110   }
111 
112   /**
113    * Gets the current node.
114    *
115    * @return the current node
116    */
117   public Node getCurrentNode() { 
118     return NodeLocation.getNodeByLocation(currentNode); 
119   }
120 
121   /**
122    * Sets the current node.
123    *
124    * @param currentNode the new current node
125    */
126   public void setCurrentNode(Node currentNode) { 
127     this.currentNode = NodeLocation.getNodeLocationByNode(currentNode); 
128   }
129 
130   /**
131    * Gets the accepted node types.
132    *
133    * @return the accepted node types
134    */
135   public String[] getAcceptedNodeTypes() { return acceptedNodeTypes; }
136 
137   /**
138    * Sets the accepted node types.
139    *
140    * @param acceptedNodeTypes the new accepted node types
141    */
142   public void setAcceptedNodeTypes(String[] acceptedNodeTypes) {
143     this.acceptedNodeTypes = acceptedNodeTypes;
144   }
145 
146   /**
147    * Gets the default excepted node types.
148    *
149    * @return the default excepted node types
150    */
151   public String[] getDefaultExceptedNodeTypes() { return defaultExceptedNodeTypes; }
152 
153   /**
154    * Sets the default excepted node types.
155    *
156    * @param defaultExceptedNodeTypes the new excepted node types
157    */
158   public void setDefaultExceptedNodeTypes(String[] defaultExceptedNodeTypes) {
159     this.defaultExceptedNodeTypes = defaultExceptedNodeTypes;
160   }
161 
162   public boolean isExceptedNodeType(Node node) throws RepositoryException {
163     if(defaultExceptedNodeTypes.length > 0) {
164       for(String nodeType: defaultExceptedNodeTypes) {
165         if(node.isNodeType(nodeType)) return true;
166       }
167     }
168     return false;
169   }
170 
171   /**
172    * Builds the tree.
173    *
174    * @throws Exception the exception
175    */
176 
177   public void buildTree() throws Exception {
178     NodeIterator sibbling = null ;
179     NodeIterator children = null ;
180     UINodeTree tree = getChild(UINodeTree.class) ;
181     Node selectedNode = getNodeByPathBreadcumbs();
182     tree.setSelected(selectedNode);
183     if (Utils.getNodeSymLink(selectedNode).getDepth() > 0) {
184       tree.setParentSelected(selectedNode.getParent()) ;
185       sibbling = Utils.getNodeSymLink(selectedNode).getNodes() ;
186       children = Utils.getNodeSymLink(selectedNode).getNodes() ;
187     } else {
188       tree.setParentSelected(selectedNode) ;
189       sibbling = Utils.getNodeSymLink(selectedNode).getNodes() ;
190       children = null;
191     }
192     if (sibbling != null) {
193       tree.setSibbling(filfer(sibbling));
194     }
195     if (children != null) {
196       tree.setChildren(filfer(children));
197     }
198   }
199 
200   private Node getNodeByPathBreadcumbs() throws PathNotFoundException, RepositoryException {
201     UIOneNodePathSelector uiOneNodePathSelector = (UIOneNodePathSelector) getParent();
202     UIBreadcumbs uiBreadcumbs = uiOneNodePathSelector.getChildById("BreadcumbCategoriesOne");
203     List<LocalPath> listLocalPath = uiBreadcumbs.getPath();
204     StringBuilder buffer = new StringBuilder(1024);
205     String rootPath = rootTreeNode.getPath();
206     for (LocalPath iterLocalPath : listLocalPath) {
207       buffer.append("/").append(iterLocalPath.getId());
208     }
209     String path = buffer.toString();
210     if (path.startsWith("//"))
211       path = path.substring(1);
212     if (!path.startsWith(rootPath)) {
213       StringBuffer sb = new StringBuffer();
214       sb.append(rootPath).append(path);
215       path = sb.toString();
216     }
217     if (path.endsWith("/")) path = path.substring(0, path.length() - 1);
218     if (path.length() == 0) path = "/";
219     if (buffer.length() == 0) return NodeLocation.getNodeByLocation(currentNode);
220     NodeFinder nodeFinder_ = getApplicationComponent(NodeFinder.class);
221     return (Node)nodeFinder_.getItem(uiOneNodePathSelector.getWorkspaceName(), path);
222   }
223 
224   private void addNodePublish(List<Node> listNode, Node node, PublicationService publicationService) throws Exception {
225     if (isAllowPublish()) {
226       NodeType nt = node.getPrimaryNodeType();
227       if (templates_.contains(nt.getName())) {
228         Node nodecheck = publicationService.getNodePublish(node, null);
229         if (nodecheck != null) {
230           listNode.add(nodecheck);
231         }
232       } else {
233         listNode.add(node);
234       }
235     } else {
236       listNode.add(node);
237     }
238   }
239 
240   private List<Node> filfer(final NodeIterator iterator) throws Exception{
241     List<Node> list = new ArrayList<Node>();
242     if (acceptedNodeTypes.length > 0) {
243       for(;iterator.hasNext();) {
244         Node sibbling = iterator.nextNode();
245         if(sibbling.isNodeType("exo:hiddenable")) continue;
246         for(String nodetype: acceptedNodeTypes) {
247           if(sibbling.isNodeType(nodetype)) {
248             list.add(sibbling);
249             break;
250           }
251         }
252       }
253       Collections.sort(list, new NodeTitleComparator(NodeTitleComparator.ASCENDING_ORDER));
254       List<Node> listNodeCheck = new ArrayList<Node>();
255       for (Node node : list) {
256         addNodePublish(listNodeCheck, node, publicationService_);
257       }
258       return listNodeCheck;
259     }
260     for(;iterator.hasNext();) {
261       Node sibbling = iterator.nextNode();
262       if(sibbling.isNodeType("exo:hiddenable") || isExceptedNodeType(sibbling)) continue;
263       list.add(sibbling);
264     }
265     Collections.sort(list, new NodeTitleComparator(NodeTitleComparator.ASCENDING_ORDER));
266     List<Node> listNodeCheck = new ArrayList<Node>();
267     for (Node node : list) addNodePublish(listNodeCheck, node, publicationService_);
268     return listNodeCheck;
269   }
270 
271   /* (non-Javadoc)
272    * @see org.exoplatform.webui.core.UIComponent#processRender(org.exoplatform.webui.application.WebuiRequestContext)
273    */
274   public void processRender(WebuiRequestContext context) throws Exception {
275     Writer writer = context.getWriter() ;
276     writer.write("<div class=\"explorerTree\">") ;
277       buildTree() ;
278       super.renderChildren() ;
279     writer.write("</div>") ;
280   }
281 
282   /**
283    * When a node is change in tree. This method will be rerender the children and sibbling nodes of
284    * current node and broadcast change node event to other uicomponent
285    *
286    * @param path the path
287    * @param context the request context
288    * @throws Exception the exception
289    */
290   public void changeNode(String path, Object context) throws Exception {
291     NodeFinder nodeFinder_ = getApplicationComponent(NodeFinder.class);
292     String rootPath = rootTreeNode.getPath();
293     if(rootPath.equals(path) || !path.startsWith(rootPath)) {
294       currentNode = rootTreeNode;
295     }else {
296       if (path.startsWith(rootPath)) path = path.substring(rootPath.length());
297       if (path.startsWith("/")) path = path.substring(1);
298       currentNode = NodeLocation.getNodeLocationByNode(nodeFinder_.getNode(
299                                   NodeLocation.getNodeByLocation(rootTreeNode), path));
300     }
301     broadcastOnChange(NodeLocation.getNodeByLocation(currentNode),context);
302   }
303 
304   /**
305    * Broadcast on change.
306    *
307    * @param node the node
308    * @param context the request context
309    * @throws Exception the exception
310    */
311   public void broadcastOnChange(Node node, Object context) throws Exception {
312     UIBaseNodeTreeSelector nodeTreeSelector = getAncestorOfType(UIBaseNodeTreeSelector.class);
313     nodeTreeSelector.onChange(node, context);
314   }
315 
316   /**
317    * The listener interface for receiving changeNodeAction events. The class
318    * that is interested in processing a changeNodeAction event implements this
319    * interface, and the object created with that class is registered with a
320    * component using the component's
321    * <code>addChangeNodeActionListener</code> method. When
322    * the changeNodeAction event occurs, that object's appropriate
323    * method is invoked.
324    */
325   static public class ChangeNodeActionListener extends EventListener<UITree> {
326 
327     /* (non-Javadoc)
328      * @see org.exoplatform.webui.event.EventListener#execute(org.exoplatform.webui.event.Event)
329      */
330     public void execute(Event<UITree> event) throws Exception {
331       UINodeTreeBuilder builder = event.getSource().getParent();
332       String uri = event.getRequestContext().getRequestParameter(OBJECTID);
333       builder.changeNode(uri,event.getRequestContext());
334       UIBaseNodeTreeSelector nodeTreeSelector = builder.getAncestorOfType(UIBaseNodeTreeSelector.class);
335       event.getRequestContext().addUIComponentToUpdateByAjax(nodeTreeSelector);
336     }
337   }
338 }