Guest User

Untitled

a guest
Dec 7th, 2017
400
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 24.24 KB | None | 0 0
  1. # PyDia Code Generation from UML Diagram
  2. # Copyright (c) 2005  Hans Breuer <hans@breuer.org>
  3.  
  4. #    This program is free software; you can redistribute it and/or modify
  5. #   it under the terms of the GNU General Public License as published by
  6. #   the Free Software Foundation; either version 2 of the License, or
  7. #   (at your option) any later version.
  8. #
  9. #   This program is distributed in the hope that it will be useful,
  10. #   but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. #   GNU General Public License for more details.
  13. #
  14. #   You should have received a copy of the GNU General Public License
  15. #   along with this program; if not, write to the Free Software
  16. #   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18. # ABAP Export made by Alexey Tveritinov
  19.  
  20. import sys, dia, codecs, time, datetime
  21.  
  22. plugname = "ABAP Exporting plugin for DIA"
  23. version  = "0.3"
  24. author   = "Alexey Tveritinov [alexey.tveritinov@sap.com]"
  25.  
  26. class Klass :
  27.     def __init__ (self, name) :
  28.         self.name = name
  29.         # use a list to preserve the order     
  30.         self.attributes = []
  31.         # As I don't know how to implement sorting on visibility levels I'll store attributes
  32.         # in a separate area, with visibility as a key
  33.         self.s_attributes = []
  34.         # a list, as java/c++ support multiple methods with the same name
  35.         self.operations = []
  36.         self.comment = ""
  37.         self.parents = []
  38.         self.templates = []
  39.         self.inheritance_type = ""
  40.     def AddAttribute(self, name, type, visibility, value, comment) :
  41.         self.attributes.append ((name, (type, visibility, value, comment)))
  42.     def AddOperation(self, name, type, visibility, params, inheritance_type, comment, class_scope) :
  43.         self.operations.append((name,(type, visibility, params, inheritance_type, comment, class_scope)))
  44.     def SetComment(self, s) :
  45.         self.comment = s
  46.     def AddParrent(self, parrent):
  47.         self.parents.append(parrent)
  48.     def AddTemplate(self, template):
  49.         self.templates.append(template)
  50.     def SetInheritance_type(self, inheritance_type):
  51.         self.inheritance_type = inheritance_type
  52.     # Sort attributes on visibility level
  53.  
  54.  
  55. def split_len(seq, length):
  56.     return [seq[i:i+length] for i in range(0, len(seq), length)]
  57.  
  58. class ObjRenderer :
  59.     "Implements the Object Renderer Interface and transforms diagram into its internal representation"
  60.     def __init__ (self) :
  61.         # an empty dictionary of classes
  62.         self.klasses = {}
  63.         self.arrows = []
  64.         self.filename = ""
  65.        
  66.     def begin_render (self, data, filename) :
  67.         self.filename = filename
  68.         # not only reset the filename but also the other state, otherwise we would accumulate information through every export
  69.         self.klasses = {}
  70.         self.arrows = []
  71.         for layer in data.layers :
  72.             # for the moment ignore layer info. But we could use this to spread accross different files
  73.             for o in layer.objects :
  74.                 if o.type.name == "UML - Class" :
  75.                     #print o.properties["name"].value
  76.                     k = Klass (o.properties["name"].value)
  77.                     k.SetComment(o.properties["comment"].value)
  78.                     if o.properties["abstract"].value:
  79.                         k.SetInheritance_type("abstract")
  80.                     if o.properties["template"].value:
  81.                         k.SetInheritance_type("template")
  82.                     for op in o.properties["operations"].value :
  83.                         # op : a tuple with fixed placing, see: objects/UML/umloperations.c:umloperation_props
  84.                         # (name, type, comment, stereotype, visibility, inheritance_type, class_scope, params)
  85.                         params = []
  86.                         for par in op[8] :
  87.                             # par : again fixed placement, see objects/UML/umlparameter.c:umlparameter_props
  88.                             # (name, type, value, comment, kind)
  89.                             params.append((par[0], par[1], par[2], par[3], par[4]))
  90.                         k.AddOperation (op[0], op[1], op[4], params, op[5], op[2], op[7])
  91.                     #print o.properties["attributes"].value
  92.                     for attr in o.properties["attributes"].value :
  93.                         # see objects/UML/umlattributes.c:umlattribute_props
  94.                         #print "\t", attr[0], attr[1], attr[4]
  95.                         # name, type, value, comment, visibility, abstract, class_scope
  96.                         k.AddAttribute(attr[0], attr[1], attr[4], attr[2], attr[3])
  97.                     self.klasses[o.properties["name"].value] = k
  98.                     #Connections
  99.                 elif o.type.name == "UML - Association" :
  100.                     # should already have got attributes relation by names
  101.                     pass
  102.                 # other UML objects which may be interesting
  103.                 # UML - Note, UML - LargePackage, UML - SmallPackage, UML - Dependency, ...
  104.        
  105.         edges = {}
  106.         for layer in data.layers :
  107.             for o in layer.objects :
  108.                 for c in o.connections:
  109.                     for n in c.connected:
  110.                         if not n.type.name in ("UML - Generalization", "UML - Realizes"):
  111.                             continue
  112.                         if str(n) in edges:
  113.                             continue
  114.                         edges[str(n)] = None
  115.                         if not (n.handles[0].connected_to and n.handles[1].connected_to):
  116.                             continue
  117.                         par = n.handles[0].connected_to.object
  118.                         chi = n.handles[1].connected_to.object
  119.                         if not par.type.name == "UML - Class" and chi.type.name == "UML - Class":
  120.                             continue
  121.                         par_name = par.properties["name"].value
  122.                         chi_name = chi.properties["name"].value
  123.                         if n.type.name == "UML - Generalization":
  124.                             self.klasses[chi_name].AddParrent(par_name)
  125.                         else: self.klasses[chi_name].AddTemplate(par_name)
  126.                    
  127.     def end_render(self) :
  128.         # without this we would accumulate info from every pass
  129.         self.attributes = []
  130.         self.operations = []
  131.  
  132. class PyRenderer(ObjRenderer) :
  133.     def __init__(self) :
  134.         ObjRenderer.__init__(self)
  135.     def end_render(self) :
  136.         f = open(self.filename, "w")
  137.         for sk in self.klasses.keys() :
  138.             parents = self.klasses[sk].parents + self.klasses[sk].templates
  139.             if not parents:
  140.                 f.write ("class %s :\n" % (sk,))
  141.             else:
  142.                 f.write ("class %s (%s) :\n" % (sk,", ".join(parents)))
  143.             k = self.klasses[sk]
  144.             if len(k.comment) > 0 :
  145.                 f.write ("\t'''" + k.comment + "'''\n")
  146.             f.write ("\tdef __init__(self) :\n")
  147.             for sa, attr in k.attributes :
  148.                 value = attr[2] == "" and "None" or attr[2]
  149.                 f.write("\t\tself.%s = %s # %s\n" % (sa, value, attr[0]))
  150.             else :
  151.                 f.write("\t\tpass\n")
  152.             for so, op in k.operations :
  153.                 # we only need the parameter names
  154.                 pars = "self"
  155.                 for p in op[2] :
  156.                     pars = pars + ", " + p[0]
  157.                 f.write("\tdef %s (%s) :\n" % (so, pars))
  158.                 if op[4]: f.write("\t\t\"\"\" %s \"\"\"\n" % op[4])
  159.                 f.write("\t\t# returns %s\n" % (op[0], ))
  160.                 f.write("\t\tpass\n")
  161.         f.close()
  162.         ObjRenderer.end_render(self)
  163.  
  164. class CxxRenderer(ObjRenderer) :
  165.     def __init__(self) :
  166.         ObjRenderer.__init__(self)
  167.     def end_render(self) :
  168.         f = open(self.filename, "w")
  169.         f.write("/* generated by dia/codegen.py */\n")
  170.         # declaration
  171.         for sk in self.klasses.keys() :
  172.             k = self.klasses[sk]
  173.             if len(k.comment) > 0 :
  174.                 f.write ("/*" + k.comment + "*/\n")
  175.             if len(k.parents) > 0 :
  176.                 f.write ("class %s : %s \n{\n" % (sk, ", ".join(k.parents)))
  177.             else :
  178.                 f.write ("class %s \n{\n" % (sk,))
  179.             # first sort by visibility
  180.             ops = [[], [], [], []]
  181.             for so, (t, v, p, i, c, s) in k.operations :
  182.                 ops[v].append((t,so,p))
  183.             vars = [[], [], [], []]
  184.             for sa, (t, vi, va, vc) in k.attributes :
  185.                 #TODO: use 'va'=value 'vc'=comment
  186.                 vars[vi].append((t, sa))
  187.             visibilities = ("public:", "private:", "protected:", "/* implementation: */")
  188.             for v in [0,2,1,3] :
  189.                 if len(ops[v]) == 0 and len(vars[v]) == 0 :
  190.                     continue
  191.                 f.write ("%s\n" % visibilities[v])
  192.                 for op in ops[v] :
  193.                     # detect ctor/dtor
  194.                     so = ""
  195.                     if sk == op[1] or ("~" + sk) == op[1] :
  196.                         so = "\t%s (" % (op[1])
  197.                     else :
  198.                         so = "\t%s %s (" % (op[0], op[1])
  199.                     f.write (so)
  200.                     # align parameters with the opening brace
  201.                     n = len(so)
  202.                     i = 0
  203.                     m = len(op[2]) - 1
  204.                     for p in op[2] :
  205.                         linefeed = ",\n\t" + " " * (n - 1)
  206.                         if i == m :
  207.                             linefeed = ""
  208.                         f.write ("%s %s%s" % (p[1], p[0], linefeed))
  209.                         i = i + 1
  210.                     f.write(");\n")
  211.                 for var in vars[v] :
  212.                     f.write("\t%s %s;\n" % (var[0], var[1]))
  213.             f.write ("};\n\n")
  214.         # implementation
  215.         # ...
  216.         f.close()
  217.         ObjRenderer.end_render(self)
  218.  
  219. # #############################################################################
  220. # PascalRenderer: export Dia UML diagram to Object Pascal (Free Pascal, Delphi)
  221. #
  222. # Please follow some "drawing guidelines" and "naming conventions" so that the
  223. # exporter can do its job.
  224. #  - Use "UML - Generalization" arrows for class inheritance.
  225. #  - Use "UML - Realizes" arrows when implementing an interface.
  226. #  - Set a class to be "abstract" to denote it is an interface definition.
  227. #  - Set Inheritance Type to "abstract" for 'virtual; abstract;' methods, set
  228. #    it to "virtual" for 'virtual;' methods.
  229. #  - Array fields are automatically recognized. If the name ends with "[]"
  230. #    an 'Array of' is used. If the name uses a number with "[1234]", an
  231. #    'Array[0..1233] of' is used. If the name uses a constant with
  232. #    "[MaxEntries]" an 'Array[0..MaxEntries-1] of' is written.
  233. #  - To inherit from classes which are not drawn (e.g. LCL/VCL classes),
  234. #    name then class with the parent class in paranthesis (e.g.
  235. #    "TMainWin(TForm)"
  236. #
  237. # Features
  238. #  - Inheriting from one class and implementing multiple interfaces is
  239. #    supported.
  240. #  - Comments for classes, attributes and operations are supported. They are
  241. #    put in the line before the method declaration with a '///' style comment
  242. #    (Doxygen-like).
  243. #  - Method parameter directions are supported (-> 'Var', 'Out').
  244. #  - Method parameter default values are supported.
  245. #  - 'Function' and 'Procedure' are automatically recognized by whether a
  246. #    return type exists or not.
  247. #  - order of classes is alphabetically
  248. #  - the order of attributes and operations is preserved
  249. #  - Prints a list of forward declarations of all classes at the beginning
  250. #    to avoid declaration order problems.
  251. #
  252. # TODO:
  253. #  - Automatically use the keyword "override" instead of "virtual" in
  254. #    descendant classes.
  255. #  - Automatically define 'Properties'. Unfortunately the UML standard
  256. #    doesn't support this and so the Dia dialog has no option to specify
  257. #    this. So a "code" has to be used.
  258. #  - Mark/recognize Constructors and Destructors
  259. #  - Write comments for method parameters (e.g. by using a big doxygen
  260. #    comment '(** ... *)' before the method)
  261. #  - Use "Packages" to split the classes in separate 'Unit's.
  262. #  - Beautify and comment the export code. Using arrays with "magic number
  263. #    indexes" for certain fields is bad and tedious to work with.
  264. #  - Support defining global constants.
  265. #  - Support defining global types (especially for enums, arrays,
  266. #    records, ...).
  267. #  - Apply some sanity checks to the UML diagram:
  268. #     - multiple inheritance is forbidded
  269. #     - if implementing an interface, all required methods must be
  270. #       implemented; alternative: just put all methods there, so the UML
  271. #       drawer doesn't have to write them twice
  272. #     - visibility for all methods of an interfaces must be "public"
  273. #     - don't write the visibility specifier 'public' for interfaces
  274. #     - no "Attributes" for interface definitions, but properties are
  275. #       allowed
  276. #     - default values for method parameters must be the last parameters
  277.  
  278. class PascalRenderer(ObjRenderer) :
  279.     def __init__(self) :
  280.         ObjRenderer.__init__(self)
  281.     def end_render(self) :
  282.         f = open(self.filename, "w")
  283.         f.write("/* generated by dia/codegen.py */\n")
  284.         f.write("Type\n")
  285.         # classes
  286.         class_names = self.klasses.keys()
  287.         class_names.sort()
  288.         # forward declarations of all classes
  289.         for sk in class_names :
  290.             k = self.klasses[sk]
  291.             # class declaration
  292.             if k.inheritance_type == "abstract" :
  293.                 f.write ("  %s = interface;\n" % (sk))
  294.             else :
  295.                 f.write ("  %s = class;\n" % (sk))
  296.         f.write("\n");
  297.         # class declarations
  298.         for sk in class_names :
  299.             k = self.klasses[sk]
  300.             # comment
  301.             if len(k.comment) > 0 :
  302.                 f.write("  /// %s\n" % (k.comment))
  303.             # class declaration
  304.             if k.inheritance_type == "abstract" :
  305.                 f.write ("  %s = interface" % (sk))
  306.             else :
  307.                 f.write ("  %s = class %s" % (sk, k.inheritance_type))
  308.             # inherited classes / implemented interfaces
  309.             p = []
  310.             if k.parents :
  311.                 p.append(k.parents[0])
  312.             if k.templates :
  313.                 p.append(",".join(k.templates))
  314.             if len(p) > 0 :
  315.                 f.write("(%s)" % ",".join(p))
  316.             f.write ("\n")
  317.             # first sort by visibility
  318.             ops = [[], [], [], [], [], []]
  319.             for op_name, (op_type, op_visibility, op_params, op_inheritance, op_comment, op_class_scope) in k.operations :
  320.                 ops[op_visibility].append((op_type, op_name, op_params, op_comment, op_inheritance))
  321.             vars = [[], [], [], []]
  322.             for var_name, (var_type, var_visibility, var_value, var_comment) in k.attributes :   # name, type, visibility, value, comment
  323.                 vars[var_visibility].append((var_type, var_name, var_value, var_comment))
  324.             visibilities = ("public", "private", "protected", "/* implementation */")
  325.             for v in [1,2,0,3] :
  326.                 if len(ops[v]) == 0 and len(vars[v]) == 0 :
  327.                     continue
  328.                 # visibility prefix
  329.                 f.write ("  %s\n" % visibilities[v])
  330.                 # variables
  331.                 for var in vars[v] :
  332.                     # comment
  333.                     if len(var[3]) > 0 :
  334.                         f.write ("    /// %s\n" % var[3])
  335.                     if var[1].endswith("]") :
  336.                         # array; check if this is dynamic or with defined size
  337.                         i = var[1].find("[")
  338.                         varname = var[1]
  339.                         arraysize = varname[i+1:-1]
  340.                         varname = varname[:i]
  341.                         if len(arraysize) > 0 :
  342.                             # array with defined size
  343.                             if arraysize.find("..") > 0 :
  344.                                 f.write("    %s : Array[%s] of %s;\n" % (varname, arraysize, var[0]))
  345.                             elif arraysize.isdigit() :
  346.                                 arraysize = int(arraysize)-1
  347.                                 f.write("    %s : Array[0..%d] of %s;\n" % (varname, arraysize, var[0]))
  348.                             else :
  349.                                 f.write("    %s : Array[0..%s-1] of %s;\n" % (varname, arraysize, var[0]))
  350.                         else :
  351.                             # dynamic size
  352.                             f.write("    %s : Array of %s;\n" % (varname, var[0]))
  353.                     else :
  354.                         # normal variable
  355.                         f.write("    %s : %s;\n" % (var[1], var[0]))
  356.                 # operations
  357.                 for op in ops[v] :
  358.                     if len(op[3]) > 0 :
  359.                         f.write ("    /// %s\n" % op[3])
  360.                     if len(op[0]) == 0 :
  361.                         f.write ("    Procedure %s" % op[1])
  362.                     else :
  363.                         f.write ("    Function %s" % op[1])
  364.                     if len(op[2]) > 0 :
  365.                         f.write ("(")
  366.                         i = 0
  367.                         m = len(op[2]) - 1
  368.                         for p in op[2] :
  369.                             if p[4] == 2 :
  370.                                 f.write ("Out ")
  371.                             elif p[4] == 3 :
  372.                                 f.write ("Var ")
  373.                             f.write ("%s:%s" % (p[0], p[1]))
  374.                             if len(p[2]) > 0 :
  375.                                 f.write (":=%s" % p[2])
  376.                             if i != m :
  377.                                 f.write(";")
  378.                             i = i + 1
  379.                         f.write (")")
  380.                     if len(op[0]) == 0 :
  381.                         f.write(";")
  382.                     else :
  383.                         f.write (" : %s;" % op[0])
  384.                     # inheritance type
  385.                     if op[4] == 0 :
  386.                         f.write (" virtual; abstract;");
  387.                     elif op[4] == 1 :
  388.                         f.write (" virtual;");
  389.                     f.write ("\n")
  390.             f.write ("  End;\n\n")
  391.         # implementation
  392.         # ...
  393.         f.close()
  394.         ObjRenderer.end_render(self)
  395.  
  396. class JavaRenderer(ObjRenderer) :
  397.     def __init__(self) :
  398.         ObjRenderer.__init__(self)
  399.        
  400.     def end_render(self) :
  401.         f = open(self.filename, "w")
  402.        
  403.         visibilities = {0:"public", 2:"private", 1:"protected"}
  404.  
  405.         for name, klass in self.klasses.iteritems() :
  406.             if len(klass.comment) > 0 :
  407.                 f.write ("/*" + klass.comment + "*/\n")
  408.             if klass.inheritance_type == "template": classtype = "interface"
  409.             elif klass.inheritance_type == "abstract": classtype = "abstract class"
  410.             else: classtype = "class"
  411.             f.write ("%s %s" % (classtype, name))
  412.             if klass.parents:
  413.                 f.write (" extends %s" % klass.parents[0])
  414.             if klass.templates:
  415.                 f.write (" implements %s" % ", ".join(klass.templates))
  416.             f.write(" {\n")
  417.            
  418.             for attrname, (type, visibility, value, comment) in klass.attributes :
  419.                 #TODO: use comment
  420.                 if visibility in visibilities:
  421.                     vis = visibilities[visibility]+" "
  422.                 else: vis = ""
  423.                 f.write("\t%s%s %s" % (vis, type, attrname))
  424.                 if value != "": f.write(" = %s" % value)
  425.                 f.write(";\n")
  426.            
  427.             if not klass.inheritance_type == "template":
  428.                 f.write ("\n\tpublic %s() {\n\t\t\n\t}\n\n" % name)
  429.            
  430.             # We should automatic implement abstract parrent and interface methods
  431.             parmethods = []
  432.             if klass.parents:
  433.                 parmethods = [(n,m[:3]+(1,)+m[4:]) for n,m in \
  434.                         self.klasses[klass.parents[0]].operations if m[3] == 0]
  435.             for template in klass.templates:
  436.                 parmethods.extend(self.klasses[template].operations)
  437.            
  438.            
  439.             for pName, pMethod in parmethods:
  440.                 pTypes = [p[1] for p in pMethod[2]]
  441.                 for name, pars in [(n,m[2]) for n,m in klass.operations]:
  442.                     types = [p[1] for p in pars]
  443.                     if pars == pMethod[2] and types == pTypes:
  444.                         break
  445.                 else: klass.operations.append((pName,pMethod))
  446.            
  447.             for methodname, method in klass.operations :
  448.                 if method[4]: f.write("\t/** %s */\n" % method[4])
  449.                 # if there are no parameter names, something else should appear
  450.                 pars = []
  451.                 v = ord("a")
  452.                 for name, type, value, comment, kind in method[2]:
  453.                     #TODO: also use: value, comment, kind
  454.                     if not name:
  455.                         pars.append((type,chr(v)))
  456.                         v += 1
  457.                     else: pars.append((type,name))
  458.                 pars = ", ".join([type+" "+name for type, name in pars])
  459.                
  460.                 vis = method[1] in visibilities and visibilities[method[1]] or ""
  461.                 returntype = method[0]=="" and "void" or method[0]
  462.                 inheritance_type = method[3]==0 and "abstract " or ""
  463.                 static = method[4] and "static " or ""
  464.                 f.write("\t%s %s%s%s %s (%s)" % (vis, static, inheritance_type, returntype, methodname, pars))
  465.                 if klass.inheritance_type == "template" or method[3]==0:
  466.                     f.write(";\n\n")
  467.                 else: f.write(" {\n\t\t\n\t}\n\n")
  468.             f.write ("}\n\n")
  469.         f.close()
  470.         ObjRenderer.end_render(self)
  471.  
  472. # This is fucking unbelivable :(
  473. # DIA render crashes if this used as constant
  474. # Grebanie kostily !
  475. def abap_long_comment():
  476.     return "*&---------------------------------------------------------------------*\n"
  477. def abap_short_comment():
  478.     return "* "
  479.  
  480. class AbapRenderer(ObjRenderer) :
  481.     #abap_comment_short = "* "
  482.     def __init__(self) :
  483.         ObjRenderer.__init__(self)
  484.        
  485.     def end_render(self) :
  486.         f = open(self.filename, "w")
  487.         f.write("%s Made with %s v%s\n%s (%s) \n%s at %s\n\n" % (abap_short_comment(), plugname, version, abap_short_comment(), author, abap_short_comment(),str(datetime.datetime.today())))
  488.         visibilities = {0:"PUBLIC", 1:"PRIVATE", 2:"PROTECTED"}
  489.         param_directions = {0:"UNDEFINED", 1:"IMPORTING", 2:"EXPORTING", 3:"CHANGING"}
  490.        
  491.        
  492.  
  493.         for name, klass in self.klasses.iteritems() :
  494.             name = name.upper()
  495.             # comments for the class
  496.             f.write(abap_long_comment())
  497.             if len(klass.comment) > 0 :
  498.                 # Split comment on small chunks    
  499.                 tmp_comment = split_len(str(klass.comment).replace("\n", "\n"+abap_short_comment()), 65)
  500.                 for x in tmp_comment :
  501.                     f.write("%s %s \n" % (abap_short_comment(), x))
  502.             else:
  503.                 f.write("%s %s\n" % (abap_short_comment(),"No comment given for this item",))
  504.             f.write(abap_long_comment())
  505.             # Class type and inheritance
  506.             if klass.inheritance_type == "abstract": abstract_x = "ABSTRACT"
  507.             else: abstract_x = " DEFINITION"
  508.             if klass.inheritance_type == "template":
  509.                 classtype = "INTERFACE"
  510.                 abstract_x = ""
  511. #           elif klass.inheritance_type == "abstract": classtype = "ABSTRACT"
  512.             else: classtype = "CLASS"  
  513.  
  514.             inheriting = ""
  515.             if klass.parents:
  516.                 inheriting = (" INHERITING FROM %s" % klass.parents[0].upper())
  517.             if klass.templates:
  518.                 #f.write (" implements %s" % upper(klass.templates))       
  519.                 # TODO : FIX this !
  520.                 pass
  521.  
  522.             f.write ("%s %s%s%s.\n" % (classtype, name, abstract_x, inheriting))
  523.             # Attributes
  524.             # We have to sort attributes and put it in apropriate section
  525.             #klass.SortAttributes(f)
  526.             for x in visibilities :
  527.                 tmp_attrs = ""
  528.                 tmp_methods = ""
  529.                 tmp_num_of_elements = 0            
  530.                 tmp_num_of_methods  = 0
  531.                 #tmp_attrs += "\n%s %s.\n" % (visibilities[x],"SECTION")
  532.                 if classtype != "INTERFACE" :
  533.                     f.write("\n%s %s.\n" % (visibilities[x],"SECTION"))
  534.                
  535.                 for attrname, (type, visibility, value, comment) in klass.attributes :
  536.                     # Write only items that belong to current visibility level
  537.                     if visibility != x : continue                  
  538.                     vis = visibilities[visibility]+" "
  539.                     if len(comment) > 0 :
  540.                     # ABAP doens't have multiline comments
  541.                         comment = comment.replace("\n", "\n\"")
  542.                         tmp_attrs += "%s %s\n" % ('"', comment)
  543.                         #f.write("%s %s\n" % (abap_short_comment(), comment))
  544.                     tmp_attrs += "\t%s \t%s %s" % (attrname.upper(), "TYPE", type.upper())
  545.                     #f.write("\t%s \t%s %s" % (attrname.upper(), "TYPE", type.upper()))
  546.                     if value != "": tmp_attrs += " VALUE %s" % value #f.write(" VALUE %s" % value)
  547.                     tmp_attrs += ".\n"
  548.                     tmp_num_of_elements += 1
  549.                     #f.write(".\n")
  550.                 # End of attributes block  
  551.                 tmp_attrs = tmp_attrs.strip()
  552.                 if tmp_num_of_elements > 1 : tmp_attrs = tmp_attrs.replace(".\n",",\n")
  553.                 if tmp_num_of_elements > 0 : tmp_attrs = "\tDATA:\n\t%s \n" % (tmp_attrs,)
  554.                 f.write(tmp_attrs)
  555.                 # Methods block
  556.                 # We should automatic implement abstract parrent and interface methods
  557.                 parmethods = []
  558.                 if klass.parents:
  559.                     parmethods = [(n,m[:3]+(1,)+m[4:]) for n,m in \
  560.                             self.klasses[klass.parents[0]].operations if m[3] == 0]
  561.                 for template in klass.templates:
  562.                     parmethods.extend(self.klasses[template].operations)
  563.                
  564.                
  565.                 for pName, pMethod in parmethods:
  566.                     pTypes = [p[1] for p in pMethod[2]]
  567.                     for name, pars in [(n,m[2]) for n,m in klass.operations]:
  568.                         types = [p[1] for p in pars]
  569.                         if pars == pMethod[2] and types == pTypes:
  570.                             break
  571.                     else: klass.operations.append((pName,pMethod))
  572.  
  573.                 # So, data gathered, let's rock'n'roll
  574.                 for methodname, method in klass.operations :                                                # if there are no parameter names, something else should appear
  575.                     #pars = []
  576.                     #v = ord("a")
  577.                     #for name, type, value, comment, kind in method[2]:
  578.                         #TODO: also use: value, comment, kind
  579.                     #   if not name:
  580.                     #       pars.append((type,chr(v)))
  581.                     #       v += 1
  582.                     #   else: pars.append((type,name))
  583.                     #pars = ", ".join([type+" "+name for type, name in pars])
  584.                    
  585.                     vis = method[1] in visibilities and visibilities[method[1]] or ""
  586.                     # Group operations by visibility                   
  587.                     if vis != visibilities[x] : continue
  588.                     else : tmp_num_of_methods += 1
  589.  
  590.                     # Write method comment, if any
  591.                     if len(method[4]) > 0 :
  592.                     # Split multiline comment  
  593.                         comment = method[4].replace("\n", "\n\"")
  594.                         tmp_methods += "%s %s\n" % ('"', comment)
  595.                     #returntype = method[0]=="" and "void" or method[0]
  596.                     inheritance_type = method[3]==0 and "abstract " or ""
  597.                     static = method[4] and "static " or ""
  598.                     #f.write("\t%s %s%s%s %s (%s)" % (vis, static, inheritance_type, returntype, methodname, pars))
  599.                     tmp_params = ""                
  600.                     for current_direction in param_directions :
  601.                         tmp_num_of_params = 0
  602.                         for name, type, value, comment, kind in method[2]:
  603.                             if kind != current_direction: continue
  604.                             # TODO :: May be set default values  ?
  605.                             tmp_params += "\t%s type %s\n" % (name, type)
  606.                             tmp_num_of_params += 1
  607.                         if tmp_num_of_params > 0 :
  608.                             tmp_params = "\t%s\n\t  %s" % (param_directions[current_direction],tmp_params)
  609.                        
  610.                     # TODO :: HERE should be parameters parser !
  611.                     if len(tmp_params) == 0 : tmp_methods += "\t%s.\n" % methodname
  612.                     else : tmp_methods += "\t%s \n %s.\n" % (methodname, tmp_params)
  613.                                        
  614.                     #if klass.inheritance_type == "template" or method[3]==0:
  615.                     #   f.write(";\n\n")
  616.                     #else: f.write(" {\n\t\t\n\t}\n\n")
  617.                 # End of section, flush buffer
  618.                 tmp_methods = tmp_methods.strip()
  619.                 if tmp_num_of_methods > 1 : tmp_methods = tmp_methods.replace(".\n",",\n")
  620.                 if tmp_num_of_methods > 0 :
  621.                     tmp_methods = "METHODS:\n\t" + tmp_methods 
  622.                 f.write(tmp_methods)
  623.                    
  624.                 #f.write ("}\n\n")
  625.             # ENDCLASS / ENDINTERFACE clause
  626.             f.write("END%s.\n\n" % (classtype,))           
  627.        
  628.         f.close()
  629.         ObjRenderer.end_render(self)
  630.  
  631. # dia-python keeps a reference to the renderer class and uses it on demand
  632. dia.register_export ("PyDia Code Generation (Python)", "py", PyRenderer())
  633. dia.register_export ("PyDia Code Generation (C++)", "cxx", CxxRenderer())
  634. dia.register_export ("PyDia Code Generation (ABAP)", "abap", AbapRenderer())
  635. dia.register_export ("PyDia Code Generation (Pascal)", "pas", PascalRenderer())
  636. dia.register_export ("PyDia Code Generation (Java)", "java", JavaRenderer())
Add Comment
Please, Sign In to add comment