View Javadoc
1   /*
2    * Copyright (C) 2003-2009 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.wcm.webui.category;
18  
19  import java.io.UnsupportedEncodingException;
20  import java.net.URLDecoder;
21  import java.util.ArrayList;
22  import java.util.List;
23  
24  import javax.jcr.Node;
25  import javax.jcr.NodeIterator;
26  import javax.jcr.RepositoryException;
27  import javax.jcr.nodetype.NodeType;
28  import javax.portlet.PortletPreferences;
29  
30  import org.apache.commons.lang.StringUtils;
31  import org.exoplatform.ecm.webui.utils.Utils;
32  import org.exoplatform.portal.webui.container.UIContainer;
33  import org.exoplatform.portal.webui.util.Util;
34  import org.exoplatform.services.cms.link.NodeFinder;
35  import org.exoplatform.services.cms.taxonomy.TaxonomyService;
36  import org.exoplatform.services.ecm.publication.PublicationService;
37  import org.exoplatform.services.log.ExoLogger;
38  import org.exoplatform.services.log.Log;
39  import org.exoplatform.services.wcm.core.NodeLocation;
40  import org.exoplatform.wcm.webui.category.config.UICategoryNavigationConfig;
41  import org.exoplatform.web.application.ApplicationMessage;
42  import org.exoplatform.webui.application.WebuiRequestContext;
43  import org.exoplatform.webui.config.annotation.ComponentConfig;
44  import org.exoplatform.webui.config.annotation.EventConfig;
45  import org.exoplatform.webui.core.UITree;
46  import org.exoplatform.webui.core.lifecycle.Lifecycle;
47  import org.exoplatform.webui.event.Event;
48  import org.exoplatform.webui.event.EventListener;
49  
50  /**
51   * Created by The eXo Platform SAS
52   * Author : eXoPlatform
53   * chuong.phan@exoplatform.com, phan.le.thanh.chuong@gmail.com
54   * Jun 19, 2009
55   */
56  @ComponentConfig(
57      lifecycle = Lifecycle.class,
58      template = "app:/groovy/CategoryNavigation/UICategoryNavigationTree.gtmpl",
59      events = {
60        @EventConfig(listeners = UICategoryNavigationTree.QuickEditActionListener.class),
61        @EventConfig(listeners = UICategoryNavigationTree.ChangeNodeActionListener.class)
62      }
63  )
64  public class UICategoryNavigationTree extends UIContainer {
65  
66    private static final Log         LOG             = ExoLogger.getLogger(UICategoryNavigationTree.class.getName());
67    
68    /** The allow publish. */
69    private boolean            allowPublish        = false;
70  
71    /** The publication service_. */
72    private PublicationService publicationService_ = null;
73  
74    /** The templates_. */
75    private List<String>       templates_          = null;
76  
77    /** The accepted node types. */
78    private String[]           acceptedNodeTypes   = {};
79  
80    /** The root tree node. */
81    protected NodeLocation rootTreeNode;
82  
83    /** The current node. */
84    protected NodeLocation currentNode;
85  
86    /**
87     * Checks if is allow publish.
88     *
89     * @return true, if is allow publish
90     */
91    public boolean isAllowPublish() {
92      return allowPublish;
93    }
94  
95    /**
96     * Sets the allow publish.
97     *
98     * @param allowPublish the allow publish
99     * @param publicationService the publication service
100    * @param templates the templates
101    */
102   public void setAllowPublish(boolean allowPublish,
103                               PublicationService publicationService,
104                               List<String> templates) {
105     this.allowPublish = allowPublish;
106     publicationService_ = publicationService;
107     templates_ = templates;
108   }
109 
110   /**
111    * Instantiates a new uI node tree builder.
112    *
113    * @throws Exception the exception
114    */
115   public UICategoryNavigationTree() throws Exception {
116 
117     PortletPreferences portletPreferences = UICategoryNavigationUtils.getPortletPreferences();
118     String preferenceTreeName = portletPreferences.getValue(UICategoryNavigationConstant.PREFERENCE_TREE_NAME, "");
119     TaxonomyService taxonomyService = getApplicationComponent(TaxonomyService.class);
120     Node rootTreeNode = null;
121     try {
122       rootTreeNode = taxonomyService.getTaxonomyTree(preferenceTreeName);
123     } catch (RepositoryException e) {
124       if (LOG.isWarnEnabled()) {
125         LOG.warn(e.getMessage());
126       }
127     }
128     setRootTreeNode(rootTreeNode);
129     setAcceptedNodeTypes(new String[] {"nt:folder", "nt:unstructured", "nt:file", "exo:taxonomy"});
130 
131     UITree tree = addChild(UICategoryNavigationTreeBase.class, null, null);
132     tree.setBeanLabelField("name");
133     tree.setBeanIdField("path");
134   }
135 
136   /**
137    * Gets the root tree node.
138    *
139    * @return the root tree node
140    */
141   public Node getRootTreeNode() {
142     return NodeLocation.getNodeByLocation(rootTreeNode);
143   }
144 
145   /**
146    * Sets the root tree node.
147    *
148    * @param node the new root tree node
149    *
150    * @throws Exception the exception
151    */
152   public final void setRootTreeNode(Node node) throws Exception {
153     this.rootTreeNode = NodeLocation.getNodeLocationByNode(node);
154     this.currentNode = NodeLocation.getNodeLocationByNode(node);
155   }
156 
157   /**
158    * Gets the current node.
159    *
160    * @return the current node
161    */
162   public Node getCurrentNode() {
163     return NodeLocation.getNodeByLocation(currentNode);
164   }
165 
166   /**
167    * Sets the current node.
168    *
169    * @param currentNode the new current node
170    */
171   public void setCurrentNode(Node currentNode) {
172     this.currentNode = NodeLocation.getNodeLocationByNode(currentNode);
173   }
174 
175   /**
176    * Gets the accepted node types.
177    *
178    * @return the accepted node types
179    */
180   public String[] getAcceptedNodeTypes() {
181     return acceptedNodeTypes;
182   }
183 
184   /**
185    * Sets the accepted node types.
186    *
187    * @param acceptedNodeTypes the new accepted node types
188    */
189   public void setAcceptedNodeTypes(String[] acceptedNodeTypes) {
190     this.acceptedNodeTypes = acceptedNodeTypes;
191   }
192 
193   /* (non-Javadoc)
194    * @see org.exoplatform.webui.core.UIComponent#processRender(org.exoplatform.webui.application.WebuiRequestContext)
195    */
196   public void processRender(WebuiRequestContext context) throws Exception {
197     String parameters = null;
198     try {
199       parameters = URLDecoder.decode(StringUtils.substringAfter(Util.getPortalRequestContext()
200                                                                     .getNodePath(),
201                                                                 Util.getUIPortal()
202                                                                     .getSelectedUserNode()
203                                                                     .getURI()
204                                                                     + "/"), "UTF-8");
205     } catch (UnsupportedEncodingException e) {
206       org.exoplatform.wcm.webui.Utils.createPopupMessage(this,
207                                                          "UICategoryNavigationConfig.msg.not-support-encoding",
208                                                          null,
209                                                          ApplicationMessage.ERROR);
210     }
211     PortletPreferences portletPreferences = UICategoryNavigationUtils.getPortletPreferences();
212     String preferenceTreeName = portletPreferences.getValue(UICategoryNavigationConstant.PREFERENCE_TREE_NAME, "");
213     TaxonomyService taxonomyService = getApplicationComponent(TaxonomyService.class);
214     Node treeNode = null;
215     try {
216       treeNode = taxonomyService.getTaxonomyTree(preferenceTreeName);
217     } catch (RepositoryException e) {
218       currentNode = null;
219       super.processRender(context);
220       return;
221     }
222 
223 
224     String categoryPath = parameters.substring(parameters.indexOf("/") + 1);
225     if (preferenceTreeName.equals(categoryPath)) categoryPath = "";
226     currentNode = NodeLocation.getNodeLocationByNode(treeNode.getNode(categoryPath));
227 
228     super.processRender(context);
229   }
230 
231   /**
232    * Builds the tree.
233    *
234    * @throws Exception the exception
235    */
236   public void buildTree() throws Exception {
237     NodeIterator sibbling = null;
238     NodeIterator children = null;
239     UICategoryNavigationTreeBase tree = getChild(UICategoryNavigationTreeBase.class);
240     Node selectedNode = NodeLocation.getNodeByLocation(currentNode);
241     tree.setSelected(selectedNode);
242     if (selectedNode == null) {
243       return;
244     }
245     if (Utils.getNodeSymLink(selectedNode).getDepth() > 0) {
246       tree.setParentSelected(selectedNode.getParent());
247       sibbling = Utils.getNodeSymLink(selectedNode).getNodes();
248       children = Utils.getNodeSymLink(selectedNode).getNodes();
249     } else {
250       tree.setParentSelected(selectedNode);
251       sibbling = Utils.getNodeSymLink(selectedNode).getNodes();
252       children = null;
253     }
254     if (sibbling != null) {
255       tree.setSibbling(filter(sibbling));
256     }
257     if (children != null) {
258       tree.setChildren(filter(children));
259     }
260   }
261 
262   /**
263    * Adds the node publish.
264    *
265    * @param listNode the list node
266    * @param node the node
267    * @param publicationService the publication service
268    *
269    * @throws Exception the exception
270    */
271   private void addNodePublish(List<Node> listNode, Node node, PublicationService publicationService) throws Exception {
272     if (isAllowPublish()) {
273       NodeType nt = node.getPrimaryNodeType();
274       if (templates_.contains(nt.getName())) {
275         Node nodecheck = publicationService.getNodePublish(node, null);
276         if (nodecheck != null) {
277           listNode.add(nodecheck);
278         }
279       } else {
280         listNode.add(node);
281       }
282     } else {
283       listNode.add(node);
284     }
285   }
286 
287   /**
288    * Filter.
289    *
290    * @param iterator the iterator
291    *
292    * @return the list< node>
293    *
294    * @throws Exception the exception
295    */
296   private List<Node> filter(final NodeIterator iterator) throws Exception {
297     List<Node> list = new ArrayList<Node>();
298     if (acceptedNodeTypes.length > 0) {
299       for (; iterator.hasNext();) {
300         Node sibbling = iterator.nextNode();
301         if (sibbling.isNodeType("exo:hiddenable"))
302           continue;
303         for (String nodetype : acceptedNodeTypes) {
304           if (sibbling.isNodeType(nodetype)) {
305             list.add(sibbling);
306             break;
307           }
308         }
309       }
310       List<Node> listNodeCheck = new ArrayList<Node>();
311       for (Node node : list) {
312         addNodePublish(listNodeCheck, node, publicationService_);
313       }
314       return listNodeCheck;
315     }
316     for (; iterator.hasNext();) {
317       Node sibbling = iterator.nextNode();
318       if (sibbling.isNodeType("exo:hiddenable"))
319         continue;
320       list.add(sibbling);
321     }
322     List<Node> listNodeCheck = new ArrayList<Node>();
323     for (Node node : list)
324       addNodePublish(listNodeCheck, node, publicationService_);
325     return listNodeCheck;
326   }
327 
328   /**
329    * When a node is change in tree. This method will be rerender the children and sibbling nodes of
330    * current node and broadcast change node event to other uicomponent
331    *
332    * @param path the path
333    * @param context the context
334    *
335    * @throws Exception the exception
336    */
337   public void changeNode(String path, Object context) throws Exception {
338     NodeFinder nodeFinder_ = getApplicationComponent(NodeFinder.class);
339     String rootPath = rootTreeNode.getPath();
340     if (rootPath.equals(path) || !path.startsWith(rootPath)) {
341       currentNode = rootTreeNode;
342     } else {
343       if (path.startsWith(rootPath))
344         path = path.substring(rootPath.length());
345       if (path.startsWith("/"))
346         path = path.substring(1);
347       currentNode = NodeLocation.getNodeLocationByNode(nodeFinder_.getNode(NodeLocation.getNodeByLocation(rootTreeNode), path));
348     }
349   }
350 
351   /**
352    * The listener interface for receiving changeNodeAction events. The class
353    * that is interested in processing a changeNodeAction event implements this
354    * interface, and the object created with that class is registered with a
355    * component using the component's
356    * <code>addChangeNodeActionListener</code> method. When
357    * the changeNodeAction event occurs, that object's appropriate
358    * method is invoked.
359    */
360   static public class ChangeNodeActionListener extends EventListener<UITree> {
361 
362     /* (non-Javadoc)
363      * @see org.exoplatform.webui.event.EventListener#execute(org.exoplatform.webui.event.Event)
364      */
365     public void execute(Event<UITree> event) throws Exception {
366       UICategoryNavigationTree categoryNavigationTree = event.getSource().getParent();
367       String uri = event.getRequestContext().getRequestParameter(OBJECTID);
368       categoryNavigationTree.changeNode(uri, event.getRequestContext());
369       event.getRequestContext().addUIComponentToUpdateByAjax(categoryNavigationTree.getParent());
370     }
371   }
372 
373   /**
374    * The listener interface for receiving quickEditAction events. The class
375    * that is interested in processing a quickEditAction event implements this
376    * interface, and the object created with that class is registered with a
377    * component using the component's
378    * <code>addQuickEditActionListener</code> method. When
379    * the quickEditAction event occurs, that object's appropriate
380    * method is invoked.
381    */
382   public static class QuickEditActionListener extends EventListener<UICategoryNavigationTree> {
383     /*
384      * (non-Javadoc)
385      *
386      * @see org.exoplatform.webui.event.EventListener#execute(org.exoplatform.webui.event.Event)
387      */
388     public void execute(Event<UICategoryNavigationTree> event) throws Exception {
389       UICategoryNavigationTree uiContainer = event.getSource();
390       UICategoryNavigationConfig configForm = uiContainer.createUIComponent(UICategoryNavigationConfig.class,
391                                                                             null,
392                                                                             null);
393       org.exoplatform.wcm.webui.Utils.createPopupWindow(uiContainer,
394                                                         configForm,
395                                                         UICategoryNavigationPortlet.CONFIG_POPUP_WINDOW,
396                                                         600);
397     }
398   }
399 
400 }