Show
Ignore:
Timestamp:
09/05/07 03:16:26 (1 year ago)
Author:
arj..@yirdis.nl
Message:

separated parser and writer code for associations.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • gaphor/trunk/utils/command/gen_uml.py

    r1140 r2087  
    8585 
    8686    def write_classdef(self, clazz): 
    87         """Write a class definition (class xx(x): pass). 
     87        """ 
     88        Write a class definition (class xx(x): pass). 
    8889        First the parent classes are examined. After that its own definition 
    8990        is written. It is ensured that class definitions are only written 
     
    102103 
    103104    def write_property(self, full_name, value): 
    104         """Write a property to the file. If the property is overridden, use the 
     105        """ 
     106        Write a property to the file. If the property is overridden, use the 
    105107        overridden value. full_name should be like Class.attribute. value is 
    106108        free format text. 
     
    110112 
    111113    def write_attribute(self, a, enumerations={}): 
    112         """Write a definition for attribute a. Enumerations may be a dict 
     114        """ 
     115        Write a definition for attribute a. Enumerations may be a dict 
    113116        of enumerations, indexed by ID. These are used to identify enums. 
    114117        """ 
     
    169172 
    170173    def write_association(self, head, tail): 
    171         """Write an association for head. False is returned if the association 
    172         is derived. 
    173         The head association end is enriched with the following attributes: 
    174             derived - association is a derived union or not 
    175             name - name of the association end (name of head is found on tail) 
    176             class_name - name of the class this association belongs to 
    177             opposite_class_name - name of the class at the other end of the assoc. 
    178             lower - lower multiplicity 
    179             upper - upper multiplicity 
    180             subsets - derived unions that use the association 
    181             redefines - redefines existing associations 
    182         Returns True if the association is written. False is returned if 
    183         the association should be handled by write_derivedunion() or 
    184         write_redefine(). 
    185         """ 
    186         navigable = head.get('class_') 
    187         if not navigable: 
    188             # from this side, the association is not navigable 
    189             return True 
    190  
    191         name = head.name 
    192         if name is None: 
    193             raise ValueError('ERROR! no name, but navigable: %s (%s.%s)' % (head.id, head.class_name, head.name)) 
    194  
    195         derived = int(head.isDerived or 0) 
    196  
    197         #print head.id, head.lowerValue 
    198         upper = head.upperValue and head.upperValue.value or '*' 
    199         lower = head.lowerValue and head.lowerValue.value or upper 
    200         if lower == '*': 
    201             lower = 0 
    202         subsets, redefines = parse_association_tags(head.taggedValue) 
    203  
    204         # Add the values found. These are used later to generate derived unions. 
    205         head.derived = derived 
    206         #head.name = name 
    207         head.class_name = head.class_['name'] 
    208         head.opposite_class_name = head.type['name'] 
    209         head.lower = lower 
    210         head.upper = upper 
    211         head.subsets = subsets 
    212         head.redefines = redefines 
    213  
     174        """ 
     175        Write an association for head.  
     176        The association should not be a redefine or derived association. 
     177        """ 
     178        assert head.navigable 
    214179        # Derived unions and redefines are handled separately 
    215         if derived or redefines: 
    216             return False 
    217  
    218         a = "association('%s', %s" % (name, head.opposite_class_name) 
    219         if lower not in ('0', 0): 
    220             a += ', lower=%s' % lower 
    221         if upper != '*': 
    222             a += ', upper=%s' % upper 
    223         if head.get('aggregation') == 'composite'
     180        assert not head.derived 
     181        assert not head.redefines 
     182 
     183        a = "association('%s', %s" % (head.name, head.opposite_class_name) 
     184        if head.lower not in ('0', 0): 
     185            a += ', lower=%s' % head.lower 
     186        if head.upper != '*': 
     187            a += ', upper=%s' % head.upper 
     188        if head.composite
    224189            a += ', composite=True' 
    225190 
    226191        # Add the opposite property if the head itself is navigable: 
    227         navigable = tail.get('class_') 
    228         if navigable: 
     192        if tail.navigable: 
    229193            try: 
    230194                #o_derived, o_name = parse_association_name(tail['name']) 
    231195                o_name = tail.name 
    232                 o_derived = int(tail.isDerived or 0) 
     196                o_derived = tail.derived 
    233197            except KeyError: 
    234198                msg('ERROR! no name, but navigable: %s (%s.%s)' % 
    235199                    (tail.id, tail.class_name, tail.name)) 
    236200            else: 
    237                 assert not (derived and not o_derived), 'One end is derived, the other end not ???' 
     201                assert not (head.derived and not o_derived), 'One end is derived, the other end not ???' 
    238202                a += ", opposite='%s'" % o_name 
    239203 
    240         self.write_property("%s.%s" % (head.class_name, name), a + ')') 
    241         return True 
     204        self.write_property("%s.%s" % (head.class_name, head.name), a + ')') 
     205 
    242206 
    243207    def write_derivedunion(self, d): 
    244         """Write a derived union. If there are no subsets a warning 
     208        """ 
     209        Write a derived union. If there are no subsets a warning 
    245210        is issued. The derivedunion is still created though. 
     211 
    246212        Derived unions may be created for associations that were returned 
    247         False by write_association().""" 
     213        False by write_association(). 
     214        """ 
    248215        subs = '' 
    249216        for u in d.union: 
     
    263230 
    264231    def write_redefine(self, r): 
    265         """Redefines may be created for associations that were returned 
    266         False by write_association().""" 
     232        """ 
     233        Redefines may be created for associations that were returned 
     234        False by write_association(). 
     235        """ 
    267236        self.write_property("%s.%s" % (r.class_name, r.name), 
    268237                            "redefine('%s', %s, %s)" % (r.name, r.opposite_class_name, r.redefines)) 
     
    311280    #print 'found', subsets, redefines 
    312281    return subsets, redefines 
     282 
     283def parse_association_end(head, tail): 
     284    """ 
     285    The head association end is enriched with the following attributes: 
     286 
     287        derived - association is a derived union or not 
     288        name - name of the association end (name of head is found on tail) 
     289        class_name - name of the class this association belongs to 
     290        opposite_class_name - name of the class at the other end of the assoc. 
     291        lower - lower multiplicity 
     292        upper - upper multiplicity 
     293        composite - if the association has a composite relation to the other end 
     294        subsets - derived unions that use the association 
     295        redefines - redefines existing associations 
     296    """ 
     297    head.navigable = head.get('class_') 
     298    if not head.navigable: 
     299        # from this side, the association is not navigable 
     300        return 
     301 
     302    name = head.name 
     303    if name is None: 
     304        raise ValueError('ERROR! no name, but navigable: %s (%s.%s)' % (head.id, head.class_name, head.name)) 
     305 
     306    #print head.id, head.lowerValue 
     307    upper = head.upperValue and head.upperValue.value or '*' 
     308    lower = head.lowerValue and head.lowerValue.value or upper 
     309    if lower == '*': 
     310        lower = 0 
     311    subsets, redefines = parse_association_tags(head.taggedValue) 
     312 
     313    # Add the values found. These are used later to generate derived unions. 
     314    head.class_name = head.class_['name'] 
     315    head.opposite_class_name = head.type['name'] 
     316    head.lower = lower 
     317    head.upper = upper 
     318    head.subsets = subsets 
     319    head.composite = head.get('aggregation') == 'composite' 
     320    head.derived = int(head.isDerived or 0) 
     321    head.redefines = redefines 
     322 
    313323 
    314324def generate(filename, outfile=None, overridesfile=None): 
     
    417427 
    418428        for e1, e2 in ((ends[0], ends[1]), (ends[1], ends[0])): 
    419             if not writer.write_association(e1, e2): 
    420                 # At this point the association is parsed, but not written. 
    421                 # assure that derived unions do not get overwritten 
    422                 if e1.redefines: 
    423                     redefines.append(e1) 
    424                 else: 
    425                     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) 
    426                     derivedunions[e1.name] = e1 
    427                     e1.union = [ ] 
    428                     e1.written = False 
     429            parse_association_end(e1, e2) 
     430 
     431        for e1, e2 in ((ends[0], ends[1]), (ends[1], ends[0])): 
     432            if e1.redefines: 
     433                redefines.append(e1) 
     434            elif e1.derived: 
     435                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) 
     436                derivedunions[e1.name] = e1 
     437                e1.union = [ ] 
     438                e1.written = False 
     439            elif e1.navigable: 
     440                writer.write_association(e1, e2) 
    429441 
    430442