#ifndef LABELEDSETFACTORY_H
#define LABELEDSETFACTORY_H

#include <string>
#include <map>

#include "vislearning/cbaselib/LabeledSet.h"
#include "LabeledSetCreatorInterface.h"

namespace OBJREC
{


/**
 * @brief Factory providing xml loading classes according to their document type.
 *
 * In order to extract ground truth information or - in general - structured data into a MultiDataset, xml files can be used as
 * containers of file and label information. This factory is used to choose the right loading function for different xml file formats
 * according to the stated document type in the xml file (e.g. < !DOCTYPE DaimlerStereoPedRecXml > ). This enables a flexible program design
 * that can handle loading different xml files at runtime.
 *
 * When initializing this factory, you map a given document type to the appropriate loading class, which implements the interface given by LabeledSetCreatorInterface.
 * For example, using the document type "DaimlerStereoPedRecXml" from above, by calling ::addCreator() this string is mapped to the xml load LabeledSetCreatorDaimlerXml,
 * which exactly knows how to handle the internal xml structure and create a LabeledSet out of it.
 *
 * <h2>Example configuration</h2>
 * contents of main_prog.config:
 *  \verbatim
 ...
 [train]
 dataset = <path to train folder containing config for training (train.config)>
 ...
 \endverbatim
 *
 * contents of training folder:<br>
 * \verbatim
 train.config
 train_files.xml
 ...
 \endverbatim
 *
 * contents of train.config:
 * \verbatim
[main]
factoryxml = train_files.xml  -> specifying that the factory is used for loading a xml file containing further information
 ...
 \endverbatim
 * contents of train_files.xml:
 * \verbatim
 < !DOCTYPE DaimlerStereoPedRecXml >   -> Doctype tells the factory which implementation of the LabeledSetCreatorInterface interface should be used for handling this particulary xml file
 < itemlist >
 < item filename="07m_04s_237599u.pgm" objectid="17028"/>
 < item filename="15m_39s_595649u.pgm" objectid="39616"/>
   ....
 < / itemlist >
 \endverbatim

 * To handle this example train_files.xml, suppose a class LabeledSetCreatorDaimlerXml was implemented (implementing interface LabeledSetCreatorInterface) .
 * You have to add this class to the factory in advance of using the factory:
 * \code
 * NICE::Config confSimple ( "main_prog.config" );
 *
 * LabeledSetCreatorDaimlerXml *daimlerXml = new LabeledSetCreatorDaimlerXml();
 * LabeledSetFactory *factory = new LabeledSetFactory();
 * factory->addCreator("DaimlerStereoPedRecXml", daimlerXml); //the daimlerXml tells the factory that it is associated with the doctype "DaimlerStereoPedRecXml"
 *
 * MultiDataset  md( &confSimple, factory);
 *
 * const LabeledSet *pTrainFiles = md["train"];
 * ...
 *  \endcode
 *
 * \date 2012/05/18
 * \author Johannes Ruehle
 */
class LabeledSetFactory
{
public:
    LabeledSetFactory();


    /**
    * @brief Fill a LabeledSet with data loaded from a xml file using the right loading object specified by the xml document type.
    *
    * Reads the document type of a xml file containing training / test data and calls the appropriate xml extraction class accordingly.
    * As a result, the xml loaded extract label information and stores them into a LabeledSet
    *
    * Note: An appropriate class derived from LabeledSetCreatorInterface had to be added in advance, by LabeledSetFactory::addCreator().
    *
    * @param sXmlFilename name of the config file (xml) containing a specific structure stated by the document type
    *                      according to which the appropriate LabeledSetCreatorInferface implementation is called for xml loading
    * @param p_conf Global config structure
    * @param p_classnames Structure containing all classnames of the ground truth
    * @param p_LabelSet labeled set of data to be created. All loaded data is appended to this structure.
    */
    void createLabeledSetFromXml(std::string sXmlFilename,
                                        const NICE::Config & p_conf,
                                        const ClassNames & p_classnames,
                                        LabeledSet &p_LabelSet);

    /**
     * @brief Create mapping from a xml document type to the appropriate loading function for a xml file.
     *
     * @param sCreatorName xml document type stating a specific xml format and its contents
     * @param pCreator object reference that knows how to load / parse the specific xml file and create a LabeledData set of it.
     */
    void addCreator(std::string sCreatorName, LabeledSetCreatorInterface *pCreator);

protected:
    /// Mapping from xml document type to loader implementation.
    std::map<std::string, LabeledSetCreatorInterface*> m_MapLSCreators;

};

} //namespace

#endif // LABELEDSETFACTORY_H
