class xmlLikeConfParser:

    _delim               = "[ \t]+"
    _new_delim           = " "
    _comment             = "#"
    _reserved_key_prefix = "@"
    _indent              = "  "

    _module  = "xml_like_conf_parser"
    _footer  = "-- Generated by karesansui"

    def __init__(self,paths=[]):
        self.dop = DictOp()
        self.dop.addconf(self._module,{})
        self.set_source_file(paths)

        self.opt_uni   = ['PIDFile']
        self.opt_multi = ['LoadPlugin','Include']
        self.opt_sect  = ['Directory','VirtualHost','View']

    def set_opt_uni(self, opts):
        self.opt_uni = opts

    def set_opt_multi(self, opts):
        self.opt_multi = opts

    def set_opt_sect(self, opts):
        self.opt_sect = opts

    def set_delim(self, delim=" "):
        self._delim = delim

    def set_new_delim(self, delim=" "):
        self._new_delim = delim

    def set_comment(self, comment="#"):
        self._comment = comment

    def set_reserved_key_prefix(self, prefix="@"):
        self._reserved_key_prefix = prefix

    def set_footer(self, footer=""):
        self._footer = footer

    def set_source_file(self,paths=[]):
        if type(paths) == str:
            paths = [paths]
        self.paths = paths
        return True

    def get_source_file(self):
        return self.paths

    def source_file(self):
        return self.get_source_file()

    def build_value(self, value=None, precomment=[], postcomment=None):
        if type(precomment) == str:
            precomment = [precomment]
        return [value, [precomment, postcomment], ]

    def read_conf(self):
        retval = {}
        orders_key = "%sORDERS" % (self._reserved_key_prefix,)

        for _afile in self.source_file():
            res = ConfigFile(_afile).read()
            self.orders = []
            self.dop.set(self._module,[_afile],self._read_conf(res))
            self.dop.set(self._module,[_afile,orders_key],self.orders)

        return self.dop.getconf(self._module)

    def _read_conf(self,lines,level=0):

        dop = DictOp()
        dop.addconf("__",{})

        pre_comment  = []   # 設定の前のコメント リスト配列
        post_comment = None # 設定行のコメント 文字列
        _in_section = False
        _res = []
        for _aline in lines:

            if _in_section is True:
                regex = "[ \t]*(?P<comment>#*)[ \t]*</(?P<key>%s)>" % _section_key #'|'.join(self.opt_sect)
                _regex = re.compile(r"%s" % regex)
                m = _regex.match(_aline)
                if m:
                    _comment = m.group('comment')
                    _key     = m.group('key').strip()
                    values = self.build_value(self._read_conf(_res,level),pre_comment,post_comment)
                    dop.set("__",[_key,_section_val],values)
                    if _comment != "":
                        dop.comment("__",[_key,_section_val])
                    if level == 1:
                        self.orders.append([_key,_section_val])
                    pre_comment  = []
                    post_comment = None
                    _in_section = False
                    _res = []
                    level = level - 1
                else:
                    _res.append(_aline)

            else:

                _aline = _aline.rstrip('\r\n')

                if _aline.strip() == "":
                    pre_comment.append(_aline)
                    continue

                match = False
                for _type in ['uni','multi','sect']:
                    exec("regex = '|'.join(self.opt_%s)" % _type)
                    if _type == "sect":
                        regex = "[ \t]*(?P<comment>#*)[ \t]*<(?P<key>%s)(?P<section>.*)>" % regex
                    elif _type == "multi":
                        regex = "[ \t]*(?P<comment>#*)[ \t]*(?P<key>%s)[ \t]+(?P<value>.+)"  % regex
                    elif _type == "uni":
                        regex = "[ \t]*(?P<comment>#*)[ \t]*(?P<key>%s)[ \t]+(?P<value>.+)"  % regex

                    _regex = re.compile(r"%s" % regex)
                    m = _regex.match(_aline)
                    if m:
                        match = True
                        _comment = m.group('comment')
                        _key     = m.group('key').strip()
                        if _type == "sect":
                            _section_key = _key
                            _section_val = re.sub(r"[\"']","",m.group('section').strip())
                            _in_section = True
                            level = level + 1
                        elif _type == "multi":
                            _value = m.group('value').strip()
                            if _value.find(self._comment) > 0:
                                post_comment = _value[_value.find(self._comment):]
                            _value = re.sub("%s$" % post_comment, "", _value).rstrip()
                            values = self.build_value(_value,pre_comment,post_comment)
                            dop.set("__",[_key,_value],values)
                            if _comment != "":
                                dop.comment("__",[_key,_value])
                            if level == 0:
                                self.orders.append([_key,_value])
                            pre_comment  = []
                            post_comment = None
                        elif _type == "uni":
                            _value   = m.group('value').strip()
                            if _value.find(self._comment) > 0:
                                post_comment = _value[_value.find(self._comment):]
                            _value = re.sub("%s$" % post_comment, "", _value).rstrip()
                            values = self.build_value(_value,pre_comment,post_comment)
                            dop.set("__",[_key],values)
                            if _comment != "":
                                dop.comment("__",[_key])
                            if level == 0:
                                self.orders.append([_key])
                            pre_comment  = []
                            post_comment = None
                        break

                if match is False:

                    # ブラケットディレクティブのパラメータは除外する (よって、ブラケットディレクティブは全ての定義が必要!)
                    # example: "<undefined_directive 'foobar'>"
                    regex_exclude1 = "[ \t]*(?P<comment>#*)[ \t]*(?P<key>%s)[ \t]" % '|'.join(self.opt_sect)
                    _regex_exclude1 = re.compile(r"%s" % regex_exclude1)

                    # 未定義のパラメータの値がクオートせずにスペース区切りで3つ以上の値を指定している場合はコメント行とみなす
                    # example: "# Read this configuration file"
                    regex_exclude2 = "[ \t]*#+[ \t]*[^ \t]+([ \t]+[^ \t]+){3,}"
                    _regex_exclude2 = re.compile(r"%s" % regex_exclude2)

                    # 未定義のパラメータの値がクオートせずにスペース区切りで2つ以上の値を指定していて、かつ、最後が:で終わる場合はコメント行とみなす
                    # example: "# Read this configuration:"
                    regex_exclude3 = "[ \t]*#+[ \t]*[^ \t]+([ \t]+[^ \t]+){2,}:$"
                    _regex_exclude3 = re.compile(r"%s" % regex_exclude3)

                    # 未定義のパラメータの値が0個以上で、かつ、最後が:で終わる場合はコメント行とみなす
                    # example: "# Read #"
                    regex_exclude4 = "[ \t]*#+[ \t]*[^ \t]+.+[ \t]+#+$"
                    _regex_exclude4 = re.compile(r"%s" % regex_exclude4)

                    m1 = _regex_exclude1.match(_aline)
                    m2 = _regex_exclude2.match(_aline)
                    m3 = _regex_exclude3.match(_aline)
                    m4 = _regex_exclude4.match(_aline)
                    if not m1 and not m2 and not m3 and not m4:

                        # opt_xxxに未定義のパラメータはuniパラメータとする
                        regex = "[ \t]*(?P<comment>#*)[ \t]*(?P<key>[A-Z][^ \t]+)[ \t]+(?P<value>.+)"
                        _regex = re.compile(r"%s" % regex)
                        m = _regex.match(_aline)
                        if m:
                            _comment = m.group('comment')
                            _key     = m.group('key').strip()
                            _value   = m.group('value').strip()
                            if _value.find(self._comment) > 0:
                                post_comment = _value[_value.find(self._comment):]
                            _value = re.sub("%s$" % post_comment, "", _value).rstrip()
                            values = self.build_value(_value,pre_comment,post_comment)
                            dop.set("__",[_key],values)
                            if _comment != "":
                                dop.comment("__",[_key])
                            if level == 0:
                                self.orders.append([_key])
                            pre_comment  = []
                            post_comment = None
                            match = True

                if match is False:

                    if _aline.lstrip()[0:1] == self._comment:
                        footer_regex = re.compile(self._footer)
                        m = footer_regex.search(_aline)
                        if not m: 
                            comment = _aline[_aline.find(self._comment):]
                            pre_comment.append(comment)
                            continue

        if len(pre_comment) > 0:
            eof_key   = "%sEOF"    % (self._reserved_key_prefix,)
            new_value = self.build_value("",pre_comment,post_comment)
            dop.set("__",[eof_key],new_value)

        return dop.getconf("__")


    def _value_to_lines(self,conf_arr,level=0):
        lines = []
        orders_key = "%sORDERS" % (self._reserved_key_prefix,)

        dop = DictOp()
        dop.addconf("__",conf_arr)

        for _k,_v in dop.getconf("__").iteritems():

            action = dop.action("__",[_k])
            if action == "delete":
                continue

            iscomment = dop.iscomment("__",[_k])

            value = dop.get("__",[_k])

            if type(value) == list:

                _val          = value[0]

                if type(_val) != dict:
                    _pre_comment  = value[1][0]
                    _post_comment = value[1][1]

                    pre_comment = []
                    try:
                        for _aline in _pre_comment:
                            if _aline.strip() == "":
                                pass
                            elif _aline[0:1] != self._comment:
                                _prefix = ""
                                if level > 0:
                                    _prefix += str_repeat(self._indent,level)
                                _prefix += self._comment
                                _aline = "%s %s" % (_prefix,_aline,)
                            pre_comment.append(_aline)
                    except:
                        pass

                    if len(pre_comment) > 0:
                        #preprint_r(pre_comment)
                        lines = lines + pre_comment

                    post_comment = _post_comment
                    try:
                        if post_comment is not None and post_comment[0:1] != self._comment:
                            post_comment = "%s %s" % (self._comment,post_comment,)
                    except:
                        pass
                else:
                    pass

            else:
                _val = value

            _prefix = ""
            if iscomment is True:
                _prefix += self._comment
            if level > 0:
                _prefix += str_repeat(self._indent,level)

            if type(_val) == dict:

                # ORDER順に設定する
                orders = []
                try:
                    old_orders = _val[orders_key]['value']
                except:
                    old_orders = []

                for kk in old_orders:
                    if type(kk) is list:
                        orders.append(kk[0])
                    elif type(kk) is str:
                        orders.append(kk)

                for kk in _val.keys():
                    if not kk in orders:
                        orders.append(kk)

                #for _k2,_v2 in _val.iteritems():
                for _k2 in orders:

                    if _k2 == orders_key:
                        continue
                    _v2 = _val[_k2]

                    sub_value = {}
                    sub_value[_k2] = _v2

                    try:
                        iscomment = sub_value[_k2]['comment']
                    except:
                        iscomment = False

                    try:
                        action = sub_value[_k2]['action']
                    except:
                        action = ""

                    if action == "delete":
                        continue

                    #try:
                    #    sub_value[_k2]['value'][1][0]
                    #    lines = lines + sub_value[_k2]['value'][1][0]
                    #except:
                    #    pass


                    is_sect = False
                    if _k in self.opt_multi and _k2 == _v2["value"][0]:
                        for _k3,_v3 in sub_value.iteritems():
                            try:
                                iscomment3 = sub_value[_k3]['comment']
                            except:
                                iscomment3 = iscomment
                            try:
                                action3 = sub_value[_k3]['action']
                            except:
                                action3 = ""

                            _prefix = ""
                            if iscomment is True:
                                _prefix += self._comment
                            if level > 0:
                                _prefix += str_repeat(self._indent,level)
                            lines.append("%s%-18s%s%s" % (_prefix,_k,self._new_delim,_k2))

                    elif _k in self.opt_sect:
                        is_sect = True
                        _prefix = ""
                        if iscomment is True:
                            _prefix += self._comment
                        if level > 0:
                            _prefix += str_repeat(self._indent,level)
                        if _k2 == "":
                            lines.append("%s<%s>" % (_prefix,_k))
                        else:
                            lines.append("%s<%s \"%s\">" % (_prefix,_k,_k2))

                    new_level = level + 1
                    new_lines = self._value_to_lines(sub_value,level=new_level)

                    for _aline in new_lines:
                        _prefix2 = ""
                        if iscomment is True:
                            _prefix2 += self._comment
                        new_aline = "%s%s" % (_prefix2,_aline,)
                        new_aline = re.sub("^%s+" % self._comment,self._comment,new_aline)
                        lines.append(new_aline)
                    #lines = lines + new_lines

                    if is_sect is True:
                        lines.append("%s</%s>" % (_prefix,_k,))

            else:

                aline = ""
                if _k in self.opt_multi:
                    aline += "%s%-18s%s%s" % (_prefix,_k,self._new_delim,_val,)
                else:
                    if re.match("^[A-Z]+[a-z]",_k):
                        aline += "%s%-18s%s%s" % (_prefix,_k,self._new_delim,_val,)

                if post_comment is not None:
                    aline = "%s %s" % (aline,post_comment,)

                if aline != "":
                    lines.append(aline)

        return lines


    def write_conf(self,conf_arr={},dryrun=False):
        retval = True

        self.dop.addconf(self._module,conf_arr)
        orders_key = "%sORDERS" % (self._reserved_key_prefix,)
        eof_key    = "%sEOF"    % (self._reserved_key_prefix,)

        for _path,_v in conf_arr.iteritems():

            if _path[0:1] != "/":
                continue

            lines = []
            try:
                _v['value']
            except:
                continue

            exclude_regex = "^%s[A-Z0-9\_]+$" % self._reserved_key_prefix

            # まずはオーダの順
            if self.dop.isset(self._module,[_path,orders_key]) is True:
                for _k2 in self.dop.get(self._module,[_path,orders_key]):
                    try:
                        if type(_k2) == str:
                            _k2 = [_k2]
                        _search_key = [_path] + _k2

                        is_opt_multi = False
                        if _k2[0] in self.opt_multi:
                            _tmp_conf = self.dop.get(self._module,_search_key)
                            # multiとsectがかぶったオプションの対応 strならmulti
                            if type(_tmp_conf[0]) == str:
                                is_opt_multi = True

                        if is_opt_multi is True:
                            _k2.pop()

                        new_lines = self._new_lines(_search_key,_k2)
                        lines = lines + new_lines
                        self.dop.unset(self._module,_search_key)
                    except:
                        pass

            # オーダにないものは最後に追加
            for _k2,_v2 in self.dop.get(self._module,[_path]).iteritems():

                #if _k2 != orders_key:
                m = re.match(exclude_regex,_k2)
                if not m:
                    try:
                        if type(_k2) == str:
                            _k2 = [_k2]
                        _search_key = [_path] + _k2

                        if _k2[0] in self.opt_multi:
                            for _k3,_v3 in self.dop.get(self._module,_search_key).iteritems():
                                _search_key.append(_k3)
                                new_lines = self._new_lines(_search_key,_k2)
                                lines = lines + new_lines
                        else:
                            new_lines = self._new_lines(_search_key,_k2)
                            lines = lines + new_lines

                    except:
                        pass


            # 最後のコメント用の処理
            if self._footer != "":
                if self.dop.isset(self._module,[_path,eof_key]) is False:
                    self.dop.cdp_set(self._module,[_path,eof_key],"",force=True)

                eof_val     = self.dop.get(self._module,[_path,eof_key])
                eof_action  = self.dop.action(self._module,[_path,eof_key])
                eof_comment = self.dop.comment(self._module,[_path,eof_key])
                try:
                    key = " %s - %s on %s" % (self._footer,self._module,time.strftime("%c",time.localtime()))
                    value = {}
                    value[key] = {}
                    value[key]["value"]   = eof_val
                    value[key]["action"]  = eof_action
                    value[key]["comment"] = eof_comment
                    self.set_new_delim(delim=" ")
                    lines = lines + self._value_to_lines(value)
                except:
                    pass

            if dryrun is False:
                if len(lines) > 0:
                    ConfigFile(_path).write("\n".join(lines) + "\n")
            else:
                print "%s -- filename: %s" % (self._comment,_path,)
                print "\n".join(lines)

        return retval

    def _new_lines(self,search_key,new_key):

        try:
            attrs = self.dop.get(self._module,search_key,with_attr=True)
            action    = attrs['action']
            iscomment = attrs['comment']
            val       = attrs['value']
        except:
            action    = self.dop.action(self._module,search_key)
            iscomment = self.dop.iscomment(self._module,search_key)
            val       = self.dop.get(self._module,search_key)
            pass

        #print val
        dop = DictOp()
        dop.addconf('__',{})
        if action == "delete":
            dop.add('__',new_key,val)
            dop.delete('__',new_key)
        elif action == "set":
            dop.set('__',new_key,val)
        else:
            dop.add('__',new_key,val)
        if iscomment is True:
            dop.comment('__',new_key)

        #preprint_r(dop.getconf('__'))
        new_lines = self._value_to_lines(dop.getconf('__'))
        #print "\n".join(new_lines)

        return new_lines
    def _value_to_lines(self,conf_arr,level=0):
        lines = []
        orders_key = "%sORDERS" % (self._reserved_key_prefix,)

        dop = DictOp()
        dop.addconf("__",conf_arr)

        for _k,_v in dop.getconf("__").iteritems():

            action = dop.action("__",[_k])
            if action == "delete":
                continue

            iscomment = dop.iscomment("__",[_k])

            value = dop.get("__",[_k])

            if type(value) == list:

                _val          = value[0]

                if type(_val) != dict:
                    _pre_comment  = value[1][0]
                    _post_comment = value[1][1]

                    pre_comment = []
                    try:
                        for _aline in _pre_comment:
                            if _aline.strip() == "":
                                pass
                            elif _aline[0:1] != self._comment:
                                _prefix = ""
                                if level > 0:
                                    _prefix += str_repeat(self._indent,level)
                                _prefix += self._comment
                                _aline = "%s %s" % (_prefix,_aline,)
                            pre_comment.append(_aline)
                    except:
                        pass

                    if len(pre_comment) > 0:
                        #preprint_r(pre_comment)
                        lines = lines + pre_comment

                    post_comment = _post_comment
                    try:
                        if post_comment is not None and post_comment[0:1] != self._comment:
                            post_comment = "%s %s" % (self._comment,post_comment,)
                    except:
                        pass
                else:
                    pass

            else:
                _val = value

            _prefix = ""
            if iscomment is True:
                _prefix += self._comment
            if level > 0:
                _prefix += str_repeat(self._indent,level)

            if type(_val) == dict:

                # ORDER順に設定する
                orders = []
                try:
                    old_orders = _val[orders_key]['value']
                except:
                    old_orders = []

                for kk in old_orders:
                    if type(kk) is list:
                        orders.append(kk[0])
                    elif type(kk) is str:
                        orders.append(kk)

                for kk in _val.keys():
                    if not kk in orders:
                        orders.append(kk)

                #for _k2,_v2 in _val.iteritems():
                for _k2 in orders:

                    if _k2 == orders_key:
                        continue
                    _v2 = _val[_k2]

                    sub_value = {}
                    sub_value[_k2] = _v2

                    try:
                        iscomment = sub_value[_k2]['comment']
                    except:
                        iscomment = False

                    try:
                        action = sub_value[_k2]['action']
                    except:
                        action = ""

                    if action == "delete":
                        continue

                    #try:
                    #    sub_value[_k2]['value'][1][0]
                    #    lines = lines + sub_value[_k2]['value'][1][0]
                    #except:
                    #    pass


                    is_sect = False
                    if _k in self.opt_multi and _k2 == _v2["value"][0]:
                        for _k3,_v3 in sub_value.iteritems():
                            try:
                                iscomment3 = sub_value[_k3]['comment']
                            except:
                                iscomment3 = iscomment
                            try:
                                action3 = sub_value[_k3]['action']
                            except:
                                action3 = ""

                            _prefix = ""
                            if iscomment is True:
                                _prefix += self._comment
                            if level > 0:
                                _prefix += str_repeat(self._indent,level)
                            lines.append("%s%-18s%s%s" % (_prefix,_k,self._new_delim,_k2))

                    elif _k in self.opt_sect:
                        is_sect = True
                        _prefix = ""
                        if iscomment is True:
                            _prefix += self._comment
                        if level > 0:
                            _prefix += str_repeat(self._indent,level)
                        if _k2 == "":
                            lines.append("%s<%s>" % (_prefix,_k))
                        else:
                            lines.append("%s<%s \"%s\">" % (_prefix,_k,_k2))

                    new_level = level + 1
                    new_lines = self._value_to_lines(sub_value,level=new_level)

                    for _aline in new_lines:
                        _prefix2 = ""
                        if iscomment is True:
                            _prefix2 += self._comment
                        new_aline = "%s%s" % (_prefix2,_aline,)
                        new_aline = re.sub("^%s+" % self._comment,self._comment,new_aline)
                        lines.append(new_aline)
                    #lines = lines + new_lines

                    if is_sect is True:
                        lines.append("%s</%s>" % (_prefix,_k,))

            else:

                aline = ""
                if _k in self.opt_multi:
                    aline += "%s%-18s%s%s" % (_prefix,_k,self._new_delim,_val,)
                else:
                    if re.match("^[A-Z]+[a-z]",_k):
                        aline += "%s%-18s%s%s" % (_prefix,_k,self._new_delim,_val,)

                if post_comment is not None:
                    aline = "%s %s" % (aline,post_comment,)

                if aline != "":
                    lines.append(aline)

        return lines
