- Purpose
- To provide support for the use, definition and management of UML profiles with ArgoUML.
- Located
org.argouml.profile
- Layer
Public API
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:
new org.argouml.profile.init.InitProfileSubsystem().init();
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:
new org.argouml.profile.init.InitProfileSubsystem().init();
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.
Profile(s) management
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:
ProfileFacade.register(profile);
Which is a synonym for:
ProfileFacade.getManager().registerProfile(profile);
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:
List<Profile> getDefaultProfiles()
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.
Since UML2 it is no longer sufficient for a profile to simply appear in the profile configuration: it is actively applied to the current user model(s). This is not the responsibility of the profile subsystem (as it doesn't know the user models, this belongs to the project management in the kernel package).
Defining profiles
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 model extends the UML meta-model with new stereotypes and tag definitions that specialize meta-classes of UML's meta-model. It is also possible to associate critics with a profile. These critics validate the user's model according to the well-formedness rules of the profile. These critics are thus going to be activated and deactivated with the associated profile.
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 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.
Besides defining critics by extending the Java class *, it is also possible to define them in OCL by the means of the class. Consider the following OCL critic example:
new CrOCL("context <<Meta-class>> inv: <<Constraint>>", "<<Description>>", null, ToDoItem.HIGH_PRIORITY, null, null, "<<Url>>"));
The attributes which describe a profile follow:
(a) Meta-class: the UML meta-class that is going to be constrained by this OCL (b) Constraint: the OCL expression (c) Description: the textual description of this critic to be displayed in the UI (d) Url: a URL with more information about this critic
There is still 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.
Fortunately, with the aid of the user defined profiles, its is not necessary to write any code in order to define a profile. This is accomplished by the use of the metaprofile when defining the XMI model for a user defined profile. This profile allows adorning profile models with meta-information which previously needed to be provided by user code. It is one of the default profiles provided by ArgoUML and should be added to the current project in order to be available.
The steps for using the metaprofile in an existing Profile:
1. Import the XMI for the existing Profile (File -> Import XMI) 2. Add the "Metaprofile" profile to the current profile configuration (Right click "Profile Configuration -> Manage Profiles").
Elements provided by the metaprofile:
(a) Dependency
type: TagDefinition usage: should be appended to the profile package (the profile package should be annotated with the <<Profile>> stereotype!) and should contain a comma-separated list of profile names. meaning: informs ArgoUML that these profiles should be also added when the current profile is added.
(b) Figure
type: TagDefinition usage: should be appended to a Stereotype defined by the profile meaning: defines the path for the Figure that could be used to represent the elements tagged by this stereotype instead of the default one
(c) Critic
- type: Stereotype usage: should be appended to a comment containing defining a constraint for the profile (a WFR or a Critic) meaning: in the current version, this comment is supposed to contain an OCL invariant (with context!) that should be validated by the model
(c) Description & Headline
type: TagDefinition usage: should be appended to a critic meaning: define the description and the headline for the critic as it should display in the "Critique -> Browse Critics" window
History of the Profile subsystem
The profile subsystem was the result of the Google Summer of Code projects of Marcos Aurélio in 2007 and in 2008. Much of the design of Marcos' original purposal is still present in the subsystem. His GSoC mentor in 2007 was Linus Tolke and the work was integrated into ArgoUML trunk by Tom Morris during September of 2007 and in 2008 was Michiel van der Wulp and the work integrated into ArgoUML trunk bu Marcos during October of 2008. 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 #4994: Editing loaded profile should be prevented;
issue #4997: user defined profile that depends from module defined profile fails to load on startup;
issue #5017: profile model elements are absent from diagrams on reload
issue #5043: Profile errors at startup not reported - ProfileManagerImpl.refreshRegisteredProfiles();
issue #5041: provide core profiles via the website;
issue #5100: Profile directory file selection dialog should default to last directory selected;
issue #5573: Implement automatic flattening of OCL Collections