/*---------------------------------------------------------------------------------------------------------------------
- File      : tags_mapping_table.h                                                        Project ELSE, EPFL - DI/LIA -
-                                                                       Evaluation in Language and Speech Engineering -
- Author    : Seydoux Florian   Creation date : 02 Aug 1999                                                           -
- Eulogist  : -                 Approval date : -                  Version: 0.1                                       -
-                                                                                                                     -
- Descript. : Define and implement the mapping of the system's tags set to the reference's tags set.                  -
-             Table are read from table file; the format of required files arent strictly define in                   -
-             [Else, Structure des fichiers, Sect. 2.3.a]                                                             -
-                                                                                                                     -
- Requested : -                                                                                                       -
-                                                                                                                     -
- Gaps      : o) (Re)Définir convenablement les opérateurs '==,<,>,!=...' des tags et contractedTag, en ajoutant, au  -
-                besoin des methodes spécifique (equal(other_type), sameBase(...)).                                   -
-                Utiliser les methodes adequates pour les projections/ensemble d'alternatives                         -
-                (Les projections portent sur des etiquettes contractées sans segmentation, tandis que les ensembles  -
-                d'alternatives doivent prendre en compte la segmentation                                             -
-                >> spécialiser les type d'étiquettes (c.f. tags.h) et/ou utiliser les segmentations 'neutre'         -
-                -> répercution dans les tests d'existences, et dans le mapping (supression de la copie locale tags)  -
-                                                                                                                     -
-             o) Regrouper dans une structure interne les attributs relatifs à chaque 'système'                       -
-                (Nom du fichier contenant la table, configuration, etiquette neutralisée, projection direct/inverse) -
-                -> minimise le nombre de paramètres à transmettres aux méthodes internes                             -
-                                                                                                                     -
-             o) Créer et maintenir des ensembles pour tous les jeux d'étiquettes (donc, ajouter au moins 1 ensemble  -
-                pour les étiquettes de références), et reféfinir une projection de la sorte:                         -
-                ContractedTag -> {ContractedTag*}                                                                    -
-                les étiquettes 'cibles' pour la projection User->Pivot étant prise dans l'ensemble de départ de la   -
-                projection Pivot->Référence, et les cibles de cette dernière dans l'ensemble additionel.             -
-                (Attention a manitenir la cohérence avec les projections inveses)                                    -
-                                                                                                                     -
-             o)  Rendre le mapping plus efficace (rapidité)                                                          -
-                 -> dérécursifier la fonction 'add()' (c.f. tags_mapping_table.cc) et l'intégrer dans 'map()'        -
-                 -> court-circuiter la seconde recherche dans le cas d'un mapping double (User->Pivot->Reference)    -
-                    (possible avec une projection de type ContractedTag -> {ContractdTag*}                           -
-                 -> Avec le meme type de projection, la recherche et élimination des étiquettes neutralisée doit     -
-                    etre nettement plus efficace (comparaison d'adresse au lieu d'une comparaison de chaine)         -
-                                                                                                                     -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Rev. date | Reviser               | Revise's description                                                            -
- - - - - - + - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- ../../....| ........              | ...                                                                             -
---------------------------------------------------------------------------------------------------------------------*/


//
// Mapping: En fait, il y a 3 ensembles (jeux) d'étiquettes: User -> Grace -> Evaluated
// L'ensemble des etiquettes grace est donc un ensemble pivot.
// La table de correspondance des participants définit 'User -> Grace', tandis que
// celle systeme definit 'Grace -> Evaluated'.
// 
// Le mapping se fait ainsi:
// Direct: User   ->   Pivot(out)  -|-  Pivot(in)   ->   Reference
//          ^              ^               ^                 ^
//       contracted     contracted      contracted        contracted
// 
//  A+B peut etre stocke dans la table en tant qu'entree (atomique sens grace).
//  Probleme: 
//  A    -> aa          des lors, comment interpreter:  B+A+B (bb+aa+bb / bb+ababa)
//  B    -> bb          En l'etat actuel (map), B+A+B est evalue t.q., et pas comme B+(A+B)
//  A+B  -> abab        -> pas de priorite, l'etiquette est consideree grace'atomique.
// 
// Le probleme soulevé ci-dessus, et d'autres (interpretation de A+B|C -> distribution ? A+(B|C)),
// révèle un/des manque/s dans la spécification actuel du format des étiquettes et des opérateurs
// (leurs propriétés ne sont pas clairement définies, et il manque visiblement un operateur de modif.
// de priorite (i.e. ()).
// Autre question: les formes contractees ne seraient-elles pas a recenser, et a ajouter a la table, en
// tant qu'etiquette atomique ordinaire ? (faisable pour le francais, mais qu'en est-il des langues
// agglutatives ??? )
// 

#ifndef MAPPING_TABLE_H
#define MAPPING_TABLE_H

#include <map>
#include <set>
#include <vector>
#include <string>

#include <fstream>
#include <iostream>
#include <stdexcept>

#include "globaldef.h"
#include "user_configuration.h"
#include "messages_manager.h"
#include "flow_basic_operators.h"

#include "tags.h"

