forked from gaphor/gaphor
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
git-svn-id: file:///Users/arjan/backup/gaphor/trunk/gaphor@365 a8418922-720d-0410-834f-a69b97ada669
- Loading branch information
Showing
22 changed files
with
705 additions
and
183 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,15 @@ | ||
# vim:sw=4:et | ||
|
||
print 'plugin',__file__ | ||
|
||
import gaphor.plugin | ||
from checkmodelgui import CheckModelWindow | ||
from checkmodel import check_associations, check_attributes | ||
|
||
class CheckMetamodelAction(gaphor.plugin.Action): | ||
|
||
def init(self, window): | ||
self._window = window | ||
|
||
def execute(self): | ||
print 'UMLSanityCheck' | ||
|
||
print 'CheckMetamodelAction' | ||
# TODO: override checkmodel.report | ||
cw = CheckModelWindow() | ||
cw.construct() | ||
self.window.add_transient_window(cw) | ||
cw.run() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
# vim:sw=4:et | ||
|
||
from gaphor import resource | ||
from gaphor import storage | ||
import gaphor.UML as UML | ||
import os.path as path | ||
|
||
def report(element, message): | ||
print '%s: %s' % (type(element).__name__, message) | ||
|
||
def get_subsets(tagged_value): | ||
subsets = [] | ||
if tagged_value.find('subsets') != -1: | ||
subsets = tagged_value[tagged_value.find('subsets') + len('subsets'):] | ||
subsets = subsets.replace(' ', '').replace('\n', '').replace('\r', '') | ||
subsets = subsets.split(',') | ||
return subsets | ||
|
||
def get_redefine(tagged_value): | ||
redefines = tag[tag.find('redefines') + len('redefines'):] | ||
# remove all whitespaces and stuff | ||
redefines = redefines.replace(' ', '').replace('\n', '').replace('\r', '') | ||
redefines = redefines.split(',') | ||
assert len(redefines) == 1 | ||
return redefines[0] | ||
|
||
def get_superclasses(class_): | ||
for superclass in class_.superClass: | ||
gen = 1 | ||
|
||
def check_association_end_subsets(end): | ||
subsets = get_subsets(end.taggedValue and end.taggedValue.value or '') | ||
opposite_subsets = get_subsets(end.opposite.taggedValue and end.opposite.taggedValue.value or '') | ||
subset_properties = UML.select(lambda e: e.isKindOf(UML.Property) and e.name in subsets) | ||
|
||
# TODO: check if properties belong to a superclass of the end's class | ||
|
||
# TODO: check if the association end is navigable when the subsets are navigable | ||
for p in subset_properties: | ||
pass | ||
|
||
# Check if bi-directional derived unions are bi-directional on this association | ||
for p in subset_properties: | ||
if p.opposite.name and p.opposite.name not in opposite_subsets: | ||
report(end, 'Subset not defined on both sides. (%s, %s)' % (p.name, p.opposite.name)) | ||
|
||
# Check if multiplicity of the properties matches the multiplicity of the subsets | ||
for p in subset_properties: | ||
if p.upperValue: | ||
if not end.upperValue: | ||
report(end, 'Association end %s has no upper value, but the subset %s has' % (end.name, p.name)) | ||
elif p.upperValue.value < end.upperValue.value: | ||
report(end, 'Association end %s has has a bigger upper value than subse %s' % (end.name, p.name)) | ||
|
||
def check_association_end(end): | ||
check_association_end_subsets(end) | ||
|
||
def check_associations(): | ||
for a in UML.select(lambda e: e.isKindOf(UML.Association)): | ||
assert len(a.memberEnd) == 2 | ||
head = a.memberEnd[0] | ||
tail = a.memberEnd[1] | ||
check_association_end(head) | ||
check_association_end(tail) | ||
|
||
def check_attributes(): | ||
for a in UML.select(lambda e: e.isKindOf(UML.Property) and not e.association): | ||
if not a.typeValue or not a.typeValue.value: | ||
report(a,'Attribute has no type: %s' % a.name) | ||
elif a.typeValue.value.lower() not in ('string', 'boolean', 'integer', 'unlimitednatural'): | ||
report(a, 'Invalid attribute type: %s' % a.taggedValue.value) | ||
|
||
# TODO: Check the sanity of the generated data model. | ||
def check_UML_module(): | ||
all_classes = map(getattr, [UML] * len(dir(UML)), dir(UML)) | ||
for c in all_classes: | ||
if not isinstance(c, UML.Element): | ||
continue | ||
# TODO: check derived unions. | ||
|
||
if __name__ == '__main__': | ||
storage.load(path.join('gaphor', 'UML', 'uml2.gaphor')) | ||
check_associations() | ||
check_attributes() | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
# vim:sw=4:et | ||
|
||
"""A GUI for the checkmodel plugin. | ||
""" | ||
|
||
import sys | ||
import gobject | ||
import gtk | ||
import gaphor | ||
from gaphor.ui.abstractwindow import AbstractWindow | ||
from gaphor.plugin import resource | ||
import checkmodel | ||
|
||
PYELEMENT_COLUMN = 0 | ||
ELEMENT_COLUMN = 1 | ||
REASON_COLUMN = 2 | ||
|
||
class CheckModelWindow(AbstractWindow): | ||
|
||
menu = ('_File', ('FileClose',)) | ||
|
||
def __init__(self): | ||
AbstractWindow.__init__(self) | ||
# Override the report method | ||
checkmodel.report = self.on_report | ||
|
||
def construct(self): | ||
model = gtk.ListStore(gobject.TYPE_PYOBJECT, | ||
gobject.TYPE_STRING, | ||
gobject.TYPE_STRING) | ||
|
||
treeview = gtk.TreeView(model) | ||
treeview.connect('row-activated', self.on_row_activated) | ||
selection = treeview.get_selection() | ||
selection.set_mode('single') | ||
treeview.set_size_request(200, -1) | ||
|
||
scrolled_window = gtk.ScrolledWindow() | ||
scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) | ||
scrolled_window.set_shadow_type(gtk.SHADOW_IN) | ||
scrolled_window.add(treeview) | ||
scrolled_window.show() | ||
|
||
cell = gtk.CellRendererText() | ||
column = gtk.TreeViewColumn("Element", cell, text=ELEMENT_COLUMN) | ||
treeview.append_column(column) | ||
|
||
cell = gtk.CellRendererText() | ||
column = gtk.TreeViewColumn("Reason", cell, text=REASON_COLUMN) | ||
treeview.append_column(column) | ||
treeview.show() | ||
|
||
self._construct_window(name='checkmodel', | ||
title='Check Model', | ||
size=(400, 400), | ||
contents=scrolled_window) | ||
self.model = model | ||
self.treeview = treeview | ||
|
||
def run(self): | ||
# TODO: Let this run in a Thread(?) | ||
checkmodel.check_attributes() | ||
checkmodel.check_associations() | ||
|
||
def on_report(self, element, message): | ||
log.info('%s: %s' % (type(element).__name__, message)) | ||
model = self.model | ||
iter = model.append() | ||
model.set_value(iter, PYELEMENT_COLUMN, element) | ||
model.set_value(iter, ELEMENT_COLUMN, type(element).__name__) | ||
model.set_value(iter, REASON_COLUMN, message) | ||
main = gobject.main_context_default() | ||
main.iteration(False) | ||
|
||
def on_row_activated(self, treeview, row, column): | ||
iter = self.model.get_iter(row) | ||
element = self.model.get_value(iter, PYELEMENT_COLUMN) | ||
print 'Looking for element', element | ||
if element.presentation: | ||
main_window = resource('MainWindow') | ||
presentation = element.presentation[0] | ||
diagram = presentation.canvas.diagram | ||
diagram_tab = main_window.show_diagram(diagram) | ||
view = diagram_tab.get_view() | ||
view_item = view.find_view_item(presentation) | ||
diagram_tab.get_view().focus(view_item) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.