#!/usr/bin/python

import codecs


class Node(object):
    """docstring for Node"""
    def __init__(self, name, value, children):
        super(Node, self).__init__()
        self.name = name
        self.value = value.strip()
        if self.value == "-":
            self.value = "0"
        self.children = children

    def append_child(self, child):
        self.children.append(child)

    def as_json(self):
        s = u'{"name":"' + self.name + '"'
        if len(self.children) > 0:
            s += u', "children":['
            children_strings = [c.as_json() for c in self.children]
            s += u",".join(children_strings)
            s += u']}'
        else:
            s += u', "size":' +  self.value + u'}'
        return s


def lines2nodes(lines):
    #return [line2node(l.strip()) for l in lines]
    stack = []
    last_indent = None
    last_node = None
    for i in range(len(lines)):
        l = lines[i]
        components = l.split(";")
        indent = len(components[0]) + 1 + len(components[1]) - len(components[1].lstrip(' '))
        node = line2node(l)
        if last_indent is not None and indent > last_indent:
            stack.append(last_node)
            last_node.append_child(node)
        elif last_indent is not None and  last_indent - indent <= 1:
            parent = stack.pop()
            parent.append_child(node)
            stack.append(parent)
        elif last_indent is not None and indent < last_indent:
            indent_diff = last_indent - indent
            while indent_diff >= 2:
                stack.pop()
                indent_diff -= 3
            parent = stack.pop()
            parent.append_child(node)
            stack.append(parent)

#        print "indent: " + str(indent) + " stack size: " + str(len(stack))
        last_indent = indent
        last_node = node

    while len(stack) > 1:
        stack.pop()
    nodes = [ stack[0] ]
    return nodes

def line2node(line):
    components = line.split(";")
    node = Node(unicode(components[1].strip()), unicode(components[2]), [])
    return node


def main():
    lines = []
    with codecs.open("sachsen_finanzen/71137-102Z-clean.csv", encoding="ISO-8859-1") as f:
        lines = f.readlines()

    lines = lines[1:] # skip header line
    nodes = lines2nodes(lines)
    flare_node = Node("flare", "-", nodes)

    with codecs.open("flare.json", "w", "utf-8") as f:
        f.write(unicode(flare_node.as_json()))


if __name__ == '__main__':
    main()

@@ -28,16 +28,221 @@
 odecs%0A%0A%0A
+INPUT_FILE = %22sachsen_finanzen/71137-102Z-clean.csv%22%0AINPUT_ENCODING = %22ISO-8859-1%22%0AOUTPUT_FILE = %22flare.json%22%0AOUTPUT_ENCODING = %22utf-8%22%0ACSV_DELIMITER = %22;%22%0A%0AINDENT_TOLERANCE = 1%0AINDENT_MIN = 2%0AINDENT = 3%0A%0A
 class No
@@ -1158,27 +1158,37 @@
 s = l.split(
-%22;%22
+CSV_DELIMITER
 )%0A        in
@@ -1503,17 +1503,32 @@
 dent %3C= 
-1
+INDENT_TOLERANCE
 :%0A      
@@ -1768,17 +1768,26 @@
 diff %3E= 
-2
+INDENT_MIN
 :%0A      
@@ -1839,17 +1839,22 @@
 diff -= 
-3
+INDENT
 %0A       
@@ -2371,70 +2371,43 @@
 pen(
-%22sachsen_finanzen/71137-102Z-clean.csv%22, encoding=%22ISO-8859-1%22
+INPUT_FILE, encoding=INPUT_ENCODING
 ) as
@@ -2582,34 +2582,41 @@
 pen(
-%22flare.json%22, %22w%22, %22utf-8%22
+OUTPUT_FILE, %22w%22, OUTPUT_ENCODING
 ) as

Refactor constants