#!/usr/bin/python
# -*- coding: iso-8859-1 -*-

# Copyright 2003, 2004 DGEFP, Georges-Andre Silber (CRI/ENSMP).
#
# $Id: lheo_utils.py,v 1.5 2004/09/24 14:45:41 silber Exp $
#
# Cette boite a outils est copiable et utilisable gratuitement
# sans limitation de duree. Par contre, aucune modification 
# n'est autorisee sans l'autorisation expresse des 
# detenteurs du copyright.

import codecs
import sys
import cgi
import cgitb

from cStringIO import StringIO
from xml.dom.ext.reader import Sax2
from xml.dom.ext import *

class ErreurDeValidation:
    def __init__(self):
        print "ERREUR DE VALIDATION"

#
# Element de base
#
class ObjetElement (object):
    typecontenu = 'vide'

    def __init__(self, motcle):
        self.motcle = motcle

    def valide(self):
        return 2
    def valideXML(self, node):
        return 2
    def affiche(self):
        pass
    def afficheXML(self):
        pass
    def afficheExempleXML(self):
        pass
    def info(self):
        print "Élément: <%s>"%self.motcle
        print "  type     = '%s'"%self.typecontenu
    def HTMLLibelle(self, urlglossaire):
        if urlglossaire != '' and self.glossaire != '':
            return "<a href=\"%s\">%s</a>"%(urlglossaire+"#"+self.glossaire,self.libelle)
        else:
            return "%s"%self.libelle
    def afficheHTMLFormLabel(self, urlglossaire):
        if urlglossaire != '' and self.glossaire != '':
            print "<label class=\"%s\"><a href=\"%s\">%s</a></label>"%(self.motcle,urlglossaire+"#"+self.glossaire,self.libelle)
        else:
            print "<label class=\"%s\">%s</label>"%(self.motcle,self.libelle)
    def afficheHTMLFormWidget(self, identificateur, lignes, colonnes):
        pass

#
# Element de type 'NUL'
#
class ObjetElementNul (ObjetElement):
    typecontenu = 'nul'
    def __init__(self):
        ObjetElement.__init__(self, 'nul')

#
# Element de type 'alpha'
#
class ObjetElementTexte (ObjetElement):
    typecontenu = 'alpha'

    def modeleContenu(self):
        print "Le contenu doit être compris entre",
        print self.lgmin,
        print "et",
        print self.lgmax,
        print "caractères."

    def info(self):
        ObjetElement.info(self)
        print "  taille       = %d"%self.tailletexte()
        print "  nblignes     = %d"%len(self.lignes)
        print "  longueur min = %d"%self.lgmin
        print "  longueur max = %d"%self.lgmax

    def valide(self):
        niveau_validation = 2
        taille_totale = self.tailletexte()
        if taille_totale < self.lgmin:            
            print "Erreur de validation"
            print "Élément <%s>: contenu trop court (%d)"%(self.motcle,taille_totale) 
            self.modeleContenu()
            niveau_validation = 0
        elif taille_totale > self.lgmax:
            print "Erreur de validation"
            print "Élément <%s>: contenu trop long (%d)"%(self.motcle,taille_totale) 
            self.modeleContenu()
            niveau_validation = 0
        return niveau_validation

    def lisDOM(self, node):
        niveau_validation = 0
        if node.nodeName != self.motcle:
            print "Erreur de lecture: l'element devrait etre un '%s'"%self.motcle
            print "  et non pas un '%s'"%node.nodeName            
            niveau_validation = -1
        for n in node.childNodes:
            if n.nodeName != '#text' and n.nodeName != 'rc':
                print "Erreur de lecture: les éléments fils de '%s'"%self.motcle
                print "  doivent etre de type '#text' ou 'rc'"
                print "  et non pas un '%s'"%node.nodeName
                niveau_validation = -1
            elif n.nodeName == '#text':
                self.ajoute(n.nodeValue)
            elif n.nodeName == 'rc':
                self.ajouterc()
        return niveau_validation
    
    def __init__(self, motcle):
        ObjetElement.__init__(self, motcle)
        self.lignes = []
        self.tailles = []

    def contenu(self):
        log = []
        pr = log.append
        if len(self.lignes) :
            for l in self.lignes[:-1]:
                pr(l)
                pr('\n')                
            pr(self.lignes[-1])
        str = ''.join(log).encode('iso-8859-1')
        return str
    
    def affiche(self):
        str = self.contenu()
        if len(str):
            print str
        
    def afficheXML(self):
        log = []
        pr = log.append        
        pr("<"+self.motcle+">")
        if len(self.lignes) :
            for l in self.lignes[:-1]:
                pr(l)
                pr('<rc/>')                
            pr(self.lignes[-1])
        pr("</"+self.motcle+">")
        print ''.join(log).encode('iso-8859-1')

    def afficheExempleXML(self):
        log = []
        pr = log.append        
        pr("<"+self.motcle+">")
        pr(self.exemple)
        pr("</"+self.motcle+">")
        print ''.join(log).encode('iso-8859-1')

    def tailletexte(self):
        taille = 0
        if len(self.lignes) > 1:
            taille = len(self.lignes) - 1
        for tailleligne in self.tailles:
            taille += tailleligne
        return taille

    def ajouterc(self):
        self.lignes.append('')
        self.tailles.append(0)

    def transcode(self, c):
        ajout = ''
        if c == '<':
            ajout = '&lt;'
        elif c == '>':
            ajout = '&gt;'
        elif c == '\'':
            ajout = '&apos;'
        elif c == '"':
            ajout = '&aquot;'
        elif c == '&':
            ajout = '&amp;'
        elif c == '\n':
            ajout = ''
        else:
            ajout = c
        return ajout

    def ajoute(self, texte):
        stexte = texte.strip()
        taille = 0
        textexml = ''
        for c in stexte:
            ajout = self.transcode(c)
            if ajout != '':
                textexml += ajout
                taille += 1
        if taille != 0:
            self.lignes.append(textexml)
            self.tailles.append(taille)

    def afficheHTMLFormWidget(self, identificateur, lignes, colonnes):
        if lignes != 0:
            l = lignes
        else:
            l = 3
        if colonnes != 0:
            c = colonnes
        else:
            c = 45
        n= identificateur+"/"+self.motcle
        if self.lgmax <= 70:
            print "<input",
            print "class=\"%s\""%self.motcle,
            print "type=\"text\"",
            print "name=\"%s\""%n,
            print "maxlength=\"%s\""%self.lgmax,
            print "size=\"%s\""%c,            
            print ">%s</input>"%self.contenu()
        else:
            print "<textarea",
            print "class=\"%s\""%self.motcle,
            print "wrap=\"soft\"",
            print "name=\"%s\""%n,
            print "cols=\"%s\""%c,
            print "rows=\"%s\""%l,
            print ">%s</textarea>"%self.contenu()
