Amete Girl Amete Girl - 7 months ago 99
Java Question

Parse indented text tree in Java

I have an indented file that I need to parsed using java,
I need some way to place this in a Section class as shown below

root
root1
text1
text1.1
text1.2
text2
text2.1
text2.2

root2
text1
text1.1
text1.2
text2
text2.1
text2.2.2


I have the class for putting the indented stuff it looks like

public class Section
{

private List<Section> children;
private String text;
private int depth;
public Section(String t)
{
text =t;
}

public List<Section> getChildren()
{
if (children == null)
{
children = new ArrayList<Section>();
}
return children;
}

public void setChildren(List<Section> newChildren)
{
if (newChildren == null) {
children = newChildren;
} else {
if (children == null) {
children = new ArrayList<Section>();
}
for (Section child : newChildren) {
this.addChild(child);
}
}
}

public void addChild(Section child)
{
if (children == null) {
children = new ArrayList<Section>();
}
if (child != null) {
children.add(child);
}
}

public String getText()
{
return text;
}

public void setText(String newText)
{
text =newText;
}
public String getDepth()
{
return depth;
}

public void setDepth(int newDepth)
{
depth = newDepth;
}
}


I need some way to parse the file and place it in expected result which us a Section object which would look like below

Section=

Text="Root"
Children
Child1: Text= "root1"

Child1: "text1"
Child1="Text 1.1"
Child2="Text 1.2"
Child2: "text2"
Child1="Text 2.1"
Child2="Text 2.2"
Children
Child2: Text= "root2"
Child1: "text1"
Child1="Text 1.1"
Child2="Text 1.2"
Child2: "text2"
Child1="Text 2.1"
Child2="Text 2.2"


Here is some code that I have started
int indentCount=0;
while(String text = reader.readline()
{
indentCount=countLeadingSpaces(String word);
//TODO create the section here
}


public static int countLeadingSpaces(String word)
{
int length=word.length();
int count=0;

for(int i=0;i<length;i++)
{
char first = word.charAt(i);
if(Character.isWhitespace(first))
{
count++;
}
else
{
return count;
}
}

return count;

}

Answer

I added a parent pointer as well. Maybe the text can be parsed without it, but parent pointers make it easier. First of all, you need to have more constructors:

static final int root_depth = 4; // assuming 4 whitespaces precede the tree root

public Section(String text, int depth) {
    this.text     = text;
    this.depth    = depth;
    this.children = new ArrayList<Section>();
    this.parent   = null;
}

public Section(String text, int depth, Section parent) {
    this.text     = text;
    this.depth    = depth;
    this.children = new ArrayList<Section>();
    this.parent   = parent;
}

Then, when you start parsing the file, read it line by line:

Section prev = null;
for (String line; (line = bufferedReader.readLine()) != null; ) {
    if (prev == null && line begins with root_depth whitespaces) {
        Section root = new Section(text_of_line, root_depth);
        prev = root;
    }
    else {
        int t_depth = no. of whitespaces at the beginning of this line;
        if (t_depth > prev.getDepth())
            // assuming that empty sections are not allowed
            Section t_section = new Section(text_of_line, t_depth, prev);
            prev.addChild(t_section);
        }
        else if (t_depth == prev.getDepth) {
            Section t_section = new Section(text_of_line, t_depth, prev.getParent());
            prev.getParent().addChild(t_section);
        }
        else {
            while (t_depth < prev.getDepth()) {
                prev = prev.getParent();
            }
            // at this point, (t_depth == prev.getDepth()) = true
            Section t_section = new Section(text_of_line, t_depth, prev.getParent());
            prev.getParent().addChild(t_section);
        }
    }
}

I have glossed over some finer points of the pseudo-code, but I think you get the overall idea of how to go about this parsing. Do remember to implement the methods addChild(), getDepth(), getParent(), etc.