Chapter 5. Working with Gaphor's internals

Table of Contents

5.1. Data model
5.1.1. Working with the data model
5.1.2. Extensions to the data model
5.2. User interface
5.2.1. Actions

As stated before, Gaphor is completely written in Python. Well, completely... It makes use of the GNOME2 desktop environment. GNOME has powerful bindings for Python.

Lots of effort has been put in the creation of an easy to use and extensible data model. The data model supports:

These items will be refered to as properties.

When a property changes, a signal is be emited. Other objects can attach signal handlers to the property owners (data objects) in order to be notified.

Note

When a property emits a signal, all redefine properties and derived unions also send a signal.

Gaphor's data model is build from properties. This makes it easy to see which properties can be set on a model element and which can not.

The data model is designed so it is easy to retrieve all kinds of information from the data model. One can retrieve all possible properties of a class by simply typing (output is slightly modified to remove default properties):

	  >>> dir(Class)
	  ['connect', 'attribute', 'clientDependency', 'disconnect', 'elementImport',
	  'feature', 'general', 'generalization', 'importedMember',
	  'inheritedMember', 'isAbstract', 'isKindOf', 'isLeaf', 'isTypeOf',
	  'load', 'member', 'name', 'namespace', 'nestedClassifier', 'notify',
	  'ownedAttribute', 'ownedComment', 'ownedElement', 'ownedMember',
	  'ownedOperation', 'ownedRule', 'ownedUseCase', 'owner', 'package',
	  'packageImport', 'postload', 'redefinedClassifier', 'redefinedElement',
	  'redefinitionContext', 'save', 'substitution', 'superClass',
	  'supplierDependency', 'unlink', 'visibility']
	
Besides properties also a few default methods can be found:
connect

Attach (connect) a signal handler to an instance

disconnect

Detach (disconnect) a signal handler.

notify

Notify all objects that attached to a specific signal. This is automatically done when a property changes.

isKindOf

OCL method. Same as isinstance().

isTypeOf

Check if the type() is equal.

load

Load a given name-value pair. This is used for loading a model.

postload

Postload is called after all information is loaded.

save

Save a name-value pair. This is used to serialize (save) the object.

unlink

End the life cycle of an object. Unlink removed all relations with the object.

Exept for those methods, all other fields are properties of the data object.

It is pretty easy to find out what type of object could be connected to an attribute:

	  >>> print Class.name
	  <attribute name: <type 'str'>[0..1] = None>
	

An association displays similar results:

	  >>> print Class.ownedAttribute
	  <association ownedAttribute: Property[0..*]>
	
This shows the definition of Class.ownedAttribute. It has a uni-directional to zero or more Property objects. The following code shows a bi-directional association:
	  >>> print Class.generalization
	  <association generalization: Generalization[0..*] -> specific>
	  >>> print Generalization.specific
	  <association specific: Classifier[1] -> generalization>
	

One of the more advanced features of the data model are derived unions (which show a / before their name and redefined properties (which carry a {redefine} tag). A derived union is a gathering of one or more other properties. a redefined property is some sort of alias. In the following example a Class object is added to a Package.

	  >>> p = Package()
	  >>> c = Class()
	  >>> c.package = p
	  >>> c.package
	  <uml2.Package object at 0x00815020>
	  >>> c.owner
	  <uml2.Package object at 0x00815020>
	  >>> c.namespace
	  <uml2.Package object at 0x00815020>
	  >>> p.ownedClassifier
	  [<uml2.Class object at 0x008166F0>]
	  >>> p.ownedElement
	  [<uml2.Class object at 0x008166F0>]
	  >>> p.ownedMember
	  [<uml2.Class object at 0x008166F0>]
	
Besides package also the namespace and owner properties of the Class are set. Well, they are not actually set, they are derived values from c.package. The same thing happens for Package.ownedClassifier (the opposite side of package).