#
# Element de type 'num'
#
class ObjetElementNombre (ObjetElement):
    typecontenu = 'num'

    def modeleContenu(self):
        print "Le contenu doit être compris entre",
        print self.lgmin,
        print "et",
        print self.lgmax,
        print "chiffres."

    def info(self):
        ObjetElement.info(self)
        print "  taille       = %d"%len(str(self.valeur))
        print "  longueur min = %d"%self.lgmin
        print "  longueur max = %d"%self.lgmax
        
    def affiche(self):
        if len(str(self.valeur)):
            print str(self.valeur).encode('iso-8859-1')

    def valide(self):
        niveau_validation = 2
        t = str(self.valeur)
        taille_totale = len(t)
        if taille_totale < self.lgmin:            
            print "Erreur de validation"
            print "Élément <%s>: contenu trop court (%d)"%(self.motcle,taille_totale) 
            self.modeleContenu()
            niveau_validation = 0
        elif taille_totale > self.lgmax:
            print "Erreur de validation"
            print "Élément <%s>: contenu trop long (%d)"%(self.motcle,taille_totale) 
            self.modeleContenu()
            niveau_validation = 0
        ok = 1
        for c in t:
            if c < '0' or c > '9':
                ok = 0
        if ok == 0:
            print "Erreur de validation"
            print "Élément <%s>: contenu erroné"%self.motcle
            self.modeleContenu()
            niveau_validation = 0
        return niveau_validation

    def lisDOM(self, node):
        niveau_validation = 0
        if node.nodeName != self.motcle:
            print "Erreur de lecture: l'element devrait etre un '%s'"%self.motcle
            print "  et non pas un '%s'"%node.nodeName            
            niveau_validation = -1
        for n in node.childNodes:
            if n.nodeName != '#text':
                print "Erreur de lecture: les éléments fils de '%s'"%self.motcle
                print "  doivent etre de type '#text' ou 'rc'"
                print "  et non pas un '%s'"%node.nodeName
                niveau_validation = -1
            elif n.nodeName == '#text' and len(n.nodeValue) != 0:
                self.ajoute(n.nodeValue)
        return niveau_validation
            
    def __init__(self, motcle):
        ObjetElement.__init__(self, motcle)
        self.valeur = ''

    def afficheXML(self):
        log = []
        pr = log.append        
        pr("<"+self.motcle+">")
        pr(self.valeur)
        pr("</"+self.motcle+">")
        print ''.join(log).encode('iso-8859-1')
        
    def afficheExempleXML(self):
        log = []
        pr = log.append        
        pr("<"+self.motcle+">")
        pr(self.exemple)
        pr("</"+self.motcle+">")
        print ''.join(log).encode('iso-8859-1')
        
    def ajoute(self, v):
        sv = str(v).strip()
        self.valeur = sv

    def tailletexte(self):
        return len(self.valeur)

    def contenu(self):
        return self.valeur

    def afficheHTMLFormWidget(self, identificateur, lignes, colonnes):
        if lignes != 0:
            l = lignes
        else:
            l = 3
        if colonnes != 0:
            c = colonnes
        else:
            c = 45
        n= identificateur+"/"+self.motcle
        print "<input",
        print "class=\"%s\""%self.motcle,
        print "type=\"text\"",
        print "name=\"%s\""%n,
        print "maxlength=\"%s\""%self.lgmax,
        print "size=\"%s\""%self.lgmax,
        print ">%s</input>"%self.contenu()

#
# Element de type 'date'
#
class ObjetElementDate (ObjetElement):
    typecontenu = 'date'

    def modeleContenu(self):
        print "Le contenu doit avoir",
        print self.lgmax,
        print "chiffres."

    def info(self):
        ObjetElement.info(self)
        print "  taille       = %d"%len(str(self.valeur))
        print "  longueur min = %d"%self.lgmin
        print "  longueur max = %d"%self.lgmax

    def affiche(self):
        if len(str(self.valeur)):
            print str(self.valeur).encode('iso-8859-1')

    def valide(self):
        niveau_validation = 2
        t = str(self.valeur)
        taille_totale = len(t)
        if taille_totale < self.lgmin:            
            print "Erreur de validation"
            print "Élément <%s>: contenu trop court (%d)"%(self.motcle,taille_totale) 
            self.modeleContenu()
            niveau_validation = 0
        elif taille_totale > self.lgmax:
            print "Erreur de validation"
            print "Élément <%s>: contenu trop long (%d)"%(self.motcle,taille_totale) 
            self.modeleContenu()
            niveau_validation = 0
        ok = 1
        for c in t:
            if c < '0' or c > '9':
                ok = 0
        if ok == 0:
            print "Erreur de validation"
            print "Élément <%s>: contenu erroné"%self.motcle
            self.modeleContenu()
            niveau_validation = 0
        return niveau_validation

    def lisDOM(self, node):
        niveau_validation = 0
        if node.nodeName != self.motcle:
            print "Erreur de lecture: l'element devrait etre un '%s'"%self.motcle
            print "  et non pas un '%s'"%node.nodeName            
            niveau_validation = -1
        for n in node.childNodes:
            if n.nodeName != '#text':
                print "Erreur de lecture: les éléments fils de '%s'"%self.motcle
                print "  doivent etre de type '#text' ou 'rc'"
                print "  et non pas un '%s'"%node.nodeName
                niveau_validation = -1
            elif n.nodeName == '#text' and len(n.nodeValue) != 0:
                self.ajoute(n.nodeValue)
        return niveau_validation
            
    def __init__(self, motcle):
        self.valeur = ''
        ObjetElement.__init__(self, motcle)
        
    def afficheXML(self):
        log = []
        pr = log.append        
        pr("<"+self.motcle+">")
        pr(self.valeur)
        pr("</"+self.motcle+">")
        #print ''.join(log)
        print ''.join(log).encode('iso-8859-1')
        
    def afficheExempleXML(self):
        log = []
        pr = log.append        
        pr("<"+self.motcle+">")
        pr(self.exemple)
        pr("</"+self.motcle+">")
        #print ''.join(log)
        print ''.join(log).encode('iso-8859-1')

    def ajoute(self, v):
        sv = str(v).strip()
        self.valeur = sv

    def tailletexte(self):
        return len(self.valeur)

    def contenu(self):
        return self.valeur

    def afficheHTMLFormWidget(self, identificateur, lignes, colonnes):
        if lignes != 0:
            l = lignes
        else:
            l = 3
        if colonnes != 0:
            c = colonnes
        else:
            c = 45
        n= identificateur+"/"+self.motcle
        print "<input",
        print "class=\"%s\""%self.motcle,
        print "type=\"text\"",
        print "name=\"%s\""%n,
        print "maxlength=\"%s\""%self.lgmax,
        print "size=\"%s\""%self.lgmax,
        print ">%s</input>"%self.contenu()

