Beispiel #1
0
 def __init__(self):
     self._fp = None
     # parse the defs file
     self.parser = defsparser.DefsParser(())
     self.overrides = override.Overrides()
     self.classmap = {}
     self.docs = {}
Beispiel #2
0
def generate(filename, outfile=None, overridesfile=None):
    # parse the file
    all_elements = parse(filename)

    def resolve(val, attr):
        """Resolve references.
        """
        try:
            refs = val.references[attr]
        except KeyError:
            val.references[attr] = None
            return

        if type(refs) is type([]):
            unrefs = []
            for r in refs:
                unrefs.append(all_elements[r])
            val.references[attr] = unrefs
        else:
            val.references[attr] = all_elements[refs]

    overrides = override.Overrides(overridesfile)
    writer = Writer(outfile, overrides)

    # extract usable elements from all_elements. Some elements are given
    # some extra attributes.
    classes = { }
    enumerations = { }
    generalizations = { }
    associations = { }
    properties = { }
    operations = { }
    extensions = { } # for identifying metaclasses
    for key, val in all_elements.items():
        # Find classes, *Kind (enumerations) are given special treatment
        if isinstance(val, element):
            if val.type == 'Class' and val.get('name'):
                if val['name'].endswith('Kind') or val['name'].endswith('Sort'):
                    enumerations[key] = val
                else:
                    # Metaclasses are removed later on (need to be checked
                    # via the Extension instances)
                    classes[key] = val
                    # Add extra properties for easy code generation:
                    val.specialization = []
                    val.generalization = []
                    val.stereotypeName = None
                    val.written = False
            elif val.type == 'Generalization':
                generalizations[key] = val
            elif val.type == 'Association':
                val.asAttribute = None
                associations[key] = val
            elif val.type == 'Property':
                properties[key] = val
                #resolve(val, 'typeValue')
                #resolve(val, 'defaultValue')
                #resolve(val, 'lowerValue')
                #resolve(val, 'upperValue')
                resolve(val, 'appliedStereotype')
                for st in val.appliedStereotype or []:
                    resolve(st, 'slot')
                    for slot in st.slot or []:
                        resolve(slot, 'value')
                        resolve(slot, 'definingFeature')
                val.written = False
            elif val.type == 'Operation':
                operations[key] = val
            elif val.type == 'Extension':
                extensions[key] = val

    # find inheritance relationships
    for g in generalizations.values():
        #assert g.specific and g.general
        specific = g['specific']
        general = g['general']
        classes[specific].generalization.append(classes[general])
        classes[general].specialization.append(classes[specific])

    # add values to enumerations:
    for e in enumerations.values():
        values = []
        for key in e['ownedAttribute']:
            values.append(str(properties[key]['name']))
        e.enumerates = tuple(values)

    # Remove metaclasses from classes dict
    # should check for Extension.memberEnd<Property>.type
    for e in extensions.values():
        ends = []
        for end in e.memberEnd:
            end = all_elements[end]
            if not end['type']:
                continue
            end.type = all_elements[end['type']]
            ends.append(end)
        e.memberEnd = ends
        if ends:
            del classes[e.memberEnd[0].type.id]


    # create file header
    writer.write(header)

    # Tag classes with appliedStereotype
    for c in classes.values():
        if c.get('appliedStereotype'):
            # Figure out stereotype name through
            # Class.appliedStereotype.classifier.name
            instSpec = all_elements[c.appliedStereotype[0]]
            sType = all_elements[instSpec.classifier[0]]
            c.stereotypeName = sType.name
            print "  class '%s' has been stereotyped as '%s'" % (c.name, c.stereotypeName)
            writer.write("# class '%s' has been stereotyped as '%s'\n" % (c.name, c.stereotypeName))
            #c.written = True
            def tag_children(me):
                for child in me.specialization:
                    child.stereotypeName = sType.name
                    print "  class '%s' has been stereotyped as '%s' too" % (child.name, child.stereotypeName)
                    writer.write("# class '%s' has been stereotyped as '%s' too\n" % (child.name, child.stereotypeName))
                    #child.written = True
                    tag_children(child)
            tag_children(c)

    ignored_classes = set()

    # create class definitions, not for SimpleAttribute
    for c in classes.values():
        if c.stereotypeName == 'SimpleAttribute':
            ignored_classes.add(c)
        else:
            writer.write_classdef(c)
 
    # create attributes and enumerations
    derivedattributes = { }
    for c in filter(lambda c: c not in ignored_classes, classes.values()):
        for p in c.get('ownedAttribute') or []:
            a = properties.get(p)
            # set class_name, since write_attribute depends on it
            a.class_name = c['name']
            if not a.get('association'):
                if overrides.derives('%s.%s' % (a.class_name, a.name)):
                    derivedattributes[a.name] = a
                else:
                    writer.write_attribute(a, enumerations)

    # create associations, derivedunions are held back
    derivedunions = { } # indexed by name in stead of id
    redefines = [ ]
    for a in associations.values():
        ends = []
        # Resolve some properties:
        for end in a.memberEnd:
            end = properties[end]
            end.type = classes[end['type']]
            end.class_ = end.get('class_') and classes[end['class_']] or None
            end.is_simple_attribute = False
            if end.type and end.type.stereotypeName == 'SimpleAttribute':
                end.is_simple_attribute = True
                a.asAttribute = end
            ends.append(end)

        for e1, e2 in ((ends[0], ends[1]), (ends[1], ends[0])):
            parse_association_end(e1, e2)

        for e1, e2 in ((ends[0], ends[1]), (ends[1], ends[0])):
            if a.asAttribute:
                if a.asAttribute is e1 and e1.navigable:
                   writer.write("# '%s.%s' is a simple attribute\n" % (e2.type.name, e1.name))
                   e1.class_name = e2.type.name
                   e1.typeValue = 'str'

                   writer.write_attribute(e1, enumerations)
                   e1.written = True
                   e2.written = True
            elif e1.redefines:
                redefines.append(e1)
            elif e1.derived or overrides.derives('%s.%s' % (e1.class_name, e1.name)):
                assert not derivedunions.get(e1.name), "%s.%s is already in derived union set in class %s" % (e1.class_name, e1.name, derivedunions.get(e1.name).class_name)
                derivedunions[e1.name] = e1
                e1.union = [ ]
                e1.written = False
            elif e1.navigable:
                writer.write_association(e1, e2)


    # create derived unions, first link the association ends to the d
    for a in (v for v in properties.values() if v.subsets):
        for s in a.subsets or ():
            try:
                if a.type not in ignored_classes:
                    derivedunions[s].union.append(a)
            except KeyError:
                msg('not a derived union: %s.%s' % (a.class_name, s))


    # TODO: We should do something smart here, since derived attributes (mostly)
    #       may depend on other derived attributes or associations.

    for d in derivedattributes.values():
        writer.write_attribute(d)

    for d in derivedunions.values():
        writer.write_derivedunion(d)

    for r in redefines or ():
        msg('redefining %s -> %s.%s' % (r.redefines, r.class_name, r.name))
        writer.write_redefine(r)

    # create operations
    for c in filter(lambda c: c not in ignored_classes, classes.values()):
        for p in c.get('ownedOperation') or ():
            o = operations.get(p)
            o.class_name = c['name']
            writer.write_operation(o)

    writer.close()
docs = docextract.extract(doc_dirs)

p = defsparser.DefsParser(defs_file)

p.startParsing()
# create list of class
c_class_list = []
for obj in p.objects:
   c_class_list.append(get_c_name(obj.c_name))

add_override_methods(p)

f = file(wrap_file)
wrap_file_cont = f.read()
override_file_cont = ""
override = override.Overrides()

#enums
"""
for enum in p.enums:
   if docs.has_key(enum.c_name):
      print "\"\"\""
      printdoc(docs[enum.c_name].description)
      print "\"\"\""
   for i in range(len(enum.values)-1):
      print enum.values[i][1].replace("GWY_", ""), ',',
   print enum.values[len(enum.values)-1][1].replace("GWY_", ""), " = range(", len(enum.values), ")"
"""   

# Keep GENERATED seprarated so that this file is not marked generated.
print "# This is dummy " + "GENERATED" + " file used for generation of documentation"