RichFaces - Rich Tree

In diesem Kapitel erfahren Sie mehr über die Baumverarbeitung in RichFaces. RichFaces bietet alle erforderlichen Komponenten zum Erstellen und Bearbeiten eines Baums.

<rich: treeNode>

Dieses Tag wird verwendet, um einen hierarchischen Baum zu erstellen. Jeder im <treeNode> bereitgestellte Knoten ist ein untergeordneter Knoten des Baums. Dieses Tag wird mit einem anderen Tag namens <rich: tree> verwendet. Alle Instanzvariablen, die wir zum Erstellen eines Baums verwenden, müssen eine dieser drei Schnittstellen implementieren.org.richfaces.model.TreeNode, org.richfaces.model.TreeDataModel, und javax.swing.tree.TreeNode.

Im folgenden Beispiel füllen wir einen Baum mit dem Tag <rich: treeNode> aus dem Backend.

<?xml version = "1.0" encoding = "UTF-8"?>  
<!DOCTYPE html> 
<html xmlns = "http://www.w3.org/1999/xhtml"   
   xmlns:h = "http://java.sun.com/jsf/html"   
   xmlns:f = "http://java.sun.com/jsf/core"   
   xmlns:ui = "http://java.sun.com/jsf/facelets"   
   xmlns:a4j = "http://richfaces.org/a4j"   
   xmlns:rich = "http://richfaces.org/rich"> 
   
   <h:head> 
      <title>TreeNode Example</title> 
      <meta name = "viewport" content = "width = device-width, initial-scale = 1.0"/>
   </h:head> 
    
   <h:body> 
      <h:form>   
         <rich:tree value = "#{tree.populateNode}" var = "tree">   
            <rich:treeNode>   
               <rich:treeModelRecursiveAdaptor> 
               </rich:treeModelRecursiveAdaptor>  
               <h:outputText value = "#{tree.data}" />   
            </rich:treeNode>
         </rich:tree>   
      </h:form>   
   </h:body> 

</html>

Im Folgenden finden Sie die zugehörige Java-Klasse, die implementiert wird “TreeNodeImpl” Schnittstelle.

import javax.faces.bean.ManagedBean;   
import javax.faces.bean.RequestScoped;   
import org.richfaces.model.TreeNodeImpl;    

@ManagedBean   
@RequestScoped   

public class Tree extends TreeNodeImpl {   
   private Tree stationRoot;   
   private Tree populateNode;   
   private Object data;   
   
   public Tree() {   
      super();   
   }   
   public Tree(boolean leaf, Object data) {   
      super(leaf);   
      this.data = data;   
   }   
   public Object getData() {   
      return data;   
   }   
   public Tree getPopulateNode() {   
      if (populateNode == null) {   
         String[] List_OF_Node = {
            "Frist Node", "Second Node", "Third Node", "Fourth Node", "Fifth Node"};
         stationRoot = new Tree(false, "Example Of Tree");
         
         for (int i = 0; i < List_OF_Node.length; i++) {   
            Tree child = new Tree(true, List_OF_Node[i]);   
            stationRoot.addChild(i, child);   
         }   
         populateNode = new Tree();   
         populateNode.addChild(0, stationRoot);   
      }   
      return populateNode;   
   }
}

Der obige Code erzeugt die folgende Ausgabe im Browser.

<rich: treeModelAdaptor>

Diese Komponente verwendet eine Karte als Eingabe, durchläuft sie und erzeugt die erforderliche Ausgabe im Browser. Wann immer wir eine rekursive Karte füllen müssen, können wir ein anderes Tag namens verwenden<rich:recursiveTreeModelAdaptor>.

Das folgende Beispiel zeigt, wie die Projektstruktur im Browser gerendert wird. In RichFaces 3 werden diese beiden Tags <rich: treeNodeAdaptor> und <rich: recursiveTreeNodeAdaptor> verwendet.

