@Override
  public void doDecode(FacesContext context, UIComponent component) {
    final Map<String, String> map = context.getExternalContext().getRequestParameterMap();
    String newToggleState = map.get(component.getClientId(context) + NEW_NODE_TOGGLE_STATE);
    if (newToggleState != null) {

      AbstractTreeNode treeNode = (AbstractTreeNode) component;

      boolean initialState = treeNode.isExpanded();
      boolean newState = Boolean.valueOf(newToggleState);
      if (initialState ^ newState) {
        new TreeToggleEvent(treeNode, newState).queue();
      }

      PartialViewContext pvc = context.getPartialViewContext();
      if (pvc.isAjaxRequest()
          && map.get(component.getClientId(context) + TRIGGER_NODE_AJAX_UPDATE) != null) {
        pvc.getRenderIds()
            .add(
                component.getClientId(context)
                    + MetaComponentResolver.META_COMPONENT_SEPARATOR_CHAR
                    + AbstractTreeNode.SUBTREE_META_COMPONENT_ID);

        context.getAttributes().put(AJAX_TOGGLED_NODE_ATTRIBUTE, component.getClientId(context));
        context
            .getAttributes()
            .put(
                AJAX_TOGGLED_NODE_STATE_ATTRIBUTE,
                initialState ? TreeNodeState.expanded : TreeNodeState.collapsed);
      }
    }
  }
 protected void encodeIconForNodeState(
     FacesContext context,
     AbstractTree tree,
     AbstractTreeNode treeNode,
     TreeNodeState nodeState,
     String customIcon)
     throws IOException {
   if (Strings.isNullOrEmpty(customIcon)) {
     encodeDefaultIcon(
         context,
         treeNode,
         concatClasses(
             nodeState.getIconClass(),
             treeNode.getAttributes().get("iconClass"),
             tree.getAttributes().get("iconClass")));
   } else {
     encodeCustomIcon(
         context,
         treeNode,
         concatClasses(
             nodeState.getCustomIconClass(),
             treeNode.getAttributes().get("iconClass"),
             tree.getAttributes().get("iconClass")),
         customIcon);
   }
 }
  protected void encodeIcon(FacesContext context, UIComponent component) throws IOException {
    TreeNodeState nodeState = getNodeState(context);

    AbstractTreeNode treeNode = (AbstractTreeNode) component;

    AbstractTree tree = treeNode.findTreeComponent();

    if (nodeState.isLeaf()) {
      String iconLeaf = (String) getFirstNonEmptyAttribute("iconLeaf", treeNode, tree);
      encodeIconForNodeState(context, tree, treeNode, nodeState, iconLeaf);
    } else {
      String iconExpanded = (String) getFirstNonEmptyAttribute("iconExpanded", treeNode, tree);
      String iconCollapsed = (String) getFirstNonEmptyAttribute("iconCollapsed", treeNode, tree);

      if (Strings.isNullOrEmpty(iconCollapsed) && Strings.isNullOrEmpty(iconExpanded)) {
        encodeIconForNodeState(context, tree, treeNode, nodeState, null);
      } else {
        SwitchType toggleType =
            TreeRendererBase.getToggleTypeOrDefault(treeNode.findTreeComponent());

        if (toggleType == SwitchType.client || nodeState == TreeNodeState.collapsed) {
          encodeIconForNodeState(context, tree, treeNode, TreeNodeState.collapsed, iconCollapsed);
        }

        if (toggleType == SwitchType.client
            || nodeState == TreeNodeState.expanded
            || nodeState == TreeNodeState.expandedNoChildren) {
          encodeIconForNodeState(context, tree, treeNode, TreeNodeState.expanded, iconExpanded);
        }
      }
    }
  }
  protected UIComponent getHandleLoadingFacetIfApplicable(UIComponent component) {
    AbstractTreeNode treeNode = (AbstractTreeNode) component;

    AbstractTree tree = treeNode.findTreeComponent();

    if (TreeRendererBase.getToggleTypeOrDefault(tree) != SwitchType.ajax) {
      return null;
    }

    UIComponent facet = treeNode.getFacet(HANDLE_LOADING_FACET_NAME);
    if (facet == null) {
      facet = tree.getFacet(HANDLE_LOADING_FACET_NAME);
    }

    if (facet != null && facet.isRendered()) {
      return facet;
    }

    return null;
  }