Retired: DMW Widgets Language Reference

NOTE: This project has been retired, and there will be no more updates. Other future projects may reuse some concepts presented here.

Introduction

The Data Model Widgets (DMW) is a model-based development environment allowing designing compact abstract units of logic accessing various databases.

The DMW Project provides tools to define a model and logic abstracting from the possible physical implementations. Therefore, it should be possible to generate physical implementation on multiple target software platforms. This document provides a description of how to achieve. This is still a provisional and volatile version and subject to change in the future.

The proposed solution incorporates the development of a language (or rather two interacting languages)  allowing to declare model part of the solution and express an access logic. The DMW Project uses Xtext Framework for the development of both languages using the Domain-Specific Languages (DSL) approach. The project also includes the development of all required instrumentation, like fully functioning editors and generators. We refer to such language as the DMW Language in the rest of the document.

The declarative part of the DMW Language dedicated to the modeling part allows to describe the data model and define a target implementation platform only at the present time.  The procedural part of the DMW Language allows describing how to access and consolidate data to fulfill a request from the user.  Both parts of the DMW Language follow the commonly accepted object-oriented approach used in many modern programming languages.

As mentioned earlier, the DMW Language uses Xtext framework and written in Java, and as such is using Eclipse Modeling Framework as the internal implementation of the meta-meta model.

Currently, the proposed DMW solution mostly supports the development of the server-side of processing.

The generation process is an essential part of the DMW development environment. You can envisage purpose-written generators targetting different programming languages, a different implementation of SQL and non-SQL databases, and target operating systems. Current efforts focus on Java and Swift programming languages, with the emphasis on Swift. Databases of choice are MySQL, SQLite, PostgreSQL, and MongoDB. Any future generator will use created ad-hoc syntax tree created automatically from the contents of a bunch of files created by the developers and containing fragments written using the DWM Language.

Current plans are that generated Swift source code will run on Linux and macOS machines wrapped using Kitura or Vapor server solutions.

Separation of concerns