<?xml version = "1.0" encoding = "UTF-8"?>  
<!DOCTYPE html> 
<html xmlns = "http://www.w3.org/1999/xhtml"   
   xmlns:h = "http://java.sun.com/jsf/html"   
   xmlns:f = "http://java.sun.com/jsf/core"   
   xmlns:ui = "http://java.sun.com/jsf/facelets"   
   xmlns:a4j = "http://richfaces.org/a4j"   
   xmlns:rich = "http://richfaces.org/rich"> 
   
   <h:head>
      <title>Tree Model and Recursive Model Example</title> 
   </h:head> 
   
   <h:body> 
      <h:form id = "form"> 
         <rich:tree toggleType = "AJAX" var = "item" style = "max-width: 400px"> 
            <rich:treeModelRecursiveAdaptor roots = "#{fileSystemBean.sourceRoots}" 
               nodes = "#{item.directories}"> 
               
               <rich:treeNode> 
                  #{item.shortPath} 
               </rich:treeNode> 
               
               <rich:treeModelAdaptor nodes = "#{item.files}"> 
                  <rich:treeNode>#{item}</rich:treeNode> 
               </rich:treeModelAdaptor> 
            </rich:treeModelRecursiveAdaptor> 
            
         </rich:tree> 
      </h:form> 
   </h:body>
   
</html>

Für dieses Beispiel müssen zwei neue Java-Beans erstellt werden. Es folgt das Codefragment für die Bean-Klasse "FileSystemBean.java", das den erforderlichen Ordnernamen enthält.

import java.util.List; 
import javax.faces.bean.ManagedBean; 
import javax.faces.bean.RequestScoped; 
  
@ManagedBean 
@RequestScoped 

public class FileSystemBean { 
   private static final String SRC_PATH = "/WEB-INF"; 
   private List<FileSystemNode> srcRoots; 
  
   public synchronized List<FileSystemNode> getSourceRoots() { 
      if (srcRoots == null) {
         srcRoots = new FileSystemNode(SRC_PATH).getDirectories(); 
      } 
      return srcRoots; 
   } 
}

Es folgt das Code-Snippet für die Bean-Klasse „FileSystemNode.java“, das den erforderlichen Blattknoten des Projekts enthält.

import static com.google.common.base.Predicates.containsPattern; 
import static com.google.common.base.Predicates.not; 
import static com.google.common.collect.Iterables.filter; 
import static com.google.common.collect.Iterables.transform; 
  
import java.util.ArrayList; 
import java.util.Collections; 
import java.util.List; 
import java.util.Set; 
  
import javax.faces.context.ExternalContext; 
import javax.faces.context.FacesContext; 
  
import com.google.common.base.Function; 
import com.google.common.collect.Iterables; 
import com.google.common.collect.Lists; 
  
public class FileSystemNode { 
   private static final Function<String, FileSystemNode> 
      FACTORY = new Function<String, FileSystemNode>() { 
      
      public FileSystemNode apply(String from) { 
         return new FileSystemNode(from.substring(0, from.length() - 1)); 
      }; 
   }; 
   private static final Function<String, String> 
      TO_SHORT_PATH = new Function<String, String>() {
      
      public String apply(String from) { 
         int idx = from.lastIndexOf('/'); 
         if (idx < 0) { 
            return from; 
         } 
         return from.substring(idx + 1); 
      }; 
   }; 
   private String path; 
   private List<FileSystemNode> directories; 
   private List<String> files; 
   private String shortPath; 
  
   public FileSystemNode(String path) { 
      this.path = path; 
      int idx = path.lastIndexOf('/'); 
      
      if (idx != -1) { 
         shortPath = path.substring(idx + 1); 
      } else { 
         shortPath = path; 
      } 
   } 
   public synchronized List<FileSystemNode> getDirectories() { 
      if (directories == null) { 
         directories = Lists.newArrayList(); 
  
         Iterables.addAll(directories, transform(filter(
            getResourcePaths(), containsPattern("/$")), FACTORY)); 
      } 
      return directories; 
   }
   public synchronized List<String> getFiles() { 
      if (files == null) { 
         files = new ArrayList<String>(); 
         
         Iterables.addAll(files, transform(filter(
            getResourcePaths(), not(containsPattern("/$"))), TO_SHORT_PATH)); 
      } 
      return files; 
   } 
   private Iterable<String> getResourcePaths() { 
      FacesContext facesContext = FacesContext.getCurrentInstance(); 
      ExternalContext externalContext = facesContext.getExternalContext(); 
      Set<String> resourcePaths = externalContext.getResourcePaths(this.path); 
      
      if (resourcePaths == null) { 
         resourcePaths = Collections.emptySet(); 
      } 
      return resourcePaths; 
   } 
   public String getShortPath() { 
      return shortPath; 
   } 
}

Das obige Beispiel erzeugt die folgende Ausgabe im Browser.