// @(#)root/reflex:$Name:  $:$Id: DictionaryGenerator.h,v 1.1 2006/08/15 15:22:51 roiser Exp $
// Author: Antti Hahto   06/20/06

// Copyright CERN, CH-1211 Geneva 23, 2004-2006, All rights reserved.
//
// Permission to use, copy, modify, and distribute this software for any
// purpose is hereby granted without fee, provided that this copyright and
// permissions notice appear in all copies and derivatives.
//
// This software is provided "as is" without express or implied warranty.

// DictGen, a replacement for genreflex.py
//================================================

//USAGE:
//
// 1. Create a new generator                        :  Dictgen generator
// 2. Set recursive parsing, optional (default:on)  :  generator.Use_recursive(true/false)
// 3. Set selection file,    optional               :  generator.Use_selection("filename")
// 4. Run, example
//      Scope::GlobalScope().Gendict(generator);
// 5. Dump results into file/stdout(if filename left empty)  : generator.Dump("filename")

#ifndef ROOT_Reflex_DictionaryGenerator
#define ROOT_Reflex_DictionaryGenerator

#include "Reflex/Kernel.h"
# include "Reflex/Type.h" 

# include <fstream>
# include <string>
# include <iostream>
# include <vector>
# include <ctime>
# include <iostream>
# include <iomanip>
# include <limits>
# include <ostream>
# include <sstream>
#include <list>   // isnewtype2
#include <algorithm> //isnewtype2



namespace ROOT 
{
   namespace Reflex 
   {

      // forward declarations
      class Type;
   
      /* 
       * @class DictionaryGenerator DictonaryGenerator.h Reflex/DictionaryGenerator.h
       * @author Antti Hahto
       * @date 20/06/2006
       * @ingroup Ref
       */

      class RFLX_API DictionaryGenerator
      {

      public:

         /* default constructor */
         DictionaryGenerator(); 
   

         /* destructor */
         ~DictionaryGenerator();
 
         friend std::ostream & operator << ( std::ostream & s,
                                             const DictionaryGenerator & obj );
        

         /**
          * Use_recursive set recursive or not
          * @param recursive
          * @return 
          */
         bool Use_recursive(bool recursive); 


         /**
          * Use_selection set selection file
          * @param filename
          * @return
          */
         bool Use_selection(const std::string & filename);


         /**
          * Dump output the results into stream
          * @param filename
          */
         void Print(const std::string & filename = "");


         /**
          * AddHeaderFile adds an extra user .h file into dump
          * @param filename
          */
         void AddHeaderFile(const std::string & filename);
         

         /**
          * GetTypeNumber allt types have a unique id-number
          * @param mebertype
          * @return 
          */         
         std::string GetTypeNumber( const Type & membertype);


         /**
          * Use_recursive get if recursion set
          * @return true if recursion is set
          */
         bool Use_recursive();
      

         /**
          * AddIntoInstances add Instances -field into output
          * @param item
          */
         void AddIntoInstances(const std::string & item);


         /**
          * AddIntoNS add NS field into output
          * @param typenumber
          * @param membertype
          */
         void AddIntoNS(const std::string & typenumber, 
                        const Type & membertype); 
 

         /**
          * AddIntoShadow add Shadow field into output
          * param item
          */
         void AddIntoShadow(const std::string & item); 


         /**
          * AddIntoFree add Free field into output
          * @param item
          */
         void AddIntoFree(const std::string & item); 


         /**
          * AddIntoClasses add Classes field into output
          * @param item
          */
         void AddIntoClasses(const std::string & item);  
     

         /**
          * fMethodCountermethod_Xn, after Stub Functions for the class
          */
         double fMethodCounter;
      
     
         /**
          * fStr_namespaces
          */
         std::ostringstream fStr_namespaces;    


         /**
          * GetParams
          * @param membertype
          */
         std::string GetParams(const Type & membertype);
	 

         /**
          * IsNewType already introduced type?
          * @param searchtype
          * @return
          */
         bool IsNewType( const Type & searchtype);
    