#
# Element de type 'code'
#
class ObjetElementCode (ObjetElement):
    typecontenu = 'code'

    def modeleContenu(self):
        print "Le contenu doit être une code de",
        print self.lgmin,
        print "à",
        print self.lgmax,
        print "caractères."

    def info(self):
        ObjetElement.info(self)
        print "  taille       = %d"%len(str(self.valeur))
        print "  table        = '%s'"%self.table
        print "  longueur min = %d"%self.lgmin
        print "  longueur max = %d"%self.lgmax

    def affiche(self):
        if len(str(self.valeur)):
            print str(self.valeur).encode('iso-8859-1')
            
    def valide(self):
        niveau_validation = 1
        t = str(self.valeur)
        taille_totale = len(t)
        if taille_totale < self.lgmin:            
            print "Erreur de validation"
            print "Élément <%s>: contenu trop court (%d)"%(self.motcle,taille_totale) 
            self.modeleContenu()
            niveau_validation = 0
        elif taille_totale > self.lgmax:
            print "Erreur de validation"
            print "Élément <%s>: contenu trop long (%d)"%(self.motcle,taille_totale) 
            self.modeleContenu()
            niveau_validation = 0
        if self.contenutable.has_key(t) and niveau_validation == 1:
            niveau_validation = 2
        else:
            print "Avertissement: code '%s' non trouvé dans la table '%s'"%(t,self.table)
        return niveau_validation

    def lisDOM(self, node):
        niveau_validation = 0
        if node.nodeName != self.motcle:
            print "Erreur de lecture: l'element devrait etre un '%s'"%self.motcle
            print "  et non pas un '%s'"%node.nodeName            
            niveau_validation = -1
        for n in node.childNodes:
            if n.nodeName != '#text' and n.nodeName != 'rc':
                print "Erreur de lecture: les éléments fils de '%s'"%self.motcle
                print "  doivent etre de type '#text' ou 'rc'"
                print "  et non pas un '%s'"%node.nodeName
                niveau_validation = -1
            elif n.nodeName == '#text' and len(n.nodeName) > 0:
                self.ajoute(n.nodeValue)
        return niveau_validation
            
    def __init__(self, motcle, table):
        ObjetElement.__init__(self, motcle)
        self.valeur = ''        
        self.table = table
        
    def afficheXML(self):
        log = []
        pr = log.append        
        pr("<"+self.motcle+">")
        pr(self.valeur)
        pr("</"+self.motcle+">")
        print ''.join(log).encode('iso-8859-1')
        
    def afficheExempleXML(self):
        log = []
        pr = log.append        
        pr("<"+self.motcle+">")
        pr(self.exemple)
        pr("</"+self.motcle+">")
        print ''.join(log).encode('iso-8859-1')

    def ajoute(self, v):
        sv = str(v).strip()
        self.valeur = sv

            
    def afficheHTMLFormWidget(self, identificateur, lignes, colonnes):
        if lignes != 0:
            l = lignes
        else:
            l = 3
        if colonnes != 0:
            c = colonnes
        else:
            c = 45
        n= identificateur+"/"+self.motcle
        print "<select",
        print "class=\"%s\""%self.motcle,
        print "name=\"%s\""%n,
        print ">"
        print "<option value=\"NC\">(Non précisé)</option>"
        for t in self.contenutable.keys():
            print "<option",
            print "value=\"%s\">%s</option>"%(t,self.contenutable[t])
        print "</select>"

#
# Element de type 'basic'
#
class ObjetElementBasic (ObjetElement):
    typecontenu = 'basic'

    def modeleContenu(self):
        print "Le contenu doit-être un élément %s", self.typedebase

    def valide(self):
        return self.element.valide()

    def info(self):
        ObjetElement.info(self)
        print "  typedebase   = '%s'"%self.typedebase
        
    def affiche(self):
        self.element.affiche()
 
    def lisDOM(self, node):
        niveau_validation = 0
        if node.nodeName != self.motcle:
            print "Erreur de lecture: l'element devrait etre un '%s'"%self.motcle
            print "  et non pas un '%s'"%node.nodeName            
            niveau_validation = -1
        nb = 0
        bt = ObjetElementNul()
        for n in node.childNodes:
            if n.nodeName != self.typedebase and n.nodeName != "#text":
                print "Erreur de lecture: l'élément fils de '%s'"%self.motcle
                print "  doit etre de type '%s'"%self.typedebase
                print "  et non pas un '%s'"%n.nodeName
                niveau_validation = -1
                break
            elif n.nodeName == self.typedebase:
                nb = nb + 1
                bt = n
        if nb == 1:
            niveau_validation = self.element.lisDOM(bt)
        else:
            print "Erreur de lecture: il doit y avoir un seul élément '%s'"%self.typedebase
            print " comme élément fils de '%s'"%self.motcle
        return niveau_validation
    
    def __init__(self, motcle, element):
        ObjetElement.__init__(self, motcle)
        self.element = element
        
    def afficheXML(self):
        print("<"+self.motcle+">")        
        self.element.afficheXML()
        print("</"+self.motcle+">")

    def afficheExempleXML(self):
        print("<"+self.motcle+">")        
        self.element.afficheExempleXML()
        print("</"+self.motcle+">")

    def ajoute(self, element):
        self.element = element

