Wednesday, March 15, 2006

I was playing a little bit further with the DSL Tools and tried to add some icons to the custom commands (menus) I created. With the help of Jezz I managed to get this working.

 

First of all we tried to use custom bmp images in the commands. Unfortunately there appears to be a bug somewhere in the VS shell that prevented us from using custom bmp images. One option to work around this is use Guidance Automation Toolkit for adding the custom commands, we decided to follow another approach and use one of the icons from the office resources. If you can live with this limitation (approx. 7000 icons), you might be interested in the information below.

 

First you need to decide which icon you want to use in the menu. Therefore, you need the so called FaceID of the icon that you want to use. There are several tools or Office add-ins that can be downloaded from the internet to help you determine the FaceID of an icon (I used this one).

 

For this example we will use FaceID 2497.

 

Now we know the FaceID of the icon we want to use, we can open the “C:\Program Files\Visual Studio 2005 SDK\2005.10\VisualStudioIntegration\Common\Inc\office10\msobtnid.h” file in VS.NET.

 

This file contains all ID’s for the Office icons. For this example, we search the file for FaceID 2497. We will find a line that looks like:

 

#define msotcidExploreWebPage          2497   //(43,25) Label: 'E&xplore Web Page'

 

From this line we get the declaration of the FaceID. In this case this is “msotcidExploreWebPage”

 

In VS.NET we now open our DSL solution and open the “Designer\CtcComponents\GeneratedCmd.dslddt” file.

 

Somewhere after the include of the “GeneratedCmd.dslddi” file we can add the following line.

 

#define OI_GENERATEDIAGRAM guidOfficeIcon:msotcidExploreWebPage

 

Of course you can change the “OI_GENERATEDIAGRAM” in whatever you want. Change the declaration (“msotcidExploreWebPage”) to the appropriate value for your icon, leave the “guidOfficeIcon” in!

 

Next, we open the “Designer\CtcComponents\CustomCmd.ctc” file and find our customer command. This line should look something like this (in your case, of course with other name and text)

 

guidCmdSet:cmdIdGenerateModel, guidMenu:grpidContextMain, 0x0200, OI_NOID,  BUTTON,            DIS_DEF,       "Generate Model from WSDL";

 

We can change the “OI_NOID” into “OI_GENERATEDIAGRAM” (your value here)

 

Last, we have to open the “Designer\Shell\Package.dslddt” file.

 

To make sure VS.NET resets its menu cache after the first build we need to increment the second integer in this line:

[ProvideMenuResource(1000, 15)]

 

Build and run the solution and the icon will appear in your command.

 

 

Doesn’t this look pretty? 

posted on 3/15/2006 11:41:57 AM UTC  #   
 Saturday, March 11, 2006

My friend Jezz started a new series about the work he is doing on building a Toolkit for developing enterprise distributed applications and services. I know some off the details of his work and this is quite interesting. Jezz is just like my pasionate abouth DSL, GAT, and all related stuff. Let’s see what he has to say in his coming posts...

posted on 3/11/2006 1:54:10 PM UTC  #   
 Thursday, February 09, 2006

I have just updated my blog to DasBlog 1.8. If something doesn't work anymore please let me know!

posted on 2/9/2006 9:04:35 PM UTC  #   

Finally! A little more information is available of the DSL Tools modelling API! In this post George Mathew provide us with (some) details on the improvements the DSL Tools team made in the modelling API.

 

As you might have noticed from my previous posts, we have a quite a lot of custom code in our Domain Specific Language that uses this modelling API. Therefore changes in the modelling API will reflect in some additional work for us also. Hopefully not to much!

 

According to George, creating new Domain Classes can now be done by using the ‘new’ keyword. Isn’t that great? (and obvious J). The good new is that also the “old” mechanism is supported in the new API. Hmmm, I think I will definitely upgrade my code to use the ‘new’.

 

Great work, waiting for more news George!

 

posted on 2/9/2006 11:03:09 AM UTC  #   
 Friday, February 03, 2006

