Filed under DSL Tools

Using DSL Integration Service (DIS) – Part 2

In the last post I’ve introduced the DSL Integration Service and it’s own usage scenarios. Now I will get into the code, illustrating the implementation of one specific scenario:

Suppose you already have a DSL which enables the specification of business entities. Now Suppose that you need to implement a DSL for the user interface specification. It would be nice to have the possibility to reference the entities defined using the entities DSL, when specifying the user interface with the second DSL.

To do so I’ve implemented a new Visual Studio 2005 tool window that displays all the business entities and corresponding attributes in all available models. Then selecting one user interface model I’m be able to create my user interface specification by doing drag & drop of the available business entities into the UI model.

These are the steps you need to follow to implement something similar:

First you need to mark the entities DSL as exportable. You do so by editing the Package.tt in DslPackage project:

[Microsoft.VisualStudio.Modeling.Integration.RegisterAsExportable(

typeof(<#= directiveName #>DomainModel),

typeof(<#= directiveName #>SerializationBehaviorMonikerResolver),

typeof(<#=domainModelRoot#>),

typeof(<#= directiveName #>SerializationBehavior))]

internal sealed partial class <#= dslName #>Package : <#= dslName #>PackageBase

{

}And for the target DSL that’s all. You need only to garantee that , in the DSL definition, you do not have any element with the attribute “Generates Double Derived” with a “True” value assigned because if you don’t the integration service will generate an error. This limitation as already been assumed in the DSL forum.

To implement a Visual Studio 2005 tool window you need to create a new Visual Studio Integration Package

In the VSIP you need to get the reference to the Integration Service. With the service reference you can get an instance of the business entities domain model browser. With the domain model browser you can get a reference to all exported instances of a given model element. Finally you expose the elements data by geting a reference to each exported instance:

IDslIntegrationService service = Business_Entities_Selector.GetGlobalService(typeof(IDslIntegrationService)) as IDslIntegrationService;

IDomainModelBrowser domainModelBrowser = service.GetDomainModelBrowser(“Company.Models.Entities”);

ReadOnlyCollection<ExportedInstance> exportedInstances = domainModelBrowser.FindAllInstances(domainModelBrowser.GetExportedClassByNamespace(“Company.Models.Entities\BusinessEntity”));

BusinessEntity resolvedElement = (BusinessEntity)service.ResolveExportedInstanceInDocument(“Company.Models.Entities”, “mell://” + exportedInstance.Namespace, true);

Still in the VSIP project you need to enable the Drag & Drop operation. You do so by calling the DoDragDrop method in the ItemDrag event from the TreeView control:

private void TreeView1_ItemDrag(object sender, ItemDragEventArgs e)

{

DoDragDrop(e.Item, DragDropEffects.Copy);

}

In the User Interface DSL you need to first enable the drag & drop operations in corresponding model:

protected override void OnAssociated(DiagramAssociationEventArgs e)

{

base.OnAssociated(e);

// Ensure we have a view

if (e.DiagramView == null || e.DiagramView.DiagramClientView == null)

return;

// Wireup the drag/drop support

Control ctrl = e.DiagramView.DiagramClientView;

ctrl.AllowDrop = true;

ctrl.DragOver += new DragEventHandler(OnDragOver);

ctrl.DragDrop += new DragEventHandler(OnDragDrop);

}

Then implement the OnDragOver event:

private void OnDragOver(object sender, DragEventArgs e)

{

e.Effect = DragDropEffects.Copy;

}

And finally the OnDragDrop event. The model element creation it’s done here:

private void OnDragDrop(object sender, DragEventArgs e)

{

if (e.Data.GetDataPresent(typeof(TreeNode)))

{

using (Transaction transaction = this.Store.TransactionManager.BeginTransaction())

{

ExampleElement exampleElement = (ExampleElement)this.Store.ElementFactory.CreateElement(ExampleElement.DomainClassId);

TreeNode entityNode = (TreeNode)e.Data.GetData(typeof(TreeNode));

exampleElement.Name = entityNode.Text;

foreach (TreeNode node in entityNode.Nodes)

{

Attribute attribute = (Attribute)this.Store.ElementFactory.CreateElement(Attribute.DomainClassId);

attribute.Name = node.Text;

exampleElement.attributes.Add(attribute);

}

ExampleModel exampleModel = GetModel(this.Store);

exampleModel.Elements.Add(exampleElement);

transaction.Commit();

}

}

}

You need to implement all this in a partial class of the UserInterfaceDiagram class

And that’s it. You now can start building you user interface specification by using the entities definitions made in another DSL.

Using DSL Integration Service (DIS) – Part 1

I finally managed to put this “thing” to work.

I’ve been struggling with this integration service, on my free time, since a couple of weeks ago. Definitely this is not a well documented feature nevertheless being only a Power Toy. There is only a readme document on the installation folder and less more.

Thanks to Edward Bakker who show me the light on the Visual Studio Team System – Domain-Specific Language Tools Forum.

I’m starting here a series of posts related to DSL integration. For now I let you with a brief introduction to this subject and in the next posts I’ll start with the bits and bytes.

DSLs are generally relatively small, highly focused languages used to model and solve certain clearly identifiable problems that various developer roles may have to tackle as part of the software development lifecycle.

Nevertheless, in many cases, architects and developers need to be able to navigate through various viewpoints, i.e. through different areas concerns and across various abstraction levels.

Navigation across viewpoints and transformation of related artifacts imposes new requirements on DSL design, especially in terms of integration among them. Perhaps the most important is the ability to refer to model elements of one language from a different one.

For example, let’s assume the development a Service Oriented Architecture (SOA) based application using two different DSL, namely Business Message Type DSL and Business Entities DSL. While using the Business Message Types DSL, the message designer may need to refer to instances of business entities, specified using the Business Entities DSL, in order to define what is the payload for any given message type.

The current release of DSL Tools does not support any integration across different DSLs. More specifically, it’s not natively possible to refer from the model elements or properties in a language to those modeled and instantiated in another one.

However, that level of integration can be programmatically obtained.

The Visual Studio DSL Integration Service (DIS) is a service added to Visual Studio by the Microsoft.VisualStudio.Modeling.Integration package, whose goal and main feature is to support referencing of model elements across different DSLs.

That’s all for today don’t miss the next series of posts. 

Implementing a VS2005 Macro for automating transformation and exporting of outputs from DSL templates

For those who are working with Domain Specific Languages Designers, there is on recurring two step task that should be automated: Tranforming and exporting the various templates ouputs to the proper locations in our working project.

To do so we can implement a simple macro that does the job for us.

Basically we need to create a method that call one command that transform all the templates in the current project:

DTE.ExecuteCommand(“TextTransformation.TransformAllTemplates”)

and then call a set of commands to copy the templates ouput to the desired directory. Here is a sample of what I said:

DTE.ExecuteCommand(“Tools.Shell”, “cmd /c copy /Y “”" + GetOriginPath() + “BusinessEntities.cs” + “”"  “”" + BusinessEntitiesDestinationFile + “”"”)

where GetOriginPath()  is defined as:

Private Function GetOriginPath() As String
      Dim lastIndex As Integer = InStrRev(DTE.Solution.FullName, “\”)
      Return Left(DTE.Solution.FullName, lastIndex) & “GeneratedCode\”
End Function

To learn how to assign a macro to a toolbar button check out this site.

To learn how to Edit and Programmatically Create Macros check out this site.

Reseting Visual Studio 2005 Experimental Hive

Upon installation of the Visual Studio SDK, a clone of the existing Visual Studio registry is created for use as the default experimental hive.

When developing applications and/or integrations for Visual Studio 2005 with the Visual Studio 2005 SDK, for example using the DSL Tools, the testing and debugging is done using a Visual Studio Instance that are running with a special registry hive, instead of the normal so you don’t mess up your normal Visual Studio operations.

So when you latelly add new add-ons to VS 2005 like the ones for Team Foundation Server they are not automatically registered under the experimental hive. To make sure that experimental hive uses all the recent settings of VS 2005 we need to do a reset to this special instance.

Reseting the experimental hive is done from the VS 2005 SDK.

Here is the command line:”C:\Program Files\Visual Studio 2005 SDK\2007.02\VisualStudioIntegration\Tools\Bin\VsRegEx.exe” GetOrig 8.0 Exp

Follow

Get every new post delivered to your Inbox.