Up Previous Next Title Page Contents

2.5 Extending the Watch Modeling Language

What about the future, then? It is obvious that in real life a modeling language like this continues to evolve, both in and of itself, and to keep pace with changes in the domain or platform. Thus it is important to be able to develop the DSM solution further according to the new requirements that may arise. The way we developed the Watch modeling language enables us to add new features to the language relatively easily by extending the modeling language definitions, code generators and pre-defined Java classes. As an example on how to extend the Watch modeling language, let us add a new Constant object type to be used in WatchApplication diagrams and code generation support for it.

To add a new object type, open Object Tool from the MetaEdit+ launcher and define a new object called ‘Constant’ with properties ‘Hours’, ‘Minutes’ and ‘Seconds’ (make sure to choose number as a data type for each of these properties). With these definitions, the Object Tool should look like in Figure 2-11.

Figure 2-11. The Object Tool with 'Constant' definitions.

Confirm the creation of the ‘Constant’ type by pressing Save (since this is the first time you have changed the metamodel in this session, it may take a few seconds). To complete the definition of the new object type, we need to create a symbol for it. Launch the Symbol Editor by pressing the Symbol button on the Object Tool. Create a symbol similar to the one shown on Figure 2-12 (you can also copy an existing symbol like the one used for ‘Variable’ and modify it for this purpose). Remember to save the symbol when leaving the Symbol Editor.

Figure 2-12. The symbol for 'Constant' object type.

The next thing to do is to integrate this new type into our existing WatchApplication diagram type. Open the Graph Tool from the MetaEdit+ launcher and open the definition of the WatchApplication graph type. Go to the Types page and add ‘Constant’ to the Objects list. Go then to the Bindings tab and add the ‘Constant’ object type for the ‘Get’, ‘Minus’ and ‘Plus’ roles in the bindings of the ‘Alarm’ and ‘Set’ relationships (an example of this kind of binding is shown in Figure 2-13). Now you can create and use Constant objects in your models.

Figure 2-13. A binding with ‘Constant’ connected to ‘Minus’ role.

The final touch to complete the addition of this new type into our modeling language is to get the code generator to support it. Open the Generator Editor for the WatchApplication graph type and modify the ‘_calcValue’ generator as follows:
Report '_calcValue'
do ~Get.()
{  if type = 'Constant'
   then '(new METime(' :Hours ', '
     :Minutes ', ' :Seconds '))'
   else 'get' id '()'
   endif
}
do ~(Minus|Plus)
{  '.me' type
   do .()
   {  if type = 'Constant'
      then '(new METime(' :Hours ', '
        :Minutes ', ' :Seconds '))'
      else '(get' id '())' 
      endif
   }
}
endreport
Accept the changes by saving the generator. The new ‘Constant’ type has been now integrated as a fully operational part of the Watch modeling language. To try out how it works, consider the fragment of the ‘Stopwatch’ WatchApplication diagram shown in Figure 2-14:

Figure 2-14. The original ‘Stopwatch’ diagram.

The implementation of resetting the stopwatch is obviously somewhat weak: to set ‘stopTime’ to zero one has to subtract the value of the ‘startTime’ variable from itself and store it into the ‘stopTime’ variable. With the new ‘Constant’ type we can define this more naturally by just assigning a constant value of zero to the ‘stopTime’ variable, as illustrated in Figure 2-15:

Figure 2-15. The new version of ‘Stopwatch’ diagram.

The issue of future extensions should be recognized and taken care of during the original design and implementation of a domain-specific language. Ease of extension was not our primary goal while implementing the Watch modeling language, but there are still certain ‘hooks’ for this purpose. The main area we felt extensions would be necessary were the different operations possible in actions. For this reason we decided to make each operation type have its own relationship type. This allowed us to easily make bindings and constraints specifying the rules of what arguments the operation can or must have. Similarly, the code generation for that kind of operation is easy to add as a new generator named after the relationship type. Together, these make it very easy to extend the modeling language with new operations.

More complex extensions usually require further additions and modifications within the modeling language, code generator and in the framework classes. However, as each of these have been implemented in a modular fashion, making the required modifications should be relatively easy. Most importantly, only one person need make the required changes, and all of the modeling language users will benefit from them.

Up Previous Next Title Page Contents