#
# Element de type 'any'
#
class ObjetElementAny (ObjetElement):
    typecontenu = 'any'

    def modeleContenu(self):
        print "Le contenu peut-être n'importe quel élément"

    def valide(self):
        return 2

    def lisDOM(self, node):
        niveau_validation = 0
        if len(node.childNodes)>1:
            print "Avertissement: contenu dans un élément <extra...>"
            niveau_validation = -1
        return niveau_validation

    def __init__(self, motcle):
        ObjetElement.__init__(self, motcle)
        
    def afficheXML(self):
        pass

    def afficheExempleXML(self):
        pass

#
# Element de type 'reference'
#
class ObjetElementReference (ObjetElement):
    typecontenu = 'reference'

    def modeleContenu(self):
        print "Le contenu est vide, avec un attribut référençant l'id d'un autre élément."

    def valide(self):
        return 2

    def lisDOM(self, node):
        niveau_validation = 0
        if len(node.childNodes)>1:
            print "Avertissement: utilisation d'un élément 'reference'"
            niveau_validation = -1
        return niveau_validation
    
    def __init__(self, motcle, reference):
        ObjetElement.__init__(self, motcle)
        self.reference = reference
        
    def afficheXML(self):
        print("<"+self.motcle+' ref="%s"/>', self.reference)
        
    def afficheExempleXML(self):
        pass

#
# Element de type 'sequence'
#
class ObjetElementSequence (ObjetElement):
    typecontenu = 'sequence'

    def modeleContenu(self):
        print "Cet objet contient une sequence d'éléments:"
        j = 0
        for i in self.elements:
            if self.options[j] > 0:
                print j, ": <"+i+">*"
            else:
                print j, ": <"+i+">"
            j += 1

    def info(self):
        ObjetElement.info(self)
        j = 0
        for i in self.elements:
            print "  sequence[%d] (%s):"%(j,i),
            print self.sequence[j].motcle
            j += 1
        
    def affiche(self):
        for i in self.sequence:
            i.affiche()
                
    def __init__(self, motcle, elements, options):
        ObjetElement.__init__(self, motcle)
        self.elements = elements
        self.options = options
        self.sequence = []
        
    def afficheXML(self):
        print("<"+self.motcle+">")
        for e in self.sequence:
            e.afficheXML()
        print("</"+self.motcle+">")        

    def afficheExempleXML(self):
        print("<"+self.motcle+">")
        for e in self.sequence:
            e.afficheExempleXML()
        print("</"+self.motcle+">")        

    def valide(self):
        niveau_validation = 2
        for e in self.sequence:
            val = e.valide()
            if val < 2:
                niveau_validation = val
        return niveau_validation

    def lisDOM(self, node):
        niveau_validation = 0
        if node.nodeName != self.motcle:
            print "Erreur de lecture: l'element devrait etre un '%s'"%self.motcle
            print "  et non pas un '%s'"%node.nodeName            
            niveau_validation = -1

        # Calcule le nombre d'éléments obligatoires de la séquence
        nbobli = 0
        for t in self.options:
            if t == 0: nbobli += 1

        # Récupère les éléments de la séquence lus dans le fichier XML
        types = []
        for n in node.childNodes:
            if n.nodeName != "#text":
                types.append(n)
                
        # vérifie qu'il y a au moins le nombre d'éléments obligatoires
        if len(types) < nbobli:
            print "Erreur de lecture: l'element '%s' a %d éléments fils obligatoires"%(self.motcle,nbobli)
            niveau_validation = -1
        # si il y a un nombre "plausible" éléments dans la séquence
        elif len(types) <= len(self.elements):
            # vérifie le type de chaque élément de la séquence
            i = 0 # indice des types
            j = 0 # indices des elements
            while i < len(types) and j < len(self.elements):                
                if types[i].nodeName == self.elements[j]:
                    i = i + 1
                j = j + 1
            if i < len(types):
                print "Erreur de lecture: les elements de la sequence dans '%s'"%self.motcle
                print "  ne sont pas du bon type (i=%d,j=%d)"%(i,j)
                self.modeleContenu()
                niveau_validation = -1
        else:
            print "Erreur de lecture: l'element '%s' a trop d'éléments fils"%(self.motcle)
            niveau_validation = -1
        
        if niveau_validation >= 0:
            i = 0
            while i < len(types):
                n = types[i]
                o = cree_element_objet(n.nodeName)
                v = o.lisDOM(n)
                self.ajoute(o)
                if v < niveau_validation:
                    niveau_validation = v
                i = i + 1
        return niveau_validation

#
# Element de type 'liste'
#
class ObjetElementListe (ObjetElement):
    typecontenu = 'liste'
    
    def modeleContenu(self):
        print "Cet objet contient une liste:"
        print "<%s> [%d,%d]"%(self.typedeliste,self.lgmin,self.lgmax)
        print "La longueur actuelle est de %d objets."%len(self.liste)

    def info(self):
        ObjetElement.info(self)
        print "  longueur     = %d"%len(self.liste)
        print "  typedeliste  = '%s'"%self.typedeliste
        print "  longueur min = %d"%self.lgmin
        print "  longueur max = %d"%self.lgmax
        
    def affiche(self):
        for i in self.liste:
            i.affiche()
    
    def valide(self):
        niveau_validation = 2
        taille_totale = len(self.liste)
        if taille_totale < self.lgmin:            
            print "Erreur de validation"
            print "Élément <%s>: contenu trop court (%d)"%(self.motcle,taille_totale) 
            self.modeleContenu()
            niveau_validation = 0
        elif self.lgmax >= 1 and taille_totale > self.lgmax:
            print "Erreur de validation"
            print "Élément <%s>: contenu trop long (%d)"%(self.motcle,taille_totale) 
            self.modeleContenu()
            niveau_validation = 0
        for e in self.liste:
            val = e.valide()
            if val < 2:
                niveau_validation = val
        return niveau_validation
    
    def __init__(self, motcle, element, typedeliste):
        ObjetElement.__init__(self, motcle)
        self.liste = []
        self.liste.append(element)
        self.typedeliste = typedeliste
        
    def afficheXML(self):
        print("<"+self.motcle+">")
        for e in self.liste:
            e.afficheXML()
        print("</"+self.motcle+">")        

    def afficheExempleXML(self):
        print("<"+self.motcle+">")
        for e in self.liste:
            e.afficheExempleXML()
        print("</"+self.motcle+">")        

    def lisDOM(self, node):
        niveau_validation = 0
        if node.nodeName != self.motcle:
            print "Erreur de lecture: l'element devrait etre un '%s'"%self.motcle
            print "  et non pas un '%s'"%node.nodeName            
            niveau_validation = -1
        l = []
        for n in node.childNodes:
            if n.nodeName != "#text" and n.nodeName != self.typedeliste:
                print "Erreur: l'element devrait etre un '%s'"%self.typedeliste
            elif n.nodeName != "#text":
                l.append(n)
        self.liste = []
        for n in l:
            o = cree_element_objet(self.typedeliste)
            v = o.lisDOM(n)
            self.liste.append(o)
            if v < niveau_validation:
                niveau_validation = v
        return niveau_validation