class commentDealParser:

    _delim               = "[ \t]+"
    _new_delim           = " "
    _comment             = "#"
    _reserved_key_prefix = "@"

    _module  = "comment_deal_parser"
    _footer  = "-- Generated by karesansui"

    def __init__(self,paths=[]):
        self.dop = DictOp()
        self.dop.addconf(self._module,{})
        self.set_source_file(paths)

    def set_delim(self, delim=" "):
        self._delim = delim

    def set_new_delim(self, delim=" "):
        self._new_delim = delim

    def set_comment(self, comment="#"):
        self._comment = comment

    def set_reserved_key_prefix(self, prefix="@"):
        self._reserved_key_prefix = prefix

    def set_footer(self, footer=""):
        self._footer = footer

    def set_source_file(self,paths=[]):
        if type(paths) == str:
            paths = [paths]
        self.paths = paths
        return True

    def get_source_file(self):
        return self.paths

    def source_file(self):
        return self.get_source_file()

    def build_value(self, string, precomment=[], postcomment=None):
        if type(precomment) == str:
            precomment = [precomment]
        return [string, [precomment, postcomment], ]

    def read_conf(self):
        retval = {}

        for _afile in self.source_file():
            res = ConfigFile(_afile).read()

            orders    = []
            comment_1 = []   # 設定の前のコメント リスト配列
            comment_2 = None # 設定行のコメント 文字列
            for _aline in res:
                _aline = _aline.rstrip('\r\n')

                if _aline.strip() == "":
                    comment_1.append(_aline)
                    continue

                if _aline.lstrip()[0:1] == self._comment:
                    footer_regex = re.compile(self._footer)
                    m = footer_regex.search(_aline)
                    if not m:
                        comment = _aline[_aline.rfind(self._comment):]
                        comment_1.append(comment)
                        continue

                regex_str = "^(?P<key>[^ \t]+)%s(?P<value>.*)$" % (self._delim,)
                regex = re.compile(r"%s" % regex_str)

                m = regex.match(_aline)
                if m:
                    key     = m.group('key')
                    value   = m.group('value')
                    if not value.rfind(self._comment) == -1:
                        comment_2 = value[value.rfind(self._comment):]
                        value = value[:value.rfind(self._comment)]

                    new_value = self.build_value(value,comment_1,comment_2)
                    if new_value is not False:
                        self.dop.set(self._module,[_afile,key],new_value)
                        orders.append(key)
                    comment_1 = []
                    comment_2 = None

            if len(comment_1) > 0:
                eof_key    = "%sEOF"    % (self._reserved_key_prefix,)
                new_value = self.build_value("",comment_1,comment_2)
                self.dop.set(self._module,[_afile,eof_key],new_value)

            orders_key = "%sORDERS" % (self._reserved_key_prefix,)
            self.dop.set(self._module,[_afile,orders_key],orders)

        #self.dop.preprint_r(self._module)
        return self.dop.getconf(self._module)


    def _value_to_lines(self,value):
        lines = []

        for _k,_v in value.iteritems():

            try:
                if _v['action'] == "delete":
                    continue
            except:
                pass

            iscomment = False
            try:
                iscomment = _v['comment']
            except:
                pass

            _prefix = ""
            if iscomment is True:
                _prefix += self._comment

            try:
                val = _v['value'][0]

                comment_1 = []
                try:
                    for com1_aline in _v['value'][1][0]:
                        if com1_aline.strip() == "":
                            pass
                        elif com1_aline[0:1] != self._comment:
                            com1_aline = "%s %s" % (self._comment,com1_aline,)
                        comment_1.append(com1_aline)
                except:
                    pass

                comment_2 = _v['value'][1][1]
                try:
                    if comment_2[0:1] != self._comment:
                        comment_2 = "%s %s" % (self._comment,comment_2,)
                except:
                    pass

                lines = lines + comment_1
                aline = "%s%s%s%s" % (_prefix,_k,self._new_delim,val,)
                if comment_2 is not None:
                    aline = "%s %s" % (aline,comment_2,)
                lines.append(aline)
            except:
                pass

        return lines


    def write_conf(self,conf_arr={},dryrun=False):
        retval = True

        self.dop.addconf(self._module,conf_arr)
        orders_key = "%sORDERS" % (self._reserved_key_prefix,)
        eof_key    = "%sEOF"    % (self._reserved_key_prefix,)

        for _path,_v in conf_arr.iteritems():

            if _path[0:1] != "/":
                continue

            lines = []
            try:
                _v['value']
            except:
                continue

            exclude_regex = "^%s[A-Z0-9\_]+$" % self._reserved_key_prefix

            # まずはオーダの順
            if self.dop.isset(self._module,[_path,orders_key]) is True:
                for _k2 in self.dop.get(self._module,[_path,orders_key]):
                    m = re.match(exclude_regex,_k2)
                    if not m:
                        try:
                            if type(_k2) == list:
                                _k2 = _k2.pop()
                            value = {}
                            value[_k2] = _v['value'][_k2]
                            lines = lines + self._value_to_lines(value)
                            self.dop.unset(self._module,[_path,_k2])
                        except:
                            pass

            # オーダにないものは最後に追加
            for _k2,_v2 in self.dop.get(self._module,[_path]).iteritems():
                #if _k2 != orders_key and _k2 != eof_key:
                m = re.match(exclude_regex,_k2)
                if not m:
                    try:
                        value = {}
                        value[_k2] = _v2
                        lines = lines + self._value_to_lines(value)
                    except:
                        pass

            # 最後のコメント用の処理
            if self._footer != "":
                if self.dop.isset(self._module,[_path,eof_key]) is False:
                    self.dop.cdp_set(self._module,[_path,eof_key],"",force=True)

                eof_val     = self.dop.get(self._module,[_path,eof_key])
                eof_action  = self.dop.action(self._module,[_path,eof_key])
                eof_comment = self.dop.comment(self._module,[_path,eof_key])
                try:
                    key = " %s - %s on %s" % (self._footer,self._module,time.strftime("%c",time.localtime()))
                    value = {}
                    value[key] = {}
                    value[key]["value"]   = eof_val
                    value[key]["action"]  = eof_action
                    value[key]["comment"] = eof_comment
                    self.set_new_delim(delim=" ")
                    lines = lines + self._value_to_lines(value)
                except:
                    pass

            if dryrun is False:
                if len(lines) > 0:
                    ConfigFile(_path).write("\n".join(lines) + "\n")
            else:
                #pass
                print "\n".join(lines)

        return retval
