/*! \file BlocDdlLim.h
    \brief def classe et fonctions template pour la lecture de ddl lim.
*/

// This file is part of the Herezh++ application.
//
// The finite element software Herezh++ is dedicated to the field
// of mechanics for large transformations of solid structures.
// It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600)
// INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) <https://www.irdl.fr/>.
//
// Herezh++ is distributed under GPL 3 license ou ultérieure.
//
// Copyright (C) 1997-2021 Université Bretagne Sud (France)
// AUTHOR : Gérard Rio
// E-MAIL  : gerardrio56@free.fr
//
// This program 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, either version 3 of the License,
// or (at your option) any later version.
//
// This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
//
// For more information, please consult: <https://herezh.irdl.fr/>.

/************************************************************************
 *     DATE:        28/03/2004                                          *
 *                                                                $     *
 *     AUTEUR:      G RIO   (mailto:gerardrio56@free.fr)                *
 *                                                                $     *
 *     PROJET:      Herezh++                                            *
 *                                                                $     *
 ************************************************************************
 *     BUT:   Gestion  de divers bloc courant du fichier de lecture .   *
 *            Cas où ces blocs sont relatif aux conditions limites,     *
 *             et héritent  de bloc classiques.                         *
 *     par rapport au bloc, l'apport est la gestion d'un nom_de maillage*
 *     éventuellement en plus du nom de référence.                      *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
 *                                                                      *
 *     VERIFICATION:                                                    *
 *                                                                      *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *     !        !            !                                    !     *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
 *     MODIFICATIONS:                                                   *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *                                                                $     *
 ************************************************************************/
#ifndef BLOC_DDLLIM_T_H
#define BLOC_DDLLIM_T_H

#include "Bloc.h"
#include "ConstMath.h"

/// @addtogroup Les_classes_Ddl_en_tout_genre
///  @{
///

///
///
///================================================
///    cas d'un bloc  template avec conditions limites
///================================================
template <class Bloc_particulier>
class BlocDdlLim : public Bloc_particulier  
{
   // surcharge de l'operator de lecture
   friend istream & operator >> (istream & entree, BlocDdlLim<Bloc_particulier> & coo)
    { // lecture d'un nom de maillage éventuel
      bool existe_nom_maillage; entree >> existe_nom_maillage;
      if (existe_nom_maillage) 
       { string nom; entree >> nom; 
         if (coo.nom_maillage == NULL) 
            coo.nom_maillage = new string(nom);
         else 
            *(coo.nom_maillage) = nom;
       };       
      // puis la classe mère
      entree >> ((Bloc_particulier&)(coo));
      return entree;      
    }
 
   // surcharge de l'operator d'ecriture
   friend ostream & operator << (ostream & sort, const BlocDdlLim<Bloc_particulier> & coo)
    { // tout d'abord le maillage éventuelle
      if (coo.nom_maillage == NULL) 
       sort << false << " "; 
      else 
       sort << true << " " << *(coo.nom_maillage) << " ";
      // puis la classe mère
      sort << ((const Bloc_particulier&)(coo));
      return sort;      
    } 

  public :
    // VARIABLES PUBLIQUES :
     // stockage d'un element 
     // class conforme a la specif de T de la class LectBloc_T
     
     // Constructeur    
     BlocDdlLim () :   // par defaut
       nom_maillage(NULL),Bloc_particulier()
        {};
     // fonction d'une instance de Bloc_particulier
     BlocDdlLim (const Bloc_particulier& a) : Bloc_particulier(a),nom_maillage(NULL) {};
     // fonction d'une instance et d'un string
     BlocDdlLim (const string& nom_mail,const Bloc_particulier& a) : 
        Bloc_particulier(a),nom_maillage(new string (nom_mail)) {};
     // fonction d'une instance et d'un pointeur de string
     BlocDdlLim (const string* nom_mail,const Bloc_particulier& a) : 
        Bloc_particulier(a),nom_maillage(NULL) 
           { if (nom_mail != NULL) nom_maillage = new string (*nom_mail);};
     // de copie   
     BlocDdlLim (const BlocDdlLim& a) : 
       nom_maillage(NULL),Bloc_particulier(a)
        {if (a.nom_maillage != NULL) nom_maillage = new string (*(a.nom_maillage));};
     // destructeur   
        ~BlocDdlLim () {if (nom_maillage != NULL) delete nom_maillage;};
	    // retourne un pointeur de string donnant le nom du maillage associé
	    // = NULL si aucun maillage
		   const string* NomMaillage() const {return nom_maillage;}; 
	    // change le  nom de maillage
	    // ATTENTION : Les modifications liees au changement du nom de maillage
	    // sont a la charge de l'utilisateur.
	    // le nouveau nom ne doit pas être vide  !! sinon erreur
		   void Change_nom_maillage(const string& nouveau);
     // lecture d'un bloc    
     void Lecture(UtilLecture & entreePrinc);  
     // affichage des informations
     void Affiche() const ;
     // surcharge des operateurs    
     bool operator == ( const BlocDdlLim& a) const; 
     BlocDdlLim& operator = (const  BlocDdlLim& a); 
     bool operator != ( const BlocDdlLim& a) const { return !(*this == a);};