#
# @element: code-FORMACODE
#
class Element_code_FORMACODE (ObjetElementCode):
  def __init__(self):    
    self.glossaire = ""
    self.lgmin = 5
    self.lgmax = 5
    self.libelle = """Code FORMACODE"""
    self.commentaire = """Code FORMACODE pour décrire le domaine de formation."""
    self.exemple = """22477"""
    ObjetElementCode.__init__(self,'code-FORMACODE', 'FORMACODE')
    self.contenutable = {'46278' : "PHOTOGRAPHIE", '42079' : "SERVICE MAISON", '21295' : "ENGIN FORESTIER", '21223' : "VITICULTURE", '21258' : "CULTURE LEGUMIERE", '21056' : "ELEVAGE", '42077' : "CASINO", '42050' : "COIFFURE", '43485' : "ASSISTANCE DENTAIRE", '42837' : "POLICE GENDARMERIE"    }

#
# @element: code-ROME
#
class Element_code_ROME (ObjetElementCode):
  def __init__(self):    
    self.glossaire = ""
    self.lgmin = 5
    self.lgmax = 5
    self.libelle = """Code ROME"""
    self.commentaire = """Code ROME pour décrire le domaine de formation."""
    self.exemple = """21131"""
    ObjetElementCode.__init__(self,'code-ROME', 'ROME')
    self.contenutable = {'21131' : "PHOTOGRAPHE", '12121' : "AGENT ADMINISTRATIF D'ENTREPRISE", '14225' : "VENDEUR EN PX CULTURELS ET LUDIQUES", '32214' : "SPECIALISTE DE LA GESTION DE L'INFORMATION", '32311' : "INFORMATICIEN D'EXPLOITATION", '32321' : "INFORMATICIEN D'ETUDE", '32331' : "INFORMATICIEN EXPERT", '32341' : "ORGANISATEUR INFORMATICIEN", '44213' : "INTERCONNECTEUR EN ELECTRONIQUE"    }

#
# @element: codes-FORMACODE
#
class Element_codes_FORMACODE (ObjetElementListe):
  def __init__(self):    
    self.glossaire = ""
    self.lgmin = 1
    self.lgmax = 5
    self.libelle = """Liste de codes FORMACODE"""
    self.commentaire = """
	Liste de codes FORMACODE.
      """
    ObjetElementListe.__init__(self,'codes-FORMACODE', Element_code_FORMACODE(), 'code-FORMACODE')

  def ajoute(self, element):
    if isinstance(element, Element_code_FORMACODE):
        self.liste.append(element)
    else:
        print "Erreur d'ajout, élément du mauvais type."

#
# @element: codes-ROME
#
class Element_codes_ROME (ObjetElementListe):
  def __init__(self):    
    self.glossaire = ""
    self.lgmin = 1
    self.lgmax = 5
    self.libelle = """Liste de codes ROME"""
    self.commentaire = """
	Liste de codes ROME.
      """
    ObjetElementListe.__init__(self,'codes-ROME', Element_code_ROME(), 'code-ROME')

  def ajoute(self, element):
    if isinstance(element, Element_code_ROME):
        self.liste.append(element)
    else:
        print "Erreur d'ajout, élément du mauvais type."

