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 ?
Related
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.
I've a university project about creating two classes, Tree class and Node class, to implement a k-ary tree using Java.
In the class Tree, there should be a constructor which recives as input an int that indicates the tree arity.
I've worked before with general trees and this was my result:
Class tree: *
Class node: *
I absolutely don't know where and how to start to build this project (as I don't know how to manage the arity, maybe with ArrayList?).
Any advice and suggestions will be greatly appreciated :)
Thanks in advance.
Here are the new versions of the classes, with the methods that you needed.
Node:
import java.util.ArrayList;
import java.util.List;
public class Node {
public Node parent; // The parent of the current node
public List<Node> children; // The children of the current node
public Object info;
public static int maxNrOfChildren; // Equal to the k-arity;
public Node (Object info)
{
this.info=info;
children = new ArrayList<Node>(maxNrOfChildren);
}
public void addChild(Node childNode, int position)
// You must take care so that future insertions don't override a child on i-th position
{
if(position>=maxNrOfChildren-1)
{
// Throw some error
}
else
{
System.out.println("this.children="+this.children);
if(this.children.get(position)!=null)
{
// There is alerady a child node on this position; throw some error;
}
else
{
childNode.parent=this;
this.children.set(position, childNode);
}
}
}
}
Tree:
import java.util.ArrayList;
import java.util.List;
public class Tree {
public Node root;
public Tree(int kArity)
{
Node.maxNrOfChildren=kArity;
}
public void addRoot(Object info)
{
root=new Node(info);
root.parent=null;
root.children=new ArrayList<Node>(Node.maxNrOfChildren);
}
public void addNewNodeVasithChildOfNodeU(Node u, Object info, int i)
{
Node child=new Node(info);
u.addChild(child, i);
}
// I've made the above two methods of type void, not Node, because
// I see no reason in returning anything; however, you can override by calling
//'return root;' or 'return child;'
public int numberOfNodesInTree(Node rootNode){
int count=0;
count++;
if(rootNode.children.size()!=0) {
for(Node ch : rootNode.children)
count=count+numberOfNodesInTree(ch);
}
return count;
}
public int numberOfNodesInTree()
{
return numberOfNodesInTree(this.root);
}
public void changeRoot(Node newRoot, int i)
{
Node oldRoot=this.root;
newRoot.parent=null;
newRoot.addChild(oldRoot, i);
oldRoot.parent=newRoot;
this.root=newRoot;
}
public static void main(String args[])
{
Tree tree=new Tree(3);
Node a = new Node("a");
Node b = new Node("b");
Node c = new Node("c");
tree.addRoot("root");
tree.root.addChild(a,0);
a.addChild(b,0);
tree.root.addChild(c,1);
System.out.println(tree.numberOfNodesInTree(tree.root));
}
}
The logic is correct, but I am getting some Java-related error when I run the main method and I haven't yet figured out what the problem is.
this can be a starting point:
Node Class
import java.util.ArrayList;
import java.util.List;
public class Node {
public Node parent;//the parent of the current node
public List<Node> children = new ArrayList<Node>();//the children of the current node
public String name;//or any other property that the node should contain, like 'info'
public static int maxNrOfChildren;//equal to the k-arity;
public Node (String nodeName)
{
name=nodeName;
}
public void addChild(Node childNode)
{
if(this.children.size()>=maxNrOfChildren)
{
//do nothing (just don't add another node), or throw an error
}
else
{
childNode.parent=this;
this.children.add(childNode);
}
}
}
Tree Class
import java.util.ArrayList;
import java.util.List;
public class Tree {
public Node root = new Node("root");
public Tree(int kArity)
{
Node.maxNrOfChildren=kArity;
root.parent=null;
}
public void traverseTree(Node rootNode)//depth first
{
System.out.println(rootNode.name);
if(rootNode.children.size()!=0)
for(Node ch : rootNode.children)
traverseTree(ch);
}
public static void main(String args[])
{
Tree tree=new Tree(3);
Node a = new Node("a");
Node b = new Node("b");
Node c = new Node("c");
tree.root.addChild(a);
a.addChild(b);
tree.root.addChild(c);
tree.traverseTree(tree.root);
}
}
Please give further details about your project specifications, otherwise i can't figure out which kind of functionality you need within these classes
The idea behind creating a k-array, is that this is not a conventional structure like a list or a set, the node is like an element in a linked list, it point to the n other child node and can also point to the parent, whant determine what should be the child or the parent in that sctructure is an entire different question. As for the list of child in the node you can use any structure you whant ArrayList most likely will be a good fit. The choice of a structure depend on many factors like size, how often it will be accessed does it need to be sorted etc.
Have a look at this. Hope it helps.
import java.util.ArrayList;
public class Nary
{
public static Node root;
public static int insert(Node rootNode, int parentId, ArrayList<Node> nodeToAdd)
{
if(rootNode == null)
return 0;
if(rootNode.children == null)
rootNode.children = new ArrayList<Node>();
if(rootNode.id == parentId)
{
for(int i =0; i < nodeToAdd.size(); i++)
{
Node node = nodeToAdd.get(i);
node.parent = rootNode;
rootNode.children.add(node);
}
return 1;
}
else
{
for(int i = 0; i < rootNode.children.size(); i++)
{
int resultFlag = insert(rootNode.children.get(i), parentId, nodeToAdd);
if(resultFlag == 1)
{
return 1;
}
}
}
return -1;
}
public static void traverse(Node root)
{
if(root == null)
{
return;
}
System.out.println(root.data + " " + root.id );
for(Node child : root.children)
{
traverse(child);
}
}
public static void main(String[] args) {
// Insertion
root = new Node(0, "root");
int parentId = root.id;
Node Bread = new Node(1, "Bread");
Node Milk = new Node(2, "Milk");
Node Meat = new Node(3, "Meat");
Node Eggs = new Node(4, "Eggs");
ArrayList<Node> nodeList = new ArrayList<Node>();
nodeList.add(Bread);
nodeList.add(Milk);
nodeList.add(Meat);
nodeList.add(Eggs);
insert(root, parentId, nodeList);
// Add children for Bread
parentId = Bread.id;
Node Bread0 = new Node(11, "Whole-Wheat");
Node Bread1 = new Node(12, "Whole-Grain");
Node Bread2 = new Node(13, "Italian");
ArrayList<Node> nodeList1 = new ArrayList<Node>();
nodeList1.add(Bread0);
nodeList1.add(Bread1);
nodeList1.add(Bread2);
insert(root, parentId, nodeList1);
Add children for Milk
parentId = Milk.id;
Node Milk0 = new Node(21, "Whole");
Node Milk1 = new Node(22, "skim");
Node Milk2 = new Node(23, "Almond");
ArrayList<Node> nodeList2 = new ArrayList<Node>();
nodeList2.add(Milk0);
nodeList2.add(Milk1);
nodeList2.add(Milk2);
insert(root, parentId, nodeList2);
traverse(root);
}
}
class Node{
int id;
String data;
Node parent;
ArrayList<Node> children;
public Node(int id, String data)
{
this.id = id;
this.data = data;
}
}
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
`The requirement is that a tree has to be populated with revisions of a file.
I have a command that fetches all the revisions of a particular file from MKS(Versioning system).
using the following command in java
Process p = Runtime.getRuntime().exec("cmd /C "+cmd);
i get all the versions of file.c. now i want to populate the data onto a Tree structure. how do i do that?
try {
List<String> lVersions = new ArrayList<String>();
Process p = Runtime.getRuntime().exec("cmd /C "+cmd);
BufferedReader in = new BufferedReader( new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = in.readLine()) != null)
{
lVersions .add(line);
}
}catch (IOException e)
{ e.printStackTrace();
}
lVersions contain the following output. It shows the all the revisions of a particular file. I need to populate this information on to a Tree structure.
1.1
1.1.1.1
1.1.1.2
1.1.1.3
1.1.1.4
1.2
1.3
I have created a Tree Class
public class Tree {
private List<Tree> children = new ArrayList<Tree>();
private String label;
private Tree parent;
private String root;
public Tree() {
super();
children = new ArrayList<Tree>();
}
public Tree(String label) {
this();
setData(label);
}
public void setRoot(String root){
this.root= root;
}
public String getRoot(){
return root;
}
public void addChild(Tree child) {
child.setParent(this);
children.add(child);
}
public void removeChild(Tree node) {
children.remove(node);
node.setParent(null);
}
public void setParent(Tree parent) {
this.parent = parent;
}
public Object[] getChildren() {
return children.toArray();
}
public Object getParent() {
return parent;
}
public String getLabel() {
return this.label;
}
public void setData(String label) {
this.label = label;
}
}
I have to generate the following tree structure and also remember the parent of each node. I am not asking for the code but some pointers as to how to start and to proceed would be very helpful !!!!
1.1
1.2 1.1.1.1
1.3 1.1.1.2
1.4 1.1.1.3
1.1.1.4
You will need to read the output of the command. See the API of ProcessBuilder for getting the output of the process as InputStream (output of process == your input, right?)
Parse the output into tree nodes. Each node has a parent reference and a list children with child nodes.
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());
}
}
}