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

from xml.sax import saxutils

# Estados
E_CLASS         = 1
E_CLASS_NAME    = 2
E_CLASS_COMMENT = 3
E_ATTRS         = 4
E_ATTR          = 5
E_ATTR_NAME     = 6
E_ATTR_COMMENT  = 7
E_ATTR_TYPE     = 8

# Caracteres a eliminar
STRIPCHARS = '#\t\n '

class ObjFinder(saxutils.DefaultHandler):
    def __init__(self):
        self.estado = None
        self.clases = []
        self.curr = None
        self.curr_attr = None
    def startElement(self, name, attrs):
        #print " #### Start <%s %s>" % (name, dict(attrs))
        if name == 'dia:object': # Comienzo de una clase
            if attrs.get('type', None) == 'UML - Class':
                self.curr = {}
                self.estado = E_CLASS
        elif name == 'dia:attribute':
            name = attrs.get('name', None)
            if self.estado == E_CLASS:   # Datos de la clase
                if name == 'name':     # Nombre de la clase
                    self.curr['name'] = ''
                    self.estado = E_CLASS_NAME
                elif name == 'comment':  # Es la descripción de la clase
                    self.curr['comment'] = ''
                    self.estado = E_CLASS_COMMENT
                elif name == 'attributes': # Paso empezó a encontrar atributos
                    self.curr['attrs'] = []
                    self.estado = E_ATTRS
            elif self.estado == E_ATTR:  # Datos del atributo
                if name == 'name':       # Nombre del atributo
                    self.curr_attr['name'] = ''
                    self.estado = E_ATTR_NAME
                elif name == 'type':     # Es el tipo del atributo
                    self.curr_attr['type'] = ''
                    self.estado = E_ATTR_TYPE
                elif name == 'comment':  # Es la descripción del atributo
                    self.curr_attr['comment'] = ''
                    self.estado = E_ATTR_COMMENT
        elif name == 'dia:composite': # Comienzo de attributos de clase
            if self.estado == E_ATTRS:  # Si estoy en una clase
                self.curr_attr = {}
                self.estado = E_ATTR   # Paso a buscar sus atributos
    def characters(self, data):
        if self.estado == E_CLASS_NAME:
            self.curr['name'] += data.strip(STRIPCHARS)
        elif self.estado == E_CLASS_COMMENT:
            self.curr['comment'] += data.strip(STRIPCHARS)
        elif self.estado == E_ATTR_NAME:
            self.curr_attr['name'] += data.strip(STRIPCHARS)
        elif self.estado == E_ATTR_TYPE:
            self.curr_attr['type'] += data.strip(STRIPCHARS)
        elif self.estado == E_ATTR_COMMENT:
            self.curr_attr['comment'] += data.strip(STRIPCHARS)
    def endElement(self, name):
        #print " #### Endt </%s>" % name
        if name == 'dia:object':
            if self.estado == E_CLASS:
                self.clases.append(self.curr)
                self.estado = None
                self.curr = None
        elif name == 'dia:attribute':
            if self.estado == E_CLASS_NAME:
                self.estado = E_CLASS
            if self.estado == E_CLASS_COMMENT:
                self.estado = E_CLASS
            if self.estado == E_ATTR_NAME:
                self.estado = E_ATTR
            if self.estado == E_ATTR_TYPE:
                self.estado = E_ATTR
            if self.estado == E_ATTR_COMMENT:
                self.estado = E_ATTR
            if self.estado == E_ATTRS:
                self.estado = E_CLASS
        elif name == 'dia:composite':
            if self.estado == E_ATTR:
                self.curr['attrs'].append(self.curr_attr)
                self.curr_attr = None
                self.estado = E_ATTRS


if __name__ == '__main__':
    import sys
    from xml.sax import make_parser
    from xml.sax.handler import feature_namespaces

    # Verifica parámetros
    if len(sys.argv) < 2:
        print >>sys.stderr, 'Uso:', sys.argv[0], 'archivo.dia'
        sys.exit(1)

    # Create a parser
    parser = make_parser()

    # Tell the parser we are not interested in XML namespaces
    parser.setFeature(feature_namespaces, 0)

    # Create the handler
    dh = ObjFinder()

    # Tell the parser to use our handler
    parser.setContentHandler(dh)

    # Parse the input
    parser.parse(sys.argv[1])

    # Recorro clases obtenidas
    for c in dh.clases:
        print
        print 'Clase:', c['name']
        print 'Descripción:', c['comment']
        print 'Atributos:'
        for a in c['attrs']:
            print '    %(name)s (%(type)s): %(comment)s' % a


# vim: set et sw=4 sts=4 :