#
# @element: departement
#
class Element_departement (ObjetElementCode):
  def __init__(self):    
    self.glossaire = ""
    self.lgmin = 1
    self.lgmax = 3
    self.libelle = """Département"""
    self.commentaire = """
	Cet élément contient un numéro de département.
      """
    self.exemple = """68"""
    ObjetElementCode.__init__(self,'departement', 'departements-france')
    self.contenutable = {'1' : "Ain", '01' : "Ain", '001' : "Ain", '2' : "Aisne", '02' : "Aisne", '002' : "Aisne", '3' : "Allier", '03' : "Allier", '003' : "Allier", '4' : "Alpes de Haute-Provence", '04' : "Alpes de Haute-Provence", '004' : "Alpes de Haute-Provence", '5' : "Hautes-Alpes", '05' : "Hautes-Alpes", '005' : "Hautes-Alpes", '6' : "Alpes-Maritimes", '06' : "Alpes-Maritimes", '006' : "Alpes-Maritimes", '7' : "Ardèche", '07' : "Ardèche", '007' : "Ardèche", '8' : "Ardennes", '08' : "Ardennes", '008' : "Ardennes", '9' : "Ariège", '09' : "Ariège", '009' : "Ariège", '10' : "Aube", '010' : "Aube", '11' : "Aude", '011' : "Aude", '12' : "Aveyron", '012' : "Aveyron", '13' : "Bouches-du-Rhône", '013' : "Bouches-du-Rhône", '14' : "Calvados", '014' : "Calvados", '15' : "Cantal", '015' : "Cantal", '16' : "Charente", '016' : "Charente", '17' : "Charente-Maritime", '017' : "Charente-Maritime", '18' : "Cher", '018' : "Cher", '19' : "Corrèze", '019' : "Corrèze", '20' : "Corse", '020' : "Corse", '21' : "Côte-d'Or", '021' : "Côte-d'Or", '22' : "Côtes-d'Armor", '022' : "Côtes-d'Armor", '23' : "Creuse", '023' : "Creuse", '24' : "Dordogne", '024' : "Dordogne", '25' : "Doubs", '025' : "Doubs", '26' : "Drôme", '026' : "Drôme", '27' : "Eure", '027' : "Eure", '28' : "Eure-et-Loir", '028' : "Eure-et-Loir", '29' : "Finistère", '029' : "Finistère", '30' : "Gard", '030' : "Gard", '31' : "Haute-Garonne", '031' : "Haute-Garonne", '32' : "Gers", '032' : "Gers", '33' : "Gironde", '033' : "Gironde", '34' : "Hérault", '034' : "Hérault", '35' : "Ille-et-Vilaine", '035' : "Ille-et-Vilaine", '36' : "Indre", '036' : "Indre", '37' : "Indre-et-Loire", '037' : "Indre-et-Loire", '38' : "Isère", '038' : "Isère", '39' : "Jura", '039' : "Jura", '40' : "Landes", '040' : "Landes", '41' : "Loir-et-Cher", '041' : "Loir-et-Cher", '42' : "Loire", '042' : "Loire", '43' : "Haute-Loire", '043' : "Haute-Loire", '44' : "Loire-Atlantique", '044' : "Loire-Atlantique", '45' : "Loiret", '045' : "Loiret", '46' : "Lot", '046' : "Lot", '47' : "Lot-et-Garonne", '047' : "Lot-et-Garonne", '48' : "Lozère", '048' : "Lozère", '49' : "Maine-et-Loire", '049' : "Maine-et-Loire", '50' : "Manche", '050' : "Manche", '51' : "Marne", '051' : "Marne", '52' : "Haute-Marne", '052' : "Haute-Marne", '53' : "Mayenne", '053' : "Mayenne", '54' : "Meurthe-et-Moselle", '054' : "Meurthe-et-Moselle", '55' : "Meuse", '055' : "Meuse", '56' : "Morbihan", '056' : "Morbihan", '57' : "Moselle", '057' : "Moselle", '58' : "Nièvre", '058' : "Nièvre", '59' : "Nord", '059' : "Nord", '60' : "Oise", '060' : "Oise", '61' : "Orne", '061' : "Orne", '62' : "Pas-de-Calais", '062' : "Pas-de-Calais", '63' : "Puy-de-Dôme", '063' : "Puy-de-Dôme", '64' : "Pyrénées-Atlantiques", '064' : "Pyrénées-Atlantiques", '65' : "Hautes-Pyrénées", '065' : "Hautes-Pyrénées", '66' : "Pyrénées-Orientales", '066' : "Pyrénées-Orientales", '67' : "Bas-Rhin", '067' : "Bas-Rhin", '68' : "Haut-Rhin", '068' : "Haut-Rhin", '69' : "Rhône", '069' : "Rhône", '70' : "Haute-Saône", '070' : "Haute-Saône", '71' : "Saône-et-Loire", '071' : "Saône-et-Loire", '72' : "Sarthe", '072' : "Sarthe", '73' : "Savoie", '073' : "Savoie", '74' : "Haute-Savoie", '074' : "Haute-Savoie", '75' : "Paris", '075' : "Paris", '76' : "Seine-Maritime", '076' : "Seine-Maritime", '77' : "Seine-et-Marne", '077' : "Seine-et-Marne", '78' : "Yvelines", '078' : "Yvelines", '79' : "Deux-Sèvres", '079' : "Deux-Sèvres", '80' : "Somme", '080' : "Somme", '81' : "Tarn", '081' : "Tarn", '82' : "Tarn-et-Garonne", '082' : "Tarn-et-Garonne", '83' : "Var", '083' : "Var", '84' : "Vaucluse", '084' : "Vaucluse", '85' : "Vendée", '085' : "Vendée", '86' : "Vienne", '086' : "Vienne", '87' : "Haute-Vienne", '087' : "Haute-Vienne", '88' : "Vosges", '088' : "Vosges", '89' : "Yonne", '089' : "Yonne", '90' : "Territoire de Belfort", '090' : "Territoire de Belfort", '91' : "Essonne", '091' : "Essonne", '92' : "Hauts-de-Seine", '092' : "Hauts-de-Seine", '93' : "Seine-Saint-Denis", '093' : "Seine-Saint-Denis", '94' : "Val-de-Marne", '094' : "Val-de-Marne", '95' : "Val-d'Oise", '095' : "Val-d'Oise", '971' : "Guadeloupe", '972' : "Martinique", '973' : "Guyane", '974' : "Réunion", '975' : "Saint-Pierre-et-Miquelon", '976' : "Mayotte"    }

#
# @element: departement-lieu-de-formation
#
class Element_departement_lieu_de_formation (ObjetElementBasic):
  def __init__(self):    
    self.cercle = '0'
    self.atomique = '0'
    self.typedebase = 'departement'
    self.base = 'non'
    self.glossaire = ""
    ObjetElementBasic.__init__(self,'departement-lieu-de-formation', Element_departement())

#
# @element: diplomante
#
class Element_diplomante (ObjetElementCode):
  def __init__(self):    
    self.cercle = '1'
    self.atomique = '1'
    self.base = 'non'
    self.glossaire = "diplome"
    self.lgmin = 1
    self.lgmax = 1
    self.libelle = """Formation diplômante"""
    self.commentaire = """
	Cet élément indique si la formation est diplomante ou
	non. Validation: si la formation est diplomante, on devrait
	retrouver dans l'intitulé de l'action (élément
	'intitule-action') ou les résultats attendus (élément
	'resultats-attendus') la description d'un diplôme.
      """
    self.exemple = """1"""
    ObjetElementCode.__init__(self,'diplomante', 'boolean')
    self.contenutable = {'0' : "non", '1' : "oui"    }

#
# @element: intitule-action
#
class Element_intitule_action (ObjetElementTexte):
  def __init__(self):    
    self.cercle = '1'
    self.atomique = '1'
    self.base = 'non'
    self.glossaire = "intitule-action"
    self.lgmin = 1
    self.lgmax = 255
    self.nomenclature = """référence aux tables de l'Éducation nationale pour
    les diplômes et au RNCP pour les titres
    professionnels"""
    self.libelle = """Intitulé de l'action ou de la certification préparée"""
    self.commentaire = """
	Cet élément décrit l'intitulé de l'action ou la certification
	préparée. Si c'est un diplôme, faire référence aux tables de
	l'éducation nationale. Si c'est un titre, faire référence au
	RNCP.
      """
    self.exemple = """CAP Photographe"""
    ObjetElementTexte.__init__(self,'intitule-action')