It’s been a long time since my last post. I have been busy lately working on a few pretty cool things. Unfortunately cannot talk about most of the things yet. But, there’s one thing I can talk about and that is the “ever lasting story” of our Domain Specific Language for designing service contracts.

 

We still plan to make it available for download as soon as the RTM of the DSL Tools is available. In the meantime we are adding some nice features that hopefully improve the usability of the Domain Specific Language. Of course, we have to make some (hopefully not to many) changes to make our custom code work against the changes API of the RTM of the DSL Tools.

 

For now, let me show you some images of some of the features and/or improvements we have been working on. Just to show you this language isn’t dead yet!

 

First of all, as you can see in the image below, we included some nice images in the ToolBox. Not that difficult but I like the Toolbox a little better now.

Further we added some custom menus. One of them to fire the “WSDL generation” another one to fire the “generating model out of WSDL file” option.

 

Below you can see an example of two custom menus that are available when right clicking a MessageShape in our model. When pressing the “Select Message XSD location” (description will probably change!) you get a FileDialog box to select an XSD file that describes the Message. After you selected the XSD, the “schemalocation” property of the MessageShape in the model gets populated with the reference to the XSD.

 

A next thing you can do is right click the MessageShape again and this time you can select the “Select Message from XSD” option. As you can see in the image below, this action results in a new window that pops up and that is populated with all the message definitions in the XSD that you selected in the previous action. You can also click on the messages to see the DataContracts that are referenced in the message.

After selecting a message the MessageShape in the model gets populated with the name of the selected message and the DataContracts belonging to the message are also added to the MessageShape. Maybe no rocket science, but it hopefully makes the Language a little easier to use.

To be continued...

posted on 2/3/2006 2:43:09 PM UTC  #   
 Sunday, December 11, 2005

The new November DSL Tools CTP comes with a totally new Validation Framework. This framework can be used to write constraints for domain classes in your domain model. After trying it out I must admit that the framework makes writing constraints very easy! All validation errors popup in the “Error List” windows in VS.NET, all of this is very cool!

  

However, I was a bit confused. I assumed that whenever a constraint was violated on a domain class in my model this was reflected in the “IsValid” property of the ModelElement and the “Store” that represents my model. None of this is true! While the Error List window shows some constraints violations the “IsValid” of the “Store” (and the ModelElement) returns “true”.

 

Because I need this information in a piece of custom code in the DSL I had to look a little further. I noticed that it is possible execute the validation myself from within the custom code. Have a look at the following code snippet where I am using the “ValidationControler” class to execute the validations. (don’t forget: using Microsoft.VisualStudio.Modeling.Validation;)

ValidationController controller = new ValidationController();

bool isValid = controller.Validate(this.Store,ValidationCategory.Save);

This code lives in the “ServiceDescriptionDiagram” class in the DSL. From there I have a reference to the “Store” that I can use in the “Validate” method. The methode has some other overloads that makes it, for example, possible to validate an ModelElement. The good thing is that this piece of code actually returns the right value (based on the violated constraints in my model). In the code above the value of “isValid” is false whenever a constraint is violated.

 

I am not sure (yet) why the IsValid property on the “Store”, “ModelElement” and “ShapeElement” doesn’t reflect the current state of any violated validation. It might have something to do with the “ValidationCategory” that is part of the validation process. This category can be specified on a constraint to tell the validation framework when a constraint should be validated. Current options are “Menu”, “Save”, “Open” and “Custom”.  It looks like no information about a model or class being valid is stored in the underlying datastore of the model. I assume there is a very “valid” reason for this!

 

For continuing our DSL, this isn’t a problem at all. We can use the “ValidationController” at any place in our DSL to decide if the model is valid enough to start generating artifacts.

 

To be continued...

posted on 12/11/2005 8:07:33 PM UTC  #   
 Tuesday, December 06, 2005

Some days ago I received an email of somebody asking me if I am (still) using T4 templates within the DSL we are building. After reading some of my latest post he got the idea that a lot of the features we are building aren’t implemented in Text templates (T4). He asked me if there is a special reason for that and if I think the T4 templates are useful enough for writing (parts of) your DSL.

 

