{"id":17,"date":"2023-07-08T17:47:53","date_gmt":"2023-07-08T15:47:53","guid":{"rendered":"http:\/\/www.janradeck.de\/wp_dsl\/?p=17"},"modified":"2023-07-25T12:56:05","modified_gmt":"2023-07-25T10:56:05","slug":"remoteadaptergenerator","status":"publish","type":"post","link":"https:\/\/www.janradeck.de\/wp_dsl\/de\/2023\/07\/08\/remoteadaptergenerator\/","title":{"rendered":"RemoteAdapterGenerator"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">This is a simple project that I did in JetBrains MPS. Since I very much like working with MPS, I&#8217;ve written this blog post to document it. I hope that it may find it useful if you&#8217;re starting with MPS.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I have tried to include as many illustrations as possible.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Motivation<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">While developing 2D algorithms, I found the debugging to be a real pain. It&#8217;s easier to see a curve on a display than to make sense from a (lengthy) set of coordinates.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Requirements<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Functional requirements<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A set of methods, constructed from the primitive commands that the display offers, eg. &#8220;drawPath&#8221;, &#8220;clearDisplay&#8221;.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Quality requirements<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">To be able to draw curves while in the debugger. The display needs to be updated even if the application under test is stopped.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Communication only needs to be one way: From the application under test to the display.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The number of calls to the draw method will be small. Therefore performance is not an issue.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Solution<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Create a stand-alone process with a JSVG canvas. This will guarantee that the display will be updated even if the application under test is stopped.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Use HTTP to connect the application under test to the display. This is simple to write and simple to test (e.g. via a web browser). The connection can be established &#8220;on demand&#8221;.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Solution design<\/h2>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/DrawInterface-01-Design.png\" alt=\"\" class=\"wp-image-20\" width=\"753\" height=\"756\" srcset=\"https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/DrawInterface-01-Design.png 1004w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/DrawInterface-01-Design-300x300.png 300w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/DrawInterface-01-Design-150x150.png 150w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/DrawInterface-01-Design-768x771.png 768w\" sizes=\"auto, (max-width: 753px) 100vw, 753px\" \/><figcaption class=\"wp-element-caption\">Client and server and their components<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The client issues remote commands, sends them via HTTP to the server, where they are translated into draw commands. The remote commands and the corresponding command handlers would be defined using a DSL.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you open the following URL in your browser<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">http:\/\/localhost:8000\/draw?message%3DHello%20World%21%26path%3DM%20100%2C100%20L%20100%2C200%20200%2C200%20200%2C%20100%20z%26style%3Dfill%3Anone%3Bstroke%3A%23000000<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">the server will display this image:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"338\" height=\"400\" src=\"http:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/RemoteAdapter-ServerApplication.png\" alt=\"\" class=\"wp-image-90\" srcset=\"https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/RemoteAdapter-ServerApplication.png 338w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/RemoteAdapter-ServerApplication-254x300.png 254w\" sizes=\"auto, (max-width: 338px) 100vw, 338px\" \/><figcaption class=\"wp-element-caption\">The server displaying an SVG path<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">To generate the query, I&#8217;ve used a simple online tool to URL-encode the parameters.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The development process in detail<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Step 1: Hand-writing a prototype solution<\/h3>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/DrawInterface-02-Process-01.png\" alt=\"\" class=\"wp-image-38\" width=\"540\" height=\"636\" srcset=\"https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/DrawInterface-02-Process-01.png 720w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/DrawInterface-02-Process-01-255x300.png 255w\" sizes=\"auto, (max-width: 540px) 100vw, 540px\" \/><figcaption class=\"wp-element-caption\">Hand-writing a prototype solution<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">A prototype client and server were written by hand, using an IDE.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 2: Creating the concepts in MPS<\/h3>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/DrawInterface-02-Process-02.png\" alt=\"\" class=\"wp-image-39\" width=\"689\" height=\"608\"\/><figcaption class=\"wp-element-caption\">Creating the concepts in MPS<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Step 3: Transferring the JAR files to MPS<\/h3>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"720\" height=\"848\" src=\"http:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/DrawInterface-02-Process-03.png\" alt=\"\" class=\"wp-image-40\" srcset=\"https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/DrawInterface-02-Process-03.png 720w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/DrawInterface-02-Process-03-255x300.png 255w\" sizes=\"auto, (max-width: 720px) 100vw, 720px\" \/><figcaption class=\"wp-element-caption\">Transferring the JAR files to MPS<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The code generated by MPS would refer to classes and methods from the hand-written solution. Therefore JAR files, containing this part of the prototype application need to be imported into MPS.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 4: Creating templates in MPS<\/h3>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/DrawInterface-02-Process-04.png\" alt=\"\" class=\"wp-image-24\" width=\"683\" height=\"610\"\/><figcaption class=\"wp-element-caption\">Creating templates in MPS<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Now that the classes and methods are available in MPS, the templates are created. The hand-written code is used as a basis for this step.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 5: Creating the model<\/h3>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/DrawInterface-02-Process-05.png\" alt=\"\" class=\"wp-image-28\" width=\"689\" height=\"614\"\/><figcaption class=\"wp-element-caption\">Creating the model<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"439\" height=\"525\" src=\"http:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/RemoteAdapter-Model-01-CommandVersionPool.png\" alt=\"\" class=\"wp-image-75\" srcset=\"https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/RemoteAdapter-Model-01-CommandVersionPool.png 439w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/RemoteAdapter-Model-01-CommandVersionPool-251x300.png 251w\" sizes=\"auto, (max-width: 439px) 100vw, 439px\" \/><figcaption class=\"wp-element-caption\">The first lines of the model: Defining (global) constants and a first command<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"307\" height=\"243\" src=\"http:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/RemoteAdapter-Model-02-ClientCommand-01.png\" alt=\"\" class=\"wp-image-76\" srcset=\"https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/RemoteAdapter-Model-02-ClientCommand-01.png 307w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/RemoteAdapter-Model-02-ClientCommand-01-300x237.png 300w\" sizes=\"auto, (max-width: 307px) 100vw, 307px\" \/><figcaption class=\"wp-element-caption\">Defining a command that references a global constant<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In the definition of this command a global constant, styleBlue, is referenced.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"424\" height=\"241\" src=\"http:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/RemoteAdapter-Model-03-ClientCommand-02.png\" alt=\"\" class=\"wp-image-74\" srcset=\"https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/RemoteAdapter-Model-03-ClientCommand-02.png 424w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/RemoteAdapter-Model-03-ClientCommand-02-300x171.png 300w\" sizes=\"auto, (max-width: 424px) 100vw, 424px\" \/><figcaption class=\"wp-element-caption\">Defining a command with a local constant.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">In the definition of this command a local constant, styleGreen, is defined and referenced.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 6: Generating the source code<\/h3>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/DrawInterface-02-Process-06.png\" alt=\"\" class=\"wp-image-29\" width=\"693\" height=\"616\"\/><figcaption class=\"wp-element-caption\">Generating the source code from the model<\/figcaption><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">Client Business Logic (generated)<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The following code is generated for the three client commands shown above. The code uses an abstraction layer QueryGenerator to specify the URI, add parameters and execute the query.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"535\" height=\"420\" src=\"http:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/RemoteAdapter-GeneratedCode-Client.png\" alt=\"\" class=\"wp-image-77\" srcset=\"https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/RemoteAdapter-GeneratedCode-Client.png 535w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/RemoteAdapter-GeneratedCode-Client-300x236.png 300w\" sizes=\"auto, (max-width: 535px) 100vw, 535px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Server Business Logic (generated)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The first block defines the global constants and registers the Request Handler classes.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"699\" height=\"463\" src=\"http:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/RemoteAdapter-GeneratedCode-Server-01.png\" alt=\"\" class=\"wp-image-78\" srcset=\"https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/RemoteAdapter-GeneratedCode-Server-01.png 699w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/RemoteAdapter-GeneratedCode-Server-01-300x199.png 300w\" sizes=\"auto, (max-width: 699px) 100vw, 699px\" \/><figcaption class=\"wp-element-caption\">Server code: Defining global constants and adding the RequestHandler classes<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"736\" height=\"93\" src=\"http:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/RemoteAdapter-GeneratedCode-Server-02.png\" alt=\"\" class=\"wp-image-81\" srcset=\"https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/RemoteAdapter-GeneratedCode-Server-02.png 736w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/RemoteAdapter-GeneratedCode-Server-02-300x38.png 300w\" sizes=\"auto, (max-width: 736px) 100vw, 736px\" \/><figcaption class=\"wp-element-caption\">Server code: A RequestHandler that references a global constant.<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"732\" height=\"106\" src=\"http:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/RemoteAdapter-GeneratedCode-Server-03.png\" alt=\"\" class=\"wp-image-82\" srcset=\"https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/RemoteAdapter-GeneratedCode-Server-03.png 732w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/RemoteAdapter-GeneratedCode-Server-03-300x43.png 300w\" sizes=\"auto, (max-width: 732px) 100vw, 732px\" \/><figcaption class=\"wp-element-caption\">Server code: RequestHandlers that defines a local constant.<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Implementation details<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Structure aspect<\/h3>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"508\" height=\"493\" src=\"http:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/ClassDiagram.png\" alt=\"\" class=\"wp-image-44\" srcset=\"https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/ClassDiagram.png 508w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/ClassDiagram-300x291.png 300w\" sizes=\"auto, (max-width: 508px) 100vw, 508px\" \/><figcaption class=\"wp-element-caption\">Simplified class hierarchy<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"393\" height=\"293\" src=\"http:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/ClassDiagram-StringEtAl-PlantUML.png\" alt=\"\" class=\"wp-image-45\" srcset=\"https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/ClassDiagram-StringEtAl-PlantUML.png 393w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/ClassDiagram-StringEtAl-PlantUML-300x224.png 300w\" sizes=\"auto, (max-width: 393px) 100vw, 393px\" \/><figcaption class=\"wp-element-caption\">Class diagram for StringValue, etc.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">I have introduced the Interface <em>StringValueTraits<\/em>. The scope of StringParameters makes them unique, if they are unique for the ClientMethod. StringConstants, on the other hand, can clash between different instances of CommandListVersion. Therefore the version of the CommandListVersion is appended to the declarationName.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">References and reference constraints<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">I want to define (client) methods with (string) parameters. In these method definitions I want to call draw methods and provide these method calls with values. A value may be<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>a parameter of the method that I am declaring<\/li>\n\n\n\n<li>a constant, that I defined within the method declaration, or<\/li>\n\n\n\n<li>a global constant.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Here I found the <em>calculator example<\/em> from the <em>MPS Advanced Online Course<\/em> rather helpful.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The following diagram shows the possible reference targets from a StringValueReference within a ServerCommand.<\/p>\n\n\n\n<figure class=\"wp-block-image size-medium\"><img loading=\"lazy\" decoding=\"async\" width=\"300\" height=\"295\" src=\"http:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/DrawInterface-03-References-300x295.png\" alt=\"\" class=\"wp-image-26\" srcset=\"https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/DrawInterface-03-References-300x295.png 300w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/DrawInterface-03-References-1024x1006.png 1024w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/DrawInterface-03-References-768x755.png 768w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/DrawInterface-03-References.png 1026w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">In the first attempt, I implemented the scope handler in StringValueReference.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"906\" height=\"325\" src=\"http:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/StringValueReference-ReferenceConstraint-ScopeHandler.png\" alt=\"\" class=\"wp-image-53\" srcset=\"https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/StringValueReference-ReferenceConstraint-ScopeHandler.png 906w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/StringValueReference-ReferenceConstraint-ScopeHandler-300x108.png 300w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/StringValueReference-ReferenceConstraint-ScopeHandler-768x275.png 768w\" sizes=\"auto, (max-width: 906px) 100vw, 906px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">This handler looks for its ancestor of type ClientCommand and collects all StringConstant instances from commandConstants and all StringParameter instances from commandParameters. It then looks for its ancestor of type CommandListVersion and collects all StringConstant instances.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"768\" src=\"http:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/RemoteAdapter-ScopeProviderHandler-1-1024x768.png\" alt=\"\" class=\"wp-image-85\" srcset=\"https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/RemoteAdapter-ScopeProviderHandler-1-1024x768.png 1024w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/RemoteAdapter-ScopeProviderHandler-1-300x225.png 300w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/RemoteAdapter-ScopeProviderHandler-1-768x576.png 768w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/RemoteAdapter-ScopeProviderHandler-1.png 1344w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Collecting all references in the ScopeProvider of ServerCommand<\/figcaption><\/figure>\n\n\n\n\n\n<p class=\"wp-block-paragraph\">In the next attempt, I went for inherited scope and implemented getScope() in <em>ClientCommand<\/em> and in <em>CommandListVersion<\/em>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"725\" height=\"241\" src=\"http:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/ClientCommand-Behaviour-ScopeProvider.png\" alt=\"\" class=\"wp-image-47\" srcset=\"https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/ClientCommand-Behaviour-ScopeProvider.png 725w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/ClientCommand-Behaviour-ScopeProvider-300x100.png 300w\" sizes=\"auto, (max-width: 725px) 100vw, 725px\" \/><figcaption class=\"wp-element-caption\">ScopeProvider for <em>ClientCommand<\/em><\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"862\" height=\"191\" src=\"http:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/CommandListVersion-Behaviour-ScopeProvider.png\" alt=\"\" class=\"wp-image-51\" srcset=\"https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/CommandListVersion-Behaviour-ScopeProvider.png 862w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/CommandListVersion-Behaviour-ScopeProvider-300x66.png 300w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/CommandListVersion-Behaviour-ScopeProvider-768x170.png 768w\" sizes=\"auto, (max-width: 862px) 100vw, 862px\" \/><figcaption class=\"wp-element-caption\">ScopeProvider for <em>CommandListVersion<\/em><\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The chain of ScopeProviders looks like this:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"768\" src=\"http:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/RemoteAdapter-ScopeProviderInherited-1-1024x768.png\" alt=\"\" class=\"wp-image-86\" srcset=\"https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/RemoteAdapter-ScopeProviderInherited-1-1024x768.png 1024w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/RemoteAdapter-ScopeProviderInherited-1-300x225.png 300w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/RemoteAdapter-ScopeProviderInherited-1-768x576.png 768w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/RemoteAdapter-ScopeProviderInherited-1.png 1344w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Using InheritedScope and ScopeProviders for ClientCommand and CommandListVersion<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Editor aspect<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">As the language is very straightforward, so I will not show the editors here.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Checking Rules<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">I use Checking Rules to validate the model on the fly:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Does the name follow the rules for a valid identifier?<\/li>\n\n\n\n<li>Are the names unique?<\/li>\n\n\n\n<li>Are version numbers unique?<\/li>\n\n\n\n<li>Are all parameters and constants referenced?<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/ClientCommand-CheckingRule-All-Parameters-referenced.png\" alt=\"\" class=\"wp-image-57\" width=\"820\" height=\"119\" srcset=\"https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/ClientCommand-CheckingRule-All-Parameters-referenced.png 867w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/ClientCommand-CheckingRule-All-Parameters-referenced-300x44.png 300w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/ClientCommand-CheckingRule-All-Parameters-referenced-768x112.png 768w\" sizes=\"auto, (max-width: 820px) 100vw, 820px\" \/><figcaption class=\"wp-element-caption\">Are all parameters of the ClientCommand <em>clientCommand<\/em> referenced?<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Generator aspect<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The generator consists of nested loops. A SWITCH macro is used to generate the code for the difference ServerCommands.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"915\" height=\"370\" src=\"http:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/Generator-Server-RequestHandlerClass.png\" alt=\"\" class=\"wp-image-58\" srcset=\"https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/Generator-Server-RequestHandlerClass.png 915w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/Generator-Server-RequestHandlerClass-300x121.png 300w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/Generator-Server-RequestHandlerClass-768x311.png 768w\" sizes=\"auto, (max-width: 915px) 100vw, 915px\" \/><figcaption class=\"wp-element-caption\">Generator template for the server side code (excerpt).<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"938\" height=\"420\" src=\"http:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/Generator-Server-TemplateSwitch-SvgCommand.png\" alt=\"\" class=\"wp-image-60\" srcset=\"https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/Generator-Server-TemplateSwitch-SvgCommand.png 938w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/Generator-Server-TemplateSwitch-SvgCommand-300x134.png 300w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/Generator-Server-TemplateSwitch-SvgCommand-768x344.png 768w\" sizes=\"auto, (max-width: 938px) 100vw, 938px\" \/><figcaption class=\"wp-element-caption\">The template switch for the different commands.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Within the property \/ reference macros behavior methods are used, to keep the templates free from application logic.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"415\" height=\"143\" src=\"http:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/PropertyValueUsedBehaviour.png\" alt=\"\" class=\"wp-image-62\" srcset=\"https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/PropertyValueUsedBehaviour.png 415w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/PropertyValueUsedBehaviour-300x103.png 300w\" sizes=\"auto, (max-width: 415px) 100vw, 415px\" \/><figcaption class=\"wp-element-caption\">Using a behavior method within a property macro.<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"852\" height=\"359\" src=\"http:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/ClientCommand-Behaviour-VersionIdentifier.png\" alt=\"\" class=\"wp-image-64\" srcset=\"https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/ClientCommand-Behaviour-VersionIdentifier.png 852w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/ClientCommand-Behaviour-VersionIdentifier-300x126.png 300w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/ClientCommand-Behaviour-VersionIdentifier-768x324.png 768w\" sizes=\"auto, (max-width: 852px) 100vw, 852px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The method commandHandlerClassname() will only generate a version identifier if there are more than one CommandListVersion. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Lessons Learned<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Isolate the generator from the implementation<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The client and server application are based on the HTTP protocol.<\/li>\n\n\n\n<li>To get the Proof of Concept up and running as fast as possible, I imported the full JDK into MPS, since the generated code relied on java.net classes. But: Importing the JDK \u201cpollutes\u201d the model.<\/li>\n\n\n\n<li>For version 2 I created an abstraction layer that consists mostly of interfaces and that contains no dependencies on the JDK. By using the <em>factory <\/em>pattern, dependencies on the handwritten code for client and server were eliminated.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"571\" src=\"http:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/DrawInterface-04-Interfaces-1024x571.png\" alt=\"\" class=\"wp-image-27\" srcset=\"https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/DrawInterface-04-Interfaces-1024x571.png 1024w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/DrawInterface-04-Interfaces-300x167.png 300w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/DrawInterface-04-Interfaces-768x429.png 768w, https:\/\/www.janradeck.de\/wp_dsl\/wp-content\/uploads\/2023\/07\/DrawInterface-04-Interfaces.png 1344w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Downloads<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The projects are available on GitHub, if you would like to take a deep dive.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The MPS project <a href=\"https:\/\/github.com\/janradeck\/RemoteAdapterGenerator\">RemoteAdapterGenerator<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The Maven project <a href=\"https:\/\/github.com\/janradeck\/remotecanvas\">remote canvas<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The Maven project contains three parts:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><em>svghttpd<\/em>: A swing application with an SVG canvas and an attached HTTP server<\/li>\n\n\n\n<li><em>svgclient<\/em>: A client library to issue drawing commands to the swing application via HTTP<\/li>\n\n\n\n<li><em>svgdemo<\/em>: A demo application that shows how to use the client library<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">To build and run the swing application:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>mvn clean compile assembly:single<\/li>\n\n\n\n<li>java -jar target\\svghttpd-1.0-jar-with-dependencies.jar<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">This project also creates the two interface JAR files that are used in RemoteAdapterGenerator:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>svgclient-1.0-interface.jar<\/li>\n\n\n\n<li>svghttpd-1.0-interface.jar<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">References<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Here are resources that I found helpful:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Gabriele Tomassetti: <a href=\"https:\/\/tomassetti.me\/how-to-add-jars-and-resources-in-a-jetbrains-mps-project\/\">How to Add JARs to a Jetbrains MPS Project &#8211; Strumenta (tomassetti.me)<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is a simple project that I did in JetBrains MPS. Since I very much like working with MPS, I&#8217;ve written this blog post to document it. I hope that it may find it useful if you&#8217;re starting with MPS. I have tried to include as many illustrations as possible. Motivation While developing 2D algorithms, &#8230; <a title=\"RemoteAdapterGenerator\" class=\"read-more\" href=\"https:\/\/www.janradeck.de\/wp_dsl\/de\/2023\/07\/08\/remoteadaptergenerator\/\" aria-label=\"Read more about RemoteAdapterGenerator\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-17","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"translation":{"provider":"WPGlobus","version":"2.12.2","language":"de","enabled_languages":["en","de"],"languages":{"en":{"title":true,"content":true,"excerpt":false},"de":{"title":false,"content":false,"excerpt":false}}},"_links":{"self":[{"href":"https:\/\/www.janradeck.de\/wp_dsl\/de\/wp-json\/wp\/v2\/posts\/17","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.janradeck.de\/wp_dsl\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.janradeck.de\/wp_dsl\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.janradeck.de\/wp_dsl\/de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.janradeck.de\/wp_dsl\/de\/wp-json\/wp\/v2\/comments?post=17"}],"version-history":[{"count":26,"href":"https:\/\/www.janradeck.de\/wp_dsl\/de\/wp-json\/wp\/v2\/posts\/17\/revisions"}],"predecessor-version":[{"id":104,"href":"https:\/\/www.janradeck.de\/wp_dsl\/de\/wp-json\/wp\/v2\/posts\/17\/revisions\/104"}],"wp:attachment":[{"href":"https:\/\/www.janradeck.de\/wp_dsl\/de\/wp-json\/wp\/v2\/media?parent=17"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.janradeck.de\/wp_dsl\/de\/wp-json\/wp\/v2\/categories?post=17"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.janradeck.de\/wp_dsl\/de\/wp-json\/wp\/v2\/tags?post=17"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}