jump to navigation

Call for arms: QtMof/QtUml December 11, 2012

Posted by Sandro Andrade in planetkde-sandroandrade, planetqt-sandroandrade.
trackback

Hi planet,

As roughly mentioned in a previous post, in last two months I’ve been working on a Qt5-based implementation of OMG’s MOF (Meta Object Facility) and UML (Unified Modeling Language) specifications. For those of you who are more familiar with a user-perspective view of UML, it’s worth mention that UML (and your defining metalanguage, MOF) provides a powerful infrastructure which enables, for example, programmatic handling of models, early analysis of architectural models, effective middleware/framework-driven artifact generation, use of deployable models in run-time, and so on. A considerable amount of work has been done towards the development of high-quality tools which leverage the use of models in software development processes. Efforts like the Eclipse Modeling Framework have been setting the stage for a number of plugins, environments, or even tailored Eclipse versions (Eclipse Modeling Project), which rely on modeling features to provide a complete toolset for model-driven engineering. QtMof/QtUml aim at bringing such features to the Qt5 world.

QtMof/QtUml rationale has been driven by the following desired properties:

  • We should support automatic code generation as much as possible. Only 8.17% of UML 2.4.1 metamodel properties are declared as ‘derived’ (and not derived unions), which prevent automatic code generation. For those properties, the specification provide the guidelines for implementation but maybe some of them could be automatically derived from their OCL specifications. QtMof/QtUml already provides a mapping from UML to Qt5 by first generating a more Qt-ish representation of a UML model (XQuery-based xmi to qtxmi conversion) and then generating source code from a couple of well-design templates. Such infrastructure has successfully been used to generate the initial skeletons of QtMof/QtUml and can also be used to convert user-defined UML models into Qt5 source code. As a consequence, we hopefully end up with a faithful implementation of OMG’s standardized metamodels.
  • We should provide a metamodel-agnostic tool for editing, analysing, and converting any MOF-based model. By having no compile-time commitments with any specific MOF-based metamodel, such tool would be also able to handle other MOF-based metamodels (such as CWM) or even user-defined meta-models.
  • QtMof/QtUml should provide a powerful modeling notation for early analysis of MOF-based models. A number of preset scripts for checking well-formed rules should be available and specific scripts may be defined by the user. OCL is a potential candidate as script language, but XQuery or even QtScript can also be considered. That would make possible, for example, analysis of conformance to architectural styles/patterns, continuously integrated models, and so on.
  • A flexible mechanism for mapping of models into middleware/framework-specific artifacts should also be provided. A uml2qt mapping is already in place, but new ones should be easily defined.

Getting right down to the business instead of talking on abstractions 🙂 that’s what a QtUml application currently looks like:



QWrappedObjectPointer<QModel> model = new QModel;
model->setName("MyModel");

QWrappedObjectPointer<QPackage> package = new QPackage;
package->setName("Package1");

QWrappedObjectPointer<QPrimitiveType> primitiveType = new QPrimitiveType;
primitiveType->setName("String");

QWrappedObjectPointer<QEnumeration> enumeration = new QEnumeration;
enumeration->setName("DirectionKind");
QWrappedObjectPointer<QEnumerationLiteral> directionIn = new QEnumerationLiteral;
directionIn->setName("DirectionIn");
enumeration->addOwnedLiteral(directionIn);

QWrappedObjectPointer<QClass> class_ = new QClass;
class_->setName("Student");
class_->setAbstract(false);

package->addOwnedType(enumeration);
package->addOwnedType(class_);

model->addPackagedElement(package);
model->addOwnedType(primitiveType);

// query model or perform 'well-formed/sanity/architectural conformance' checks

delete model.data();

Let’s shed some light on the code above. First of all, UML 2.4.1 metamodel specifies a set of 242 metaclasses (193 out of those are concrete metaclasses) with a couple of dreaded diamonds. In order to overcome the inherent QObject disabilities to cope with virtual inheritance, QtMof/QtUml provides (and relies on) the QtWrappedObjects library: an easy-to-use Qt5-based implementation of “smart delegators” and “delegation-based multiple inheritance”. All behind-the-scene hard work is handled by a new smart pointer (QWrappedObjectPointer) and a new casting operator (qwrapperobject_cast). Secondly, model elements can easily be imported from other (meta)models instead of explicitly instantiating them by “new QPrimitiveType“, for example (use QElementImport/QPackageImport for that purpose). Thirdly, an element takes ownership of any (multi-valued or single-valued) UML property which was declared with “aggregate = composite”, so that a single “delete model.data()” do the whole work.