Exemple #4
0
class xmlLikeConfParser:

    _delim = "[ \t]+"
    _new_delim = " "
    _comment = "#"
    _reserved_key_prefix = "@"
    _indent = "  "

    _module = "xml_like_conf_parser"
    _footer = "-- Generated by karesansui"

    def __init__(self, paths=[]):
        self.dop = DictOp()
        self.dop.addconf(self._module, {})
        self.set_source_file(paths)

        self.opt_uni = ['PIDFile']
        self.opt_multi = ['LoadPlugin', 'Include']
        self.opt_sect = ['Directory', 'VirtualHost', 'View']

    def set_opt_uni(self, opts):
        self.opt_uni = opts

    def set_opt_multi(self, opts):
        self.opt_multi = opts

    def set_opt_sect(self, opts):
        self.opt_sect = opts

    def set_delim(self, delim=" "):
        self._delim = delim

    def set_new_delim(self, delim=" "):
        self._new_delim = delim

    def set_comment(self, comment="#"):
        self._comment = comment

    def set_reserved_key_prefix(self, prefix="@"):
        self._reserved_key_prefix = prefix

    def set_footer(self, footer=""):
        self._footer = footer

    def set_source_file(self, paths=[]):
        if type(paths) == str:
            paths = [paths]
        self.paths = paths
        return True

    def get_source_file(self):
        return self.paths

    def source_file(self):
        return self.get_source_file()

    def build_value(self, value=None, precomment=[], postcomment=None):
        if type(precomment) == str:
            precomment = [precomment]
        return [
            value,
            [precomment, postcomment],
        ]

    def read_conf(self):
        retval = {}
        orders_key = "%sORDERS" % (self._reserved_key_prefix, )

        for _afile in self.source_file():
            res = ConfigFile(_afile).read()
            self.orders = []
            self.dop.set(self._module, [_afile], self._read_conf(res))
            self.dop.set(self._module, [_afile, orders_key], self.orders)

        return self.dop.getconf(self._module)

    def _read_conf(self, lines, level=0):

        dop = DictOp()
        dop.addconf("__", {})

        pre_comment = []  # 設定の前のコメント リスト配列
        post_comment = None  # 設定行のコメント 文字列
        _in_section = False
        _res = []
        for _aline in lines:

            if _in_section is True:
                regex = "[ \t]*(?P<comment>#*)[ \t]*</(?P<key>%s)>" % _section_key  #'|'.join(self.opt_sect)
                _regex = re.compile(r"%s" % regex)
                m = _regex.match(_aline)
                if m:
                    _comment = m.group('comment')
                    _key = m.group('key').strip()
                    values = self.build_value(self._read_conf(_res, level),
                                              pre_comment, post_comment)
                    dop.set("__", [_key, _section_val], values)
                    if _comment != "":
                        dop.comment("__", [_key, _section_val])
                    if level == 1:
                        self.orders.append([_key, _section_val])
                    pre_comment = []
                    post_comment = None
                    _in_section = False
                    _res = []
                    level = level - 1
                else:
                    _res.append(_aline)

            else:

                _aline = _aline.rstrip('\r\n')

                if _aline.strip() == "":
                    pre_comment.append(_aline)
                    continue

                match = False
                for _type in ['uni', 'multi', 'sect']:
                    exec("regex = '|'.join(self.opt_%s)" % _type)
                    if _type == "sect":
                        regex = "[ \t]*(?P<comment>#*)[ \t]*<(?P<key>%s)(?P<section>.*)>" % regex
                    elif _type == "multi":
                        regex = "[ \t]*(?P<comment>#*)[ \t]*(?P<key>%s)[ \t]+(?P<value>.+)" % regex
                    elif _type == "uni":
                        regex = "[ \t]*(?P<comment>#*)[ \t]*(?P<key>%s)[ \t]+(?P<value>.+)" % regex

                    _regex = re.compile(r"%s" % regex)
                    m = _regex.match(_aline)
                    if m:
                        match = True
                        _comment = m.group('comment')
                        _key = m.group('key').strip()
                        if _type == "sect":
                            _section_key = _key
                            _section_val = re.sub(r"[\"']", "",
                                                  m.group('section').strip())
                            _in_section = True
                            level = level + 1
                        elif _type == "multi":
                            _value = m.group('value').strip()
                            if _value.find(self._comment) > 0:
                                post_comment = _value[_value.find(self._comment
                                                                  ):]
                            _value = re.sub("%s$" % post_comment, "",
                                            _value).rstrip()
                            values = self.build_value(_value, pre_comment,
                                                      post_comment)
                            dop.set("__", [_key, _value], values)
                            if _comment != "":
                                dop.comment("__", [_key, _value])
                            if level == 0:
                                self.orders.append([_key, _value])
                            pre_comment = []
                            post_comment = None
                        elif _type == "uni":
                            _value = m.group('value').strip()
                            if _value.find(self._comment) > 0:
                                post_comment = _value[_value.find(self._comment
                                                                  ):]
                            _value = re.sub("%s$" % post_comment, "",
                                            _value).rstrip()
                            values = self.build_value(_value, pre_comment,
                                                      post_comment)
                            dop.set("__", [_key], values)
                            if _comment != "":
                                dop.comment("__", [_key])
                            if level == 0:
                                self.orders.append([_key])
                            pre_comment = []
                            post_comment = None
                        break

                if match is False:

                    # ブラケットディレクティブのパラメータは除外する (よって、ブラケットディレクティブは全ての定義が必要!)
                    # example: "<undefined_directive 'foobar'>"
                    regex_exclude1 = "[ \t]*(?P<comment>#*)[ \t]*(?P<key>%s)[ \t]" % '|'.join(
                        self.opt_sect)
                    _regex_exclude1 = re.compile(r"%s" % regex_exclude1)

                    # 未定義のパラメータの値がクオートせずにスペース区切りで3つ以上の値を指定している場合はコメント行とみなす
                    # example: "# Read this configuration file"
                    regex_exclude2 = "[ \t]*#+[ \t]*[^ \t]+([ \t]+[^ \t]+){3,}"
                    _regex_exclude2 = re.compile(r"%s" % regex_exclude2)

                    # 未定義のパラメータの値がクオートせずにスペース区切りで2つ以上の値を指定していて、かつ、最後が:で終わる場合はコメント行とみなす
                    # example: "# Read this configuration:"
                    regex_exclude3 = "[ \t]*#+[ \t]*[^ \t]+([ \t]+[^ \t]+){2,}:$"
                    _regex_exclude3 = re.compile(r"%s" % regex_exclude3)

                    # 未定義のパラメータの値が0個以上で、かつ、最後が:で終わる場合はコメント行とみなす
                    # example: "# Read #"
                    regex_exclude4 = "[ \t]*#+[ \t]*[^ \t]+.+[ \t]+#+$"
                    _regex_exclude4 = re.compile(r"%s" % regex_exclude4)

                    m1 = _regex_exclude1.match(_aline)
                    m2 = _regex_exclude2.match(_aline)
                    m3 = _regex_exclude3.match(_aline)
                    m4 = _regex_exclude4.match(_aline)
                    if not m1 and not m2 and not m3 and not m4:

                        # opt_xxxに未定義のパラメータはuniパラメータとする
                        regex = "[ \t]*(?P<comment>#*)[ \t]*(?P<key>[A-Z][^ \t]+)[ \t]+(?P<value>.+)"
                        _regex = re.compile(r"%s" % regex)
                        m = _regex.match(_aline)
                        if m:
                            _comment = m.group('comment')
                            _key = m.group('key').strip()
                            _value = m.group('value').strip()
                            if _value.find(self._comment) > 0:
                                post_comment = _value[_value.find(self._comment
                                                                  ):]
                            _value = re.sub("%s$" % post_comment, "",
                                            _value).rstrip()
                            values = self.build_value(_value, pre_comment,
                                                      post_comment)
                            dop.set("__", [_key], values)
                            if _comment != "":
                                dop.comment("__", [_key])
                            if level == 0:
                                self.orders.append([_key])
                            pre_comment = []
                            post_comment = None
                            match = True

                if match is False:

                    if _aline.lstrip()[0:1] == self._comment:
                        footer_regex = re.compile(self._footer)
                        m = footer_regex.search(_aline)
                        if not m:
                            comment = _aline[_aline.find(self._comment):]
                            pre_comment.append(comment)
                            continue

        if len(pre_comment) > 0:
            eof_key = "%sEOF" % (self._reserved_key_prefix, )
            new_value = self.build_value("", pre_comment, post_comment)
            dop.set("__", [eof_key], new_value)

        return dop.getconf("__")

    def _value_to_lines(self, conf_arr, level=0):
        lines = []
        orders_key = "%sORDERS" % (self._reserved_key_prefix, )

        dop = DictOp()
        dop.addconf("__", conf_arr)

        for _k, _v in dop.getconf("__").iteritems():

            action = dop.action("__", [_k])
            if action == "delete":
                continue

            iscomment = dop.iscomment("__", [_k])

            value = dop.get("__", [_k])

            if type(value) == list:

                _val = value[0]

                if type(_val) != dict:
                    _pre_comment = value[1][0]
                    _post_comment = value[1][1]

                    pre_comment = []
                    try:
                        for _aline in _pre_comment:
                            if _aline.strip() == "":
                                pass
                            elif _aline[0:1] != self._comment:
                                _prefix = ""
                                if level > 0:
                                    _prefix += str_repeat(self._indent, level)
                                _prefix += self._comment
                                _aline = "%s %s" % (
                                    _prefix,
                                    _aline,
                                )
                            pre_comment.append(_aline)
                    except:
                        pass

                    if len(pre_comment) > 0:
                        #preprint_r(pre_comment)
                        lines = lines + pre_comment

                    post_comment = _post_comment
                    try:
                        if post_comment is not None and post_comment[
                                0:1] != self._comment:
                            post_comment = "%s %s" % (
                                self._comment,
                                post_comment,
                            )
                    except:
                        pass
                else:
                    pass

            else:
                _val = value

            _prefix = ""
            if iscomment is True:
                _prefix += self._comment
            if level > 0:
                _prefix += str_repeat(self._indent, level)

            if type(_val) == dict:

                # ORDER順に設定する
                orders = []
                try:
                    old_orders = _val[orders_key]['value']
                except:
                    old_orders = []

                for kk in old_orders:
                    if type(kk) is list:
                        orders.append(kk[0])
                    elif type(kk) is str:
                        orders.append(kk)

                for kk in _val.keys():
                    if not kk in orders:
                        orders.append(kk)

                #for _k2,_v2 in _val.iteritems():
                for _k2 in orders:

                    if _k2 == orders_key:
                        continue
                    _v2 = _val[_k2]

                    sub_value = {}
                    sub_value[_k2] = _v2

                    try:
                        iscomment = sub_value[_k2]['comment']
                    except:
                        iscomment = False

                    try:
                        action = sub_value[_k2]['action']
                    except:
                        action = ""

                    if action == "delete":
                        continue

                    #try:
                    #    sub_value[_k2]['value'][1][0]
                    #    lines = lines + sub_value[_k2]['value'][1][0]
                    #except:
                    #    pass

                    is_sect = False
                    if _k in self.opt_multi and _k2 == _v2["value"][0]:
                        for _k3, _v3 in sub_value.iteritems():
                            try:
                                iscomment3 = sub_value[_k3]['comment']
                            except:
                                iscomment3 = iscomment
                            try:
                                action3 = sub_value[_k3]['action']
                            except:
                                action3 = ""

                            _prefix = ""
                            if iscomment is True:
                                _prefix += self._comment
                            if level > 0:
                                _prefix += str_repeat(self._indent, level)
                            lines.append("%s%-18s%s%s" %
                                         (_prefix, _k, self._new_delim, _k2))

                    elif _k in self.opt_sect:
                        is_sect = True
                        _prefix = ""
                        if iscomment is True:
                            _prefix += self._comment
                        if level > 0:
                            _prefix += str_repeat(self._indent, level)
                        if _k2 == "":
                            lines.append("%s<%s>" % (_prefix, _k))
                        else:
                            lines.append("%s<%s \"%s\">" % (_prefix, _k, _k2))

                    new_level = level + 1
                    new_lines = self._value_to_lines(sub_value,
                                                     level=new_level)

                    for _aline in new_lines:
                        _prefix2 = ""
                        if iscomment is True:
                            _prefix2 += self._comment
                        new_aline = "%s%s" % (
                            _prefix2,
                            _aline,
                        )
                        new_aline = re.sub("^%s+" % self._comment,
                                           self._comment, new_aline)
                        lines.append(new_aline)
                    #lines = lines + new_lines

                    if is_sect is True:
                        lines.append("%s</%s>" % (
                            _prefix,
                            _k,
                        ))

            else:

                aline = ""
                if _k in self.opt_multi:
                    aline += "%s%-18s%s%s" % (
                        _prefix,
                        _k,
                        self._new_delim,
                        _val,
                    )
                else:
                    if re.match("^[A-Z]+[a-z]", _k):
                        aline += "%s%-18s%s%s" % (
                            _prefix,
                            _k,
                            self._new_delim,
                            _val,
                        )

                if post_comment is not None:
                    aline = "%s %s" % (
                        aline,
                        post_comment,
                    )

                if aline != "":
                    lines.append(aline)

        return lines

    def write_conf(self, conf_arr={}, dryrun=False):
        retval = True

        self.dop.addconf(self._module, conf_arr)
        orders_key = "%sORDERS" % (self._reserved_key_prefix, )
        eof_key = "%sEOF" % (self._reserved_key_prefix, )

        for _path, _v in conf_arr.iteritems():

            if _path[0:1] != "/":
                continue

            lines = []
            try:
                _v['value']
            except:
                continue

            exclude_regex = "^%s[A-Z0-9\_]+$" % self._reserved_key_prefix

            # まずはオーダの順
            if self.dop.isset(self._module, [_path, orders_key]) is True:
                for _k2 in self.dop.get(self._module, [_path, orders_key]):
                    try:
                        if type(_k2) == str:
                            _k2 = [_k2]
                        _search_key = [_path] + _k2

                        is_opt_multi = False
                        if _k2[0] in self.opt_multi:
                            _tmp_conf = self.dop.get(self._module, _search_key)
                            # multiとsectがかぶったオプションの対応 strならmulti
                            if type(_tmp_conf[0]) == str:
                                is_opt_multi = True

                        if is_opt_multi is True:
                            _k2.pop()

                        new_lines = self._new_lines(_search_key, _k2)
                        lines = lines + new_lines
                        self.dop.unset(self._module, _search_key)
                    except:
                        pass

            # オーダにないものは最後に追加
            for _k2, _v2 in self.dop.get(self._module, [_path]).iteritems():

                #if _k2 != orders_key:
                m = re.match(exclude_regex, _k2)
                if not m:
                    try:
                        if type(_k2) == str:
                            _k2 = [_k2]
                        _search_key = [_path] + _k2

                        if _k2[0] in self.opt_multi:
                            for _k3, _v3 in self.dop.get(
                                    self._module, _search_key).iteritems():
                                _search_key.append(_k3)
                                new_lines = self._new_lines(_search_key, _k2)
                                lines = lines + new_lines
                        else:
                            new_lines = self._new_lines(_search_key, _k2)
                            lines = lines + new_lines

                    except:
                        pass

            # 最後のコメント用の処理
            if self._footer != "":
                if self.dop.isset(self._module, [_path, eof_key]) is False:
                    self.dop.cdp_set(self._module, [_path, eof_key],
                                     "",
                                     force=True)

                eof_val = self.dop.get(self._module, [_path, eof_key])
                eof_action = self.dop.action(self._module, [_path, eof_key])
                eof_comment = self.dop.comment(self._module, [_path, eof_key])
                try:
                    key = " %s - %s on %s" % (self._footer, self._module,
                                              time.strftime(
                                                  "%c", time.localtime()))
                    value = {}
                    value[key] = {}
                    value[key]["value"] = eof_val
                    value[key]["action"] = eof_action
                    value[key]["comment"] = eof_comment
                    self.set_new_delim(delim=" ")
                    lines = lines + self._value_to_lines(value)
                except:
                    pass

            if dryrun is False:
                if len(lines) > 0:
                    ConfigFile(_path).write("\n".join(lines) + "\n")
            else:
                print "%s -- filename: %s" % (
                    self._comment,
                    _path,
                )
                print "\n".join(lines)

        return retval

    def _new_lines(self, search_key, new_key):

        try:
            attrs = self.dop.get(self._module, search_key, with_attr=True)
            action = attrs['action']
            iscomment = attrs['comment']
            val = attrs['value']
        except:
            action = self.dop.action(self._module, search_key)
            iscomment = self.dop.iscomment(self._module, search_key)
            val = self.dop.get(self._module, search_key)
            pass

        #print val
        dop = DictOp()
        dop.addconf('__', {})
        if action == "delete":
            dop.add('__', new_key, val)
            dop.delete('__', new_key)
        elif action == "set":
            dop.set('__', new_key, val)
        else:
            dop.add('__', new_key, val)
        if iscomment is True:
            dop.comment('__', new_key)

        #preprint_r(dop.getconf('__'))
        new_lines = self._value_to_lines(dop.getconf('__'))
        #print "\n".join(new_lines)

        return new_lines
