View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.custom.tree.renderkit.html;
20  
21  import org.apache.myfaces.renderkit.html.util.AddResource;
22  import org.apache.myfaces.renderkit.html.util.AddResourceFactory;
23  import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
24  import org.apache.myfaces.custom.tree.HtmlTree;
25  import org.apache.myfaces.custom.tree.HtmlTreeColumn;
26  import org.apache.myfaces.custom.tree.HtmlTreeImageCommandLink;
27  import org.apache.myfaces.custom.tree.HtmlTreeNode;
28  import org.apache.myfaces.custom.tree.IconProvider;
29  import org.apache.myfaces.custom.tree.TreeNode;
30  import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
31  import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils;
32  import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlTableRendererBase;
33  import org.apache.myfaces.shared_tomahawk.util.ArrayUtils;
34  import org.apache.myfaces.shared_tomahawk.util.StringUtils;
35  
36  import javax.faces.component.UIColumn;
37  import javax.faces.component.UIComponent;
38  import javax.faces.context.FacesContext;
39  import javax.faces.context.ResponseWriter;
40  
41  import java.io.IOException;
42  import java.util.ArrayList;
43  import java.util.Iterator;
44  import java.util.List;
45  
46  /**
47   * @JSFRenderer
48   *   renderKitId = "HTML_BASIC" 
49   *   family = "org.apache.myfaces.HtmlTree"
50   *   type = "org.apache.myfaces.HtmlTree"
51   * 
52   * @author <a href="mailto:oliver@rossmueller.com">Oliver Rossmueller </a>
53   * @version $Revision: 659874 $ $Date: 2008-05-24 15:59:15 -0500 (Sat, 24 May 2008) $
54   */
55  public class HtmlTreeRenderer extends HtmlTableRendererBase
56  {
57      // Defaut images
58      private static final String DEFAULT_IMAGE_ICON_LINE = "images/line.gif";
59      private static final String DEFAULT_IMAGE_ICON_NOLINE = "images/noline.gif";
60      private static final String DEFAULT_IMAGE_ICON_CHILD_FIRST = "images/line_first.gif";
61      private static final String DEFAULT_IMAGE_ICON_CHILD_MIDDLE = "images/line_middle.gif";
62      private static final String DEFAULT_IMAGE_ICON_CHILD_LAST = "images/line_last.gif";
63      private static final String DEFAULT_IMAGE_ICON_NODE_OPEN = "images/node_open.gif";
64      private static final String DEFAULT_IMAGE_ICON_NODE_OPEN_FIRST = "images/node_open_first.gif";
65      private static final String DEFAULT_IMAGE_ICON_NODE_OPEN_MIDDLE = "images/node_open_middle.gif";
66      private static final String DEFAULT_IMAGE_ICON_NODE_OPEN_LAST = "images/node_open_last.gif";
67      private static final String DEFAULT_IMAGE_ICON_NODE_CLOSE = "images/node_close.gif";
68      private static final String DEFAULT_IMAGE_ICON_NODE_CLOSE_FIRST = "images/node_close_first.gif";
69      private static final String DEFAULT_IMAGE_ICON_NODE_CLOSE_MIDDLE = "images/node_close_middle.gif";
70      private static final String DEFAULT_IMAGE_ICON_NODE_CLOSE_LAST = "images/node_close_last.gif";
71  
72      private static final Integer ZERO = new Integer(0);
73  
74      private static final String DEFAULT_IMAGE_ICON_FOLDER = "images/folder.gif";
75  
76      public boolean getRendersChildren()
77      {
78          return true;
79      }
80  
81      public void encodeBegin(FacesContext facesContext, UIComponent uiComponent) throws IOException
82      {
83          // Rendering occurs in encodeEnd.
84      }
85  
86      public void encodeChildren(FacesContext facesContext, UIComponent component) throws IOException
87      {
88          // children are rendered in encodeEnd
89      }
90  
91      public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException
92      {
93          RendererUtils.checkParamValidity(facesContext, component, HtmlTree.class);
94          ResponseWriter writer = facesContext.getResponseWriter();
95          HtmlTree tree = (HtmlTree) component;
96  
97          HtmlRendererUtils.writePrettyLineSeparator(facesContext);
98          writer.startElement(HTML.TABLE_ELEM, component);
99          HtmlRendererUtils.renderHTMLAttributes(writer, tree, HTML.TABLE_PASSTHROUGH_ATTRIBUTES);
100         writer.writeAttribute(HTML.BORDER_ATTR, ZERO, null);
101         writer.writeAttribute(HTML.CELLSPACING_ATTR, ZERO, null);
102         writer.writeAttribute(HTML.CELLPADDING_ATTR, ZERO, null);
103 
104         int maxLevel = tree.getRootNode().getMaxChildLevel();
105 
106         // Create initial children list from root node facet
107         ArrayList childNodes = new ArrayList(1);
108         childNodes.add(tree.getRootNode());
109 
110         // Render header.
111         renderFacet(facesContext, writer, component, true, maxLevel);
112 
113         // Render children.
114         renderChildren(facesContext, writer, tree, childNodes, maxLevel, tree.getIconProvider(), component);
115 
116         // Render footer.
117         renderFacet(facesContext, writer, component, false, maxLevel);
118         writer.endElement(HTML.TABLE_ELEM);
119     }
120 
121     /**
122      * <p>
123      * Overrides super renderFacet to render the {@link HtmlTree} facets.
124      * <p>
125      *
126      * @param facesContext The facesContext
127      * @param writer The writer.
128      * @param component The component.
129      * @param header Whether there is a header.
130      * @param maxLevel The max level for the rendered tree.
131      * @throws IOException Throws IOException.
132      */
133     protected void renderFacet(FacesContext facesContext, ResponseWriter writer, UIComponent component, boolean header, int maxLevel)
134             throws IOException
135     {
136         int colspan = 0;
137         boolean hasColumnFacet = false;
138         for (Iterator it = component.getChildren().iterator(); it.hasNext();)
139         {
140             UIComponent uiComponent = (UIComponent) it.next();
141             if ((uiComponent.getFamily().equals(UIColumn.COMPONENT_FAMILY))
142                     && ((UIColumn) uiComponent).isRendered())
143             {
144                 colspan++;
145                 if (!hasColumnFacet)
146                 {
147                     hasColumnFacet = header ? ((UIColumn) uiComponent).getHeader() != null : ((UIColumn) uiComponent)
148                             .getFooter() != null;
149                 }
150             }
151             else if ((uiComponent.getFamily().equals(HtmlTreeColumn.COMPONENT_FAMILY))
152                     && ((HtmlTreeColumn) uiComponent).isRendered())
153             {
154                 colspan += maxLevel + 3;
155                 if (!hasColumnFacet)
156                 {
157                     hasColumnFacet = header ? ((UIColumn) uiComponent).getHeader() != null : ((UIColumn) uiComponent)
158                             .getFooter() != null;
159                 }
160             }
161         }
162 
163         UIComponent facet = header ? (UIComponent) component.getFacets().get(HEADER_FACET_NAME)
164                 : (UIComponent) component.getFacets().get(FOOTER_FACET_NAME);
165         if (facet != null || hasColumnFacet)
166         {
167             // Header or Footer present
168             String elemName = header ? HTML.THEAD_ELEM : HTML.TFOOT_ELEM;
169 
170             HtmlRendererUtils.writePrettyLineSeparator(facesContext);
171             writer.startElement(elemName, component);
172             if (header)
173             {
174                 String headerStyleClass = getHeaderClass(component);
175                 if (facet != null)
176                     renderTableHeaderRow(facesContext, writer, component, facet, headerStyleClass, colspan);
177                 if (hasColumnFacet)
178                     renderColumnHeaderRow(facesContext, writer, component, headerStyleClass, maxLevel);
179             }
180             else
181             {
182                 String footerStyleClass = getFooterClass(component);
183                 if (hasColumnFacet)
184                     renderColumnFooterRow(facesContext, writer, component, footerStyleClass, maxLevel);
185                 if (facet != null)
186                     renderTableFooterRow(facesContext, writer, component, facet, footerStyleClass, colspan);
187             }
188             writer.endElement(elemName);
189         }
190     }
191 
192     protected void renderColumnHeaderRow(FacesContext facesContext, ResponseWriter writer, UIComponent component,
193             String headerStyleClass, int maxLevel) throws IOException
194     {
195         renderColumnHeaderOrFooterRow(facesContext, writer, component, headerStyleClass, true, maxLevel);
196     }
197 
198     protected void renderColumnFooterRow(FacesContext facesContext, ResponseWriter writer, UIComponent component,
199             String footerStyleClass, int maxLevel) throws IOException
200     {
201         renderColumnHeaderOrFooterRow(facesContext, writer, component, footerStyleClass, false, maxLevel);
202     }
203 
204     private void renderColumnHeaderOrFooterRow(FacesContext facesContext, ResponseWriter writer, UIComponent component,
205             String styleClass, boolean header, int maxLevel) throws IOException
206     {
207         HtmlRendererUtils.writePrettyLineSeparator(facesContext);
208         writer.startElement(HTML.TR_ELEM, component);
209         for (Iterator it = component.getChildren().iterator(); it.hasNext();)
210         {
211             UIComponent uiComponent = (UIComponent) it.next();
212             if ((uiComponent.getFamily().equals(UIColumn.COMPONENT_FAMILY))
213                     && ((UIColumn) uiComponent).isRendered())
214             {
215                 if (header)
216                 {
217                     renderColumnHeaderCell(facesContext, writer, (UIColumn) uiComponent, styleClass, 0);
218                 }
219                 else
220                 {
221                     renderColumnFooterCell(facesContext, writer, (UIColumn) uiComponent, styleClass, 0);
222                 }
223             }
224             else if ((uiComponent.getFamily().equals(HtmlTreeColumn.COMPONENT_FAMILY))
225                     && ((HtmlTreeColumn) uiComponent).isRendered())
226             {
227                 if (header)
228                 {
229                     renderColumnHeaderCell(facesContext, writer, (UIColumn) uiComponent, styleClass, maxLevel + 3);
230                 }
231                 else
232                 {
233                     renderColumnFooterCell(facesContext, writer, (UIColumn) uiComponent, styleClass, maxLevel + 3);
234                 }
235             }
236         }
237         writer.endElement(HTML.TR_ELEM);
238     }
239 
240     /**
241      * <p>
242      * Renders the children.
243      * </p>
244      *
245      * @param facesContext The facesContext.
246      * @param writer The writer.
247      * @param tree The tree component.
248      * @param children The children to render.
249      * @param maxLevel The maximum level.
250      * @param iconProvider The icon provider.
251      * @throws IOException Throws an IOException.
252      */
253     protected void renderChildren(FacesContext facesContext, ResponseWriter writer, HtmlTree tree, List children,
254             int maxLevel, IconProvider iconProvider, UIComponent component) throws IOException
255     {
256         renderChildren(facesContext, writer, tree, children, maxLevel, iconProvider, 0, component);
257     }
258 
259     /**
260      * <p>
261      * Renders the children given the rowClassIndex.
262      * </p>
263      *
264      * @param facesContext The facesContext.
265      * @param writer The writer.
266      * @param tree The tree component.
267      * @param children The children to render.
268      * @param maxLevel The maximum level.
269      * @param iconProvider The icon provider.
270      * @param rowClassIndex The row class index.
271      * @throws IOException Throws an IOException.
272      */
273     protected void renderChildren(FacesContext facesContext, ResponseWriter writer, HtmlTree tree, List children,
274             int maxLevel, IconProvider iconProvider, int rowClassIndex, UIComponent component) throws IOException
275     {
276         String rowClasses = tree.getRowClasses();
277         String columnClasses = tree.getColumnClasses();
278 
279         String[] rowClassesArray = (rowClasses == null) ? ArrayUtils.EMPTY_STRING_ARRAY : StringUtils.trim(StringUtils
280                 .splitShortString(rowClasses, ','));
281         int rowClassesCount = rowClassesArray.length;
282 
283         String[] columnClassesArray = (columnClasses == null) ? ArrayUtils.EMPTY_STRING_ARRAY : StringUtils
284                 .trim(StringUtils.splitShortString(columnClasses, ','));
285         int columnClassesCount = columnClassesArray.length;
286         int columnClassIndex = 0;
287 
288         for (Iterator it = children.iterator(); it.hasNext();)
289         {
290             HtmlTreeNode child = (HtmlTreeNode) it.next();
291 
292             if (!child.isRendered())
293             {
294                 continue;
295             }
296             HtmlRendererUtils.writePrettyLineSeparator(facesContext);
297 
298             writer.startElement(HTML.TR_ELEM, component);
299 
300             if (rowClassIndex < rowClassesCount)
301             {
302                 writer.writeAttribute(HTML.CLASS_ATTR, rowClassesArray[rowClassIndex], null);
303             }
304             if (rowClassesCount > 0)
305             {
306                 rowClassIndex++;
307                 rowClassIndex = rowClassIndex % rowClassesCount;
308             }
309 
310             if (null != tree.getVar())
311             {
312                 facesContext.getExternalContext().getSessionMap().put(tree.getVar(),
313                         ((TreeNode) child.getUserObject()).getUserObject());
314             }
315 
316             List componentChildren = tree.getChildren();
317             if ((null != componentChildren) && (componentChildren.size() > 0))
318             {
319                 for (int j = 0, size = tree.getChildCount(); j < size; j++)
320                 {
321                     UIComponent componentChild = (UIComponent) componentChildren.get(j);
322                     if ((componentChild.getFamily().equals(UIColumn.COMPONENT_FAMILY))
323                             && ((UIColumn) componentChild).isRendered())
324                     {
325                         writer.startElement(HTML.TD_ELEM, tree);
326                         if (columnClassIndex < columnClassesCount)
327                         {
328                             writer.writeAttribute(HTML.CLASS_ATTR, columnClassesArray[columnClassIndex], null);
329                         }
330                         if (columnClassesCount > 0)
331                         {
332                             columnClassIndex++;
333                             columnClassIndex = columnClassIndex % columnClassesCount;
334                         }
335                         RendererUtils.renderChild(facesContext, componentChild);
336                         writer.endElement(HTML.TD_ELEM);
337                     }
338                     else if ((componentChild.getFamily().equals(HtmlTreeColumn.COMPONENT_FAMILY))
339                             && ((HtmlTreeColumn) componentChild).isRendered())
340                     {
341                         renderTreeColumnChild(facesContext, writer, componentChild, tree, child, maxLevel, iconProvider);
342                     }
343                 }
344             }
345             else
346             {
347                 renderTreeColumnChild(facesContext, writer, null, tree, child, maxLevel, iconProvider);
348             }
349 
350             writer.endElement(HTML.TR_ELEM);
351 
352             if (child.getChildCount() > 0)
353             {
354                 renderChildren(facesContext, writer, tree, child.getChildren(), maxLevel, iconProvider, rowClassIndex, component);
355                 if (rowClassesCount > 0)
356                 {
357                     rowClassIndex += (child.getChildCount() % rowClassesCount);
358                     rowClassIndex = rowClassIndex % rowClassesCount;
359                 }
360             }
361         }
362     }
363 
364     public String getDefaultImagePath(FacesContext context, String relativePathInResourceFolder)
365     {
366         AddResource instance = AddResourceFactory.getInstance(context);
367         return instance.getResourceUri(context, HtmlTree.class, relativePathInResourceFolder, false);
368     }
369 
370     /**
371      * <p>
372      * Render the column where the tree is displayed.
373      * </p>
374      *
375      * @param facesContext The facesContext.
376      * @param writer The writer.
377      * @param component The component that will contain the tree. Null for
378      *            default tree or {@link HtmlTreeColumn}for table rendering.
379      * @param tree The tree,
380      * @param child The tree node child.
381      * @param maxLevel The max number of levels.
382      * @param iconProvider The iconProvider.
383      * @throws IOException Throws IOException.
384      */
385     protected void renderTreeColumnChild(FacesContext facesContext, ResponseWriter writer, UIComponent component,
386             HtmlTree tree, HtmlTreeNode child, int maxLevel, IconProvider iconProvider) throws IOException
387     {
388         String iconClass = tree.getIconClass();
389         int[] layout = child.getLayout();
390         // tree lines
391         for (int i = 0; i < layout.length - 1; i++)
392         {
393             int state = layout[i];
394             writer.startElement(HTML.TD_ELEM, child);
395             String url = getLayoutImage(facesContext, tree, state);
396 
397             if ((url != null) && (url.length() > 0))
398             {
399                 //writer.startElement(HTML.IMG_ELEM, child);
400 
401                 //String src;
402                 //if (url.startsWith(HTML.HREF_PATH_SEPARATOR))
403                 //{
404                 //    String path = facesContext.getExternalContext().getRequestContextPath();
405                 //    src = path + url;
406                 //}
407                 //else
408                 //{
409                 //    src = url;
410                 //}
411                 //Encode URL
412                 //Although this is an url url, encodeURL is no nonsense,
413                 // because the
414                 //actual url url could also be a dynamic servlet request:
415                 //src = facesContext.getExternalContext().encodeResourceURL(src);
416                 //writer.writeAttribute(HTML.SRC_ATTR, src, null);
417                 //writer.writeAttribute(HTML.BORDER_ATTR, ZERO, null);
418 
419                 //HtmlRendererUtils.renderHTMLAttributes(writer, child, HTML.IMG_PASSTHROUGH_ATTRIBUTES);
420 
421                 //writer.endElement(HTML.IMG_ELEM);
422                 writeImageElement(url, facesContext, writer, child);
423             }
424             writer.endElement(HTML.TD_ELEM);
425 
426         }
427 
428         // command link
429         writer.startElement(HTML.TD_ELEM, tree);
430         int state = layout[layout.length - 1];
431         String url = getLayoutImage(facesContext, tree, state);
432 
433         if (state == HtmlTreeNode.CHILD || state == HtmlTreeNode.CHILD_FIRST || state == HtmlTreeNode.CHILD_LAST)
434         {
435             // no action, just img
436             writeImageElement(url, facesContext, writer, child);
437         }
438         else
439         {
440             HtmlTreeImageCommandLink expandCollapse = (HtmlTreeImageCommandLink) child
441                     .getExpandCollapseCommand(facesContext);
442             expandCollapse.setImage(getLayoutImage(facesContext, tree, layout[layout.length - 1]));
443 
444             expandCollapse.encodeBegin(facesContext);
445             expandCollapse.encodeEnd(facesContext);
446         }
447         writer.endElement(HTML.TD_ELEM);
448 
449         int labelColSpan = maxLevel - child.getLevel() + 1;
450 
451         // node icon
452         if (iconProvider != null)
453         {
454             url = iconProvider.getIconUrl(child.getUserObject(), child.getChildCount(), child.isLeaf(facesContext));
455         }
456         else
457         {
458             if (!child.isLeaf(facesContext))
459             {
460                 // todo: icon provider
461                 url = getDefaultImagePath(facesContext, DEFAULT_IMAGE_ICON_FOLDER );
462             }
463             else
464             {
465                 url = null;
466             }
467         }
468 
469         if ((url != null) && (url.length() > 0))
470         {
471             writer.startElement(HTML.TD_ELEM, tree);
472             if (iconClass != null)
473             {
474                 writer.writeAttribute(HTML.CLASS_ATTR, iconClass, null);
475             }
476             writeImageElement(url, facesContext, writer, child);
477             writer.endElement(HTML.TD_ELEM);
478         }
479         else
480         {
481             // no icon, so label has more room
482             labelColSpan++;
483         }
484 
485         // node label
486         writer.startElement(HTML.TD_ELEM, tree);
487         writer.writeAttribute(HTML.COLSPAN_ATTR, new Integer(labelColSpan), null);
488         if (child.isSelected() && tree.getSelectedNodeClass() != null)
489         {
490             writer.writeAttribute(HTML.CLASS_ATTR, tree.getSelectedNodeClass(), null);
491         }
492         else if (!child.isSelected() && tree.getNodeClass() != null)
493         {
494             writer.writeAttribute(HTML.CLASS_ATTR, tree.getNodeClass(), null);
495         }
496 
497         List componentChildren = null;
498         if (null != component)
499         {
500             componentChildren = component.getChildren();
501         }
502         if ((null != componentChildren) && (componentChildren.size() > 0))
503         {
504             for (int k = 0; k < componentChildren.size(); k++)
505             {
506                 UIComponent componentChild = (UIComponent) componentChildren.get(k);
507                 RendererUtils.renderChild(facesContext, componentChild);
508             }
509         }
510         else
511         {
512             child.encodeBegin(facesContext);
513             child.encodeEnd(facesContext);
514         }
515         writer.endElement(HTML.TD_ELEM);
516     }
517 
518     private void writeImageElement(String url, FacesContext facesContext, ResponseWriter writer, HtmlTreeNode child)
519             throws IOException
520     {
521         writer.startElement(HTML.IMG_ELEM, child);
522         String src = facesContext.getApplication().getViewHandler().getResourceURL(facesContext, url);
523         //        if (url.startsWith(HTML.HREF_PATH_SEPARATOR))
524         //        {
525         //            String path =
526         // facesContext.getExternalContext().getRequestContextPath();
527         //            src = path + url;
528         //        } else
529         //        {
530         //            src = url;
531         //        }
532         //        //Encode URL
533         //        src = facesContext.getExternalContext().encodeResourceURL(src);
534         writer.writeAttribute(HTML.SRC_ATTR, src, null);
535         writer.writeAttribute(HTML.BORDER_ATTR, ZERO, null);
536 
537         HtmlRendererUtils.renderHTMLAttributes(writer, child, HTML.IMG_PASSTHROUGH_ATTRIBUTES);
538 
539         writer.endElement(HTML.IMG_ELEM);
540     }
541 
542     protected String getLayoutImage(FacesContext context, HtmlTree tree, int state)
543     {
544         switch (state)
545         {
546         case HtmlTreeNode.OPEN:
547             return getImageUrl(context, tree.getIconNodeOpenMiddle(), DEFAULT_IMAGE_ICON_NODE_OPEN_MIDDLE);
548         case HtmlTreeNode.OPEN_FIRST:
549             return getImageUrl(context, tree.getIconNodeOpenFirst(), DEFAULT_IMAGE_ICON_NODE_OPEN_FIRST);
550         case HtmlTreeNode.OPEN_LAST:
551             return getImageUrl(context, tree.getIconNodeOpenLast(), DEFAULT_IMAGE_ICON_NODE_OPEN_LAST);            
552         case HtmlTreeNode.OPEN_SINGLE:
553             return getImageUrl(context, tree.getIconNodeOpen(), DEFAULT_IMAGE_ICON_NODE_OPEN);            
554         case HtmlTreeNode.CLOSED:
555             return getImageUrl(context, tree.getIconNodeCloseMiddle(), DEFAULT_IMAGE_ICON_NODE_CLOSE_MIDDLE);            
556         case HtmlTreeNode.CLOSED_FIRST:
557             return getImageUrl(context, tree.getIconNodeCloseFirst(), DEFAULT_IMAGE_ICON_NODE_CLOSE_FIRST);            
558         case HtmlTreeNode.CLOSED_LAST:
559             return getImageUrl(context, tree.getIconNodeCloseLast(), DEFAULT_IMAGE_ICON_NODE_CLOSE_LAST);            
560         case HtmlTreeNode.CLOSED_SINGLE:
561             return getImageUrl(context, tree.getIconNodeClose(), DEFAULT_IMAGE_ICON_NODE_CLOSE);            
562         case HtmlTreeNode.CHILD:
563             return getImageUrl(context, tree.getIconChildMiddle(), DEFAULT_IMAGE_ICON_CHILD_MIDDLE);            
564         case HtmlTreeNode.CHILD_FIRST:
565             return getImageUrl(context, tree.getIconChildFirst(), DEFAULT_IMAGE_ICON_CHILD_FIRST);            
566         case HtmlTreeNode.CHILD_LAST:
567             return getImageUrl(context, tree.getIconChildLast(), DEFAULT_IMAGE_ICON_CHILD_LAST);            
568         case HtmlTreeNode.LINE:
569             return getImageUrl(context, tree.getIconLine(), DEFAULT_IMAGE_ICON_LINE);            
570         case HtmlTreeNode.EMPTY:
571             return getImageUrl(context, tree.getIconNoline(), DEFAULT_IMAGE_ICON_NOLINE);            
572         default:
573             return getImageUrl(context, tree.getIconNoline(), DEFAULT_IMAGE_ICON_NOLINE);
574         }
575     }
576 
577     protected String getImageUrl(FacesContext context, String userValue, String resourceValue)
578     {
579         AddResource addResource = AddResourceFactory.getInstance(context);
580         if(userValue != null)
581         {
582             return addResource.getResourceUri(context, userValue, false);
583         }
584         return addResource.getResourceUri(context, HtmlTree.class, resourceValue, false);
585     }
586 }