/**
 * File: contextxmlparser.h
 * Created by: <Joern Reimerdes>
 * Created on: 2004/08/31 13:48:00
 * @file
 * $Id$
 * $Revision$
 * $Author$
 * $Date$
 *
 * This file is a part of The iWear Framework.
 * In particular is this file a part of the Framework context Library
 *
 * The iWear Framework is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by the
 * Free Software Foundation as in version 2 of the License.

 * 
 * The iWear Framework is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * The iWear Framework; if not, write to the Free Software Foundation, Inc., 59
 * Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef __CONTEXTXMLPARSER_H_
#define __CONTEXTXMLPARSER_H_

#include <string>
#include <iwear-context/compositecontext.h>
#include <iwear-context/logiccontextterm.h>
#include <iwear-context/logiccompositecontext.h>
#include <iwear-context/contextenums.h>
#include <iwear-context/contextmanager.h>
#include <iwear-context/contextxmlhandler.h>
#include <iwear-context/contextxmlfactoryatomic.h>
#include <iwear_utils_xml/xmlhandler.h>

using namespace std;
using namespace iwear::xml;
using namespace iwear::context;

namespace iwear{ 
namespace context{


/** The ContextXMLParser is used to create ContextObject from an
 * XML File that defines SensorContexts or LogicCompositeContexts.
 * @note The parser can not load files simultaneously so either
 * use different parsers or load the context files one after
 * another (recommended).
 */
class ContextXMLParser
{
public:

    /** Creates a new instance of ContextXMLParser.
     *
     * @param context_manager the ContextManager where we register our
     * contexts.
     */
    ContextXMLParser(ContextManager* context_manager);

    /** Distroys the instance of ContextXMLParser.
     *
     */
    ~ContextXMLParser();
    
    /** 
     * Creates a list of ContextObjects from an xml file.
     * warum wird das nirgends angezeigt ???
     * @param string uri The URI of the xml file containing the
     *  context information.
     * @return list<ContextObject*>* A list of ContextObject pointer.
     */
    list<ContextObject*>* load_contexts_from_file(string uri);

    /** Gets the context manager.
     * @return The context manager the ContextXMLParser works with.
     */
    inline ContextManager* get_context_manager(){
	return this->context_manager;
    }
    
    /** Gets the XML handler.
     * @return The XML handler the ContextXMLParser works with.
     */
    inline XMLHandler* get_xml_handler(){
	return this->xml_handler;
    }


protected:

    /** Map for ContextType XML names to enum values. */
    map<const string, ContextType>* context_type_enum_map;

    /** Map for CompositeContext Type XML names to enum values. */
    map<const string, CompositeType>* composite_type_enum_map;

    /** Map for ContextValueTypes XML to enum values. */
    map<const string, ContextValueType>* value_type_enum_map;

    /** Map ContextValueTypes enum values to XML names. */
    map<ContextValueType, const XMLCh* >* value_type_map;

    /** Map for LogicRelation XML names to enum values. */
    map<const string, LogicRelation>* logic_relation_enum_map;

    /** Map for LogicRelation enum values to XML names. */
    map<LogicRelation, const XMLCh*>* logic_relation_map;

private:

    /** Creates a new ContextObject from a context node.
     * @note The created contexts are registered to the context
     *  manager within this method. This is needed for recursive
     *  context definitions within the xml file.
     * @param DOMElement* context_node The context node witch contains
     *  the definition of the new composite context.
     * @return ContextObject* The ContextObject created form the node.
     *  NULL if the context was already defined.
     * @throws consistency_error If there was unexpected data within
     *  the DOMElement.
     */
    ContextObject* create_composite_context(DOMElement* context_node);

    /** Creates a LogicContextTerm from a logic_node.
     * @param DOMElement* logic_node The DOM representation of the
     *  logic node. 
     * @param LogicCompositionContext* upper_logic_composite The
     *  LogicCompositionContext that is the parent of the
     *  LogicContextTerm. This might be more than one level above the
     *  logic relation but is necessary because all ContextObjects
     *  in the tree, below the LogicCompositionContext, must be added
     *  as children of it.
     * @return LogicContextTerm* Returns the object that contains the
     *  LogicContextTerm.
     */
    LogicContextTerm* create_logic_context_term(DOMElement* logic_node,
			LogicCompositeContext* upper_logic_composite);

    /** Returns the value of the logic relation attribute of a DOMElement.
     * @param DOMElement* logic_node The node the logic relation value
     *  should be retreaved from.
     * @return const string The type value
     */
    inline const string get_logic_relation_from_node(DOMElement* logic_node){
	const char * str = XMLString::transcode(logic_node->
				    getAttribute(ATTRIBUTE_LOGIC_RELATION));
	string z = str;
	delete[] str;
	return z;
    }

    /** Get a list of all context nodes of the DOMDocument read by the
     * 	parser.
     * @param DOMDocument* document The document element of the
     *  context definition file.
     * @return list<DOMElement*>* the list of context nodes.
     */
    list<DOMElement*>* get_context_element_list(DOMDocument* document); 


    /** Returns the value of the type attribute of a DOMElement.
     * @param DOMElement* node The node the type value should be
     *  retreaved from.
     * @return const string The type value
     */
    inline const string get_type_from_node(DOMElement* node){
	const char * str = XMLString::transcode(node->getAttribute(ATTRIBUTE_TYPE));
	string z = str;
	delete[] str;
	return z;
    }

//     /** Gets the nodes from all names within a map blow a parent node. 
//      *
//      */
//     template<class T> list<DOMElement*>* 
//     get_elements(map< T , const XMLCh* >* node_map, DOMElement* node);

    /** Initialises the node name and attribute name constants if they
     * were net initialised before.
     */
    void init_constants(void);

    /** The contextmanager to wich the parsed contexts should be
     * registered to.
     */
    ContextManager* context_manager;
    
    /** The XMLHandler is used for dealing with xml files and DOM
     * trees in general. It has some helper methods to support the
     * traversing of the tree.
     * @note The instance will be deleted within the destructer of the
     *  ContextXMLParser.
     */
    XMLHandler* xml_handler;	

    /** The ContextXMLHandler is used for dealing with xml files and DOM
     * trees. It has some helper methods to support the traversing of
     * the tree.
     * @note The instance will be deleted within the destructer of the
     *  ContextXMLParser.
     */
    ContextXMLHandler* context_xml_handler;	

    /** The ContextXMLFactoryAtomic is used to create AtomicContexts.
     */
    ContextXMLFactoryAtomic* context_xml_factory_atomic;

    /** The context nodes of the DOMTree.
     */
    list<DOMElement*>* context_nodes;

}; // ContextXMLParser

// /** Gets the nodes from all names within a map blow a parent node. 
//  * @todo: Use template function to reduce code overhead
//  */
// template<class T> list<DOMElement*>* 
// ContextXMLParser::get_elements(map< T , const XMLCh* >* node_map, DOMElement* node)
// {
//     list<DOMElement*>* element_list = new list<DOMElement*>();
//     /* for all elements in the node_map get the nodes an
//       add them to the element_list. */
//     typename map< T, const XMLCh*>::iterator node_name_iterator(node_map->begin());
//     while(node_name_iterator != node_map->end()){
//  	list<DOMElement*>* tmp_list = this->xml_handler
//  	    ->get_element_list_by_name(logic_relation_node,
//  				       node_name_iterator->second);
//  	element_list->merge(*tmp_list);
//  	delete tmp_list; 
//  	node_name_iterator++;
//     }
//     return element_list;
// }

}  // context
}  // iwear

#endif	//__CONTEXTXMLPARSER_H_