#
# @element: lheo-requete
#
class Element_lheo_requete (ObjetElementSequence):
  def __init__(self):    
    self.cercle = '0'
    self.atomique = '0'
    self.base = 'non'
    self.glossaire = ""
    self.libelle = """Requête permettant d'effectuer une recherche sur des offres"""
    self.commentaire = """
	Cet élément permet de modéliser une requête dans une base
	d'offres en LHÉO/XML ou une base d'offres résumées en
	LHÉO-LÉGER/XML. L'élément 'nombre-offres' permet d'indiquer le
	nombre maximal d'offres à retourner. Par rapport aux niveaux de
	validation LHÉO/XML, certains champs de cette requête en
	LHÉO-REQUÊTE peuvent être vides. Les éléments
	'prise-en-charge-frais-possible' (1),
	'departement-lieu-de-formation' (2) et 'diplomante' (3)
	doivent correspondre exactement aux champs correspondant dans
	une offre ou un résumé d'offre. Pour la recherche, on fait un
	ET de ces trois premiers critères (uniquement pour ceux qui ne
	sont pas vides). Pour les deux éléments 'codes-FORMACODE' (4)
	et 'codes-ROME' (5), on fait un OU des différents codes
	présents. On fait ensuite un ET avec les éléments précédents.
	Les quatre éléments 'intitule-action' (6),
	'resultats-attendus' (7), 'ville-lieu-de-formation' (8) et
	'nom-organisme' (9) peuvent contenir des caractères (3 au
	minimum) qui seront recherchés dans les offres ou les résumés
	d'offres.  La formule complète est donc (1) ET (2) ET (3) ET
	((4) OU (5)) ET (6) ET (7) ET (8) ET (9). Au moins un des
	éléments doit être non nul.
      """
    ObjetElementSequence.__init__(self,'lheo-requete', ['nombre-offres', 'codes-FORMACODE', 'codes-ROME', 'prise-en-charge-frais-possible', 'departement-lieu-de-formation', 'diplomante', 'intitule-action', 'resultats-attendus', 'ville-lieu-de-formation', 'nom-organisme'], [0, 1, 1, 1, 1, 1, 1, 1, 1, 1])
    self.sequence = [ Element_nombre_offres(), ObjetElementNul(), ObjetElementNul(), ObjetElementNul(), ObjetElementNul(), ObjetElementNul(), ObjetElementNul(), ObjetElementNul(), ObjetElementNul(), ObjetElementNul() ]

  def ajoute(self, element):
    if isinstance(element, Element_nombre_offres):
      self.sequence[0] = element
    elif isinstance(element, Element_codes_FORMACODE):
      self.sequence[1] = element
    elif isinstance(element, Element_codes_ROME):
      self.sequence[2] = element
    elif isinstance(element, Element_prise_en_charge_frais_possible):
      self.sequence[3] = element
    elif isinstance(element, Element_departement_lieu_de_formation):
      self.sequence[4] = element
    elif isinstance(element, Element_diplomante):
      self.sequence[5] = element
    elif isinstance(element, Element_intitule_action):
      self.sequence[6] = element
    elif isinstance(element, Element_resultats_attendus):
      self.sequence[7] = element
    elif isinstance(element, Element_ville_lieu_de_formation):
      self.sequence[8] = element
    elif isinstance(element, Element_nom_organisme):
      self.sequence[9] = element
    else:
        print "Erreur d'ajout, élément du mauvais type."
	self.modeleContenu()

#
# @element: nom-organisme
#
class Element_nom_organisme (ObjetElementTexte):
  def __init__(self):    
    self.cercle = '1'
    self.atomique = '1'
    self.base = 'non'
    self.glossaire = "nom-organisme"
    self.lgmin = 1
    self.lgmax = 250
    self.libelle = """Nom de l'organisme de formation"""
    self.commentaire = """
	Cet élément décrit le nom usuel de l'organisme responsable de
	la formation.
      """
    self.exemple = """Centre de formation d'apprentis académique (CFA)"""
    ObjetElementTexte.__init__(self,'nom-organisme')

#
# @element: nombre-offres
#
class Element_nombre_offres (ObjetElementNombre):
  def __init__(self):    
    self.cercle = '0'
    self.atomique = '0'
    self.base = 'non'
    self.glossaire = ""
    self.lgmin = 1
    self.lgmax = 5
    self.libelle = """Nombre de résumés d'offres de formation"""
    ObjetElementNombre.__init__(self,'nombre-offres')

#
# @element: prise-en-charge-frais-possible
#
class Element_prise_en_charge_frais_possible (ObjetElementCode):
  def __init__(self):    
    self.cercle = '1'
    self.atomique = '1'
    self.base = 'non'
    self.glossaire = "prise-charge-frais"
    self.lgmin = 1
    self.lgmax = 1
    self.libelle = """Prise en charge des frais de formation possible"""
    self.commentaire = """
	Cet élément indique si une prise en charge des frais de
	formation est possible (renvoi vers les conseillers en charge
	de l'élaboration des parcours).
      """
    self.exemple = """1"""
    ObjetElementCode.__init__(self,'prise-en-charge-frais-possible', 'boolean')
    self.contenutable = {'0' : "non", '1' : "oui"    }

#
# @element: resultats-attendus
#
class Element_resultats_attendus (ObjetElementTexte):
  def __init__(self):    
    self.cercle = '1'
    self.atomique = '1'
    self.base = 'non'
    self.glossaire = "resultats-formation"
    self.lgmin = 1
    self.lgmax = 200
    self.nomenclature = """référence aux tables de l'Éducation nationale pour
    les diplômes et au RNCP pour les titres
    professionnels"""
    self.libelle = """Résultats attendus de la formation"""
    self.commentaire = """
	Cet élément décrit les résultats attendus de la formation
	(titre, diplôme, certificat, attestation, ...). Si c'est un
	diplôme, faire référence aux tables de l'éducation
	nationale. Si c'est un titre, faire référence au
	RNCP.
      """
    self.exemple = """CAP Photographe"""
    ObjetElementTexte.__init__(self,'resultats-attendus')

#
# @element: ville
#
class Element_ville (ObjetElementTexte):
  def __init__(self):    
    self.glossaire = ""
    self.lgmin = 1
    self.lgmax = 50
    self.libelle = """Ville"""
    self.commentaire = """
	Cet élément contient un nom de ville. Validation: vérifier
	l'adéquation entre l'élément 'ville' et le contenu de
	l'élément 'codepostal'.
      """
    self.exemple = """Lyon"""
    ObjetElementTexte.__init__(self,'ville')

