KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > web > bean > CategoriesBean


1 /*
2  * Copyright (C) 2005 Alfresco, Inc.
3  *
4  * Licensed under the Mozilla Public License version 1.1
5  * with a permitted attribution clause. You may obtain a
6  * copy of the License at
7  *
8  * http://www.alfresco.org/legal/license.txt
9  *
10  * Unless required by applicable law or agreed to in writing,
11  * software distributed under the License is distributed on an
12  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific
14  * language governing permissions and limitations under the
15  * License.
16  */

17 package org.alfresco.web.bean;
18
19 import java.io.Serializable JavaDoc;
20 import java.text.MessageFormat JavaDoc;
21 import java.util.ArrayList JavaDoc;
22 import java.util.Collection JavaDoc;
23 import java.util.Collections JavaDoc;
24 import java.util.HashMap JavaDoc;
25 import java.util.List JavaDoc;
26 import java.util.Map JavaDoc;
27
28 import javax.faces.context.FacesContext;
29 import javax.faces.event.ActionEvent;
30 import javax.transaction.UserTransaction JavaDoc;
31
32 import org.alfresco.model.ContentModel;
33 import org.alfresco.service.cmr.repository.ChildAssociationRef;
34 import org.alfresco.service.cmr.repository.InvalidNodeRefException;
35 import org.alfresco.service.cmr.repository.NodeRef;
36 import org.alfresco.service.cmr.repository.NodeService;
37 import org.alfresco.service.cmr.search.CategoryService;
38 import org.alfresco.service.cmr.search.CategoryService.Depth;
39 import org.alfresco.service.cmr.search.CategoryService.Mode;
40 import org.alfresco.service.namespace.QName;
41 import org.alfresco.web.app.Application;
42 import org.alfresco.web.app.context.IContextListener;
43 import org.alfresco.web.app.context.UIContextService;
44 import org.alfresco.web.bean.repository.Node;
45 import org.alfresco.web.bean.repository.Repository;
46 import org.alfresco.web.ui.common.Utils;
47 import org.alfresco.web.ui.common.component.IBreadcrumbHandler;
48 import org.alfresco.web.ui.common.component.UIActionLink;
49 import org.alfresco.web.ui.common.component.UIBreadcrumb;
50 import org.alfresco.web.ui.common.component.UIModeList;
51 import org.alfresco.web.ui.common.component.data.UIRichList;
52 import org.alfresco.web.ui.repo.component.IRepoBreadcrumbHandler;
53 import org.apache.log4j.Logger;
54
55 /**
56  * Backing Bean for the Category Management pages.
57  *
58  * @author Kevin Roast
59  */

