- To provide support for the use, definition and management of UML profiles with ArgoUML.
The Profile subsystem is located in the package org.argouml.profile and its sub-packages. In package org.argouml.profile there are classes that define almost all the subsystem API, concerning the definition and management of UML profiles. The package org.argouml.profile.init contains the remaining subsystem API, being its only purpose to provide the subsystem initialization API (this is therefore of use only to a minority of other subsystems).
Design of the subsystem
Figure 5.5. Profile subsystem overview class diagram.
The profile subsystem is similar in some ways to the model subsystem – there is a ?ProfileFacade that is the main entry point to the methods and classes that provide management functions to the subsystem (notably the ?ProfileManager). It also maintains a one to one relationship with the remaining subsystems of ArgoUML, although it is not Singleton based in order to facilitate testing and easy cleanup or reset of its internal state.
This section which describes the Profile subsystem is organized according to the main usages of it from a point of view of programming. We hope that it provides guidance for the developers that want to write code that interacts with this subsystem, but, we also try to provide enough internal design information that it serves as an invitation for those same developers to delve, enhance and fix! Therefore we have the following sub-sections:
- Initialization of the profile subsystem, below – describes how to initialize the subsystem or the related issue how to re-initialize the subsystem and what does that mean to your profiles.
- Profile(s) management, below – describes the API involved in the management of the profiles and some classes related to this, even if these aren't in the Profile subsystem. This is probably the most interesting section for the majority of the readers since it goes well inside the guts of the subsystem, as well as it shows how there is support by other subsystems that helps the Profile subsystem to accomplish the goals of managing the profiles within ArgoUML.
- Defining profiles, below – describes what means the subsystem provides that enable profiles to be defined by modules and by users.
- History of the Profile subsystem, below – provides a small history on the subsystem and some links to issues that might be interesting to someone that wants to get involved in the Profile subsystem maintenance and evolution.
Initialization of the profile subsystem
To initialize the profile subsystem you do:
This will create a new instance of the class that implements the ?ProfileManager interface and set ?ProfileFacade to use this instance of ?ProfileManager... Which, by the way is currently ?ProfileManagerImpl, from the org.argouml.profile.internal package. Check Figure 5.6, “Sequence diagram of the profile subsystem initialization.” for more details.
Figure 5.6. Sequence diagram of the profile subsystem initialization.
To complete the description we explain how to re-initialize the subsystem:
Simple enough?! But, what does it mean from an internal point of view? Well, the prior internal objects that were used by the subsystem are left alone and hopefully the garbage collector will clean the memory they occupy. So, it simply creates new fresh objects and these are attached to ?ProfileFacade. This is of use in the automated tests, where there is the need to guarantee that the status of the subsystem isn't changed by previously executed test fixtures.
For a profile to be known by the profile subsystem it must be registered. A profile may be registered in three ways. The first one is when the profile manager registers its own profiles. That happens for example, to the UML profile, that is created by the profile manager and then registered by it. That also happens for user defined profiles, which consist of XMI files that the user places in some directories and afterwards, using the GUI, marks the directories as containing user defined profiles. These profiles are thus automatically loaded and do not need to be registered.
The second way is to use the mechanism of loading profiles and critics as bundled in ArgoUML plug-ins. By this mechanism, a plug-in may declare its list of plug-ins and critics in its MANIFEST. The declared profiles are then going to be loaded, registered and the associated critics are going to be activated and deactivated when needed (more details in the role that critics play in profile see the next section).
See the following sample MANIFEST:
Manifest-Version: 1.0 Class-Path: argouml.jar Created-By: 1.2 (Sun Microsystems Inc.) Name: <<Profile Name>> Profile: true Model: <<Path for Profile XMI>> Depends-on: <<List of Profile Names>> Java-Critics: <<Comma separated list of Critic classes>>
The attributes which describe a profile follow:
(a) Name: The name of the profile (as shown in the explorer) (b) Profile: should be set to "true" in order to the profile be loaded (if this attribute is absent or is set to false this entry is ignored) (c) Model: the absolute path for the XMI model of the profile in the JAR (d) Java-Critics: a list of Java critics provided by this profile.
- The third way is to do it by the means of external entities, like for instance, a language module to register its UML profile would do:
Which is a synonym for:
All of these registered profiles have the common base class Profile, which establishes the interface that must be implemented by a profile so that it is registrable. The Figure 5.7, “Class diagram of the Profile class and some derived classes” shows the Profile class and its specialized classes ProfileUML and ?UserDefinedProfile. Generally speaking, profiles can be created in two ways: by directly specializing the Profile class and implementing some of its operations or by loading a profile XMI as a user defined profile which in turn generates an instance of the ?UserDefinedProfile class, which automates much of the work that otherwise would have to be done manually.
Figure 5.7. Class diagram of the Profile class and some derived classes
As it is possible to register a Profile in the ?ProfileManager, it is possible to unregister it also. A common case is that of a ArgoUML language module, which registers its specific Profile when enabled and unregisters it when it is disabled. Figure 5.8, “Sequence diagram of the registering and unregistering of a profile” illustrates this, standing the module ?ClassifierRole as a language module which is activated by moduleManager by a call to its operation enable. As part of the activation, module creates the moduleProfile and registers it in the profile subsystem by a call to the register(moduleProfile) operation of the ?ProfileFacade. The deactivation of the module causes the call to the remove(moduleProfile), which will unregister the moduleProfile in the profile subsystem.
Figure 5.8. Sequence diagram of the registering and unregistering of a profile
After a profile is registered, it may be chosen as a default profile by the user. A default profile is a profile which is added to new projects by default. For this there is the class org.argouml.ui.SettingsTabProfile that is part of the ArgoUML application settings dialog and shows all the registered profiles, being the profiles set as default profiles shown in a specific list.
The ?ProfileManager is responsible for keeping track of the profiles chosen as default. For this, it has the operations:
void addToDefaultProfiles(Profile profile)
and void removeFromDefaultProfiles(Profile profile)
Besides the class org.argouml.ui.SettingsTabProfile for handling application wide settings of the profile subsystem, there is the class org.argouml.ui.ProjectSettingsTabProfile to enable the users to modify the profile subsystem project settings, which take the form of an instance of the class org.argouml.kernel.ProfileConfiguration. The class org.argouml.ui.ProjectSettingsTabProfile also shows all the registered profiles, as org.argouml.ui.SettingsTabProfile does, but, this time it is to enable the user to add or remove profiles to an open project. In its operation handleSettingsTabSave() the changes the user did are made in the instance of org.argouml.kernel.ProfileConfiguration.
The ?ProfileConfiguration is a ?ProjectMember and is part of a Project. It is persisted and loaded to/from a project file by means of an instance of the class org.argouml.persistence.?ProfileConfigurationFilePersister. These two classes aren't part of the profile subsystem, but, are closely related. Specifically, the ?ProfileConfiguration is part of the kernel subsystem and the ?ProfileConfigurationFilePersister is part of the persistence subsystem.
It all starts with a XMI file containing a model... User defined profiles are simply this, at least from the point of view of the author of the profile. So, to define a profile you start by modeling the profile in an ArgoUML project and then export it as XMI.
The profile subsystem provides means to add additional features to the profiles, but, for this you must get your hands dirty with a bit of java coding. Recall the Profile class in Figure 5.7, “Class diagram of the Profile class and some derived classes”. The additional things that may be added to an ArgoUML profile, but, which require coding are:
a ?FormatingStrategy, which provides specific formatting services to profile model elements;
a ?FigNodeStrategy, which provides figures to be shown instead of the textual representation of the profile stereotypes;
a ?DefaultTypeStrategy, which defines default types for attributes, parameters and return values appropriate for the profile.
Unfortunately these extras are only possible for profiles contained in extension modules, such as the UML profile for C++, or profiles contained within ArgoUML, such as the UML profile of UML. This limitation is caused by the need to load the Java classes that would implement the extended behavior.
If the work in progress by Marcos Aurélio is successful and is integrated into ArgoUML it is possible that the above customizations are performed without any Java coding. This could make user defined profiles and module contained profiles virtually equivalent in what concerns the functionality provided. For more information see issue #5029: Improve Plugability of Profile Subsystem.
CategoryFix: Hasn't this been integrated.
There is a detail that must be taken into account when defining profiles which is the ?ProfileReference that must be associated to each profile. See Figure 5.9, “Class diagram of the ?ProfileReference class and associated classes” for a diagram that shows how these classes are associated with Profile and ?ProfileModelLoader derived classes.
Figure 5.9. Class diagram of the ?ProfileReference class and associated classes
When a profile model is loaded, it must be associated with a ?ProfileReference instance which defines for the profile a path and a public reference (a URL). The path part of a profile reference is something that enables ArgoUML to locate and load the actual XMI file. The public reference is something that will identify the profile uni-vocally, enabling references to model elements of profiles from other models. Specifically it is very important to guarantee that the persisted models that refer to profiles are correctly loaded in other ArgoUML installations than the ones that originally created the models.
History of the Profile subsystem
The profile subsystem was the result of the Google Summer of Code project of Marcos Aurélio in 2007. Much of the design of Marcos' original purposal is still present in the subsystem. His GSoC mentor was Linus Tolke and the work was integrated into ArgoUML trunk by Tom Morris during September of 2007. Previously Tom Morris was involved in adding support for cross XMI file references, which are required for the profiles to work.
After the bulk of the work in creating and integrating the subsystem, we list some issues that might be of interest to persons that want to go after the reasoning behind some of the decisions that took the subsystem to where it is now or which should be solved to raise the subsystem to a quality level above average:
issue #4885: refactoring org.argouml.uml.profile – consisted in a refactoring effort by Luís Sérgio Oliveira in order to make the subsystem more inline with the canonical form ArgoUML subsystems have;
issue #4946: Loading project which references non-default profile doesn't work – a difficult to solve problem that caused persistency failures, which is related to the cross XMI file reference support needed for profiles;
issue #4991: Profiles subsystem missing in the cookbook;
issue #4992: Profiles description is missing from the manual;
issue #4993: Reloading a profile does not undo edits;
issue #4994: Editing loaded profile should be prevented;
issue #4997: user defined profile that depends from module defined profile fails to load on startup;
issue #5040: better error messages when loading of zargo fails due to profile problems;
issue #5043: Profile errors at startup not reported - ?ProfileManagerImpl.refreshRegisteredProfiles();
issue #5064: Duplicate xmi.id warning for different files;
issue #5041: provide core profiles via the website;
issue #5088: not possible to save models loaded as profiles;
issue #5100: Profile directory file selection dialog should default to last directory selected;
issue #5101: All ArgoUML supported XMI file extensions should be allowed.
Follow some of the issues that might affect the future of the subsystem:
issue #5029: Improve Plugability of Profile Subsystem;
issue #5042: Constraints defined in the Profile model should work as Critics.