Exemple #5
0
    def _value_to_lines(self, conf_arr, level=0):
        lines = []
        orders_key = "%sORDERS" % (self._reserved_key_prefix, )

        dop = DictOp()
        dop.addconf("__", conf_arr)

        for _k, _v in dop.getconf("__").iteritems():

            action = dop.action("__", [_k])
            if action == "delete":
                continue

            iscomment = dop.iscomment("__", [_k])

            value = dop.get("__", [_k])

            if type(value) == list:

                _val = value[0]

                if type(_val) != dict:
                    _pre_comment = value[1][0]
                    _post_comment = value[1][1]

                    pre_comment = []
                    try:
                        for _aline in _pre_comment:
                            if _aline.strip() == "":
                                pass
                            elif _aline[0:1] != self._comment:
                                _prefix = ""
                                if level > 0:
                                    _prefix += str_repeat(self._indent, level)
                                _prefix += self._comment
                                _aline = "%s %s" % (
                                    _prefix,
                                    _aline,
                                )
                            pre_comment.append(_aline)
                    except:
                        pass

                    if len(pre_comment) > 0:
                        #preprint_r(pre_comment)
                        lines = lines + pre_comment

                    post_comment = _post_comment
                    try:
                        if post_comment is not None and post_comment[
                                0:1] != self._comment:
                            post_comment = "%s %s" % (
                                self._comment,
                                post_comment,
                            )
                    except:
                        pass
                else:
                    pass

            else:
                _val = value

            _prefix = ""
            if iscomment is True:
                _prefix += self._comment
            if level > 0:
                _prefix += str_repeat(self._indent, level)

            if type(_val) == dict:

                # ORDER順に設定する
                orders = []
                try:
                    old_orders = _val[orders_key]['value']
                except:
                    old_orders = []

                for kk in old_orders:
                    if type(kk) is list:
                        orders.append(kk[0])
                    elif type(kk) is str:
                        orders.append(kk)

                for kk in _val.keys():
                    if not kk in orders:
                        orders.append(kk)

                #for _k2,_v2 in _val.iteritems():
                for _k2 in orders:

                    if _k2 == orders_key:
                        continue
                    _v2 = _val[_k2]

                    sub_value = {}
                    sub_value[_k2] = _v2

                    try:
                        iscomment = sub_value[_k2]['comment']
                    except:
                        iscomment = False

                    try:
                        action = sub_value[_k2]['action']
                    except:
                        action = ""

                    if action == "delete":
                        continue

                    #try:
                    #    sub_value[_k2]['value'][1][0]
                    #    lines = lines + sub_value[_k2]['value'][1][0]
                    #except:
                    #    pass

                    is_sect = False
                    if _k in self.opt_multi and _k2 == _v2["value"][0]:
                        for _k3, _v3 in sub_value.iteritems():
                            try:
                                iscomment3 = sub_value[_k3]['comment']
                            except:
                                iscomment3 = iscomment
                            try:
                                action3 = sub_value[_k3]['action']
                            except:
                                action3 = ""

                            _prefix = ""
                            if iscomment is True:
                                _prefix += self._comment
                            if level > 0:
                                _prefix += str_repeat(self._indent, level)
                            lines.append("%s%-18s%s%s" %
                                         (_prefix, _k, self._new_delim, _k2))

                    elif _k in self.opt_sect:
                        is_sect = True
                        _prefix = ""
                        if iscomment is True:
                            _prefix += self._comment
                        if level > 0:
                            _prefix += str_repeat(self._indent, level)
                        if _k2 == "":
                            lines.append("%s<%s>" % (_prefix, _k))
                        else:
                            lines.append("%s<%s \"%s\">" % (_prefix, _k, _k2))

                    new_level = level + 1
                    new_lines = self._value_to_lines(sub_value,
                                                     level=new_level)

                    for _aline in new_lines:
                        _prefix2 = ""
                        if iscomment is True:
                            _prefix2 += self._comment
                        new_aline = "%s%s" % (
                            _prefix2,
                            _aline,
                        )
                        new_aline = re.sub("^%s+" % self._comment,
                                           self._comment, new_aline)
                        lines.append(new_aline)
                    #lines = lines + new_lines

                    if is_sect is True:
                        lines.append("%s</%s>" % (
                            _prefix,
                            _k,
                        ))

            else:

                aline = ""
                if _k in self.opt_multi:
                    aline += "%s%-18s%s%s" % (
                        _prefix,
                        _k,
                        self._new_delim,
                        _val,
                    )
                else:
                    if re.match("^[A-Z]+[a-z]", _k):
                        aline += "%s%-18s%s%s" % (
                            _prefix,
                            _k,
                            self._new_delim,
                            _val,
                        )

                if post_comment is not None:
                    aline = "%s %s" % (
                        aline,
                        post_comment,
                    )

                if aline != "":
                    lines.append(aline)

        return lines