60 public class CategoriesBean implements IContextListener
61 {
62    private static final String JavaDoc DEFAULT_OUTCOME = "finish";
63
64    private static final String JavaDoc MSG_CATEGORIES = "categories";
65
66    private static Logger logger = Logger.getLogger(CategoriesBean.class);
67    
68    /** The NodeService to be used by the bean */
69    protected NodeService nodeService;
70    
71    protected CategoryService categoryService;
72    
73    /** Component references */
74    protected UIRichList categoriesRichList;
75    
76    /** Currently visible category Node*/
77    private Node category = null;
78    
79    /** Current category ref */
80    private NodeRef categoryRef = null;
81    
82    /** Action category node */
83    private Node actionCategory = null;
84       
85    /** Members of the linked items of a category */
86    private Collection JavaDoc<ChildAssociationRef> members = null;
87    
88    /** Dialog properties */
89    private String JavaDoc name = null;
90    private String JavaDoc description = null;
91    
92    /** RichList view mode */
93    private String JavaDoc viewMode = "icons";
94    
95    /** Category path breadcrumb location */
96    private List JavaDoc<IBreadcrumbHandler> location = null;
97    
98    
99    // ------------------------------------------------------------------------------
100
// Construction
101

102    /**
103     * Default Constructor
104     */

105    public CategoriesBean()
106    {
107       UIContextService.getInstance(FacesContext.getCurrentInstance()).registerBean(this);
108    }
109    
110    
111    // ------------------------------------------------------------------------------
112
// Bean property getters and setters
113

114    /**
115     * @param nodeService The NodeService to set.
116     */

117    public void setNodeService(NodeService nodeService)
118    {
119       this.nodeService = nodeService;
120    }
121    
122    /**
123     * @param categoryService The CategoryService to set.
124     */

125    public void setCategoryService(CategoryService categoryService)
126    {
127       this.categoryService = categoryService;
128    }
129    
130    /**
131     * @param list The categories RichList to set.
132     */

133    public void setCategoriesRichList(UIRichList list)
134    {
135       this.categoriesRichList = list;
136    }
137    
138    /**
139     * @return Returns the categories RichList to set.
140     */

141    public UIRichList getCategoriesRichList()
142    {
143       return this.categoriesRichList;
144    }
145    
146    /**
147     * @return Returns the description.
148     */

149    public String JavaDoc getDescription()
150    {
151       return this.description;
152    }
153
154    /**
155     * @param description The description to set.
156     */

157    public void setDescription(String JavaDoc description)
158    {
159       this.description = description;
160    }
161    
162    /**
163     * @return Returns the viewMode.
164     */

165    public String JavaDoc getViewMode()
166    {
167       return this.viewMode;
168    }
169
170    /**
171     * @param viewMode The viewMode to set.
172     */

173    public void setViewMode(String JavaDoc viewMode)
174    {
175       this.viewMode = viewMode;
176    }
177
178    /**
179     * @return Returns the name.
180     */

181    public String JavaDoc getName()
182    {
183       return this.name;
184    }
185
186    /**
187     * @param name The name to set.
188     */

189    public void setName(String JavaDoc name)
190    {
191       this.name = name;
192    }
193    
194    /**
195     * @return Returns the members count for current action category.
196     */

197    public int getMembers()
198    {
199       return (this.members != null ? this.members.size() : 0);
200    }
201    
202    /**
203     * @return Returns the Node being used for the current action screen.
204     */

205    public Node getActionCategory()
206    {
207       return this.actionCategory;
208    }
209    
210    /**
211     * @param actionSpace Set the Node to be used for the current category screen action.
212     */

213    public void setActionCategory(Node node)
214    {
215       this.actionCategory = node;
216       
217       if (node != null)
218       {
219          // setup form properties
220
this.name = node.getName();
221          this.description = (String JavaDoc)node.getProperties().get(ContentModel.PROP_DESCRIPTION);
222          this.members = this.categoryService.getChildren(node.getNodeRef(), Mode.MEMBERS, Depth.ANY);
223       }
224       else
225       {
226          this.name = null;
227          this.description = null;
228          this.members = Collections.emptyList();
229       }
230    }
231    
232    /**
233     * @return The currently displayed category as a Node or null if at the root.
234     */

235    public Node getCurrentCategory()
236    {
237       if (this.category == null)
238       {
239          if (this.categoryRef != null)
240          {
241             this.category = new Node(this.categoryRef);
242          }
243       }
244       
245       return this.category;
246    }
247    
248    /**
249     * @return The ID of the currently displayed category or null if at the root.
250     */

251    public String JavaDoc getCurrentCategoryId()
252    {
253       if (this.categoryRef != null)
254       {
255          return categoryRef.getId();
256       }
257       else
258       {
259          return null;
260       }
261    }
262    
263    /**
264     * Set the current category node.
265     * <p>
266     * Setting this value causes the UI to update and display the specified node as current.
267     *
268     * @param ref The current category node.
269     */

270    public void setCurrentCategory(NodeRef ref)
271    {
272       if (logger.isDebugEnabled())
273          logger.debug("Setting current category: " + ref);
274       
275       // set the current NodeRef for our UI context operations
276
this.categoryRef = ref;
277       
278       // clear current node context
279
this.category = null;
280       
281       // inform that the UI needs updating after this change
282
contextUpdated();
283    }
284    
285    /**
286     * @return Breadcrumb location list
287     */

288    public List JavaDoc<IBreadcrumbHandler> getLocation()
289    {
290       if (this.location == null)
291       {
292          List JavaDoc<IBreadcrumbHandler> loc = new ArrayList JavaDoc<IBreadcrumbHandler>(8);
293          loc.add(new CategoryBreadcrumbHandler(null,
294                Application.getMessage(FacesContext.getCurrentInstance(), MSG_CATEGORIES)));
295          
296          this.location = loc;
297       }
298       return this.location;
299    }
300    
301    /**
302     * @param location Breadcrumb location list
303     */

304    public void setLocation(List JavaDoc<IBreadcrumbHandler> location)
305    {
306       this.location = location;
307    }
308    
309    /**
310     * @return The list of categories Nodes to display. Returns the list root categories or the
311     * list of sub-categories for the current category if set.
312     */

313    public List JavaDoc<Node> getCategories()
314    {
315       List JavaDoc<Node> categories;
316       
317       UserTransaction JavaDoc tx = null;
318       try
319       {
320          FacesContext context = FacesContext.getCurrentInstance();
321          tx = Repository.getUserTransaction(context, true);
322          tx.begin();
323          
324          Collection JavaDoc<ChildAssociationRef> refs;
325          if (this.categoryRef == null)
326          {
327             // root categories
328
refs = this.categoryService.getCategories(Repository.getStoreRef(), ContentModel.ASPECT_GEN_CLASSIFIABLE, Depth.IMMEDIATE);
329          }
330          else
331          {
332             // sub-categories of an existing category
333
refs = this.categoryService.getChildren(this.categoryRef, Mode.SUB_CATEGORIES, Depth.IMMEDIATE);
334          }
335          categories = new ArrayList JavaDoc<Node>(refs.size());
336          for (ChildAssociationRef child : refs)
337          {
338             Node categoryNode = new Node(child.getChildRef());
339             // force early props init within transaction
340
categoryNode.getProperties();
341             categories.add(categoryNode);
342          }
343          
344          // commit the transaction
345
tx.commit();
346       }
347       catch (InvalidNodeRefException refErr)
348       {
349          Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
350                FacesContext.getCurrentInstance(), Repository.ERROR_NODEREF), new Object JavaDoc[] {refErr.getNodeRef()}) );
351          categories = Collections.<Node>emptyList();
352          try { if (tx != null) {tx.rollback();} } catch (Exception JavaDoc tex) {}
353       }
354       catch (Throwable JavaDoc err)
355       {
356          Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
357                FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err);
358          categories = Collections.<Node>emptyList();
359          try { if (tx != null) {tx.rollback();} } catch (Exception JavaDoc tex) {}
360       }
361       
362       return categories;
363    }
364    
365    /**
366     * Set the Category to be used for next action dialog
367     */

