| 1 |
|
|---|
| 2 |
""" |
|---|
| 3 |
Convert a model from Gaphor version 0.2 to Gaphor version 0.3. |
|---|
| 4 |
""" |
|---|
| 5 |
import env |
|---|
| 6 |
import operator |
|---|
| 7 |
|
|---|
| 8 |
import gaphor.parser as parser |
|---|
| 9 |
import gaphor.storage as storage |
|---|
| 10 |
import gaphor.UML as UML |
|---|
| 11 |
from gaphor.misc.uniqueid import generate_id |
|---|
| 12 |
|
|---|
| 13 |
def get_ref(elem, key): |
|---|
| 14 |
try: |
|---|
| 15 |
return elem.references[key] |
|---|
| 16 |
except KeyError: |
|---|
| 17 |
return elem.references[properties_conversion_map[key]] |
|---|
| 18 |
|
|---|
| 19 |
def _convert_multiplicity(elements, elem, prop): |
|---|
| 20 |
spec = parser.element(generate_id(), 'LiteralSpecification') |
|---|
| 21 |
spec.values['value'] = elem.values['multiplicity'] |
|---|
| 22 |
elem.references['lowerValue'] = [ spec.id ] |
|---|
| 23 |
elements[spec.id] = spec |
|---|
| 24 |
del elem.values['multiplicity'] |
|---|
| 25 |
|
|---|
| 26 |
def _convert_aggregation(elements, elem, prop): |
|---|
| 27 |
"""Strip first three characters from aggregation type (e.g. ak_none ->none) |
|---|
| 28 |
""" |
|---|
| 29 |
|
|---|
| 30 |
elem.values['aggregation'] = elem.values['aggregation'][3:] |
|---|
| 31 |
|
|---|
| 32 |
def _convert_isNavigable(elements, elem, prop): |
|---|
| 33 |
if eval(elem['isNavigable']): |
|---|
| 34 |
|
|---|
| 35 |
|
|---|
| 36 |
assoc_id = elem.references['association'] |
|---|
| 37 |
assert len(assoc_id) == 1 |
|---|
| 38 |
assoc = elements[assoc_id[0]] |
|---|
| 39 |
end_ids = get_ref(assoc, 'connection') |
|---|
| 40 |
other_end = elements[(end_ids[0] == elem.id) and end_ids[1] or end_ids[0]] |
|---|
| 41 |
clazz = elements[get_ref(other_end, 'participant')[0]] |
|---|
| 42 |
|
|---|
| 43 |
attr = clazz.references.get('ownedAttribute') |
|---|
| 44 |
if attr is None: |
|---|
| 45 |
attr = clazz.references['ownedAttribute'] = [] |
|---|
| 46 |
attr.append(elem.id) |
|---|
| 47 |
assert elem.references.get('class_') is None |
|---|
| 48 |
elem.references['class_'] = [clazz.id] |
|---|
| 49 |
else: |
|---|
| 50 |
elem.references['owningAssociation'] = elem['association'] |
|---|
| 51 |
del elem.values['isNavigable'] |
|---|
| 52 |
|
|---|
| 53 |
def _convert_ownedElement(elements, elem, prop): |
|---|
| 54 |
for ref in elem.references['ownedElement']: |
|---|
| 55 |
if elements[ref].type == 'Diagram': |
|---|
| 56 |
own = 'ownedDiagram' |
|---|
| 57 |
elif elements[ref].type == 'Package': |
|---|
| 58 |
own = 'nestedPackage' |
|---|
| 59 |
else: |
|---|
| 60 |
own = 'ownedClassifier' |
|---|
| 61 |
l = elem.references.get(own) |
|---|
| 62 |
if l is None: |
|---|
| 63 |
l = elem.references[own] = [] |
|---|
| 64 |
l.append(ref) |
|---|
| 65 |
|
|---|
| 66 |
del elem.references['ownedElement'] |
|---|
| 67 |
|
|---|
| 68 |
def remove (elements, elem, prop): |
|---|
| 69 |
del elem.references[prop] |
|---|
| 70 |
|
|---|
| 71 |
|
|---|
| 72 |
properties_conversion_map = { |
|---|
| 73 |
'comment': 'ownedComment', |
|---|
| 74 |
'namespace': 'package', |
|---|
| 75 |
|
|---|
| 76 |
'connection': 'memberEnd', |
|---|
| 77 |
|
|---|
| 78 |
'aggregation': _convert_aggregation, |
|---|
| 79 |
'isNavigable': _convert_isNavigable, |
|---|
| 80 |
'multiplicity': _convert_multiplicity, |
|---|
| 81 |
'participant': 'type', |
|---|
| 82 |
|
|---|
| 83 |
'Attribute.owner': 'class_', |
|---|
| 84 |
|
|---|
| 85 |
'feature': 'ownedAttribute', |
|---|
| 86 |
'specialization': remove, |
|---|
| 87 |
'Class.association': remove, |
|---|
| 88 |
|
|---|
| 89 |
'child': 'specific', |
|---|
| 90 |
'parent': 'general', |
|---|
| 91 |
|
|---|
| 92 |
'ownedElement': _convert_ownedElement |
|---|
| 93 |
} |
|---|
| 94 |
|
|---|
| 95 |
classname_conversion_map = { |
|---|
| 96 |
'Model': 'Package', |
|---|
| 97 |
'Attribute': 'Property', |
|---|
| 98 |
'AssociationEnd': 'Property' |
|---|
| 99 |
} |
|---|
| 100 |
|
|---|
| 101 |
def convert_elements(elements): |
|---|
| 102 |
"""Change the elements dictionary (as it is returned from |
|---|
| 103 |
gaphor.parser.parse()) and convert the entries so they can be loaded in |
|---|
| 104 |
the data model of the current version. |
|---|
| 105 |
""" |
|---|
| 106 |
element_list = filter(lambda x: isinstance(x, parser.element), elements.values()) |
|---|
| 107 |
|
|---|
| 108 |
for e in element_list: |
|---|
| 109 |
|
|---|
| 110 |
|
|---|
| 111 |
if e.type == 'AssociationEnd' and not e.values.get('isNavigable'): |
|---|
| 112 |
e.values['isNavigable'] = 'True' |
|---|
| 113 |
|
|---|
| 114 |
for p in e.values.keys() + e.references.keys(): |
|---|
| 115 |
func_or_str = properties_conversion_map.get('%s.%s' % (e.type, p)) \ |
|---|
| 116 |
or properties_conversion_map.get(p) |
|---|
| 117 |
if func_or_str: |
|---|
| 118 |
if operator.isCallable(func_or_str): |
|---|
| 119 |
func_or_str(elements, e, p) |
|---|
| 120 |
else: |
|---|
| 121 |
if p in e.values.keys(): |
|---|
| 122 |
e.values[func_or_str] = e.values[p] |
|---|
| 123 |
del e.values[p] |
|---|
| 124 |
else: |
|---|
| 125 |
e.references[func_or_str] = e.references[p] |
|---|
| 126 |
del e.references[p] |
|---|
| 127 |
|
|---|
| 128 |
for e in element_list: |
|---|
| 129 |
if e.type in classname_conversion_map.keys(): |
|---|
| 130 |
e.type = classname_conversion_map[e.type] |
|---|
| 131 |
|
|---|
| 132 |
item_list = filter(lambda x: isinstance(x, parser.canvasitem), elements.values()) |
|---|
| 133 |
for i in item_list: |
|---|
| 134 |
subject = i.references.get('subject') |
|---|
| 135 |
if subject: |
|---|
| 136 |
e = elements[subject[0]] |
|---|
| 137 |
p = e.references.get('presentation') |
|---|
| 138 |
if p is None: |
|---|
| 139 |
p = e.references['presentation'] = [] |
|---|
| 140 |
p.append(i.id) |
|---|
| 141 |
|
|---|
| 142 |
def convert_factory(factory): |
|---|
| 143 |
for a in factory.select(lambda e: isinstance(e, UML.Association)): |
|---|
| 144 |
|
|---|
| 145 |
|
|---|
| 146 |
p = a.presentation[0] |
|---|
| 147 |
a.package = p.canvas.diagram.namespace |
|---|
| 148 |
|
|---|
| 149 |
|
|---|
| 150 |
|
|---|
| 151 |
for p in a.memberEnd: |
|---|
| 152 |
if not p.class_ and not p.owningAssociation: |
|---|
| 153 |
p.owningAssociation = a |
|---|
| 154 |
|
|---|
| 155 |
if __name__ == '__main__': |
|---|
| 156 |
import sys |
|---|
| 157 |
elements = parser.parse(sys.argv[1]) |
|---|
| 158 |
convert_elements(elements) |
|---|
| 159 |
factory = UML.ElementFactory() |
|---|
| 160 |
storage._load(elements, factory) |
|---|
| 161 |
convert_factory(factory) |
|---|
| 162 |
storage.save('converted.gaphor', factory) |
|---|
| 163 |
|
|---|