Initial idea was to develop a one language serving all purposes. An approach was to try different approaches to how such language should look like. Each time language structure was too complex and not very flexible to absorb emerging changes. Developing many versions of the language structure and its possible implementation resulted had one positive effect. It helped to develop some ex[pertiose in using the Xtext Framework as a tool, but each tested concept was not very encouraging. Considered solutions were too complex and lacking flexibility.

Considering separation of two distinct phases in design became most apparent as a way out of convoluted solutions.

The current approach is to separate the modeling part from the logic part. It results in two separate languages serv9ng two different purposes. They are separate but yet interlaced. Here is how it works.

Defining Data Model

A developer uses a part of the DMW Language to define the data model. There are dedicated statements to define entities, attributes, and relationships. Those are the main objects constituting the ERD model. The DMW Language allows defining also many other aspects that are relevant during the design process.

Data Types

DMW language is statically typed and also a strongly typed language.  Each type of data is predefined as part of the language and all constants or variables defined for a given widget must be described as one of the data types. The below tables list currently available data types and how they translate to types in Swift, Java, and MySQL.

DMW Swift Java MySQL Derby
String String String CHAR, VARCHAR CHAR, VARCHAR
Int Int int INTEGER INTEGER
Short Int16 short SMALLINT SMALLINT
Long Int64 long BIGINT BIGINT
Double Double double DECIMAL DECIMAL
Date Date Date DATE DATE
Time Date Time TIME TIME
Timestamp Date Timestamp TIMESTAMP TIMESTAMP
Bool Bool boolean BOOLEAN BOOLEAN

NOTES:

  1. The above list of data types in DMW Language is subject to change and possibly more data types will be added in the future.
  2. Derby database has been added as a reference implementation. There are plans to use DDL to create the in-memory instance of the database and access it by default Java implementation code in unit tests.

Entity-Relationship Model

Data modeling is the first step when designing the widgets in the DMW Framework. It is essential to create a conceptual model of how data items relate to each other. It is the first step before developing logic using the object-oriented programming paradigm.  The DMW Developer does not operate on any possible physical future implementation of the data model like tables or documents. All physical data access and boilerplate code should be generated automatically by dedicated source code generators.

The DMW Framework is using an entity-relationship model and provides a mechanism to declare how the created entity-relationship model should be transformed into physical tables and documents.

Entity

GRAMMAR

entity-declaration –> @entity entity-type-name extension-clauseopt {inner-items }

extension-clause –> : entity-type-name

inner-items –> inner-item inner-itemsopt

        inner-item –> : attribute | relationship | identifier

@entity Log : SpecialObject{
   
}

Attribute

GRAMMAR

attribute –> @attr attribute-name  : data-type ?opt  annotations 

annotations –> : annotation annotationsopt  

        annotation –> length | decimal

length –> : @length ( number )

        decimal –> : @decimal( number , number )

@entity Log {
   @attr entryType : Short @decimal(2,0); 
   @attr message : String @length(128);
   @attr timeCreated : Time;
}

Relationships

GRAMMAR

relationship –> @rel relationship-name ?opt  -> target-entity-type *opt <- inverse-relationship

inverse-relatioship –> entity-type-name . relationship-name

@entity Server {
   @attr name : String @length(8);
   @id myid(name);
   @rel produces -> Log * <- Log.isFor;
}

@entity Log {
   @attr entryType : Short @decimal(2,0);
   @attr message : String @length(128);
   @attr timeCreated : Time;
   @id logid(timeCreated,isFor);
   @rel isFor -> Server <- Server.produces;
}

Identifier

GRAMMAR

identifier –> @id identifier-name (identifier-items)

identifier-items –> identifier-item  identifier-itemsopt

       identifier-item –> attribute-name | relationship-name

Technical Design

(TBD)

Classes and Members

Classes

The class declaration reuses a lot of typical object-oriented syntax but still is different in some aspects. Also, the DMW Language approach to the inheritance is conceptually the same as in other object-oriented languages. Declared class type can inherit from a single class. The DMW Language classes can extend other DMW Language classes. The language uses default Object if no supertype is specified.

GRAMMAR

class-declaration –> class class-type-name extension-clause opt annotation-reference opt {  }

extension-clause –> : class-type-name

annotation-reference –> -> annotation-name

Examples of the class declaration:

class ExitStates : GlobalExitStates {
}
class RecordShort : Structure -> Log {
}

Statements

Loop Statements

Loop statements allow a block of statements to be executed repeatedly, depending on the conditions specified in the loop.

GRAMMAR

loop-statement –> for-in-statement

loop-statement –> while-statement

loop-statement –> repeat-while-statement

For-In Statement

GRAMMAR

for-in-statement –> for item in collection block-of-statements

Example of an for-in statement:

sum : Int = 0;	
for imp in array {
   sum = sum + self.imp.counter;
}

While Statement

A while statement allows a block of statements to be executed repeatedly, as long as a condition remains true.

GRAMMAR

while-statement –> while  expression  block-of-statements

Example of a while statement:

index : Int = 0;	
while index < 10 {
// do something 
   index = index + 1;
}

Repeat-While Statement

A repeat-while statement allows a block of statements to be executed one or more times, as long as a condition remains true.

GRAMMAR

repeat-while-statement –> repeat block-of-statements while ( expression  )

Example of a repeat-while statement:

i : Int = 0;	
repeat {
   // do something 
   i = i + 1;
} while (i < 10)

Control Transfer Statements

Control transfer statements can change the order in which statements are executed by unconditionally transferring program control from one place to another.

GRAMMAR

control-transfer-statement –> break-statement

control-transfer-statement –> continue-statement

control-transfer-statement –> return-statement

Break Statement

A break statement ends execution of a loop, an if statement, or a switch statement.

GRAMMAR

break-statement –> break ;

Example of a break statement:

sum : Int = 0;	
for imp in array {
   sum = sum + self.imp.counter;
   if (sum > 100) {
    break;
   }
}

Continue Statement

A continue statement ends execution of the current iteration of a loop statement but does not stop the execution of the loop statement.

GRAMMAR

continue-statement –> continue ;

Example of a continue statement:

index : Int = 0;	
while index < 10 {
   // do something 
   index = index + 1;
   if (index > 100) {
     index = 5;
     continue;
   } 
   // do something else
}

Return Statement

A return statement occurs in the body of the function and causes program execution to return to the calling function.Program execution continues at the point immediately following the function call.

GRAMMAR

return-statement –> return expression opt;

Example of a return statement:

if (i > 100) {
   return "reached limit";
}

Branch Statements

Branch statements allow the program to execute certain parts of code depending on the value of one or more conditions.

GRAMMAR

branch-statement –> if-statement

branch-statement –> switch-statement

If Statement

An if statement is used to test the condition and executing a block of statements if the condition is true. There are two basic forms of an if statement. The first form executes only a block of statements if the condition is true. The second form of an if statement introduces optional else clause. An else clause is executed if the condition is false. The grammar of if statement allows creating an if-else-if ladder.

GRAMMAR

if-statement –> if expression block-of-statements else-clause opt

else-clause –> else block-of-statements | else if-statement

Example of an if-else-if ladder:

if (self.current.message == "Done") {
   self.current.entryType = 0;
} else if (self.current.message == "Abandoned") {
   self.current.entryType = 99;
}

Switch Statement

A switch statement allows a block of statements executed depending on the value of the expression.

GRAMMAR

switch-statement –> switch expression { switch-cases opt

switch-cases –> switch-case switch-cases opt

switch-case –> case-label block-of-statements | default-label block-of-statements

case-label –> case expression :

default-label –> default :

Example of a switch statement:

switch self.current.message {
case "Done" : {
   self.current.entryType = 0;
   }
case "Abandoned" : {
   self.current.entryType = 99;
   }  
default : {
   // insert some default action here
   }
}

Database Statements

Database statements allow to access and modify SQL databases without using the raw SQL statements and any particular target implementation of SQL database.  All database operations are written using five specialized statements handling entities and relationships on the logical data model level.

GRAMMAR

database-statement –> create-statement

database-statement –> delete-statement

database-statement –> update-statement

database-statement –> read-while-statement

database-statement –> read-each-while-statement

Create Statement

A create statement records information about entities.

GRAMMAR

create-statement –> db-create struct-ref-pair block-of-statements success block-of-statements              already exist  block-of-statements     

struct-ref-pair –> property-name -> entity-name

Example of a create statement:

db-create current -> Log {
   self.current.message = "Hello World";
   self.current.entryType = self.imp.entryType;
   self.current.timeCreated = self.imp.timeCreated;
} success {			
   return self.current;
} already exist {
   super.setExitState(self.exits.logAlreadyExists);
}

Delete Statement

A delete statement removes all information about entity from the store.

GRAMMAR

delete-statement –> db-delete struct-ref-pair ;

struct-ref-pair –> property-name -> entity-name

Example of a delete statement:

db-delete current -> Log;

Update Statement

An update statement modifies the information stored about an entity.

GRAMMAR

update-statement –> db-update struct-ref-pair block-of-statements success block-of-statements                

struct-ref-pair –> property-name -> entity-name

Example of a update statement:

db-update current -> Log {		
   self.current.message = "Goodbye World";
} success {
   return self.current;
}

Read Statement

A read statement retrieves  information about previously stored entities.

GRAMMAR

read-statement –> db-read struct-ref-pair-list join-expression where-expression

struct-ref-pair-list –> struct-ref-pair | (, struct-ref-pair-list)opt

success block-of-statements not found  block-of-statements            

struct-ref-pair –> property-name -> entity-name

join-expression –> join join-expression-list

join-expression-list –> join-definition | (, join-expression-list)opt

join-definition > property-name -> relationship-name -> property-name

where-expression –> where expression

Example of a read statement:

db-read currentPerson -> Person
   where self.currentPerson.number == self.impPerson.number
   success {
      super.moveView(self.currentPerson, self.expPerson); 
      super.setExitState(self.exits.processCompleted);
   } not found {
      super.setExitState(self.exits.personNF);
   }

Read Each Statement

A read each statement retrieves  information about previously stored entities.

GRAMMAR

read-each-statement –> db-readeach struct-ref-pair-list join-expression where-expression target { block-of-statements }  

struct-ref-pair-list –> struct-ref-pair | (, struct-ref-pair-list)opt   

struct-ref-pair –> property-name -> entity-name

join-expression –> join join-expression-list

join-expression-list –> join-definition | (, join-expression-list)opt

join-definition > property-name -> relationship-name -> property-name

where-expression –> where expression

target –> target property-name

Example of a read-each statement:

db-read-each currentPerson -> Person
   where self.currentPerson.number == self.impPerson.number
   target self.group {


   }

Association Statement

An associate statement modifies the information stored about two entities by making them associated.

GRAMMAR

associate-statement –> db-associate struct-ref-pair    with    struct-ref-pair 

struct-ref-pair –> property-name -> entity-name

Example of a association statement:

db-read currentOrderHeader -> OrderHeader where self.currentOrderHeader.number == self.importOrderHeader.number
success {
   db-create currentOrderDetail -> OrderDetail {
   super.moveStruct(self.importOrderDetail, self.currentOrderDetail);
   db-associate currentOrderDetail -> OrderDetail with currentOrderHeader -> OrderDetail.isPartOf -> currentOrderHeader;
}
success {
	}
already exist {
		}
} not found {
}

Disassociation Statement

A disassociate statement modifies the information stored about two entities by removing association.

GRAMMAR

disassociate-statement –> db-disassociate struct-ref-pair    from    struct-ref-pair 

struct-ref-pair –> property-name -> entity-name

Example of a disassociation statement:

db-disassiate