   protected :
	    string*  nom_maillage; // nom d'un maillage
}; 
/// @}  // end of group


/// lecture d'un bloc
template <class Bloc_particulier>
void BlocDdlLim<Bloc_particulier>::Lecture(UtilLecture & entreePrinc)
    { // on regarde tout d'abord si il y a un nom de maillage, qui doit être le premier nom
      string nom;
      if (strstr(entreePrinc.tablcar,"nom_mail=")!=NULL)
        { // cas où il y a un nom de maillage
          *(entreePrinc.entree) >> nom >> nom; // lecture du mot_clé et du nom
          if (nom_maillage == NULL) { nom_maillage = new string(nom);}
          else                      { *nom_maillage = nom;};  	
        }
      // puis lecture de la classe mère
      Bloc_particulier::Lecture(entreePrinc);
    }
     
/// affichage des infos
template <class Bloc_particulier>
void BlocDdlLim<Bloc_particulier>::Affiche()  const 
  {  // affichage éventuelle du nom de maillage
     if (nom_maillage != NULL)
       { cout << "\n nom_mail= " << *nom_maillage;} else cout << "\n";	
	// puis affichage des infos de la classe mère
    Bloc_particulier::Affiche();
   }
    
/// surcharge de l'operateur  ==
template <class Bloc_particulier>
bool BlocDdlLim<Bloc_particulier>::operator == ( const BlocDdlLim<Bloc_particulier>& a) const
   { if (nom_maillage == NULL)
        { if (a.nom_maillage != NULL) return false;        
         }
     else
        { if (a.nom_maillage == NULL) return false;
          // sinon les deux sont non null: on test leur égalité
          if (*nom_maillage != *(a.nom_maillage)) return false;         
         };    
     // puis la classe mère 
     if (((Bloc_particulier&)(*this)).operator==(a))    
       return true;
     else  
      { return false; };
    }
    
/// surcharge de l'operateur  =
template <class Bloc_particulier>
BlocDdlLim<Bloc_particulier>& BlocDdlLim<Bloc_particulier>::operator
     = ( const BlocDdlLim<Bloc_particulier>& a) 
    { if (a.nom_maillage == NULL)
		      { if (nom_maillage != NULL) {delete nom_maillage;nom_maillage=NULL;}}
      else
		      { if (nom_maillage == NULL) nom_maillage = new string(*(a.nom_maillage));
		        else                      *nom_maillage = *(a.nom_maillage);
		       };   
      // puis la classe mère
      ((Bloc_particulier&)(*this)).operator=(a);
      return *this;
     }
     
/// change le  nom de maillage
/// ATTENTION : Les modifications liees au changement du nom de maillage
/// sont a la charge de l'utilisateur.
/// le nouveau nom ne doit pas être vide  !! sinon erreur
template <class Bloc_particulier>
void BlocDdlLim<Bloc_particulier>::Change_nom_maillage(const string& nouveau)
  {	if (nouveau.length() == 0)
	   { cout << "\nErreur : reference de nom de maillage non valide  car de longueur nulle ! "
	          << " nom_mail= " << nouveau << "\n";
		 cout << "BlocDdlLim<Bloc_particulier>::Change_nom_maillage(....) \n";
		 Sortie(1);
		}
     if (nom_maillage == NULL)
       { nom_maillage = new string(nouveau);}
     else 
       { *nom_maillage = nouveau;};  	
	}

#endif  