#
# @element: ville-lieu-de-formation
#
class Element_ville_lieu_de_formation (ObjetElementBasic):
  def __init__(self):    
    self.cercle = '0'
    self.atomique = '0'
    self.typedebase = 'ville'
    self.base = 'non'
    self.glossaire = ""
    ObjetElementBasic.__init__(self,'ville-lieu-de-formation', Element_ville())
def dom2objet(node):
  objet = ObjetElementNul()
  if node.nodeName=='code-FORMACODE':
    objet = Element_code_FORMACODE()
    nv = objet.lisDOM(node)
    if nv != 0:
      raise ErreurDeValidation
  elif node.nodeName=='code-ROME':
    objet = Element_code_ROME()
    nv = objet.lisDOM(node)
    if nv != 0:
      raise ErreurDeValidation
  elif node.nodeName=='codes-FORMACODE':
    objet = Element_codes_FORMACODE()
    nv = objet.lisDOM(node)
    if nv != 0:
      raise ErreurDeValidation
  elif node.nodeName=='codes-ROME':
    objet = Element_codes_ROME()
    nv = objet.lisDOM(node)
    if nv != 0:
      raise ErreurDeValidation
  elif node.nodeName=='departement':
    objet = Element_departement()
    nv = objet.lisDOM(node)
    if nv != 0:
      raise ErreurDeValidation
  elif node.nodeName=='departement-lieu-de-formation':
    objet = Element_departement_lieu_de_formation()
    nv = objet.lisDOM(node)
    if nv != 0:
      raise ErreurDeValidation
  elif node.nodeName=='diplomante':
    objet = Element_diplomante()
    nv = objet.lisDOM(node)
    if nv != 0:
      raise ErreurDeValidation
  elif node.nodeName=='intitule-action':
    objet = Element_intitule_action()
    nv = objet.lisDOM(node)
    if nv != 0:
      raise ErreurDeValidation
  elif node.nodeName=='lheo-requete':
    objet = Element_lheo_requete()
    nv = objet.lisDOM(node)
    if nv != 0:
      raise ErreurDeValidation
  elif node.nodeName=='nom-organisme':
    objet = Element_nom_organisme()
    nv = objet.lisDOM(node)
    if nv != 0:
      raise ErreurDeValidation
  elif node.nodeName=='nombre-offres':
    objet = Element_nombre_offres()
    nv = objet.lisDOM(node)
    if nv != 0:
      raise ErreurDeValidation
  elif node.nodeName=='prise-en-charge-frais-possible':
    objet = Element_prise_en_charge_frais_possible()
    nv = objet.lisDOM(node)
    if nv != 0:
      raise ErreurDeValidation
  elif node.nodeName=='resultats-attendus':
    objet = Element_resultats_attendus()
    nv = objet.lisDOM(node)
    if nv != 0:
      raise ErreurDeValidation
  elif node.nodeName=='ville':
    objet = Element_ville()
    nv = objet.lisDOM(node)
    if nv != 0:
      raise ErreurDeValidation
  elif node.nodeName=='ville-lieu-de-formation':
    objet = Element_ville_lieu_de_formation()
    nv = objet.lisDOM(node)
    if nv != 0:
      raise ErreurDeValidation
  return objet
def cree_element_objet(nom):
  objet = ObjetElementNul()
  if nom=='code-FORMACODE':
    objet = Element_code_FORMACODE()
  elif nom=='code-ROME':
    objet = Element_code_ROME()
  elif nom=='codes-FORMACODE':
    objet = Element_codes_FORMACODE()
  elif nom=='codes-ROME':
    objet = Element_codes_ROME()
  elif nom=='departement':
    objet = Element_departement()
  elif nom=='departement-lieu-de-formation':
    objet = Element_departement_lieu_de_formation()
  elif nom=='diplomante':
    objet = Element_diplomante()
  elif nom=='intitule-action':
    objet = Element_intitule_action()
  elif nom=='lheo-requete':
    objet = Element_lheo_requete()
  elif nom=='nom-organisme':
    objet = Element_nom_organisme()
  elif nom=='nombre-offres':
    objet = Element_nombre_offres()
  elif nom=='prise-en-charge-frais-possible':
    objet = Element_prise_en_charge_frais_possible()
  elif nom=='resultats-attendus':
    objet = Element_resultats_attendus()
  elif nom=='ville':
    objet = Element_ville()
  elif nom=='ville-lieu-de-formation':
    objet = Element_ville_lieu_de_formation()
  return objet
# $Id: lheo_fonctions.py,v 1.4 2004/09/23 15:51:14 silber Exp $

def litXML(stream):
    try:
        reader = Sax2.Reader()
        doc = reader.fromStream(stream)
    except:
        raise ErreurDeValidation()
    else:
        return doc.lastChild

def ouvreFichierXML(nom):
    fichier = open(nom, 'r')
    return litXML(fichier)

def ouvreLHEO(nom):
    d = ouvreFichierXML(nom)
    lheo = dom2objet(d)
    return lheo

def valide(objet):
    print "Validation de l'objet <%s>"%objet.motcle
    nv = objet.valide()
    if nv == 0:
        print "Objet valide au niveau 0 (DTD)"
    elif nv == 1:
        print "Objet valide au niveau 1 (0 + XML Schema + tailles)"
    elif nv == 2:
        print "Objet valide au niveau 2 (1 + Codes de tables)"
    else:
        print "Objet non valide !"
    return nv

def ouvreEtValideLHEO(nom):
    lheo = ouvreLHEO(nom)
    valide(lheo)
    return lheo

def formulaire2listeobjets(formulaire):
    listeelements=[]
    listeobjets=[]
    for entree in formulaire:
        listeelements.append(entree)
    for element in listeelements:
        val = formulaire[element].value
        if val != '' and val != 'NC':
            objet = cree_element_objet(element)
            objet.ajoute(val)
            listeobjets.append(objet)
    return listeobjets

def cgivalide(string):
    try:
        doc = litXML(StringIO(fichier_xml))
        l = dom2objet(doc)
    except:
        print "Erreur de validation !"
        print "Fichier LHEO/XML non valide par rapport à la DTD"
    else:
        nv = valide(l)
        if nv >= 0:
            print
            print "===================================="
            print " CONTENU DU FICHIER LHEO/XML "
            print "===================================="
            l.afficheXML()