368    public void setupCategoryAction(ActionEvent event)
369    {
370       UIActionLink link = (UIActionLink)event.getComponent();
371       Map JavaDoc<String JavaDoc, String JavaDoc> params = link.getParameterMap();
372       String JavaDoc id = params.get("id");
373       if (id != null && id.length() != 0)
374       {
375          if (logger.isDebugEnabled())
376             logger.debug("Setup for action, setting current Category to: " + id);
377          
378          try
379          {
380             // create the node ref, then our node representation
381
NodeRef ref = new NodeRef(Repository.getStoreRef(), id);
382             Node node = new Node(ref);
383             
384             // prepare a node for the action context
385
setActionCategory(node);
386             
387             // clear datalist cache ready from return from action dialog
388
contextUpdated();
389          }
390          catch (InvalidNodeRefException refErr)
391          {
392             Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
393                FacesContext.getCurrentInstance(), Repository.ERROR_NODEREF), new Object JavaDoc[] {id}) );
394          }
395       }
396    }
397    
398    /**
399     * Clear the category action context - e.g. ready for a Create operation
400     */

401    public void clearCategoryAction(ActionEvent event)
402    {
403       setActionCategory(null);
404       
405       // clear datalist cache ready from return from action dialog
406
contextUpdated();
407    }
408    
409    /**
410     * Action called when a category folder is clicked.
411     * Navigate into the category.
412     */

413    public void clickCategory(ActionEvent event)
414    {
415       UIActionLink link = (UIActionLink)event.getComponent();
416       Map JavaDoc<String JavaDoc, String JavaDoc> params = link.getParameterMap();
417       String JavaDoc id = params.get("id");
418       if (id != null && id.length() != 0)
419       {
420          try
421          {
422             NodeRef ref = new NodeRef(Repository.getStoreRef(), id);
423             
424             // refresh UI based on node selection
425
updateUILocation(ref);
426          }
427          catch (InvalidNodeRefException refErr)
428          {
429             Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
430                FacesContext.getCurrentInstance(), Repository.ERROR_NODEREF), new Object JavaDoc[] {id}) );
431          }
432       }
433    }
434    
435    /**
436     * Action handler called on Create Category finish button click.
437     */