Actually it is true that a lot of the things I am currently working on is implemented in pure C# code and is hooked into the diagram itself by using techniques described in earlier posts. For me this works just great.

 

The thing I like about integrating as many features as possible directly in the diagram itself is that it requires no user actions (selecting menu items) to “execute the feature”. For example, in our DSL you don’t have to select a menu item to translate a Service that is modelled in our Designer into WSDL. This is done on the fly whenever a change is made in the designer and the diagram is still a valid representation of a Service. All of this is done by events that get triggered “automatically” through the designer. Another option was to implement the WSDL generation into T4 templates and let the user trigger the execution of the T4 template through a menu item.

 

It’s not that I don’t like writing T4 templates! Actually I do like the templates. I have to admit that there are some improvements possible in the “writing experiences” of these templates but I am sure this will improve in future builds of the DSL Tools. I can imagine that we will use the T4 templates for some other artifacts that get generated out of our domain model. To be honest, the WSDL generation for our DSL is besides the “pure C#” version also available in a T4 template. Translating the “pure C#” version into a T4 template (and vice versa) was done in a few minutes.

 

So, to answer the question in the email that starts me writing this post. A lot of the functionality in our DSL is built in “pure C#” directly hooked into the diagram, but that doesn’t mean that I don’t like T4 templates or think they are not useful! In fact, they will be part of our DSL. I think you have to find out for yourself what features and/or customizations you need in your DSL and what can be best implemented in pure C# and what can be best implemented in T4 templates.

 

I noticed that George Mathew (team member DSL Tools) wrote one of his first posts on his blog about new features in the Text Templates (T4) of the DSL Tools. Maybe he (or other team members) has some thoughts or better explanation on when to use the T4 templates and when to implement things directly into the designer or diagram?

 

 

posted on 12/6/2005 9:48:53 PM UTC  #   
 Monday, December 05, 2005

In an earlier post I mentioned I am using the “OnTransactionCommiting” on the Diagram class to implement some logic (generating WSDL) for the DSL we are writing. My remark at that point was that the event is triggered a lot and therefore might not be the best place to implement time consuming logic. At that point I didn’t pay a lot of attention to the “TransactionCommitEventArgs” parameter of the event. After some further investigation I found out that the “Transaction” (that can be reached through the TransactionCommitedEventArgs) has a logical name that “indicates” what is happening in the diagram and what (user) action triggered this event.

 

For example, when changing the value of a property named “WSDLDescription” in the diagram, the name of the Transaction is “Set WSDLDescription”, when first loading a diagram the name of the Transaction is “LoadDocData”, etc. The code snippet below gives you an idea how to limit unnecessary (custom) code executions that you might implement in the “OnTransactionCommiting”.

 

public override void OnTransactionCommitting(TransactionCommitEventArgs e)
{
   base.OnTransactionCommitting(e);

   if ( e.Transaction.Name.ToUpper() == "SET WSDLDESCRIPTION")
   {

      //only execute in case of a change in the WSDLDescription property
      DoStuff();
   }
}

 

This actually means that I have much more control than I initially thought and therefore makes the “OnTransactionCommiting” a usefull event to implement some other logic too.

 

To be continued…

posted on 12/5/2005 7:14:04 PM UTC  #   
 Tuesday, November 22, 2005

One of the things I *really* want to implement for our DSL is “round tripping”. This means in my case, (at least) generate a “Service Description diagram” out of a valid WSDL file and visa versa.

 

Some weeks ago I already did an attempt in this direction but eventually I ran into problems with the serializer. As you can read in this post on the DSL forum the relations between concept got lost when trying to serialize (save to disk) the in-memory representation of the generated diagram. Probably this is caused by either a mistake on my side or a bug in the DSL Tools. Some days ago while playing with the propagation rules I found a way to make “round tripping” work in our DSL. Let me explain a little further.

 