#ifdef _USE_NAMESPACES
    namespace Else { 
#endif // _USE_NAMESPACES

// 
// define 'CONTRACTED_PATCH' to enable the patch that transform reference tag like <T1+T2+...+Tn> to
// <T1+T2+...+Tn|T1|T2|...|Tn> before mapping of a reference tag.
// 
// define 'SPECIFIC' to enable the post-mapping adjustement of non-neutralized tag.
// 

struct LessPredicates {
  bool operator()(const ContractedTag& t1, const ContractedTag& t2) const;
  bool operator()(const AtomicTag& a1, const AtomicTag& a2) const;
};

typedef ContractedTag::iterator           ContractedIterator;
typedef ContractedTag::const_iterator     ContractedConstIterator;
typedef AlternatedTagsSet::iterator       AlternatedIterator;
typedef AlternatedTagsSet::const_iterator AlternatedConstIterator;

typedef set<ContractedTag> TagsSet;
typedef multimap<ContractedTag, ContractedTag, LessPredicates> Projection;

class TagsMappingTable : public GraceTools {
// Pre-definition (type, friend, inner classes) ............................................................

public:
	// Public types definition .............................................................................
	
	// Class's public methodes .............................................................................

	// Class's public attributes ...........................................................................

	// Intances's public methodes ..........................................................................
	// Spcl member methodes (Constructors, destructors, copy cstr) ......................
    TagsMappingTable();
    ~TagsMappingTable();
    // Operators definition ............................................................
    // Others methodes .................................................................
    const string& nickname() const;
    const unsigned char& id() const;
    bool readReference(const UserConfiguration& config,            // first
                       const string& filename   = string(),
                       const TypeTable& mapMode = UnknownTbl);
    bool readSystem(const UserConfiguration& config,               // second
                    const string& filename = string(),
                    const TypeTable& mapMode = UnknownTbl);
    Natural sizeRef() const;
    Natural sizePivot() const;
    Natural sizeSys() const;
    void reset();
    bool buffersEmpty() const;
    void clearSavedMapping();  // Free memory
    bool existRef(const AtomicTag& refTag) const;
    bool existRef(const ContractedTag& refTag) const;
    bool existSys(const AtomicTag& sysTag) const;
    bool existSys(const ContractedTag& sysTag) const;
    bool isDefinedAsRef(const ContractedTag& tags) const;
    bool isDefinedAsRef(const AlternatedTagsSet& tags) const;
    bool isDefinedAsSys(const ContractedTag& tags) const;
    bool isDefinedAsSys(const AlternatedTagsSet& tags) const;
    bool checkRef(const GraceTools& tools, const string& origin, const LocalisedTag& tag) const;
    bool checkSys(const GraceTools& tools, const string& origin, const LocalisedTag& tag) const;
    AlternatedTagsSet mapPivotToRef(const BasicTag& tags) const;
    AlternatedTagsSet mapSysToRef(const BasicTag& tags) const; // don't check unknown tag !
    AlternatedTagsSet mapPivotToSys(const BasicTag& tags) const;
    void dump() const; // debug only
    void dumpInv() const; // debug only

	// Instances's public attributes .......................................................................
    const string&         systemFileName;      // Read visibility.
    const string&         referenceFileName;   // Read visibility.
    const ContractedTag&  systemNeutralTag;
    const ContractedTag&  referenceNeutralTag;

protected:
	// Class's protected methodes ..........................................................................

	// Class's protected attributes ........................................................................

	// Intances's protected methodes .......................................................................

	// Instances's protected attributes ....................................................................

private:
	// Class's private methodes ............................................................................

	// Class's private attributes ..........................................................................

    static const unsigned char  TOOLS_ID;  // gcc 2.8.1. internal compiler error...
    static const string         TOOLS_NICKNAME;

	// Intances's private methodes .........................................................................
    bool makeProjection(const string& fileName, TypeTable mode, const UserConfiguration& config, const bool reference);
	AlternatedTagsSet map(AlternatedTagsSet tags, const Projection& projection, const ContractedTag& neutral) const;
//	AlternatedTagsSet map(AlternatedTagsSet tags, const Projection& projection, const ContractedTag& neutral,
//	                      const UserConfigurationCPtr conf) const;

	// Instances's private attributes ......................................................................
	typedef map<BasicTag, AlternatedTagsSet> MappedTag;

    conform_string         refFileName;      // Name of file who contain the reference tags table
    conform_string         sysFileName;      // Name of the file who contain the system tags table
    UserConfigurationCPtr  refConfig;        // Definition of separators.
    UserConfigurationCPtr  sysConfig;

    ContractedTag          refNeutralTag;    // Neutralized reference tag
    ContractedTag          sysNeutralTag;    // Neutralized system tag

    Projection             refDirectPrj;     // Mapping from Pivot -> Reference(Out).
    Projection             sysDirectPrj;     // Mapping from User(In) -> Pivot
    Projection             refReversePrj;    // ReverseMapping from Reference -> Pivot. (not very necessary but...)
    Projection             sysReversePrj;    // ReverseMapping, Pivot -> User(In)

    mutable MappedTag      mappedSystem;     // Always mapped System -> Reference
    mutable MappedTag      mappedPivot;      // Always mapped Pivot -> (Ref | Sys)
};

#ifdef _USE_NAMESAPCES
}
#endif // _USE_NAMESPACES

#endif // MAPPING_TABLE_H