438    public String JavaDoc finishCreate()
439    {
440       String JavaDoc outcome = DEFAULT_OUTCOME;
441       
442       UserTransaction JavaDoc tx = null;
443       try
444       {
445          FacesContext context = FacesContext.getCurrentInstance();
446          tx = Repository.getUserTransaction(context);
447          tx.begin();
448          
449          // create category using categoryservice
450
NodeRef ref;
451          if (categoryRef == null)
452          {
453             ref = this.categoryService.createRootCategory(Repository.getStoreRef(), ContentModel.ASPECT_GEN_CLASSIFIABLE, this.name);
454          }
455          else
456          {
457             ref = this.categoryService.createCategory(categoryRef, this.name);
458          }
459          
460          // apply the titled aspect - for description
461
Map JavaDoc<QName, Serializable JavaDoc> titledProps = new HashMap JavaDoc<QName, Serializable JavaDoc>(1, 1.0f);
462          titledProps.put(ContentModel.PROP_DESCRIPTION, this.description);
463          this.nodeService.addAspect(ref, ContentModel.ASPECT_TITLED, titledProps);
464          
465          // commit the transaction
466
tx.commit();
467       }
468       catch (Throwable JavaDoc err)
469       {
470          // rollback the transaction
471
try { if (tx != null) {tx.rollback();} } catch (Exception JavaDoc tex) {}
472          Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
473                FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err);
474          outcome = null;
475       }
476       
477       return outcome;
478    }
479    
480    /**
481     * Action handler called on Edit Category finish button click.
482     */

483    public String JavaDoc finishEdit()
484    {
485       String JavaDoc outcome = DEFAULT_OUTCOME;
486       
487       UserTransaction JavaDoc tx = null;
488       try
489       {
490          FacesContext context = FacesContext.getCurrentInstance();
491          tx = Repository.getUserTransaction(context);
492          tx.begin();
493          
494          // update the category node
495
NodeRef nodeRef = getActionCategory().getNodeRef();
496          this.nodeService.setProperty(nodeRef, ContentModel.PROP_NAME, this.name);
497          
498          // apply the titled aspect - for description
499
if (this.nodeService.hasAspect(nodeRef, ContentModel.ASPECT_TITLED) == false)
500          {
501             Map JavaDoc<QName, Serializable JavaDoc> titledProps = new HashMap JavaDoc<QName, Serializable JavaDoc>(1, 1.0f);
502             titledProps.put(ContentModel.PROP_DESCRIPTION, this.description);
503             this.nodeService.addAspect(nodeRef, ContentModel.ASPECT_TITLED, titledProps);
504          }
505          else
506          {
507             this.nodeService.setProperty(nodeRef, ContentModel.PROP_DESCRIPTION, this.description);
508          }
509          
510          // commit the transaction
511
tx.commit();
512          
513          // edit the node in the breadcrumb if required
514
List JavaDoc<IBreadcrumbHandler> location = getLocation();
515          IBreadcrumbHandler handler = location.get(location.size() - 1);
516          
517          // see if the current breadcrumb location is our node
518
if ( nodeRef.equals(((IRepoBreadcrumbHandler)handler).getNodeRef()) )
519          {
520             // and update with the modified node details
521
IBreadcrumbHandler newHandler = new CategoryBreadcrumbHandler(
522                   nodeRef, Repository.getNameForNode(nodeService, nodeRef));
523             location.set(location.size() - 1, newHandler);
524          }
525       }
526       catch (Throwable JavaDoc err)
527       {
528          // rollback the transaction
529
try { if (tx != null) {tx.rollback();} } catch (Exception JavaDoc tex) {}
530          Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
531                FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err);
532          outcome = null;
533       }
534       
535       return outcome;
536    }
537    
538    /**
539     * Action handler called on Delete Category finish button click.
540     */