I added a new property to the “Service” concept in the DSL, called “WsdlDescription”. This property represents a reference to a WSDL file describing the service. I added a new propagation rule that fires whenever the “WsdlDescription” property of the Service concept changes. This propagation rule, on its turn, fires a piece of code that parses the WSDL file (referenced by the “WsdlDescription” property) and generates a diagram out of this. With this code in place I can generate a diagram out of a WSDL file by simply creating a new empty diagram. To be more precise, adding a new item to the Visual Studio solution based on the “ServiceDescription” (name of the DSL) template. This results in an (valid) empty diagram. I can set the “WsdlDescription” property (service concept) in the empty diagram to reference a valid WSDL file and the magic happens, the diagram is generated! The advantage of this approach, compared to creating an empty diagram from scratch by using custom code, is that we can rely on the DSL Tools infra structure to properly initialize the diagram.

 

Of course you can find another “hook” to implement your round tripping code. This depends on the DSL you are building. For this moment, in our DSL, the propagation rule on this property does the trick.

 

Let’s have a look at some code. Below you see the code for the propagation rule that is defined for the “Service” concept in the model. First we try to cast the input parameter of the “ElementAttributeChanged” method to a “Service”. If that succeeds and the rule is fired because of a change in the “WsdlDescription” property we can continue. To create any new concepts in the diagram we need the “Store”. This can be seen as the in-  memory representation of the diagram. We can get this by using the “Store” property on the “Service”. Then we create a “ServiceInterface and ServiceOperation and register both elements under the Service by using the “ServiceArtifacts” relation. (To better understand the model of this DSL, have a look at the, slightly outdated, image of the domain model of the DSL). Finally we add the “ServiceOperation” as an “Operation” under the “ServiceInterface” and we are done. We now created two model elements and a relation between them in code. All displayed perfectly in the diagram.

 

[RuleOn(typeof(OurCompany.Design.ServiceDescription.DomainModel.Service),
                                                     FireTime
= TimeToFire.TopLevelCommit)]
    
public sealed class DomainModelServicePropertiesChangesRule : ChangeRule
    {
        
public override void ElementAttributeChanged(ElementAttributeChangedEventArgs e)
        {
            
            
// cast input parameter to Service element
            OurCompany.Design.ServiceDescription.DomainModel.Service service
=
                                 e.ModelElement
as OurCompany.Design.ServiceDescription.DomainModel.Service;
            
if (service != null)
            {

                
// only execute it when the rules is fired because of a change in the WsdlDescription property.
                
if (e.MetaAttribute.Id ==
                        OurCompany.Design.ServiceDescription.DomainModel.Service.WsdlDescriptionMetaAttributeGuid)
                {
                    
                    
// create new ServiceInterface. Use the store of the service
                    ServiceInterface serviceInterface
=                                                                 ServiceInterface.CreateServiceInterface(service.Store);
                    serviceInterface.Name
= "GeneratedInterface";
                    
                    
// add ServiceInterface as an ServiceArtifact of the service
                    service.ServiceArtifacts.Add(serviceInterface);

                    
// create new ServiceOperation. Use the store of the service
                    ServiceOperation serviceOperation
= ServiceOperation.CreateServiceOperation(service.Store);
                    serviceOperation.Name
= "GeneratedServiceOperation";

                    
// add ServiceOperation as an ServiceArtifact of the service
                    service.ServiceArtifacts.Add(serviceOperation);

                    
// add the relation from serviceInterface to serviceOperation
                    serviceInterface.ServiceOperation.Add(serviceOperation);
                }
            }


        }

    }




In the above code snippet all of the diagram generating is hard coded, this is, of course, just for this example. In my situation the hard coded stuff is replaced by some calls to helper functions that parse the WSDL and translate this back in a diagram.

 

To make sure the rules gets executed on changes in the Service concept we need to facilitate that it can be “picked up” by the “rule engine”. This is done by reflection; therefore we need the following code.

    // This class is reflected on to load rules dynamically.
    
// Add a variable for each custom rule.
    
internal static partial class GeneratedMetaModelTypes
    {
        
internal static Type DomainModelServicePropertiesChangesRule =
                                    
typeof(DomainModelServicePropertiesChangesRule);
    }

 

