# -*- coding: iso-8859-1 -*-

# ==============================================================================
# COPYRIGHT (C) 1991 - 2003  EDF R&D                  WWW.CODE-ASTER.ORG
# 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 2 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, WRITE TO EDF R&D CODE_ASTER,
#    1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
# ==============================================================================

"""Definition of ASTER_PROFIL class.
"""

__revision__ = "$Id: as_profil.py 2566 2006-12-08 10:09:20Z courtois $"


# ----- differ messages translation
def _(mesg):
   return mesg

import os
import re
from types import ListType, TupleType
EnumTypes = (ListType, TupleType)

#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
class ASTER_PROFIL:
   """Class to read and parse an exported ASTK profile.
   Attributes :
      filename : absolute filename of the '.export' file
      param    : value of each parameters (type dict) (each param is a list)
      args     : arguments (type dict)
      data     : list of the files/directories which are datas
      resu     : list of the files/directories which are results
         (each of data/resu is a dict of : path, ul, compr, type, rep)
   """
#-------------------------------------------------------------------------------
   def __init__(self, filename=None, run=None):
      """filename : filename of the '.export' file to read
      run   : ASTER_RUN object (optional)
      """
      # initialisations
      self.param = {}
      self.args = {}
      self.data = []
      self.resu = []
      self.filename = filename
      self.verbose = False
      self.debug = False
      # ----- reference to ASTER_RUN object which manages the execution
      self.run = run
      if run != None:
         self.verbose = run['verbose']
         self.debug   = run['debug']
      if filename != None:
         # check if file exists
         if not os.path.isfile(filename):
            self._mess(_('file not found : %s') % filename, _('<A>_ALARM'))
         else:
            # read the file
            f = open(filename, 'r')
            content = f.read()
            f.close()
            self._parse(content)
      
      if self.debug:
         print '<DBG> <init> ASTER_PROFIL :'
         print self

#-------------------------------------------------------------------------------
   def __repr__(self):
      """Pretty print content of the profile
      """
      fmt = ' %-10s = %s'
      fmt2 = ' %-6s %2s %1s %-s %1s'
      txt = []
      txt.append(fmt % ('Filename', self.filename))
      for comm, d in ('Parameters :', self.param), ('Arguments :', self.args):
         txt.append(comm)
         sorted_keys = d.keys()
         sorted_keys.sort()
         for key in sorted_keys:
            txt.append(fmt % (key, d[key]))
      for comm, l in ('Data :', self.data), ('Result :', self.resu):
         txt.append(comm)
         for d in l:
            c = ' '
            if d['compr']:
               c = 'C'
            rep = ' '
            if d['isrep']:
               rep = 'R'
            txt.append(fmt2 % (d['type'], d['ul'], c, d['path'], rep))
      return os.linesep.join(txt)

#-------------------------------------------------------------------------------
   def __getitem__(self, key):
      """Return the value of parameter 'key', or '' if not exists
      (so never raise KeyError exception).
      """
      if self.param.has_key(key):
         return self.param[key]
      else:
         return ['']

#-------------------------------------------------------------------------------
   def Get(self, DR, typ):
      """Return the list of datas (DR='D') or results (DR='R') or both (DR='DR')
      of the type 'typ'
      """
      lr = []
      if   DR == 'D':
         what = self.data
      elif DR == 'R':
         what = self.resu
      else:
         what = self.data + self.resu
      for entry in what:
         if entry['type'] == typ:
            lr.append(entry)
      return lr

#-------------------------------------------------------------------------------
   def Set(self, DR, dico):
      """Add an entry defined in `dico` in .data/.resu.
      """
      if   DR == 'D':
         l_what = [self.data]
      elif DR == 'R':
         l_what = [self.resu]
      else:
         l_what = [self.data, self.resu]
      l_k = ('type', 'isrep', 'path', 'ul', 'compr')
      for k in l_k:
         if not dico.has_key(k):
            self._mess(_("key '%s' missing") % k, _('<F>_PROGRAM_ERROR'))
      for what in l_what:
         what.append(dico)

#-------------------------------------------------------------------------------
   def __setitem__(self, p, v):
      """Add the parameter 'p' with the value 'v'
      """
      if self.debug and self.param.has_key(p):
         print '<DBG> (AS_PROFIL.setitem) force param['+p+'] = ', v
      if type(v) not in EnumTypes:
         v = [v,]
      self.param[p] = v

#-------------------------------------------------------------------------------
   def _mess(self, msg, cod='', store=False):
      """Just print a message
      """
      if hasattr(self.run, 'Mess'):
         self.run.Mess(msg, cod, store)
      else:
         print '%-18s %s' % (cod, msg)

#-------------------------------------------------------------------------------
   def _parse(self, content):
      """Extract fields of config from 'content'
      """
      self.content = content
      for l in content.split(os.linesep):
         if not re.search('^[ ]*#', l):
            spl = l.split()
            typ = ''
            if len(spl) > 0:
               typ = spl[0]
               if typ not in ('A', 'P', 'F', 'R'):
                  self._mess(_('unexpected type : %s') % typ, _('<A>_ALARM'))
            else:
               continue
            if len(spl) >= 3:
               if typ == 'P':
                  if self.param.has_key(spl[1]):
                     self.param[spl[1]].append(' '.join(spl[2:]))
                  else:
                     self.param[spl[1]] = [' '.join(spl[2:])]
               elif typ == 'A':
                  self.args[spl[1]] = ' '.join(spl[2:])
               elif typ == 'F' or typ == 'R':
                  if len(spl) >= 5:
                     dico = {
                        'type'  : spl[1],
                        'path'  : spl[2],
                        'isrep' : typ == 'R',
                        'ul'    : spl[4],
                        'compr' : spl[3].find('C') > -1,
                     }
                     if spl[3].find('D')>-1:
                        self.data.append(dico)
                     if spl[3].find('R')>-1:
                        self.resu.append(dico)
                  else:
                     self._mess(_('fields missing on line : %s') % l, _('<A>_ALARM'))
            elif len(spl) >= 2:
               typ = spl[0]
               if typ == 'A':
                  self.args[spl[1]] = ''

#-------------------------------------------------------------------------------
   def copy(self):
      """Return a copy of the profile
      """
      newp = self.__class__(None, self.run)
      for attr in ('args', 'param', 'data', 'resu'):
         setattr(newp, attr, getattr(self, attr))
      return newp
      
#-------------------------------------------------------------------------------
   def WriteExportTo(self, fich):
      """Write the export file represents this profile.
      """
      self.filename = self.filename or fich
      txt = []
      for p, dico in ('P', self.param), ('A', self.args):
         sorted_keys = dico.keys()
         sorted_keys.sort()
         for key in sorted_keys:
            l_val = dico[key]
            if type(l_val) not in EnumTypes:
               l_val = [l_val,]
            for v in l_val:
               txt.append(' '.join([p, key, str(v)]))
      for dr, l_val in ('D', self.data), ('R', self.resu):
         for d in l_val:
            c = ' '
            if d['compr']:
               c = 'C'
            fr = 'F'
            if d['isrep']:
               fr = 'R'
            txt.append(' '.join([fr, d['type'], d['path'], dr+c, str(d['ul'])]))
      txt.append('')
      try:
         open(fich, 'w').write(os.linesep.join(txt))
      except IOError, msg:
         self._mess(_('No write access to %s') % fich, _('<F>_ERROR'))