541    public String JavaDoc finishDelete()
542    {
543       String JavaDoc outcome = DEFAULT_OUTCOME;
544       
545       if (getActionCategory() != null)
546       {
547          UserTransaction JavaDoc tx = null;
548          try
549          {
550             FacesContext context = FacesContext.getCurrentInstance();
551             tx = Repository.getUserTransaction(context);
552             tx.begin();
553             
554             // delete the category node using the nodeservice
555
NodeRef categoryNodeRef = getActionCategory().getNodeRef();
556             this.categoryService.deleteCategory(categoryNodeRef);
557             
558             // if there are other items in the repository using this category
559
// all the associations to the category should be removed too
560
if (this.members != null && this.members.size() > 0)
561             {
562                for (ChildAssociationRef childRef : this.members)
563                {
564                   List JavaDoc<NodeRef> list = new ArrayList JavaDoc<NodeRef>(this.members.size());
565                   
566                   NodeRef member = childRef.getChildRef();
567                   Collection JavaDoc<NodeRef> categories = (Collection JavaDoc<NodeRef>)this.nodeService.
568                         getProperty(member, ContentModel.PROP_CATEGORIES);
569
570                   for (NodeRef category : categories)
571                   {
572                      if (category.equals(categoryNodeRef) == false)
573                      {
574                         list.add(category);
575                      }
576                   }
577                   
578                   // persist the list back to the repository
579
this.nodeService.setProperty(member, ContentModel.PROP_CATEGORIES, (Serializable JavaDoc)list);
580                }
581             }
582             
583             // commit the transaction
584
tx.commit();
585             
586             // remove this node from the breadcrumb if required
587
List JavaDoc<IBreadcrumbHandler> location = getLocation();
588             IBreadcrumbHandler handler = location.get(location.size() - 1);
589             
590             // see if the current breadcrumb location is our node
591
if ( categoryNodeRef.equals(((IRepoBreadcrumbHandler)handler).getNodeRef()) )
592             {
593                location.remove(location.size() - 1);
594                
595                // now work out which node to set the list to refresh against
596
if (location.size() != 0)
597                {
598                   handler = location.get(location.size() - 1);
599                   this.setCurrentCategory(((IRepoBreadcrumbHandler)handler).getNodeRef());
600                }
601             }
602             
603             // clear action context
604
setActionCategory(null);
605          }
606          catch (Throwable JavaDoc err)
607          {
608             // rollback the transaction
609
try { if (tx != null) {tx.rollback();} } catch (Exception JavaDoc tex) {}
610             Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
611                FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err);
612             outcome = null;
613          }
614       }
615       
616       return outcome;
617    }
618    
619    /**
620     * Change the current view mode based on user selection
621     *
622     * @param event ActionEvent
623     */

624    public void viewModeChanged(ActionEvent event)
625    {
626       UIModeList viewList = (UIModeList)event.getComponent();
627       
628       // get the view mode ID
629
setViewMode(viewList.getValue().toString());
630    }
631    
632    /**
633     * Update the breadcrumb with the clicked category location
634     */

635    private void updateUILocation(NodeRef ref)
636    {
637       String JavaDoc name = Repository.getNameForNode(this.nodeService, ref);
638       this.location.add(new CategoryBreadcrumbHandler(ref, name));
639       this.setCurrentCategory(ref);
640    }
641    
642    
643    // ------------------------------------------------------------------------------
644
// IContextListener implementation
645

646    /**
647     * @see org.alfresco.web.app.context.IContextListener#contextUpdated()
648     */

649    public void contextUpdated()
650    {
651       if (logger.isDebugEnabled())
652          logger.debug("Invalidating Category Management Components...");
653       
654       // force a requery of the current category ref properties
655
this.category = null;
656       
657       // force a requery of the richlist dataset
658
this.categoriesRichList.setValue(null);
659    }
660    
661    
662    // ------------------------------------------------------------------------------
663
// Inner classes
664

665    /**
666     * Class to handle breadcrumb interaction for Categories pages
667     */

668    private class CategoryBreadcrumbHandler implements IRepoBreadcrumbHandler
669    {
670       private static final long serialVersionUID = 3831234653171036630L;
671       
672       /**
673        * Constructor
674        *
675        * @param NodeRef The NodeRef for this browse navigation element
676        * @param label Element label
677        */

678       public CategoryBreadcrumbHandler(NodeRef nodeRef, String JavaDoc label)
679       {
680          this.label = label;
681          this.nodeRef = nodeRef;
682       }
683       
684       /**
685        * @see java.lang.Object#toString()
686        */

687       public String JavaDoc toString()
688       {
689          return this.label;
690       }
691
692       /**
693        * @see org.alfresco.web.ui.common.component.IBreadcrumbHandler#navigationOutcome(org.alfresco.web.ui.common.component.UIBreadcrumb)
694        */

695       public String JavaDoc navigationOutcome(UIBreadcrumb breadcrumb)
696       {
697          // All category breadcrumb elements relate to a Categiry Node Id
698
// when selected we set the current category Id and return
699
setCurrentCategory(this.nodeRef);
700          setLocation( (List JavaDoc)breadcrumb.getValue() );
701          
702          return null;
703       }
704       
705       public NodeRef getNodeRef()
706       {
707          return this.nodeRef;
708       }
709       
710       private NodeRef nodeRef;
711       private String JavaDoc label;
712    }
713 }
714
Popular Tags