Even though not 100% implemented, UML Profiles and profile applications may currently be defined programmatically:


// Create a profile
 QWrappedObjectPointer<QProfile> profile = new QProfile;
 profile->setName("MyProfile");

// Add a stereotype to profile
 QWrappedObjectPointer<QStereotype> stereotype = new QStereotype;
 stereotype->setName("MyStereotype");
 profile->addPackagedElement(stereotype);

// Show profile's owned stereotypes
 QScopedPointer<QStereotypeList> ownedStereotypes (profile->ownedStereotypes());
 qDebug() << "Owned stereotypes:";
 foreach (QStereotype *ownedStereotype, *ownedStereotypes)
qDebug() << " " << ownedStereotype->name();

// Adding attribute to stereotype
 QWrappedObjectPointer<QPrimitiveType> booleanPrimitiveType = new QPrimitiveType;
 booleanPrimitiveType->setName("boolean");
 QWrappedObjectPointer<QProperty> property = new QProperty;
 property->setName("isTransient");
 property->setType(booleanPrimitiveType);
 stereotype->addOwnedAttribute(property);

The following lines apply an existing UML profile to a package:


// Create UML meta-model element import
 QWrappedObjectPointer<QElementImport> elementImport = new QElementImport;
 elementImport->setImportedElement(umlModel->packagedElements()->toList().first());

// Add meta-class reference to profile
 profile->addMetaclassReference(elementImport);
 profile->addOwnedType(booleanPrimitiveType);

// Create extension
 QWrappedObjectPointer<QExtension> extension = new QExtension;
 extension->setName("class_stereotype");

QWrappedObjectPointer<QProperty> stereotypeProperty = new QProperty;
 stereotypeProperty->setName("base_class");
 stereotypeProperty->setType(class_);

QWrappedObjectPointer<QExtensionEnd> extensionEnd = new QExtensionEnd;
 extensionEnd->setName("extension_stereotype");
 extensionEnd->setType(stereotype);

extension->addMemberEnd(stereotypeProperty);
 extension->addMemberEnd(extensionEnd);
 extension->setOwnedEnd(extensionEnd);

stereotype->addOwnedAttribute(stereotypeProperty);

Of course, a helper function or a QtScript can be created to provide a simpler API for creating and applying profiles. As for the editor, current status is still far from usable but it already works as a proof-of-concept for a metamodel-agnostic tool (it links only against QtWrappedObjects):

arcade

Potential future uses of QtMof/QtUml include: development of model-driven mechanisms in QtCreator/KDevelop, full UML2.4.1/2.5 support in Umbrello, effective Qt code generation from UML models, and so on.

So, if you like modeling and would like to do some code reviewing and/or help hacking QtMof/QtUml you are quite welcome :). You can grab QtMof/QtUml source code at Qt Playground Repository. Alternatively, if you run openSUSE, there is an OBS repository which provides QtMof/QtUml binaries. In order to use them you must include Qt5 and QtMof/QtUml repositories and install the required packages. The libQtMof-devel package provide the examples for profiles and the current editor:

zypper ar -f http://download.opensuse.org/repositories/KDE:/Qt50/openSUSE_12.2 openSUSE-12.2-Qt5
zypper ar -f http://download.opensuse.org/repositories/home:sandroandrade/openSUSE_12.2 openSUSE-12.2-QtMof
zypper ref
zypper in libQtUml-devel

See you …

Comments»

1. Jan - December 12, 2012

very interesting…are there any graphical editors in planning? a class, state machine and sequence chart editor would be fine..would be great, if the community is growing for this project…

good luck!

regards
Jan

Sandro Andrade - December 12, 2012

Hi,

Yes, concrete syntax is planned but not for the next weeks. I’m currently working on XMI serialization and some OCL parser/QtScript/XQuery infrastructure,
since those feature have higher priorities by now.

Thanks,

2. QtMof/QtUml: XMI serialization and metamodel plugins « Live Blue - January 21, 2013

[…] lot has happening since my last post about QtMof/QtUml – a Qt5 add-on module devoted to (meta-)modeling and model-driven support in Qt (currently in Qt […]

3. How cute can modeling be ? | Live Blue - November 18, 2013

[…] of things have happened in QtModeling land tough. In case you haven’t read my previous ‘call for arms‘ and ‘XMI serialization and metamodel plugins‘ posts, QtModeling is intended to […]


Leave a comment