]> git.llucax.com Git - z.facultad/75.10/miklolife.git/blob - carpeta/scripts/clases2spec.py
* Pasos finales ... la pucha que esta query me hace renegar :D
[z.facultad/75.10/miklolife.git] / carpeta / scripts / clases2spec.py
1 #!/usr/bin/env python
2 # -*- coding: iso-8859-1 -*-
3
4 from xml.sax import saxutils
5
6 # Estados
7 E_CLASS             = 1
8 E_CLASS_NAME        = 2
9 E_CLASS_COMMENT     = 3
10 E_ATTRS             = 4
11 E_ATTR              = 5
12 E_ATTR_NAME         = 6
13 E_ATTR_COMMENT      = 7
14 E_ATTR_TYPE         = 8
15 E_OPS               = 9
16 E_OP                = 10
17 E_OP_NAME           = 11
18 E_OP_COMMENT        = 12
19 E_OP_TYPE           = 13
20 E_OP_PARAMS         = 14
21 E_OP_PARAM          = 15
22 E_OP_PARAM_NAME     = 16
23 E_OP_PARAM_COMMENT  = 17
24 E_OP_PARAM_TYPE     = 18
25
26 # Caracteres a eliminar
27 STRIPCHARS = '#\t\n '
28
29 DEBUG = 0
30
31 def dprint(s):
32     if DEBUG: print >>sys.stderr, s.encode('iso-8859-1', 'replace')
33
34 class ObjFinder(saxutils.DefaultHandler):
35     def __init__(self):
36         self.estado = None
37         self.clases = []
38         self.curr = None
39         self.curr_attr = None
40         self.curr_op = None
41         self.curr_param = None
42     def startElement(self, name, attrs):
43         if name == 'dia:object': # Comienzo de una clase
44             if attrs.get('type', None) == 'UML - Class':
45                 self.curr = {}
46                 self.estado = E_CLASS
47                 dprint("E_CLASS (encontrado dia:object)")
48         elif name == 'dia:attribute':
49             name = attrs.get('name', None)
50             if self.estado == E_CLASS:   # Datos de la clase
51                 if name == 'name':     # Nombre de la clase
52                     self.curr['name'] = ''
53                     self.estado = E_CLASS_NAME
54                     dprint("E_CLASS -> E_CLASS_NAME (encontrado dia:attribute con name)")
55                 elif name == 'comment':  # Es la descripción de la clase
56                     self.curr['comment'] = ''
57                     self.estado = E_CLASS_COMMENT
58                     dprint("E_CLASS -> E_CLASS_COMMENT (encontrado dia:attribute con comment)")
59                 elif name == 'attributes': # Paso a encontrar atributos
60                     self.curr['attrs'] = []
61                     self.estado = E_ATTRS
62                     dprint("E_CLASS -> E_ATTRS (encontrado dia:attribute con attributes)")
63                 elif name == 'operations': # Paso a encontrar operaciones
64                     self.curr['ops'] = []
65                     self.estado = E_OPS
66                     dprint("E_CLASS -> E_OPS (encontrado dia:attribute con operations)")
67             elif self.estado == E_ATTR:  # Datos del atributo
68                 if name == 'name':       # Nombre del atributo
69                     self.curr_attr['name'] = ''
70                     self.estado = E_ATTR_NAME
71                     dprint("E_ATTR -> E_ATTR_NAME (encontrado dia:attribute con name)")
72                 elif name == 'type':     # Es el tipo del atributo
73                     self.curr_attr['type'] = ''
74                     self.estado = E_ATTR_TYPE
75                     dprint("E_ATTR -> E_ATTR_TYPE (encontrado dia:attribute con type)")
76                 elif name == 'comment':  # Es la descripción del atributo
77                     self.curr_attr['comment'] = ''
78                     self.estado = E_ATTR_COMMENT
79                     dprint("E_ATTR -> E_ATTR_COMMENT (encontrado dia:attribute con comment)")
80             elif self.estado == E_OP:    # Datos del atributo
81                 if name == 'name':       # Nombre del atributo
82                     self.curr_op['name'] = ''
83                     self.estado = E_OP_NAME
84                     dprint("E_OP -> E_OP_NAME (encontrado dia:attribute con name)")
85                 elif name == 'type':     # Es el tipo del atributo
86                     self.curr_op['type'] = ''
87                     self.estado = E_OP_TYPE
88                     dprint("E_OP -> E_OP_TYPE (encontrado dia:attribute con type)")
89                 elif name == 'comment':  # Es la descripción del atributo
90                     self.curr_op['comment'] = ''
91                     self.estado = E_OP_COMMENT
92                     dprint("E_OP -> E_OP_COMMENT (encontrado dia:attribute con comment)")
93                 elif name == 'parameters': # Paso a encontrar parámetros de operaciones
94                     self.curr_op['params'] = []
95                     self.estado = E_OP_PARAMS
96                     dprint("E_OP -> E_OP_PARAMS (encontrado dia:attribute con parameters)")
97             elif self.estado == E_OP_PARAM:  # Datos del parametro
98                 if name == 'name':       # Nombre del parametro
99                     self.curr_param['name'] = ''
100                     self.estado = E_OP_PARAM_NAME
101                     dprint("E_OP_PARAM -> E_OP_PARAM_NAME (encontrado dia:attribute con name)")
102                 elif name == 'type':     # Es el tipo del parametro
103                     self.curr_param['type'] = ''
104                     self.estado = E_OP_PARAM_TYPE
105                     dprint("E_OP_PARAM -> E_OP_PARAM_TYPE (encontrado dia:attribute con type)")
106                 elif name == 'comment':  # Es la descripción del parametro
107                     self.curr_param['comment'] = ''
108                     self.estado = E_OP_PARAM_COMMENT
109                     dprint("E_OP_PARAM -> E_OP_PARAM_COMMENT (encontrado dia:attribute con comment)")
110         elif name == 'dia:composite':   # Comienza composite
111             if self.estado == E_ATTRS:  # Si estoy en atributos
112                 self.curr_attr = {}
113                 self.estado = E_ATTR    # Paso a buscar sus atributos
114                 dprint("E_ATTRS -> E_ATTR (encontrado dia:composite)")
115             elif self.estado == E_OPS:  # Si estoy en operaciones
116                 self.curr_op = {}
117                 self.estado = E_OP   # Paso a buscar sus operaciones
118                 dprint("E_OPS -> E_OP (encontrado dia:composite)")
119             elif self.estado == E_OP_PARAMS:  # Si estoy en parametros de operaciones
120                 self.curr_param = {}
121                 self.estado = E_OP_PARAM   # Paso a buscar sus parametros
122                 dprint("E_OP_PARAMS -> E_OP_PARAM (encontrado dia:composite)")
123     def characters(self, data):
124         if self.estado == E_CLASS_NAME:
125             self.curr['name'] += data.strip(STRIPCHARS)
126             dprint("E_CLASS_NAME: %s" % data.strip(STRIPCHARS))
127         elif self.estado == E_CLASS_COMMENT:
128             self.curr['comment'] += data.strip(STRIPCHARS)
129             dprint("E_CLASS_COMMENT: %s" % data.strip(STRIPCHARS))
130         elif self.estado == E_ATTR_NAME:
131             self.curr_attr['name'] += data.strip(STRIPCHARS)
132             dprint("E_ATTR_NAME: %s" % data.strip(STRIPCHARS))
133         elif self.estado == E_ATTR_TYPE:
134             self.curr_attr['type'] += data.strip(STRIPCHARS)
135             dprint("E_ATTR_TYPE: %s" % data.strip(STRIPCHARS))
136         elif self.estado == E_ATTR_COMMENT:
137             self.curr_attr['comment'] += data.strip(STRIPCHARS)
138             dprint("E_ATTR_COMMENT: %s" % data.strip(STRIPCHARS))
139         elif self.estado == E_OP_NAME:
140             self.curr_op['name'] += data.strip(STRIPCHARS)
141             dprint("E_OP_NAME: %s" % data.strip(STRIPCHARS))
142         elif self.estado == E_OP_TYPE:
143             self.curr_op['type'] += data.strip(STRIPCHARS)
144             dprint("E_OP_TYPE: %s" % data.strip(STRIPCHARS))
145         elif self.estado == E_OP_COMMENT:
146             self.curr_op['comment'] += data.strip(STRIPCHARS)
147             dprint("E_OP_COMMENT: %s" % data.strip(STRIPCHARS))
148         elif self.estado == E_OP_PARAM_NAME:
149             self.curr_param['name'] += data.strip(STRIPCHARS)
150             dprint("E_OP_PARAM_NAME: %s" % data.strip(STRIPCHARS))
151         elif self.estado == E_OP_PARAM_TYPE:
152             self.curr_param['type'] += data.strip(STRIPCHARS)
153             dprint("E_OP_PARAM_TYPE: %s" % data.strip(STRIPCHARS))
154         elif self.estado == E_OP_PARAM_COMMENT:
155             self.curr_param['comment'] += data.strip(STRIPCHARS)
156             dprint("E_OP_PARAM_COMMENT: %s" % data.strip(STRIPCHARS))
157     def endElement(self, name):
158         if name == 'dia:object':
159             if self.estado == E_CLASS:
160                 self.clases.append(self.curr)
161                 self.estado = None
162                 self.curr = None
163                 dprint("E_CLASS -> None")
164         elif name == 'dia:attribute':
165             if self.estado == E_CLASS_NAME:
166                 self.estado = E_CLASS
167                 dprint("E_CLASS_NAME -> E_CLASS")
168             elif self.estado == E_CLASS_COMMENT:
169                 self.estado = E_CLASS
170                 dprint("E_CLASS_COMMENT -> E_CLASS")
171             elif self.estado == E_ATTR_NAME:
172                 self.estado = E_ATTR
173                 dprint("E_ATTR_NAME -> E_ATTR")
174             elif self.estado == E_ATTR_TYPE:
175                 self.estado = E_ATTR
176                 dprint("E_ATTR_TYPE -> E_ATTR")
177             elif self.estado == E_ATTR_COMMENT:
178                 self.estado = E_ATTR
179                 dprint("E_ATTR_COMMENT -> E_ATTR")
180             elif self.estado == E_ATTRS:
181                 self.estado = E_CLASS
182                 dprint("E_ATTRS -> E_CLASS")
183             elif self.estado == E_OP_NAME:
184                 self.estado = E_OP
185                 dprint("E_OP_NAME -> E_OP")
186             elif self.estado == E_OP_TYPE:
187                 self.estado = E_OP
188                 dprint("E_OP_TYPE -> E_OP")
189             elif self.estado == E_OP_COMMENT:
190                 self.estado = E_OP
191                 dprint("E_OP_COMMENT -> E_OP")
192             elif self.estado == E_OPS:
193                 self.estado = E_CLASS
194                 dprint("E_OPS -> E_CLASS")
195             elif self.estado == E_OP_PARAM_NAME:
196                 self.estado = E_OP_PARAM
197                 dprint("E_OP_PARAM_NAME -> E_OP_PARAM")
198             elif self.estado == E_OP_PARAM_TYPE:
199                 self.estado = E_OP_PARAM
200                 dprint("E_OP_PARAM_TYPE -> E_OP_PARAM")
201             elif self.estado == E_OP_PARAM_COMMENT:
202                 self.estado = E_OP_PARAM
203                 dprint("E_OP_PARAM_COMMENT -> E_OP_PARAM")
204             elif self.estado == E_OP_PARAMS:
205                 self.estado = E_OP
206                 dprint("E_OP_PARAMS -> E_OP")
207         elif name == 'dia:composite':
208             if self.estado == E_ATTR:
209                 self.curr['attrs'].append(self.curr_attr)
210                 self.curr_attr = None
211                 self.estado = E_ATTRS
212                 dprint("E_ATTR -> E_ATTRS")
213             elif self.estado == E_OP:
214                 self.curr['ops'].append(self.curr_op)
215                 self.curr_op = None
216                 self.estado = E_OPS
217                 dprint("E_OP -> E_OPS")
218             elif self.estado == E_OP_PARAM:
219                 self.curr_op['params'].append(self.curr_param)
220                 self.curr_param = None
221                 self.estado = E_OP_PARAMS
222                 dprint("E_OP_PARAM -> E_OP_PARAMS")
223
224 def param2str(params):
225     ret = []
226     for p in params:
227         ret.append('%s: %s' \
228             % (p['name'].encode('iso-8859-1', 'replace'),
229                 p['type'].encode('iso-8859-1', 'replace')))
230     return ', '.join(ret)
231
232 def to_text(clases):
233     # Recorro clases
234     for c in clases:
235         print c['name'].encode('iso-8859-1', 'replace')
236         print c['comment'].encode('iso-8859-1', 'replace')
237         print 'Atributo\tTipo\tDescripción'
238         for a in c['attrs']:
239             print '%s\t%s\t%s' \
240                 % (a['name'].encode('iso-8859-1', 'replace'),
241                     a['type'].encode('iso-8859-1', 'replace'),
242                     a['comment'].encode('iso-8859-1', 'replace'))
243         if metodos and c['ops']:
244             for o in c['ops']:
245                 print 'Método %s(%s): %s' \
246                     % (o['name'].encode('iso-8859-1', 'replace'),
247                         param2str(o['params']),
248                         o['type'].encode('iso-8859-1', 'replace'))
249                 print o['comment'].encode('iso-8859-1', 'replace')
250                 if o['params']:
251                     print 'Parámetro\tTipo\tDescripción'
252                     for p in o['params']:
253                         print '%s\t%s\t%s' \
254                             % (p['name'].encode('iso-8859-1', 'replace'),
255                                 p['type'].encode('iso-8859-1', 'replace'),
256                                 p['comment'].encode('iso-8859-1', 'replace'))
257
258 def to_html(clases):
259     print '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">'
260     print '<html lang="es"><head><title>Especificación</title></head><body>'
261     # Recorro clases obtenidas
262     for c in dh.clases:
263         print '<table width="100%%" border="1" summary="Especificación de clase %s">' \
264             % c['name'].encode('iso-8859-1', 'replace')
265         print '<tr><th colspan="3">%s</th></tr>' % c['name'].encode('iso-8859-1', 'replace')
266         print '<tr><td colspan="3">%s</td></tr>' % c['comment'].encode('iso-8859-1', 'replace')
267         print '<tr><th>Atributo</th><th>Tipo</th><th>Descripción</th></tr>'
268         for a in c['attrs']:
269             print '<tr><td>%s</td><td>%s</td><td>%s</td></tr>' \
270                 % (a['name'].encode('iso-8859-1', 'replace'),
271                     a['type'].encode('iso-8859-1', 'replace'),
272                     a['comment'].encode('iso-8859-1', 'replace'))
273         if metodos and c['ops']:
274             for o in c['ops']:
275                 print '<tr><th colspan="3">Método</th></tr>'
276                 print '<tr><td colspan="3">%s(%s): %s</td></tr>' \
277                     % (o['name'].encode('iso-8859-1', 'replace'),
278                         param2str(o['params']),
279                         o['type'].encode('iso-8859-1', 'replace'))
280                 print '<tr><td colspan="3">%s</td></tr>' % \
281                     o['comment'].encode('iso-8859-1', 'replace')
282                 if o['params']:
283                     print '<tr><th>Parámetro</th><th>Tipo</th><th>Descripción</th></tr>'
284                     for p in o['params']:
285                         print '<tr><td>%s</td><td>%s</td><td>%s</td></tr>' \
286                             % (p['name'].encode('iso-8859-1', 'replace'),
287                                 p['type'].encode('iso-8859-1', 'replace'),
288                                 p['comment'].encode('iso-8859-1', 'replace'))
289         print '</table>'
290     print '</body></html>'
291
292 if __name__ == '__main__':
293     import sys
294     from xml.sax import make_parser
295     from xml.sax.handler import feature_namespaces
296
297     # Verifica parámetros
298     if len(sys.argv) < 2:
299         print >>sys.stderr, 'Uso:', sys.argv[0], 'archivo.dia [-n]'
300         print >>sys.stderr, '-n si no se quieren incluir los métodos'
301         sys.exit(1)
302
303     # Create a parser
304     parser = make_parser()
305
306     # Tell the parser we are not interested in XML namespaces
307     parser.setFeature(feature_namespaces, 0)
308
309     # Create the handler
310     dh = ObjFinder()
311
312     # Tell the parser to use our handler
313     parser.setContentHandler(dh)
314
315     # Parse the input
316     parser.parse(sys.argv[1])
317
318     # Veo si hay que poner métodos
319     metodos = True
320     if len(sys.argv) > 2 and sys.argv[2] == '-n':
321         metodos = False
322
323     # Imprimo como txt feo para convertir a RTF
324     to_text(dh.clases)
325     #to_html(dh.clases)
326
327 # vim: set et sw=4 sts=4 :