
class apacheParser {
    inherit genericParser
    
    #Need to know which modules are enabled
    
    public variable moduleManager

    # Include root. Apache uses serverroot by default

    public variable includeroot

    constructor { dirDef confDoc  } {
	genericParser::constructor $dirDef $confDoc
    } {
    }
    method parseLine { data }
    method beginSection {value class}
    method endSection {}
    method processDirective { text }
    method loadValue {xuiObj text}
    method isSpecialCase  
    method processSpecialCase
}


body apacheParser::parseLine { data } {
    set data [string trim $data]
    if {[regexp "^ *#+" $data] || [regexp "^ *$" $data]} {
	return
    }
    if [regexp "^ *</+.*>+$" $data] {
	endSection
	return
    }
    if [regexp "^ *<+(.*)>+$" $data dummy tag] {
	if [regexp {<([^ ]*) (.*)>}  $data  dummy class value] {
	    beginSection \
		    $value [string tolower $class]
	} else {
	    # Empty sections
	    beginSection \
		    {} [string tolower $tag]
	}
    } else {
	processDirective $data
    }                                     
}

body apacheParser::beginSection { value class } {
    $stack push $currentContainer
    set currentContainer  \
	    [$xmlConf addContainer $currentContainer $value $class]
}

body apacheParser::endSection {} {
    set currentContainer [$stack pop]
}


body apacheParser::processDirective { text } {
    set elements [::apacheparserutils::getElements $text ]
    set dirName [string tolower [lindex $elements 0]]

    # Vary includeroot depending on the serverroot directive

    if [string match serverroot $dirName] {

	# join is necessary to handle spaces on Windows

	set includeroot [join [lindex $elements 1]]
    }

    # include directives

    if [string match include $dirName] {

	# Need to handle full and relative paths

	set includeFile [join [lindex $elements 1]]
	switch [file pathtype $includeFile] {
	    absolute {
		
		# Do nothing, we can open it

		$this parseFile $includeFile

	    } relative { 
		
		# Ok, we need to prepend the conf directives dir
		
		set includeFile [file join $includeroot $includeFile]
		if ![file exists $includeFile] {
		    puts "Include file $includeFile could not be processed. \
			    Check that it exists"
		} else {
		   $this parseFile $includeFile
		}

	    } volumerelative {

		# Um, unsure about what volume relative is.

		puts "Include path was volume relative"

	    }
	}
	
    }
    

    # If module is not enabled, directive is treated as unknown
    # (we can this way disable modules that could mistreat info)

    if ![$moduleManager isDirectiveEnabled $dirName] { 
	set xuiUnknown [ xuiString ::#auto ]
	$xuiUnknown setName $dirName
	$xuiUnknown setValue $text
	$xuiUnknown addClass unknownDirective
	$xmlConf addDirective $xuiUnknown $currentContainer
	return
    }

    if [ isSpecialCase $dirName ] {
	processSpecialCase $dirName $text
	return
    }
    
    # If error here is that the directive is unknown to us

    if ![catch {set xuiObj [apacheparserutils::getOrCreateIfNotExists \
	    $dirName $dirDefinition $xmlConf $currentContainer]} kk] {
	switch [$xuiObj getXuiClass] {
	    string - choice - boolean - number {
		::apacheparserutils::loadValue $xuiObj [lindex $elements 1]
		return
	    } structure {
		error "Structure cannot be done (order issues) for [$xuiObj getName], $xuiObj"
	    }
	}
    } else {
	set xuiUnknown [ xuiString ::#auto ]
	$xuiUnknown setName $dirName
	$xuiUnknown setValue $text
	$xuiUnknown addClass unknownDirective
	$xmlConf addDirective $xuiUnknown $currentContainer
	return
    }
}


body apacheParser::loadValue { dirObject value } {
    switch [$dirObject getXuiClass] {
	string - number {
	    $dirObject setValue [string trim $value]
	} choice {
	    
	    $dirObject selectItem [string trim $value]
	} boolean {
	    switch [string tolower [string trim $value]] {
		on - yes - true - 1{
		    $dirObject setValue
		}    off - false - no - 0{
		    $dirObject clearValue
		}    default {
		    error "Boolean with value different from on/off"
		}   
	    }
	}
    }
}


body apacheParser::isSpecialCase { dirName } {
    return [info exists specialCaseMapping($dirName)]
}

body apacheParser::processSpecialCase \
	{dirName elements} {
    $specialCaseMapping($dirName) $elements $this\
	    $dirDefinition $xmlConf $currentContainer 
    
}
