/*
** SellaNMS
** $Id: format_statement_from_group.cxx,v 1.7 2005/11/25 02:57:47 sella Exp $
** Copyright (c) 2001-2005 Digital Genesis Software, LLC. All Rights Reserved.
** Released under the GPL Version 2 License.
** http://www.digitalgenesis.com
*/

static const char rcsid[] = "$Id: format_statement_from_group.cxx,v 1.7 2005/11/25 02:57:47 sella Exp $";

#include "format_statement_from_group.h"
#include <stdio.h>
#include <stl/string>
#include <stl/vector>

ACTION FormatStatementFromGroup::evaluate(variable_binding_t &input) {
	ACTION result = FormatStatementFromVariable::evaluate(input);

	return result;
}

/*
	Compile this group.
	
	Parameters
		config:		the part of the configuration from the level "policy-options policy-statement <policy> term <term> from <group>".

	Return Values
		SUCCESS:	if the group was successfully compiled.
		FAILURE:	if the group was unable to be compiled.
*/
RESULT FormatStatementFromGroup::compile(ConfigNode *config) {
	RESULT result = FormatStatementFromVariable::compile(config);

	ConfigNode							variable_config;
	ConfigNode							group_config;

	string								function;
	vector<string>						values;

	FormatStatementFromGroup		group;
	FormatStatementFromVariable	variable;

	if (config->assignValues("group", values)) {
		for (vector<string>::iterator g = values.begin(); g != values.end(); ++g) {
			if (config->assignNode("group " + *g, group_config)) {
				group.clear();
				group.setName(*g);

				if (group.compileInherited(&group_config, this->required, this->type, this->function, this->mapStatements) == SUCCESS) {
					this->groups.insert(this->groups.end(), group);
				} else {
					result = FAILURE;
				}
			} else {
				result = FAILURE;
			}
		}
	}

	if (config->assignValues("variable", values)) {
		for (vector<string>::iterator v = values.begin(); v != values.end(); ++v) {
			if (config->assignNode("variable " + *v, variable_config)) {
				variable.clear();
				variable.setName(*v);

				if (variable.compileInherited(&variable_config, this->required, this->type, this->function, this->mapStatements) == SUCCESS) {
					this->variables[*v] = variable;
				} else {
					result = FAILURE;
				}
			} else {
				result = FAILURE;
			}
		}	
	}

	return result;
}

/*
	Add a new group to this group. 

	Parameters
		group:	the group to add.
	
	Return Values
		SUCCESS:	if the new group was successfully added.
		FAILURE:	if the new group was unable to be added.
*/
RESULT FormatStatementFromGroup::addGroup(FormatStatementFromGroup &group) {
	this->groups.insert(this->groups.end(), group);
	
	return SUCCESS;
}

/*
	Add a new variable to this group. 

	Parameters
		variable:	the variable to add.
	
	Return Values
		SUCCESS:	if the new variable was successfully added.
		FAILURE:	if the new variable was unable to be added.
*/
RESULT FormatStatementFromGroup::addVariable(FormatStatementFromVariable &variable) {
	this->variables[variable.getName()] = variable;
	
	return SUCCESS;
}

RESULT FormatStatementFromGroup::setVariableType(unsigned long &type, string &variable) {
	RESULT result = FAILURE;

	for (slist<FormatStatementFromGroup>::iterator g = this->groups.begin(); g != this->groups.end(); ++g) {
		if (g->setVariableType(type, variable) == SUCCESS) {
			result = SUCCESS;
		}
	}
	if (this->variables.find(variable) != this->variables.end()) {
		result = (this->variables[variable]).setVariableType(type, variable);
	}
	return result;
}

RESULT FormatStatementFromGroup::setVariableFunction(unsigned long &function, string &variable) {
	RESULT result = FAILURE;

	for (slist<FormatStatementFromGroup>::iterator g = this->groups.begin(); g != this->groups.end(); ++g) {
		if (g->setVariableFunction(function, variable) == SUCCESS) {
			result = SUCCESS;
		}
	}
	if (this->variables.find(variable) != this->variables.end()) {
		result = (this->variables[variable]).setVariableFunction(function, variable);
	}
	return result;
}

RESULT FormatStatementFromGroup::setVariableMap(slist<string> &mapStatements, string &variable) {
	RESULT result = FAILURE;

	for (slist<FormatStatementFromGroup>::iterator g = this->groups.begin(); g != this->groups.end(); ++g) {
		if (g->setVariableMap(mapStatements, variable) == SUCCESS) {
			result = SUCCESS;
		}
	}
	if (this->variables.find(variable) != this->variables.end()) {
		result = (this->variables[variable]).setVariableMap(mapStatements, variable);
	}
	return result;
}

/*
	Print the information about this group. 
	
	Return Values
		SUCCESS:	if the group was successfully printed.
		FAILURE:	if the group was unable to be printed.
*/
RESULT FormatStatementFromGroup::print(unsigned long depth) {
	string	tab = "", str;
	for (unsigned long i = 0; i < depth; i++) {
		tab.append("   ");
	}

	LMSG("%sgroup %s {", tab.c_str(), this->name.c_str());
	LMSG("%s   required     %s;", tab.c_str(), this->required ? "yes" : "no");
	LMSG("%s   type         0x%x;", tab.c_str(), this->type);
	LMSG("%s   function     0x%x;", tab.c_str(), this->function);
	LMSG("");

	if (!this->values.empty()) {
		str.erase();
		for (hash_map<string, bool>::iterator value = this->values.begin(); value != this->values.end(); ++value) {
			str.append(" " + value->first);
		}
		LMSG("%s   valid-values [%s ];", tab.c_str(), str.c_str());
		LMSG("");
	}
	if (!this->mapStatements.empty()) {
		str.erase();
		for (slist<string>::iterator mapStatement = this->mapStatements.begin(); mapStatement != this->mapStatements.end(); ++mapStatement) {
			str.append(" " + *mapStatement);
		}
		LMSG("%s   apply-map [%s ];", tab.c_str(), str.c_str());
		LMSG("");
	}
	for (slist<FormatStatementFromGroup>::iterator group = this->groups.begin(); group != this->groups.end(); ++group) {
		group->print(depth + 1);
	}
	for (hash_map<string, FormatStatementFromVariable>::iterator variable = this->variables.begin(); variable != this->variables.end(); ++variable) {
		variable->second.print(depth + 1);
	}
	for (hash_map<string, Suffix>::iterator suffix = this->suffixes.begin(); suffix != this->suffixes.end(); ++suffix) {
		suffix->second.print(depth + 1);
	}
	for (hash_map<string, Dependency>::iterator dep = this->dependencies.begin(); dep != this->dependencies.end(); ++dep) {
		dep->second.print(depth + 1);
	}
	LMSG("%s}", tab.c_str());

	return SUCCESS;
}

/*
	Clear the information about this group.
	
	Return Values
		SUCCESS:	if the group was successfully cleared.
		FAILURE:	if the group was unable to be cleared.
*/
RESULT FormatStatementFromGroup::clear() {
	this->required = false;
	this->type = 0;
	this->function = 0;
	this->name = "unknown";
	this->values.clear();
	this->mapStatements.clear();
	this->dependencies.clear();
	this->suffixes.clear();
	this->variables.clear();
	this->groups.clear();

	return SUCCESS;
}

/*
** Local Variables:
** c-basic-offset: 3
** tab-width: 3
** End:
** vim600: fdm=marker
** vim: noet ts=3 sw=3 sts=3
*/
