In class Tree I got error message:
The method removeparent() is undefined for the type String.
I want to convert string "Grandchild3" to object which instance MyTreeNode class, then I can use removep("Grandchild3") call the method like this Grandchild3.removeparent().
How can I do this?
Here's class MyTreeNode:
public class MyTreeNode<T>{
private T data = null;
private List<MyTreeNode> children = new ArrayList<>();
private MyTreeNode parent = null;
public MyTreeNode(T data) {
this.data = data;
}
public void addChild(MyTreeNode child) {
child.setParent(this);
this.children.add(child);
}
public void addChild(T data) {
MyTreeNode<T> newChild = new MyTreeNode<>(data);
newChild.setParent(this);
children.add(newChild);
}
public void addChildren(List<MyTreeNode> children) {
for(MyTreeNode t : children) {
t.setParent(this);
}
this.children.addAll(children);
}
public List<MyTreeNode> getChildren() {
return children;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
private void setParent(MyTreeNode parent) {
this.parent = parent;
}
public MyTreeNode getParent() {
return parent;
}
public void removeparent() {
this.parent = null;
}
public void removeChild(MyTreeNode<T> child)
{
this.children.remove(child);
}
}
Here's class Tree:
public class Tree {
public static void main(String[] args) throws ClassNotFoundException {
// TODO Auto-generated method stub
MyTreeNode<String> root = new MyTreeNode<>("Root");
MyTreeNode<String> child1 = new MyTreeNode<>("Child1");
child1.addChild("Grandchild1");
child1.addChild("Grandchild2");
MyTreeNode<String> child2 = new MyTreeNode<>("Child2");
child2.addChild("Grandchild3");
root.addChild(child1);
root.addChild(child2);
root.addChild("Child3");
root.addChildren(Arrays.asList(
new MyTreeNode<>("Child4"),
new MyTreeNode<>("Child5"),
new MyTreeNode<>("Child6")
));
for(MyTreeNode<String> node : root.getChildren()) {
System.out.println(node.getData());
}
printTree(root, " ");
removep("Grandchild3"); //error message"The method removeparent() is undefined for the type String"
printTree(root, " ");
}
private static void printTree(MyTreeNode<String> node, String appender) {
System.out.println(appender+node.getData());
for (MyTreeNode each : node.getChildren()){
printTree(each, appender + appender);
}
}
public static void removep(MyTreeNode<String> node)
{
node.getParent().removeChild(node);
node.removeparent();
}
}
So basically what you want is to convert a string to a class object. Now there are probably several ways it could be done, but in the context used here it seems like you could simply pass the appropriate object instead of messing with strings.
So in your case, the most appropriate way to do so would be to create a method which receives a string name and the top node of your tree and iterates over the tree to find the node with the given name. When found the method returns the node.
Then you can use that method to get the node from the name and then call removep.
All this program is trying to achieve is listing files as well as folders in a correct fashion , so that folders are assigned their own lists of objects.Files are excluded from having a list of objects as they won't contain any files or folders inside of themselves.
My main concern here is that the objects that are being recursively read and written in the data.class, that the objects from the main , or rather "root", are not being all joined into one , consecutive list of objects at the end. Please help.
package bstTest2;
import java.io.*;
public class Main {
public static void main(String[] args) {
String filename = "G:/a";
File f = new File(filename);
data d= new data();
d.explore(f);
}
}
package bstTest2;
import java.io.File;
import java.util.LinkedList;
import java.util.List;
public class Node{
private String filename;
private long size;
private List<Node> prevList;
private List<Node> curList;
private List<Node> chList;//child list of the current node - could be null if the node is a file
private List<Node> root;
Node(String fn, long s,List<Node> previousList, List<Node> currentList,List<Node> childList){
filename = fn;
size = s;
setPrevList(previousList);
setCurList(currentList);
setChList(childList);
}
public Node() {
initList();
}
public void initList(){
curList = new LinkedList<Node>();
setRoot(curList);
}
public void createNode(File file){
curList.add(new Node(file.getName(),file.length(),null,curList,null));
}
public void createNodeList(File file){
curList.add(new Node(file.getName(),file.length(),
prevList,
setCurList(chList), setChList(setCurList(new LinkedList<Node>()))));
}
public List<Node> getChList() {
return chList;
}
public List<Node> setChList(List<Node> chList) {
this.chList = chList;
return chList;
}
public List<Node> getCurList() {
return curList;
}
public List<Node> setCurList(List<Node> curList) {
this.curList = curList;
return curList;
}
public List<Node> getRoot() {
return root;
}
public void setRoot(List<Node> root) {
this.root = root;
}
public List<Node> getPrevList() {
return prevList;
}
public void setPrevList(List<Node> prevList) {
this.prevList = prevList;
}
}
package bstTest2;
import java.io.File;
import java.util.*;
public class data {
private Node node = new Node();
private File f[];
public void explore(File dir){
f=dir.listFiles();
if(f!=null){
for(File file:f){
if(!file.isDirectory()){
//System.out.println("BFIL"+node.getCurList());
System.out.println("FILE: "+file.getName()+" "+file.length() +":");
node.createNode(file);
System.out.println(node.getCurList().size()+" AFIL"+node.getCurList());
}else{
//System.out.println("BFOL"+node.getCurList());
System.out.println("FOLDER: "+file.getName()+" "+file.length() +":");
node.createNodeList(file);
System.out.println(node.getCurList().size() +" AFOL"+node.getCurList() );
explore(file);
}
}
}
}
}
You can return the list of files that are contained within a directory. Doing that will allow you to add that list of files to the directory node.
To do this you would change your expore(File dir) method to return the list of nodes within the directory and you would update your explore(file); call to add that list to the directory node.
public List<Node> explore(File directory) {
List<Node> result = new ArrayList<Node>();
for (File current : directory.listFiles()) {
Node node = toNode(current);
// do the real work here
if (file.isDirectory()) {
node.setChildren(explore(file));
}
result.add(node);
}
return result;
}
The alternative is to pass the directory node to the explore(File dir) method and update it within that method. You can then add each contained file or directory node to that parent node.
public void explore(File directory, Node parent) {
for (File current : directory.listFiles()) {
Node node = toNode(current);
// do the real work here
if (file.isDirectory()) {
explore(file, node);
}
parent.add(node);
}
}
I am working on a eclipse rcp project where I need to create a treeviewer out of TreeStructured Java object. Currently I have hardcorded the Java objects to create the structure and that is working fine. I need to create a method which calculates all the Parents and children object and form the tree structure. It should be a recursive method. I wrote a recursive method to generate a
tree structured java object. But it does not work properly.
I dont know where exactly the problem. request you to help on this. Please find the code below.
private FileParent getInput() {
FileParent root = new FileParent("Root");
FileParent A = new FileParent("A");
FileParent a1 = new FileParent("A1");
FileObject a11 = new FileObject("A11");
a1.addChild(a11);
FileObject a2 = new FileObject("A2");
A.addChild(a1);
A.addChild(a2);
FileParent b = new FileParent("B"); FileObject b1 = new
FileObject("B1"); FileObject b2 = new FileObject("B2");
b.addChild(b1); b.addChild(b2);
root.addChild(A);
// root.addChild(b);
return root;
}
My recursive method which is to traverse through all the Parents and children objects
and creates the tree structured object.
FileParent root1 = new FileParent("Root");
public FileParent getChildren(FileParent root) {
if (!root.hasChildren()) {
return root;
}
if (root != null && root.hasChildren()) {
FileObject[] children = root.getChildren();// size two
for (FileObject fileObject : children) { // 2 times
// here children will be the folders
if (fileObject instanceof FileParent) {
FileParent folder = (FileParent) fileObject;
// root1.setParent(folder.getParent());
// if (root1.getParent() != null) {
root1.addChild(folder);
// }
getChildren((FileParent) folder);
} else {
System.out.println("FileName: " + fileObject.getName());
// root1.setParent(fileObject.getParent());
// if (root1.getParent() != null) {
root1.addChild(fileObject);
// }
}
}
}
return root1;
}
public class FileObject {
private String name;
private FileParent parent;
public FileObject(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setParent(FileParent parent) {
this.parent = parent;
}
public FileParent getParent() {
return parent;
}
public String toString() {
return getName();
}
}
public class FileParent extends FileObject {
/**
*
*/
private List<FileObject> children;
public FileParent(String name) {
super(name);
children = new ArrayList<FileObject>();
}
public void addChild(FileObject child) {
// if (children.contains(child)) {
children.add(child);
child.setParent(this);
// }
}
public void removeChild(FileObject child) {
children.remove(child);
child.setParent(null);
}
public FileObject[] getChildren() {
return (FileObject[]) children.toArray(new FileObject[children.size()]);
}
public boolean hasChildren() {
return children.size() > 0;
}
}
In Swing there is interface TreeModel with default implementation Supposed to be used in JTree and generally not written the best way (like no generics), but can do the job.
There is one method in treeviewer.setInput(Object obj).If I pass getInput() as parameter It will work fine. But if I pass getChildren() which is my recursive method it does not work.
Do you mean you are calling treeviewer.setInput(foo.getChildren())? This is definitely wrong. Read this article: http://www.vogella.com/articles/EclipseJFaceTree/article.html.
Basically, you need to 1) implement ITreeContentProvider to provide the tree structure; 2) implement ILabelProvider to provide text and images; 3) call
treeViewer.setContentProvider(yourContentProvider);
treeViewer.setLabelProvider(yourLabelProvider);
treeviewer.setInput(new Object()); // or anything for which your content provider returns correct roots
I am trying to parse xsd file and make an Tree of strings with it's hierarchy.
I read the following questions:
Parsing XSD and getting nested elements ,
Java API to parse XSD schema file .
However, I still don't get it.
I wrote the following code:
public class Tree {
public String Data;
private Tree Parent;
private ArrayList<Tree> Children;
public Tree(String data) {
Data = data;
Parent = null;
Children = new ArrayList<Tree>();
}
public Tree AddChild(String data){
Tree child = new Tree(data);
child.Parent = this;
Children.add(child);
return child;
}
public ArrayList<Tree> Children(){
return Children;
}
public Tree Parent(){
return Parent;
}
public static Tree MakeTreeFromXsd(String xsdPath)
throws ClassNotFoundException, InstantiationException,
IllegalAccessException, ClassCastException{
System.setProperty(DOMImplementationRegistry.PROPERTY,
"com.sun.org.apache.xerces.internal.dom.DOMXSImplementationSourceImpl");
DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
com.sun.org.apache.xerces.internal.xs.XSImplementation impl =
(com.sun.org.apache.xerces.internal.xs.XSImplementation)
registry.getDOMImplementation("XS-Loader");
XSLoader schemaLoader = impl.createXSLoader(null);
XSModel model = schemaLoader.loadURI(xsdPath);
XSNamedMap map = model.getComponents(XSConstants.ELEMENT_DECLARATION);
Tree t = new Tree("root");
for (int j=0; j<map.getLength(); j++) {
XSObject o = map.item(j);
t.AddChild(o.getName());
}
return t;
}
}
How can I improve the function MakeTreeFromXsd to return a tree with all the hierarchy of the xsd and not only the top-level components ?
I have a collection of string paths like ["x1/x2/x3","x1/x2/x4","x1/x5"] in a list.
I need to construct a tree-like structure from this list which can be iterated to get a pretty printed tree.
like this
x1
/ \
x5 x2
/ \
x3 x4
Any ideas/suggestions?
I believe that the problem can be attacked first by processing the list of strings EDIT: The correct answer chosen was an elegant implementation, other suggestions were good too.
Follow an implementation of naive implementation of a visitable tree:
class Tree<T> implements Visitable<T> {
// NB: LinkedHashSet preserves insertion order
private final Set<Tree> children = new LinkedHashSet<Tree>();
private final T data;
Tree(T data) {
this.data = data;
}
void accept(Visitor<T> visitor) {
visitor.visitData(this, data);
for (Tree child : children) {
Visitor<T> childVisitor = visitor.visitTree(child);
child.accept(childVisitor);
}
}
Tree child(T data) {
for (Tree child: children ) {
if (child.data.equals(data)) {
return child;
}
}
return child(new Tree(data));
}
Tree child(Tree<T> child) {
children.add(child);
return child;
}
}
interfaces for Visitor Pattern:
interface Visitor<T> {
Visitor<T> visitTree(Tree<T> tree);
void visitData(Tree<T> parent, T data);
}
interface Visitable<T> {
void accept(Visitor<T> visitor);
}
sample implementation for Visitor Pattern:
class PrintIndentedVisitor implements Visitor<String> {
private final int indent;
PrintIndentedVisitor(int indent) {
this.indent = indent;
}
Visitor<String> visitTree(Tree<String> tree) {
return new IndentVisitor(indent + 2);
}
void visitData(Tree<String> parent, String data) {
for (int i = 0; i < indent; i++) { // TODO: naive implementation
System.out.print(" ");
}
System.out.println(data);
}
}
and finally (!!!) a simple test case:
Tree<String> forest = new Tree<String>("forest");
Tree<String> current = forest;
for (String tree : Arrays.asList("x1/x2/x3", "x1/x2/x4", "x1/x5")) {
Tree<String> root = current;
for (String data : tree.split("/")) {
current = current.child(data);
}
current = root;
}
forest.accept(new PrintIndentedVisitor(0));
output:
forest
x1
x2
x3
x4
x5
Just split each path by its delimiter and then add them to a tree structure one by one.
i.e. if 'x1' does not exist create this node, if it does exist go to it and check if there is a child 'x2' and so on...
I'd make the tree one string at a time.
Make an empty tree (which has a root node - I assume there could be a path like "x7/x8/x9").
Take the first string, add x1 to the root node, then x2 to x1, then x3 to x2.
Take the second string, see that x1 and x2 are already there, add x4 to x2.
Do this for every path you have.
Create an Object Node which contains a parent (Node) and a List of children (Node).
First split the string using ",". For every splitted string you split the string using "/".
Search for the first node identifier (e.g x1) in the root list.
If you can find it, use the node to find the next node identifier (e.g. x2).
If you can not find a node, add the node to the last node you was able to find in the existing lists.
After you have created the list structure, you can print the list to the screen. I would make it recursive.
NOT TESTED, just an animation
public void print(List nodes, int deep) {
if (nodes == null || nodes.isEmpty()) {
return;
}
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < deep; i++) {
buffer.append("---");
}
for (Iterator iterator = nodes.iterator(); iterator.hasNext();) {
Node node = (Node)iterator.next();
System.out.println(buffer.toString() + " " + node.getIdentifier());
print(node.getChildren(), deep + 1);
}
}
public class Menu {
private String path;
private List<Menu> children;
public Menu(String path) {
this.path = path;
children = new ArrayList<>();
}
public void addChild(Menu child) {
children.add(child);
}
public List<Menu> getChildren() {
return children;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public Menu getChild(String data) {
for (Menu n : children)
if (n.path.equals(data)) {return n;}
return null;
}
}
Tree builder class:
public class MenuTree {
private Menu root;
public MenuTree() {
root = new Menu("");
}
public void add(String str) {
Menu current = root;
StringTokenizer s = new StringTokenizer(str, "/");
while (s.hasMoreElements()) {
str = (String) s.nextElement();
Menu child = current.getChild(str);
if (child == null) {
current.addChild(new Menu(str));
child = current.getChild(str);
}
current = child;
}
}
public JSONObject toJSON() {
try {
return new JSONObject(new ObjectMapper().writeValueAsString(this.root));
} catch (JsonProcessingException e) {
return null;
}
}
}
Usage:
String slist[] = new String[]{
"mnt/sdcard/folder1/a/b/file1.file",
"mnt/sdcard/folder1/a/b/file2.file",
"D/a/b/c.file",
};
MenuTree t = new MenuTree();
for (String s : slist) {
t.add(s);
}
System.out.println(t.toJSON().toString());
JSONObject result:
{"path":"","children":[{"path":"mnt","children":[{"path":"sdcard","children":[{"path":"folder1","children":[{"path":"a","children":[{"path":"b","children":[{"path":"file1.file","children":[]},{"path":"file2.file","children":[]}]}]}]}]}]},{"path":"D","children":[{"path":"a","children":[{"path":"b","children":[{"path":"c.file","children":[]}]}]}]}]}
Make your tree for every string in array.
Just split path for '/' , check whether the node exists in your tree or not, if it exists then move on... otherwise create a new node and add this node in childrens of parent node.
Iterate using recursion.
Following is model for tree's node.
Class Node{
string name;
List<Node> childrens;
Node(string name){
this.name = name;
this.childrens = new List<Node>();
}
}
This is way how I am doing tree from path (folders) structure. Maybe should help someone with basic logic.
Node:
public class Node {
private String path;
private List<Node> children;
public Node(String path) {
this.path = path;
children = new ArrayList<>();
}
public String getName() {
return getName(path);
}
private String getName(String path) {
String[] split = path.split("\\\\");
return split[split.length - 1];
}
public void addChild(Node child) {
children.add(child);
}
public List<Node> getChildren() {
return children;
}
public String getPath() {
return path;
}
}
FilesTree:
public class FilesTree {
private static final Logger log = Logger.getLogger(FilesTree.class.getName());
private FilesTree() {}
private static void createTree(Node root, List<String> paths) {
for (String path : paths) {
addNode(root, Arrays.asList(path.split("\\\\")), "");
}
}
private static void addNode(Node node, List<String> path, String nodePath) {
if (!path.isEmpty()) {
nodePath = nodePath.equals("") ? path.get(0) : String.format("%s\\%s", nodePath, path.get(0));
}
if (node.getChildren().isEmpty() && path.size() == 1) {
node.addChild(new Node(nodePath));
} else if (!node.getChildren().isEmpty()) {
for (Node actual : node.getChildren()) {
if (actual.getName().equals(path.get(0))) {
addNode(actual, path.subList(1, path.size()), nodePath);
return;
}
}
node.addChild(new Node(nodePath));
} else {
log.info("Without children but with size: " + path.size());
}
}
}