/****************************************************************************/
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
// Copyright (C) 2007-2019 German Aerospace Center (DLR) and others.
// This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v2.0
// which accompanies this distribution, and is available at
// http://www.eclipse.org/legal/epl-v20.html
// SPDX-License-Identifier: EPL-2.0
/****************************************************************************/
/// @file    SAXWeightsHandler.h
/// @author  Daniel Krajzewicz
/// @author  Jakob Erdmann
/// @author  Michael Behrisch
/// @date    Fri, 30 Mar 2007
///
// An XML-handler for network weights
/****************************************************************************/
#ifndef SAXWeightsHandler_h
#define SAXWeightsHandler_h


// ===========================================================================
// included modules
// ===========================================================================
#include <config.h>

#include <string>
#include <utils/xml/SUMOSAXHandler.h>
#include <utils/common/SUMOTime.h>


// ===========================================================================
// class declarations
// ===========================================================================
class OptionsCont;
class RONet;
class ROEdge;


// ===========================================================================
// class definitions
// ===========================================================================
/**
 * @class SAXWeightsHandler
 * @brief An XML-handler for network weights
 *
 * As network weights are used both in the simulation and the routers, a base
 *  class for loading them was built. Instances of this class should be supplied
 *  with at least one definition about what shall be retrieved
 *  (ToRetrieveDefinition, defined as inner class) which also contains the information
 *  about the retriever (EdgeFloatTimeLineRetriever, defined as inner class).
 *
 * The ToRetrieveDefinition names the attribute which the SAXWeightsHandler shall
 *  parse and reporte. Within the parsed xml-file these attributes may be embedded
 *  in "lane" or "edge" elements, one for each edge or for each lane (see below).
 *  These elements should be embedded in interval-tags which specify the time the
 *  weight is valid at.
 *  The boolean "edgeBased" tells SAXWeightsHandler whether the weights are supplied
 *  on edge- or on lane-basis (whether it shall parse the "edge" or the "lane" elements).
 *
 * Examples for files the SAXWeightsHandler can handle are the edgedump and the lanedump
 *  generated by the simulation.
 *
 * The EdgeFloatTimeLineRetriever to which read values will be reported should have the
 *  method "addEdgeWeight" implemented. It wil be supplied with the current edge name,
 *  the interval the weight is valid for and the value.
 */
class SAXWeightsHandler : public SUMOSAXHandler {
public:
    /**
     * @class EdgeFloatTimeLineRetriever
     * @brief Interface for a class which obtains read weights for named edges
     */
    class EdgeFloatTimeLineRetriever {
    public:
        /// @brief Constructor
        EdgeFloatTimeLineRetriever() { }

        /// @brief Destructor
        virtual ~EdgeFloatTimeLineRetriever() { }

        /** @brief Adds a weight for a given edge and time period
         *
         * @param[in] id The id of the object to add a weight for
         * @param[in] val The weight
         * @param[in] beg The begin of the interval the weight is valid for
         * @param[in] end The end of the interval the weight is valid for
         */
        virtual void addEdgeWeight(const std::string& id,
                                   double val, double beg, double end) const = 0;

    private:
        EdgeFloatTimeLineRetriever& operator=(const EdgeFloatTimeLineRetriever&); // just to avoid a compiler warning
    };

    /**
     * @class ToRetrieveDefinition
     * @brief Complete definition about what shall be retrieved and where to store it
     */
    class ToRetrieveDefinition {
    public:
        /// Constructor
        ToRetrieveDefinition(const std::string& attributeName, bool edgeBased,
                             EdgeFloatTimeLineRetriever& destination);

        /// Destructor
        ~ToRetrieveDefinition();

    public:
        /// The attribute name that shall be parsed
        std::string myAttributeName;

        /// Information whether edge values shall be used (lane value if false)
        bool myAmEdgeBased;

        /// The class that shall be called when new data is avaiable
        EdgeFloatTimeLineRetriever& myDestination;

        /// aggregated value over the lanes read within the current edge
        double myAggValue;

        /// The number of lanes read for the current edge
        int myNoLanes;

        /// Information whether the attribute has been found for the current edge
        bool myHadAttribute;

    private:
        /// @brief Invalidated copy constructor.
        ToRetrieveDefinition(const ToRetrieveDefinition&);

        /// @brief Invalidated assignment operator.
        ToRetrieveDefinition& operator=(const ToRetrieveDefinition&);

    };

    /**
     * @brief Constructor
     *
     * Gets a list of retriever definitions. Please note that the retrievers are
     *  not deleted!
     */
    SAXWeightsHandler(const std::vector<ToRetrieveDefinition*>& defs,
                      const std::string& file);


    /**
     * @brief Constructor
     *
     * Gets a single definition. Please note that the retrievers are not deleted!
     */
    SAXWeightsHandler(ToRetrieveDefinition* def,
                      const std::string& file);


    /// Destructor
    ~SAXWeightsHandler();


protected:
    /// @name inherited from GenericSAXHandler
    //@{

    /** @brief Called on the opening of a tag;
     *
     * @param[in] element ID of the currently opened element
     * @param[in] attrs Attributes within the currently opened element
     * @exception ProcessError If something fails
     * @see GenericSAXHandler::myStartElement
     */
    void myStartElement(int element,
                        const SUMOSAXAttributes& attrs);


    /** @brief Called when a closing tag occurs
     *
     * @param[in] element ID of the currently opened element
     * @exception ProcessError If something fails
     * @see GenericSAXHandler::myEndElement
     */
    void myEndElement(int elemente);
    //@}


private:
    /// Parses the efforts of a lane for the previously read times
    void tryParse(const SUMOSAXAttributes& attrs, bool isEdge);


private:
    /// List of definitions what shall be read and whereto stored while parsing the file
    std::vector<ToRetrieveDefinition*> myDefinitions;

    /// the begin of the time period that is currently processed
    double myCurrentTimeBeg;

    /// the end of the time period that is currently processed
    double myCurrentTimeEnd;

    /// the edge which is currently being processed
    std::string myCurrentEdgeID;


private:
    /// we made the copy constructor invalid
    SAXWeightsHandler(const SAXWeightsHandler& src);

    /// we made the assignment operator invalid
    SAXWeightsHandler& operator=(const SAXWeightsHandler& src);

};


#endif

/****************************************************************************/

