1 33 34 package com.icesoft.faces.component.tree; 35 36 import com.icesoft.faces.component.CSS_DEFAULT; 37 import com.icesoft.faces.component.InvalidComponentTypeException; 38 import com.icesoft.faces.component.ext.taglib.Util; 39 import com.icesoft.faces.component.util.CustomComponentUtils; 40 import com.icesoft.faces.context.DOMContext; 41 import com.icesoft.faces.renderkit.dom_html_basic.DomBasicRenderer; 42 import com.icesoft.faces.renderkit.dom_html_basic.FormRenderer; 43 import com.icesoft.faces.renderkit.dom_html_basic.HTML; 44 import com.icesoft.faces.renderkit.dom_html_basic.PassThruAttributeRenderer; 45 import com.icesoft.faces.util.CoreUtils; 46 47 import org.w3c.dom.Element ; 48 49 import javax.faces.component.UIComponent; 50 import javax.faces.context.FacesContext; 51 import javax.faces.event.ActionEvent; 52 import javax.swing.tree.DefaultMutableTreeNode ; 53 import javax.swing.tree.TreeModel ; 54 import java.io.IOException ; 55 import java.util.Map ; 56 57 63 public class TreeRenderer extends DomBasicRenderer { 64 65 68 public static final String PATH_DELIMITER = "-"; 69 70 73 public boolean getRendersChildren() { 74 return true; 75 } 76 77 81 public void decode(FacesContext facesContext, UIComponent uiComponent) { 82 if (isStatic(uiComponent)) { 83 return; 84 } 85 86 Tree treeComponent = (Tree) uiComponent; 87 String expandNodeKey = CustomComponentUtils 88 .getHiddenTreeExpandFieldName( 89 uiComponent.getClientId(facesContext), 90 CustomComponentUtils.getFormName(uiComponent, 91 facesContext)); 92 String pathToExpandedNode = (String ) facesContext.getExternalContext() 93 .getRequestParameterMap().get(expandNodeKey); 94 if (pathToExpandedNode != null && 98 !pathToExpandedNode.equalsIgnoreCase("")) { 99 try { 100 DefaultMutableTreeNode navigatedNode = 102 treeComponent.getNodeAtPathsEnd(pathToExpandedNode); 103 treeComponent.setNavigatedNode(navigatedNode); 104 IceUserObject userObject = 105 (IceUserObject) navigatedNode.getUserObject(); 106 if (userObject != null) { 107 treeComponent.setNavigationEventType( 108 userObject.isExpanded() ? 109 Tree.NAVIGATION_EVENT_COLLAPSE : 110 Tree.NAVIGATION_EVENT_EXPAND); 111 userObject.setExpanded(!userObject.isExpanded()); 112 } 113 114 ActionEvent actionEvent = new ActionEvent(uiComponent); 115 uiComponent.queueEvent(actionEvent); 116 117 } catch (NumberFormatException nfe) { 118 throw new InvalidNavigationId( 119 "TreeRenderer.decode() NumberFormatException invalid tree navigation id", 120 nfe); 121 } 122 } 123 } 124 125 130 public void encodeBegin(FacesContext facesContext, UIComponent uiComponent) 131 throws IOException { 132 133 DOMContext domContext = 135 DOMContext.attachDOMContext(facesContext, uiComponent); 136 137 validateParameters(facesContext, uiComponent, Tree.class); 139 140 Tree treeComponent = (Tree) uiComponent; 141 TreeModel treeModel = (TreeModel ) uiComponent 142 .getValueBinding("value").getValue(facesContext); 143 144 if (treeComponent.getChildCount() != 1) { 145 throw new MalformedTreeTagException( 146 "The tree tag requires a single child treeNode tag. Found [" + 147 treeComponent.getChildCount() + "]"); 148 } 149 150 if (treeModel == null) { 151 return; 152 } 153 154 FormRenderer.addHiddenField(facesContext, 156 CustomComponentUtils.getHiddenTreeExpandFieldName( 157 uiComponent.getClientId( 158 facesContext), 159 CustomComponentUtils.getFormName( 160 uiComponent, 161 facesContext))); 162 FormRenderer.addHiddenField(facesContext, 163 CustomComponentUtils.getHiddenTreeActionFieldName( 164 uiComponent.getClientId( 165 facesContext), 166 CustomComponentUtils.getFormName( 167 uiComponent, 168 facesContext))); 169 170 if (!domContext.isInitialized()) { 172 Element rootDOMNode = domContext.createRootElement(HTML.DIV_ELEM); 173 rootDOMNode.setAttribute(HTML.ID_ATTR, 174 uiComponent.getClientId(facesContext)); 175 } 176 Element rootDomNode = (Element ) domContext.getRootNode(); 178 179 rootDomNode 181 .setAttribute(HTML.CLASS_ATTR, treeComponent.getStyleClass()); 182 String style = treeComponent.getStyle(); 183 if(style != null && style.length() > 0) 184 rootDomNode.setAttribute(HTML.STYLE_ATTR, style); 185 else 186 rootDomNode.removeAttribute(HTML.STYLE_ATTR); 187 188 DOMContext.removeChildren(rootDomNode); 190 191 if (PassThruAttributeRenderer.passThruAttributeExists(uiComponent)) { 192 PassThruAttributeRenderer 193 .renderAttributes(facesContext, uiComponent, null); 194 } 195 196 domContext.startNode(facesContext, treeComponent, rootDomNode); 198 199 domContext.stepInto(uiComponent); 200 201 } 202 203 private boolean isHideRootNode(Tree treeComponent) { 204 String hideRootNodeAttribute = 205 (String ) treeComponent.getAttributes().get("hideRootNode"); 206 return hideRootNodeAttribute != null && 207 hideRootNodeAttribute.equalsIgnoreCase("true"); 208 } 209 210 private boolean isHideNavigation(Tree treeComponent) { 211 String hideNavAttr = 212 (String ) treeComponent.getAttributes().get("hideNavigation"); 213 return hideNavAttr != null && hideNavAttr.equalsIgnoreCase("true"); 214 } 215 216 221 public void encodeChildren(FacesContext facesContext, 222 UIComponent uiComponent) 223 throws IOException { 224 225 DOMContext domContext = 227 DOMContext.getDOMContext(facesContext, uiComponent); 228 229 TreeModel treeModel = (TreeModel ) uiComponent 230 .getValueBinding("value").getValue(facesContext); 231 DefaultMutableTreeNode treeComponentRootNode = 232 (DefaultMutableTreeNode ) treeModel.getRoot(); 233 Element rootNode = (Element ) domContext.getRootNode(); 234 com.icesoft.faces.component.tree.TreeNode treeNode = 235 (TreeNode) (uiComponent).getChildren().get(0); 236 boolean hideRootNode; 237 if (uiComponent instanceof Tree) { 238 hideRootNode = isHideRootNode((Tree) uiComponent); 239 } else { 240 throw new InvalidComponentTypeException("Expecting a Tree"); 241 } 242 243 encodeParentAndChildNodes(facesContext, (Tree) uiComponent, 244 (DefaultMutableTreeNode ) treeModel.getRoot(), 245 hideRootNode, rootNode, treeComponentRootNode, 246 treeNode); 247 248 } 249 250 259 public void encodeParentAndChildNodes(FacesContext facesContext, 260 Tree treeComponent, 261 DefaultMutableTreeNode current, 262 boolean hideCurrentNode, 263 Element parentDOMNode, 264 DefaultMutableTreeNode treeComponentRootNode, 265 TreeNode treeNode) { 266 267 DOMContext domContext = 268 DOMContext.getDOMContext(facesContext, treeComponent); 269 270 Element treeNodeDiv = domContext.createElement(HTML.DIV_ELEM); 271 if (!hideCurrentNode) { 272 Map requestMap = facesContext.getExternalContext().getRequestMap(); 274 String varAttribute = treeComponent.getVar(); 275 requestMap.put(varAttribute, current); 276 domContext.setCursorParent(parentDOMNode); 277 278 treeNodeDiv.setAttribute(HTML.NAME_ATTR, "treeNodeDiv"); 279 treeNodeDiv 280 .setAttribute(HTML.CLASS_ATTR, treeComponent.getTreeRowStyleClass()); 281 parentDOMNode.appendChild(treeNodeDiv); 282 domContext.setCursorParent(treeNodeDiv); 283 try { 285 domContext.startNode(facesContext, treeComponent, treeNodeDiv); 286 } catch (IOException ioe) { 287 ioe.printStackTrace(); 288 } 289 290 encodeNode(facesContext, treeComponent, current, treeNodeDiv, 291 domContext, treeComponentRootNode, treeNode, 292 parentDOMNode); 293 294 } else { 295 Map requestMap = facesContext.getExternalContext().getRequestMap(); 298 String varAttribute = treeComponent.getVar(); 299 requestMap.put(varAttribute, current); 300 domContext.setCursorParent(parentDOMNode); 301 302 treeNodeDiv.setAttribute(HTML.NAME_ATTR, "treeNodeDiv"); 303 treeNodeDiv 304 .setAttribute(HTML.CLASS_ATTR, treeComponent.getTreeRowStyleClass()); 305 treeNodeDiv.setAttribute(HTML.ID_ATTR, treeComponent 307 .getClientId(facesContext) + "-div-root"); 308 parentDOMNode.appendChild(treeNodeDiv); 309 domContext.setCursorParent(treeNodeDiv); 310 try { 312 domContext.startNode(facesContext, treeComponent, treeNodeDiv); 313 } catch (IOException ioe) { 314 ioe.printStackTrace(); 315 } 316 317 } 318 int childCount = current.getChildCount(); 320 if (childCount > 0 && 321 ((IceUserObject) current.getUserObject()).isExpanded()) { 322 Element childDiv = domContext.createElement(HTML.DIV_ELEM); 324 childDiv.setAttribute(HTML.NAME_ATTR, "CHILD"); 325 childDiv.setAttribute(HTML.ID_ATTR, treeNodeDiv 326 .getAttribute(HTML.ID_ATTR) + "-child"); 327 328 treeNodeDiv.appendChild(childDiv); 329 330 try { 332 domContext.startNode(facesContext, treeComponent, childDiv); 333 } catch (IOException ioe) { 334 ioe.printStackTrace(); 335 } 336 337 DefaultMutableTreeNode next; 339 for (int i = 0; i < childCount; i++) { 340 next = (DefaultMutableTreeNode ) current.getChildAt(i); 341 encodeParentAndChildNodes(facesContext, treeComponent, next, 342 false, childDiv, 343 treeComponentRootNode, treeNode); 344 } 345 try { 347 domContext.endNode(facesContext, treeComponent, childDiv); 348 } catch (IOException ioe) { 349 ioe.printStackTrace(); 350 } 351 352 } 353 354 } 355 356 366 public void encodeNode(FacesContext facesContext, 367 Tree treeComponent, 368 DefaultMutableTreeNode currentNode, 369 Element treeNodeDiv, 370 DOMContext domContext, 371 DefaultMutableTreeNode treeComponentRootNode, 372 TreeNode treeNode, 373 Element parentDOMNode) { 374 375 String pathToCurrentRoot = 376 getPathAsString(currentNode, treeComponentRootNode); 377 boolean hideRootNode = isHideRootNode(treeComponent); 378 boolean hideNavigation = isHideNavigation(treeComponent); 379 380 treeNode.setMutable(currentNode); 381 treeNode.setId(Tree.ID_PREFIX + pathToCurrentRoot); 382 treeNode.setParent(treeComponent); 383 384 IceUserObject userObject = (IceUserObject) currentNode.getUserObject(); 386 boolean isBranchNode = !userObject.isLeaf(); 388 boolean isExpanded = userObject.isExpanded(); 389 boolean isLastChild = 390 treeComponentRootNode.getLastLeaf() == currentNode; 391 boolean isCollapsedAndFinalBranch = false; 392 if (isBranchNode && !isExpanded) { 393 isCollapsedAndFinalBranch = isCollapsedAndFinalBranch(currentNode); 394 } 395 int level = currentNode.getLevel(); 396 UIComponent myForm = findForm(treeComponent); 397 String formId = myForm.getClientId(facesContext); 398 399 if (hideRootNode) { 403 level--; 404 } 405 for (int i = 0; i < level; i++) { 406 Element verticalLine = domContext.createElement(HTML.IMG_ELEM); 408 verticalLine.setAttribute(HTML.ALT_ATTR, ""); 409 410 DefaultMutableTreeNode parentNode = null; 413 if ((i > 0) || (hideRootNode)) { 414 int j = 1; 416 parentNode = (DefaultMutableTreeNode ) currentNode.getParent(); 417 while (j < (level - i)) { 418 parentNode = 419 (DefaultMutableTreeNode ) parentNode.getParent(); 420 j++; 421 } 422 } 423 424 boolean renderBlank = false; 425 426 if ((null != parentNode) && (parentNode.getNextSibling() == null)) { 427 renderBlank = true; 428 } 429 430 if (renderBlank) { 431 verticalLine.setAttribute(HTML.SRC_ATTR, 432 treeComponent.getLineBlankImage()); 433 } else if ((i == 0) && (!hideRootNode)) { 434 verticalLine.setAttribute(HTML.SRC_ATTR, 435 treeComponent.getLineBlankImage()); 436 } else if (isLastChild || isCollapsedAndFinalBranch) { 437 verticalLine.setAttribute(HTML.SRC_ATTR, 438 treeComponent.getLineBottomImage()); 439 } else { 440 verticalLine.setAttribute(HTML.SRC_ATTR, 441 treeComponent.getLineVerticalImage()); 442 } 443 444 verticalLine.setAttribute(HTML.BORDER_ATTR, "0"); 445 treeNodeDiv.appendChild(verticalLine); 446 try { 448 domContext.startNode(facesContext, treeComponent, verticalLine); 449 domContext.endNode(facesContext, treeComponent, verticalLine); 450 } catch (IOException ioe) { 451 ioe.printStackTrace(); 452 } 453 454 } 455 456 if (isBranchNode && !hideNavigation) { 457 Element navAnchor = domContext.createElement(HTML.ANCHOR_ELEM); 458 navAnchor.setAttribute(HTML.HREF_ATTR, "#"); 459 navAnchor.setAttribute(HTML.ID_ATTR, 460 formId + ":" + pathToCurrentRoot); 461 navAnchor.setAttribute(HTML.ONFOCUS_ATTR, "setFocus(this.id);"); 462 navAnchor.setAttribute(HTML.ONBLUR_ATTR, "setFocus('');"); 463 String hiddenFieldName = 464 CustomComponentUtils.getHiddenTreeExpandFieldName( 465 treeComponent.getClientId(facesContext), 466 CustomComponentUtils.getFormName(treeComponent, 467 facesContext)); 468 469 String onclickString = 470 "document.forms['" + formId + "']['" + hiddenFieldName + 471 "'].value=" 472 + "'" + pathToCurrentRoot + "';" 473 + "iceSubmitPartial(" 474 + " document.forms['" + formId + "']," 475 + " this,event); " 476 + "return false;"; 477 478 navAnchor.setAttribute(HTML.ONCLICK_ATTR, onclickString); 479 treeNodeDiv.appendChild(navAnchor); 480 Element iconImage = domContext.createElement(HTML.IMG_ELEM); 482 if (currentNode.isRoot() && !isExpanded || 495 hideRootNode 496 && currentNode.getNextSibling() == null 497 && currentNode == treeComponentRootNode.getFirstChild() 498 ) { 499 iconImage.setAttribute(HTML.SRC_ATTR, 500 treeComponent.getNavOpenTopNoSiblingsImage()); 501 } else if (currentNode.isRoot() || 502 hideRootNode && 503 treeComponentRootNode.getFirstChild() == currentNode) { 504 if (isExpanded) { 505 iconImage.setAttribute(HTML.SRC_ATTR, 506 treeComponent.getNavCloseTopNoSiblingsImage()); 507 } else { 508 iconImage.setAttribute(HTML.SRC_ATTR, 509 treeComponent.getNavOpenTopNoSiblingsImage()); 510 } 511 } else if (currentNode.getNextSibling() == null 512 && currentNode.getChildCount() > 0) { 513 if (isExpanded) { 514 iconImage.setAttribute(HTML.SRC_ATTR, 515 treeComponent.getNavCloseBottomImage()); 516 } else { 517 iconImage.setAttribute(HTML.SRC_ATTR, 518 treeComponent.getNavOpenBottomImage()); 519 } 520 } else { 521 if (isExpanded) { 522 iconImage.setAttribute(HTML.SRC_ATTR, 523 treeComponent.getNavCloseMiddleImage()); 524 } else { 525 iconImage.setAttribute(HTML.SRC_ATTR, 526 treeComponent.getNavOpenMiddleImage()); 527 } 528 } 529 iconImage.setAttribute(HTML.BORDER_ATTR, "0"); 530 iconImage.setAttribute(HTML.ALT_ATTR, ""); 531 532 navAnchor.appendChild(iconImage); 533 try { 535 domContext.startNode(facesContext, treeComponent, navAnchor); 536 domContext.startNode(facesContext, treeComponent, iconImage); 537 domContext.endNode(facesContext, treeComponent, iconImage); 538 domContext.endNode(facesContext, treeComponent, navAnchor); 539 } catch (IOException ioe) { 540 ioe.printStackTrace(); 541 } 542 543 } else { Element lineImage = domContext.createElement(HTML.IMG_ELEM); 545 treeNodeDiv.appendChild(lineImage); 546 lineImage.setAttribute(HTML.BORDER_ATTR, "0"); 547 lineImage.setAttribute(HTML.ALT_ATTR, ""); 548 549 if (currentNode.getNextSibling() == null) { 550 lineImage.setAttribute(HTML.SRC_ATTR, 552 treeComponent.getLineBottomImage()); 553 } else { 554 lineImage.setAttribute(HTML.SRC_ATTR, 556 treeComponent.getLineMiddleImage()); 557 } 558 559 try { 561 domContext.startNode(facesContext, treeComponent, lineImage); 562 domContext.endNode(facesContext, treeComponent, lineImage); 563 } catch (IOException ioe) { 564 ioe.printStackTrace(); 565 } 566 } 567 568 String pathToNode = TreeRenderer.getPathAsString(currentNode, 569 (DefaultMutableTreeNode ) treeComponent 570 .getModel() 571 .getRoot()); 572 treeNodeDiv.setAttribute(HTML.ID_ATTR, treeComponent 573 .getClientId(facesContext) + "-div-" + pathToNode); 574 575 try { 576 encodeParentAndChildren(facesContext, treeNode); 577 } catch (IOException e) { 578 e.printStackTrace(); 579 } 580 try { 582 domContext.endNode(facesContext, treeComponent, treeNodeDiv); 583 } catch (IOException ioe) { 584 ioe.printStackTrace(); 585 } 586 587 } 588 589 594 public void encodeEnd(FacesContext facesContext, UIComponent uiComponent) 595 throws IOException { 596 validateParameters(facesContext, uiComponent, Tree.class); 608 609 DOMContext domContext = 610 DOMContext.getDOMContext(facesContext, uiComponent); 611 612 Element rootNode = (Element ) domContext.getRootNode(); 613 614 Element imageLoaderDiv = domContext.createElement(HTML.DIV_ELEM); 615 imageLoaderDiv.setAttribute(HTML.ID_ATTR, "imageCache"); 616 imageLoaderDiv.setAttribute(HTML.STYLE_ATTR, "display:none;"); 617 rootNode.appendChild(imageLoaderDiv); 618 619 Element tree_document = domContext.createElement(HTML.IMG_ELEM); 620 Element tree_line_blank = domContext.createElement(HTML.IMG_ELEM); 621 Element tree_line_vertical = domContext.createElement(HTML.IMG_ELEM); 622 Element tree_nav_middle_close = domContext.createElement(HTML.IMG_ELEM); 623 Element tree_nav_top_open = domContext.createElement(HTML.IMG_ELEM); 624 Element tree_folder_close = domContext.createElement(HTML.IMG_ELEM); 625 Element tree_line_last_node = domContext.createElement(HTML.IMG_ELEM); 626 Element tree_nav_bottom_close = domContext.createElement(HTML.IMG_ELEM); 627 Element tree_nav_middle_open = domContext.createElement(HTML.IMG_ELEM); 628 Element tree_nav_top_open_no_siblings = 629 domContext.createElement(HTML.IMG_ELEM); 630 Element tree_folder_open = domContext.createElement(HTML.IMG_ELEM); 631 Element tree_line_middle_node = domContext.createElement(HTML.IMG_ELEM); 632 Element tree_nav_bottom_open = domContext.createElement(HTML.IMG_ELEM); 633 Element tree_nav_top_close = domContext.createElement(HTML.IMG_ELEM); 634 635 String appBase = CoreUtils.resolveResourceURL(facesContext, "/xmlhttp/css/xp/css-images/"); 636 637 tree_document.setAttribute(HTML.SRC_ATTR, appBase + "tree_document.gif"); 638 tree_line_blank.setAttribute(HTML.SRC_ATTR, appBase + "tree_line_blank.gif"); 639 tree_line_vertical.setAttribute(HTML.SRC_ATTR, appBase + "tree_line_vertical.gif"); 640 tree_nav_middle_close.setAttribute(HTML.SRC_ATTR, appBase + "tree_nav_middle_close.gif"); 641 tree_nav_top_open.setAttribute(HTML.SRC_ATTR, appBase + "tree_nav_top_open.gif"); 642 tree_folder_close.setAttribute(HTML.SRC_ATTR, appBase + "tree_folder_close.gif"); 643 tree_line_last_node.setAttribute(HTML.SRC_ATTR, appBase + "tree_line_last_node.gif"); 644 tree_nav_bottom_close.setAttribute(HTML.SRC_ATTR, appBase + 645 "tree_nav_bottom_close.gif"); 646 tree_nav_middle_open.setAttribute(HTML.SRC_ATTR, appBase + 647 "tree_nav_middle_open.gif"); 648 tree_nav_top_open_no_siblings.setAttribute(HTML.SRC_ATTR, appBase + 649 "tree_nav_top_open_no_siblings.gif"); 650 tree_folder_open.setAttribute(HTML.SRC_ATTR, appBase + 651 "tree_folder_open.gif"); 652 tree_line_middle_node.setAttribute(HTML.SRC_ATTR, appBase + 653 "tree_line_middle_node.gif"); 654 tree_nav_bottom_open.setAttribute(HTML.SRC_ATTR, appBase + 655 "tree_nav_bottom_open.gif"); 656 tree_nav_top_close.setAttribute(HTML.SRC_ATTR, appBase + 657 "tree_nav_top_close.gif"); 658 659 imageLoaderDiv.appendChild(tree_document); 660 imageLoaderDiv.appendChild(tree_line_blank); 661 imageLoaderDiv.appendChild(tree_line_vertical); 662 imageLoaderDiv.appendChild(tree_nav_middle_close); 663 imageLoaderDiv.appendChild(tree_nav_top_open); 664 imageLoaderDiv.appendChild(tree_folder_close); 665 imageLoaderDiv.appendChild(tree_line_last_node); 666 imageLoaderDiv.appendChild(tree_nav_bottom_close); 667 imageLoaderDiv.appendChild(tree_nav_middle_open); 668 imageLoaderDiv.appendChild(tree_nav_top_open_no_siblings); 669 imageLoaderDiv.appendChild(tree_folder_open); 670 imageLoaderDiv.appendChild(tree_line_middle_node); 671 imageLoaderDiv.appendChild(tree_nav_bottom_open); 672 imageLoaderDiv.appendChild(tree_nav_top_close); 673 674 domContext.endNode(facesContext, uiComponent, rootNode); 677 678 domContext.stepOver(); 679 } 680 681 private boolean isCollapsedAndFinalBranch(DefaultMutableTreeNode branch) { 682 javax.swing.tree.TreeNode [] path = branch.getPath(); 683 for (int i = 0; i + 1 < path.length; i++) { 684 DefaultMutableTreeNode nextParent = 685 (DefaultMutableTreeNode ) path[i]; 686 DefaultMutableTreeNode nextChild = 687 (DefaultMutableTreeNode ) path[i + 1]; 688 if (!(nextParent.getLastChild() == nextChild)) { 689 return false; 690 } 691 } 692 return true; 693 } 694 695 700 public static String getPathAsString(DefaultMutableTreeNode currentRoot, 701 DefaultMutableTreeNode treeComponentRootNode) { 702 if (currentRoot == treeComponentRootNode) { 703 return "root"; 705 } 706 StringBuffer convertedPath = new StringBuffer (); 707 javax.swing.tree.TreeNode [] path = currentRoot.getPath(); 708 int pathLength = path.length; 709 javax.swing.tree.TreeNode parent = treeComponentRootNode; 710 for (int i = 1; i < pathLength; i++) { 711 javax.swing.tree.TreeNode nextNodeInPath = path[i]; 712 int indexOfNextNodeInPath = parent.getIndex(nextNodeInPath); 713 convertedPath.append(indexOfNextNodeInPath); 714 if (i + 1 < pathLength) { 715 convertedPath.append(PATH_DELIMITER); 716 } 717 parent = nextNodeInPath; 718 } 719 return convertedPath.toString(); 720 } 721 } 722 | Popular Tags |