Exemple #6
0
class commentDealParser:

    _delim = "[ \t]+"
    _new_delim = " "
    _comment = "#"
    _reserved_key_prefix = "@"

    _module = "comment_deal_parser"
    _footer = "-- Generated by karesansui"

    def __init__(self, paths=[]):
        self.dop = DictOp()
        self.dop.addconf(self._module, {})
        self.set_source_file(paths)

    def set_delim(self, delim=" "):
        self._delim = delim

    def set_new_delim(self, delim=" "):
        self._new_delim = delim

    def set_comment(self, comment="#"):
        self._comment = comment

    def set_reserved_key_prefix(self, prefix="@"):
        self._reserved_key_prefix = prefix

    def set_footer(self, footer=""):
        self._footer = footer

    def set_source_file(self, paths=[]):
        if type(paths) == str:
            paths = [paths]
        self.paths = paths
        return True

    def get_source_file(self):
        return self.paths

    def source_file(self):
        return self.get_source_file()

    def build_value(self, string, precomment=[], postcomment=None):
        if type(precomment) == str:
            precomment = [precomment]
        return [
            string,
            [precomment, postcomment],
        ]

    def read_conf(self):
        retval = {}

        for _afile in self.source_file():
            res = ConfigFile(_afile).read()

            orders = []
            comment_1 = []  # 設定の前のコメント リスト配列
            comment_2 = None  # 設定行のコメント 文字列
            for _aline in res:
                _aline = _aline.rstrip('\r\n')

                if _aline.strip() == "":
                    comment_1.append(_aline)
                    continue

                if _aline.lstrip()[0:1] == self._comment:
                    footer_regex = re.compile(self._footer)
                    m = footer_regex.search(_aline)
                    if not m:
                        comment = _aline[_aline.rfind(self._comment):]
                        comment_1.append(comment)
                        continue

                regex_str = "^(?P<key>[^ \t]+)%s(?P<value>.*)$" % (
                    self._delim, )
                regex = re.compile(r"%s" % regex_str)

                m = regex.match(_aline)
                if m:
                    key = m.group('key')
                    value = m.group('value')
                    if not value.rfind(self._comment) == -1:
                        comment_2 = value[value.rfind(self._comment):]
                        value = value[:value.rfind(self._comment)]

                    new_value = self.build_value(value, comment_1, comment_2)
                    if new_value is not False:
                        self.dop.set(self._module, [_afile, key], new_value)
                        orders.append(key)
                    comment_1 = []
                    comment_2 = None

            if len(comment_1) > 0:
                eof_key = "%sEOF" % (self._reserved_key_prefix, )
                new_value = self.build_value("", comment_1, comment_2)
                self.dop.set(self._module, [_afile, eof_key], new_value)

            orders_key = "%sORDERS" % (self._reserved_key_prefix, )
            self.dop.set(self._module, [_afile, orders_key], orders)

        #self.dop.preprint_r(self._module)
        return self.dop.getconf(self._module)

    def _value_to_lines(self, value):
        lines = []

        for _k, _v in value.iteritems():

            try:
                if _v['action'] == "delete":
                    continue
            except:
                pass

            iscomment = False
            try:
                iscomment = _v['comment']
            except:
                pass

            _prefix = ""
            if iscomment is True:
                _prefix += self._comment

            try:
                val = _v['value'][0]

                comment_1 = []
                try:
                    for com1_aline in _v['value'][1][0]:
                        if com1_aline.strip() == "":
                            pass
                        elif com1_aline[0:1] != self._comment:
                            com1_aline = "%s %s" % (
                                self._comment,
                                com1_aline,
                            )
                        comment_1.append(com1_aline)
                except:
                    pass

                comment_2 = _v['value'][1][1]
                try:
                    if comment_2[0:1] != self._comment:
                        comment_2 = "%s %s" % (
                            self._comment,
                            comment_2,
                        )
                except:
                    pass

                lines = lines + comment_1
                aline = "%s%s%s%s" % (
                    _prefix,
                    _k,
                    self._new_delim,
                    val,
                )
                if comment_2 is not None:
                    aline = "%s %s" % (
                        aline,
                        comment_2,
                    )
                lines.append(aline)
            except:
                pass

        return lines

    def write_conf(self, conf_arr={}, dryrun=False):
        retval = True

        self.dop.addconf(self._module, conf_arr)
        orders_key = "%sORDERS" % (self._reserved_key_prefix, )
        eof_key = "%sEOF" % (self._reserved_key_prefix, )

        for _path, _v in conf_arr.iteritems():

            if _path[0:1] != "/":
                continue

            lines = []
            try:
                _v['value']
            except:
                continue

            exclude_regex = "^%s[A-Z0-9\_]+$" % self._reserved_key_prefix

            # まずはオーダの順
            if self.dop.isset(self._module, [_path, orders_key]) is True:
                for _k2 in self.dop.get(self._module, [_path, orders_key]):
                    m = re.match(exclude_regex, _k2)
                    if not m:
                        try:
                            if type(_k2) == list:
                                _k2 = _k2.pop()
                            value = {}
                            value[_k2] = _v['value'][_k2]
                            lines = lines + self._value_to_lines(value)
                            self.dop.unset(self._module, [_path, _k2])
                        except:
                            pass

            # オーダにないものは最後に追加
            for _k2, _v2 in self.dop.get(self._module, [_path]).iteritems():
                #if _k2 != orders_key and _k2 != eof_key:
                m = re.match(exclude_regex, _k2)
                if not m:
                    try:
                        value = {}
                        value[_k2] = _v2
                        lines = lines + self._value_to_lines(value)
                    except:
                        pass

            # 最後のコメント用の処理
            if self._footer != "":
                if self.dop.isset(self._module, [_path, eof_key]) is False:
                    self.dop.cdp_set(self._module, [_path, eof_key],
                                     "",
                                     force=True)

                eof_val = self.dop.get(self._module, [_path, eof_key])
                eof_action = self.dop.action(self._module, [_path, eof_key])
                eof_comment = self.dop.comment(self._module, [_path, eof_key])
                try:
                    key = " %s - %s on %s" % (self._footer, self._module,
                                              time.strftime(
                                                  "%c", time.localtime()))
                    value = {}
                    value[key] = {}
                    value[key]["value"] = eof_val
                    value[key]["action"] = eof_action
                    value[key]["comment"] = eof_comment
                    self.set_new_delim(delim=" ")
                    lines = lines + self._value_to_lines(value)
                except:
                    pass

            if dryrun is False:
                if len(lines) > 0:
                    ConfigFile(_path).write("\n".join(lines) + "\n")
            else:
                #pass
                print "\n".join(lines)

        return retval