         /**
          * Replace_colon 
          * @param scoped_name
          * @return
          */
         std::string Replace_colon(std::string scoped_name);

         
         /**
          * fSelections
          */
         std::vector <std::string> fSelections;  // for explicitly choosing classes to include into generation


         /**
          * fPattern_selections
          */
         std::vector <std::string> fPattern_selections;
	 
         bool IsNewType2 ( const Type & searchtype);  // testing; work-in-progress

      private:


         /** 
          * GetSubScopes one scope can include multiple subscopes
          * @param allscopes
          */
         void GetSubScopes (Scope_Iterator allscopes );


         /** 
          * GetMembers and subscope can include members
          */
         void GetMembers ( Scope_Iterator subsco);
   
	
         /**
          * fTypes store used types
          */
         std::vector<ROOT::Reflex::Type> fTypes;


         /**
          * fStr_header
          */
         std::ostringstream fStr_header;


         /**
          * fStr_shadow
          */
         std::ostringstream fStr_shadow;


         /**
          * fStr_shadow2 member predefinations for shadow
          */
         std::ostringstream fStr_shadow2;


         /**
          * fStr_classes
          */
         std::ostringstream fStr_classes;


         /**
          * fStr_classes_method for class part, method_xn
          */
         std::ostringstream fStr_classes_method;


         /**
          * fStr_frees
          */
         std::ostringstream fStr_frees;


         /**
          * fStr_instances
          */
         std::ostringstream fStr_instances;


         /**
          * fStr_instances2 instances unload() -part
          */
         std::ostringstream fStr_instances2; 


         /**
          * fSelect_recursive if set true, recursive go throught all the scopes
          */   
         bool fSelect_recursive; 
   
         /*
         // FIND2 START testing
         struct mydata
         {
            ROOT::Reflex::Type itemnum;
            ROOT::Reflex::Type value;
         };
         struct MatchItemNum
         {
            ROOT::Reflex::Type itemnum;
            MatchItemNum(ROOT::Reflex::Type num) : itemnum(num)  
            {
            }
            bool operator()(const mydata &data) const
            {
               //return (data.itemnum == itemnum);
               return (data.itemnum.IsEquivalentTo(itemnum));
            }
         };
         std::list<mydata> types2;
         // FIND2 END
	  */

      }; // class DictionaryGenerator


   } // namespace Reflex
} // namespace ROOT


//-------------------------------------------------------------------------------
inline void ROOT::Reflex::DictionaryGenerator::AddHeaderFile(const std::string & filename) {
//-------------------------------------------------------------------------------
// Adds an extra user .h -file into dump  
   fStr_header<< "#include \"" << filename << "\"\n";
}


//-------------------------------------------------------------------------------
inline void ROOT::Reflex::DictionaryGenerator::AddIntoInstances(const std::string & item) {
//-------------------------------------------------------------------------------
// The last field of the generated file
   fStr_instances << item;

}


//-------------------------------------------------------------------------------
inline void ROOT::Reflex::DictionaryGenerator::AddIntoShadow(const std::string & item) {
//-------------------------------------------------------------------------------
// Shadow field of the generated file
   fStr_shadow << item;
}


//-------------------------------------------------------------------------------
inline void ROOT::Reflex::DictionaryGenerator::AddIntoFree(const std::string & item) {
//-------------------------------------------------------------------------------
// Free field generation
   fStr_frees << item;
}


//-------------------------------------------------------------------------------
inline void ROOT::Reflex::DictionaryGenerator::AddIntoClasses(const std::string & item) {
//-------------------------------------------------------------------------------
// Classes field generation
   fStr_classes << item;
}


//-------------------------------------------------------------------------------
inline ROOT::Reflex::DictionaryGenerator::DictionaryGenerator() 
//-------------------------------------------------------------------------------
   : fMethodCounter(0), 
     fSelect_recursive(true) {
   fTypes.clear(); // storage of used types
}


//-------------------------------------------------------------------------------
inline ROOT::Reflex::DictionaryGenerator::~DictionaryGenerator() {
//-------------------------------------------------------------------------------
}

        
#endif // ROOT_Reflex_DictionaryGenerator