Now the diagram is generated out of the WSDL, we have to make sure the WSDL stays in synch with any changes that might be made in the diagram. It’s my intention to let this synchronisation magic happen automatically, so without any user actions (pressing menu options, etc.). To experiment with this I added the “synchronization logic” to the “OnTransactionCommiting” event of the diagram. As you can see in the code snippet below this is just a matter of overriding the “OnTransactionCommiting” method in a partial “ServiceDescriptionDiagram” class.

 

public partial class ServiceDescriptionDiagram
{
   public override void OnTransactionCommitting(TransactionCommitEventArgs e)
   {
      base.OnTransactionCommitting(e);

      //validate the diagram and execute synch code


   }

}

 

Although this works perfect I am not absolutely sure if this is the right place to implement this kind of logic. I noticed that the code gets fired a lot. Within this method I first validate the diagram to make sure there is enough information in the diagram to generate a valid WSDL file. If so, the generation (synchronisation) starts. I haven’t experienced any performance issues with this approach but maybe it is better to only synch when the diagram gets saved. I have to do some more investigation on this area.

 

To be continued….

 

posted on 11/22/2005 8:24:24 PM UTC  #   
 Sunday, November 20, 2005

 

The MessageHeader concept in our DSL has an attribute “SchemaLocation” (the same is true for Message and DataContract). This property is a reference to the XSD description of the MessageHeader. Another property of the Message concept is the “Namespace” property. The value of this property is used in the WSDL that is generated out of the Domain model of our DSL. In an attempt to make our DSL as user friendly as possible I decided to set the “Namespace” property automatically as soon as the “SchemaLocation” is populated.

 

To make this possible I wrote a propagation rule (one of the customization features of the DSL Tools) to make this happen.

 

Below you can see the code that is needed for a propagation rule. I stored this code in a separate .cs file in a folder called “custom” that I created in the designer project. The rule inherits from “ChangeRule”. The implementation isn’t that difficult (note: just demo code)

 

[RuleOn(typeof(OurCompany.Design.ServiceDescription.DomainModel.MessageHeader),
FireTime = TimeToFire.TopLevelCommit)]
public sealed class DomainModelMessageHeaderPropertiesChangesRule : ChangeRule
{
   public override void ElementAttributeChanged(ElementAttributeChangedEventArgs e)
   {
      // store the Namespace in
      string messageHeaderNamespace;


      OurCompany.Design.ServiceDescription.DomainModel.MessageHeader messageHeader =
      e.ModelElement as OurCompany.Design.ServiceDescription.DomainModel.MessageHeader;
      

      if (messageHeader != null)
      {
         if (e.MetaAttribute.Id ==
         OurCompany.Design.ServiceDescription.DomainModel.MessageHeader.SchemaLocationMetaAttributeGuid)
         {

            if (!String.IsNullOrEmpty(messageHeader.SchemaLocation))
            {

               // helper code to retrieve the Namespace from the XSD 
               ServiceDescriptionEngine.GetSchemasFromXsd(messageHeader.SchemaLocation, out messageHeaderNamespace);


               // set the value of the Namespace property 
               messageHeader.Namespace = messageHeaderNamespace;

            }

         }   

      }
}

}

 

 

Because the code that actually retrieves the “Namespace” out of the XSD file is stored in another assembly that isn’t part of the DSL assemblies, I had to add the assembly to the GAC to make it work.

 

To make sure the rule gets fired we need to add a variable to the “GeneratedMetaModelTypes” class. This class is reflected on to dynamically load rules. The variable is the reference to the new propagation rule described above. The following code snippet will do the trick.

 

Internal static partial class GeneratedMetaModelTypes
{
        
internal static Type DomainModelMessageHeaderPropertiesChangesRule =
                                    
typeof(DomainModelMessageHeaderPropertiesChangesRule);
}

 

As you can see in the image below (I know this image doesn’t prove a lot!) the “Namespace” property gets set after we populate the “SchemaLocation” property of the MessageHeader with a valid value.

To be continued...

posted on 11/20/2005 8:12:43 PM UTC  #