650 likes | 839 Views
Language Workbench Competition 2011 The OOMEGA language workbench. Christian Merenda 2011/05/24. Agenda. Introducing the OOMEGA language workbench Exploration of the Language Workbench Competition 2011 The Preamble Phase 0 – Basics Phase 1 – Advanced Phase 2 – Non- Functional
E N D
Language WorkbenchCompetition 2011The OOMEGA languageworkbench Christian Merenda2011/05/24 The OOMEGA language workbench - www.oomega.net
Agenda • Introducingthe OOMEGA languageworkbench • Exploration ofthe Language WorkbenchCompetition 2011 • The Preamble • Phase 0 – Basics • Phase 1 – Advanced • Phase 2 – Non-Functional • Phase 3 - Freestyle The OOMEGA language workbench - www.oomega.net
Introducingthe OOMEGA languageworkbench The OOMEGA language workbench - www.oomega.net
OOMEGA isbased on theEclipse IDE OOMEGA isbased on theEclipse IDE ATL supportfor model-to-model transformations Xpandsupportfor model-to-text transformations The OOMEGA language workbench - www.oomega.net
CorrelationoftheEdgeAlgebra, M2L, OOMEGA and metaMODELS.org Platform for collaborative metamodel engineering powered by Open source implementation with commercial database backends implements Formal and high expressive metamodelling language M2L based on Theoretical foundation for graph-based queries EdgeAlgebra The OOMEGA language workbench - www.oomega.net
Clear separation of abstract and concrete syntaxes M E T A M O D E L - M2L – Abstract Syntax structureofthemodel Concrete Syntax Concrete Syntax bridge the gap between this structure and concrete textual representations The OOMEGA language workbench - www.oomega.net
Text editors with folding, linking and syntax highlighting The OOMEGA language workbench - www.oomega.net
Incrementalparsingandprojectionofmodels Model Text p1.Personp= { name=„Merenda“ firstname= „Christian“ } Changestothemodelareprojectedtothetext. Incremental update ofthemodelifthetextischanged. OOMEGA has implemented its own scannerless parser; we do not rely on ANTLR or some other parser generator. The OOMEGA language workbench - www.oomega.net
Varioustechniquesfordefiningconstraints • Primary local keysmust be unique within the set of all sister nodes in the composition tree. • Context sensitive domainsfurther constrain the domain of a property with respective Edge Algebra statements – beyond the traditional type safety. • Weak entity and attribute conceptsmust be referenced by exactly one composite object. • Multiplicitiesdefine lower and upper limits for the number of referenced objects in the context of a property. • Abstract conceptscan’t be instantiated – i.e. corresponding objects must not exist in the database. • Additional constraintsmust hold for every instance of the respective concept. Again – the Edge Algebra is used to define those constraints. The OOMEGA language workbench - www.oomega.net
Agenda • Introducingthe OOMEGA languageworkbench • Exploration ofthe Language WorkbenchCompetition 2011 • The Preamble • Phase 0 – Basics • Phase 1 – Advanced • Phase 2 – Non-Functional • Phase 3 - Freestyle The OOMEGA language workbench - www.oomega.net
The Preamble The OOMEGA language workbench - www.oomega.net
We‘vedesignedfiveinterelated DSLs toshowcaselanguagemodularityandcomposition Domain Instance EntityRelationship Expression Primitive The OOMEGA language workbench - www.oomega.net
No 3GL code / ~350 linesofcode • The final solution does not contain a single line of 3GL code for designing the language, implementing constraints or setting up text editors • You need to code ~350 lines of code with OOMEGA’s meta-modelling language M2L in order to realize the whole functionality of the LWC2011 case • You do only specify abstract and concrete syntaxes of your DSLs. That‘s it. The OOMEGA language workbench - www.oomega.net
Phase 0 - Basics The OOMEGA language workbench - www.oomega.net
Task 0.1 - Simple (structural) DSL without any fancy expression language or such • Challenge:Build a simple data definition language to define entities with properties. Properties have a name and a type. It should be possible to use primitive types for properties, as well as other Entities. entity Person { string name string firstname date bithdate Car ownedCar } entity Car { string make string model } The OOMEGA language workbench - www.oomega.net
The languagemodule „Primitive“ The OOMEGA language workbench - www.oomega.net
The languagemodule „Primitive“ • [Primitive!!] refinesAttributeObject ::> ; • P_String!! refinesPrimitive::=&javaMapping[0..1](Singleton) : C:String := {{ String}},&xmlMapping[0..1](Singleton) : C:String := {{ String }} ; • P_Date!! refinesPrimitive ::=&javaMapping[0..1](Singleton) : C:String := {{ "java.util.Date" }},&xmlMapping[0..1](Singleton) : C:String := {{ Date }} ; The OOMEGA language workbench - www.oomega.net
The languagemodule „Primitive“ • textualconcretesyntaxLWC { <default> P_String: "string";<default> P_Date : "date" ;} • textualconcretesyntaxSQL {P_String: "CHAR" ;P_Date : "DATE" ;} The OOMEGA language workbench - www.oomega.net
The languagemodule „Domain“ • DomainModel! refinesFolderEntry::=packages[0..*](Set) <-> belongsTo : C:Package,&entities[0..*](Set) : C:Entity := (P:packages.P:entities) ; • Entity! refinesNamed::>&belongsTo[0..1](Singleton) <-> entities : C:Package,&usedBy[0..*](Set) <-> type : C:Association,properties[0..*](Set) <-> belongsTo : C:Prop,&attributes[0..*](Set) : C:Attribute := (P:propertiesprojectOn C:org.metamodels.lwc2011.domain.Attribute),&associations[0..*](Set) : C:Association := (P:propertiesprojectOn C:org.metamodels.lwc2011.domain.Association),&context[0..1](Singleton) : C:EntityObject := self ; The OOMEGA language workbench - www.oomega.net
The languagemodule „Domain“ • [Prop!] refinesNamed::>&belongsTo[0..1](Singleton) <-> properties : C:Entity; • Attribute! refinesProp::>type[1..1](Singleton) : C:Primitive; • Association! refinesProp::>&type[1..1](Singleton) <-> usedBy : C:EntityprojectOn ((P:belongsTo.P:belongsTo.P:entities) union (P:belongsTo.P:belongsTo.P:importedPackages.P:entities)),&includedContext[0..*](Set) : C:EntityObject := (P:belongsTo.P:belongsTo.P:importedPackages) ; The OOMEGA language workbench - www.oomega.net
The languagemodule „Domain“ • textualconcretesyntaxDIRECTORY{ <helper> DomainModel: "domain" _ "model" _ <Named> ;} • textualconcretesyntaxLWC{ <default> DomainModel: "domain" _ "model" _ <Named> _ "{" (nl | P:packages) nl"}";<default> Entity : "entity" _ <Named> _ "{" (nl | P:properties) nl"}" ;<default> Attribute: (!P:type) _ <Named> ;<default> Association: "ref" _ (&P:type) _ <Named> ;} The OOMEGA language workbench - www.oomega.net
Task 0.2 - Code generation to GPL such as Java, C#, C++ or XML • Challenge:Generate Java Beans (or some equivalent data structure in C#, Scala, etc.) with setters, getters and fields for the properties. • Solution: Code canbegeneratedwithOOMEGA‘sgeneratororEclipseXpand. WedemonstratedtheusageofXpand. Basicallythiscanbedone in three simple steps: • Code a Xpandtemplate • Create a workflow • Execute theworkflowwithin an Antscript Due to time restrictions the code generation task is not explained here. Please have a look at our online documentation of the LWC2011 case. The OOMEGA language workbench - www.oomega.net
Task 0.3 - Simple constraint checks such as name-uniqueness • Challenge:For example, check the name uniqueness of the properties in the entities. • Solution: The name uniqueness of the properties in the entities is already built in. • [Prop!] refinesNamed ::>&belongsTo[0..1](Singleton) <-> properties : C:Entity; • [Named] refinesEntityObject::>(PK)name[1..1](Singleton) : C:String,(K)alternativeName[0..*](Set) : C:String • Primary local keys must be unique within the set of all sister nodes in the composition tree. This means in our example: an Entity mustn’t contain multiple properties with identical names. The OOMEGA language workbench - www.oomega.net
Task 0.4 - Show how to break down a (large) model into several parts, while still cross-referencing between the parts • Challenge:For example, put the Car and Person entities into different files, while still having the Person -> Car reference work. ViewAspect PersistenceAspect A large model shouldn’t be stored in a single text file. If you’ve got a large model you want to be able to view only parts of it. Models are – by default – partitioned into little pieces: you can always decide which object to view or edit. The persistence aspect is solved by appropriate storage back-ends, e.g. an object-oriented database. The OOMEGA language workbench - www.oomega.net
Phase 1 - Advanced The OOMEGA language workbench - www.oomega.net
Task 1.1 - Show the integration of several languages • Challenge:Define a second language to define instances of the entities, including assignment of values to the properties. This should ideally really be a second language that integrates with the first one, not just "more syntax" in the same grammar. We want to showcase language modularity and composition here. Person p = { name = "Voelter" firstname = "Markus" birthdate = 14.02.1927 ownedCar = c } Car c = { make = "VW" model = "Touran" } The OOMEGA language workbench - www.oomega.net
The languagemodule „Instance“ • InstanceModel! refinesFolderEntry::=&basedOn[0..1](Singleton) : C:DomainModel,instances[0..*](Set) <-> belongsTo : C:Instance; • Instance! refinesNamed::>&belongsTo[0..1](Singleton) <-> instances : C:InstanceModel,&entity[0..1](Singleton) : C:EntityprojectOn (P:belongsTo.P:basedOn.P:entities),propertyValues[0..*](Set) <-> belongsTo : C:PropertyValue,&includedContext[0..*](Set) : C:EntityObject := (P:belongsTo.P:basedOn) ; The OOMEGA language workbench - www.oomega.net
The languagemodule „Instance“ • PropertyValue! refinesEntityObject::>&belongsTo[0..1](Singleton) <-> propertyValues : C:Instance,(PK)&property[0..1](Singleton) : C:PropprojectOn (P:belongsTo.P:entity.P:properties),val[1..1](Singleton) : C:Value,&includedContext[0..1](Singleton) : C:EntityObject := (P:belongsTo.P:entity) • [Value!!] refinesAttributeObject ::> ; • V_Boolean!! refinesValue::>booleanValue[1..1](Singleton) : C:Boolean; • V_Ref!! refinesValue::>&refValue[0..1](Singleton) : C:Instance ; The OOMEGA language workbench - www.oomega.net
The languagemodule „Instance“ • textualconcretesyntaxDIRECTORY{ <helper> InstanceModel: "instance" _ "model" _ <Named> ;} • textualconcretesyntaxLWC{ <default> InstanceModel: "instance" _ "model" _ <Named> _ ("based" _ "on" _ || &P:basedOn / "," || _) "{" (nl | P:instances) nl"}" ;<default> Instance : (&P:entity) _ <Named> _ "=" _ "{" (nl | P:propertyValues) nl"}";<default> PropertyValue : (&P:property) _ "=" _ (P:val) ;<default> V_Boolean : (P:booleanValue) ;<default> V_Ref : (&P:refValue) ;} The OOMEGA language workbench - www.oomega.net
Instance model The OOMEGA language workbench - www.oomega.net
Task 1.2 - Demonstrate how to implement runtime type systems • Challenge:The initialization values in the instance-DSL must be of the same type as the types of the properties. The implementation of the runtime type system can be achieved with only one additional constraint for the concept PropertyValue in the language module “Instance”. The OOMEGA language workbench - www.oomega.net
Additional constraint „typeSafety“ • PropertyValue! refinesEntityObject ::>(PK)&property[0..1](Singleton) : C:PropprojectOn (P:belongsTo.P:entity.P:properties),val[1..1](Singleton) : C:Value,where typeSafety["Type of the value must match the property's type"]:(P:propertyconsistsOfC:Association=> (P:valconsistsOfC:V_Ref &(P:property.P:type) = (P:val.P:refValue.P:entity)))& (P:propertyconsistsOfC:Attribute=> (((P:property.P:type) consistsOfC:P_Boolean=> P:valconsistsOfC:V_Boolean) & ((P:property.P:type) consistsOfC:P_Date=> P:valconsistsOfC:V_Date) & ((P:property.P:type) consistsOfC:P_Natural=> P:valconsistsOfC:V_Natural) & ((P:property.P:type) consistsOfC:P_String=> P:valconsistsOfC:V_String))) ; The OOMEGA language workbench - www.oomega.net
Task 1.3 - Show how to do a model-to-model transformation • Challenge:Define an ER-meta model (Database, Table, Column) and transform the entity model into an instance of this ER meta model. • Solution:Model-to-model transformationscanbedonewith ATLAS Transformation Language (ATL). Basicallythiscanbedone in two simple steps: • Code an ATL template • Execute the ATL transformation within an Ant script Due to time restrictions the model-to-model transformation with ATL is not explained here. Please have a look at our online documentation. The OOMEGA language workbench - www.oomega.net
The languagemodule „EntityRelationship“ • Database! refinesFolderEntry::=tables[0..*](Set) <-> belongsTo : C:Table; • Table! refinesNamed::>&belongsTo[0..1](Singleton) <-> tables : C:Database,columns[1..*](Set) <-> belongsTo : C:Column,foreignKeys[0..*](Set) <-> belongsTo : C:ForeignKey; • Column! refinesNamed::>&belongsTo[0..1](Singleton) <-> columns : C:Table,type[1..1](Singleton) : C:Primitive,length[0..1](Singleton) : C:Natural,primaryKey[1..1](Singleton) : C:Boolean The OOMEGA language workbench - www.oomega.net
The languagemodule „EntityRelationship“ • ForeignKey! refinesEntityObject::>&belongsTo[0..1](Singleton) <-> foreignKeys : C:Table,&fkColumn[1..1](Singleton) : C:ColumnprojectOn (P:belongsTo.P:columns),&referencedTable[1..1](Singleton) : C:TableprojectOn (P:belongsTo.P:belongsTo.P:tables),&referencedColumn[1..1](Singleton) : C:ColumnprojectOn (P:referencedTable.P:columns) ; The OOMEGA language workbench - www.oomega.net
The languagemodule „EntityRelationship“ • textualconcretesyntaxDIRECTORY{ <helper> Database: "database" _ <Named> ;} • textualconcretesyntaxLWC{<default> Database : "database" _ <Named> _ "{" (nl | P:tables) nl"}" ;<default> Table : "table" _ <Named> _ "{" (nl | P:columns / ",") ("," || nl | P:foreignKeys / ",") nl"}" ; <default> Column: ((bool)P:primaryKey ? "pk" _ : "") (!P:type) ("("| P:length | ")") _ <Named> ;<default> ForeignKey: "fk" _ (&P:fkColumn) _ "references" _ (&P:referencedTable) ("(" | &P:referencedColumn | ")") ;} The OOMEGA language workbench - www.oomega.net
The languagemodule „EntityRelationship“ • textualconcretesyntaxSQL{ <readonly> Database : "CREATE" _ "DATABASE" _ <Named> (nl | P:tables) ;<readonly> Table: "CREATE" _ "TABLE" _ <Named> nl"(" (nl | P:columns / ",") ("," || nl | P:foreignKeys / ",") nl")";<readonly> Column: <Named> _ (P:type) ("(" | P:length | ")") ((bool)P:primaryKey ? _ "PRIMARY" _ "KEY" : "") ;<readonly> ForeignKey: "FOREIGN" _ "KEY" ("(" | &P:fkColumn | ")") _ "REFERENCES" _ (&P:referencedTable) ("("| P:referencedColumn.P:name | ")") ;} The OOMEGA language workbench - www.oomega.net
E/R model: „LWC“ syntaxtab The OOMEGA language workbench - www.oomega.net
E/R model: „SQL“ syntaxtab The OOMEGA language workbench - www.oomega.net
Task 1.4 - Some kind of visibility/namespaces/scoping for references • Challenge:Integrate namespaces/packages into the entity DSL package p1 { import p2 entity Person { string name string firstname date birthdate Car ownedCar } } package p2 { entity Car { string make string model } } The OOMEGA language workbench - www.oomega.net
Task 1.4 - Some kind of visibility/namespaces/scoping for references • …and make sure in the instance DSL you can only assign values to the properties of the respective entity, i.e. make sure that writingis illegal. Car c = { birthdate = … } The OOMEGA language workbench - www.oomega.net
Namespaces – Introducingtheconcept „Package“ • DomainModel! refinesFolderEntry::=packages[0..*](Set) <-> belongsTo : C:Package, ... • Package! refinesNamed::>&belongsTo[0..1](Singleton) <-> packages : C:DomainModel,entities[0..*](Set) <-> belongsTo : C:Entity,&importedPackages[0..*](Set) : C:Package,&path[0..1](Singleton) : C:String := Java: "return getName().replace('.', '/');" ; • textualconcretesyntaxLWC{ <default> Package: "package" _ <Named> _ "{" (nl"import" _ || &P:importedPackages / "," _) (nl | P:entities)nl"}" ;} The OOMEGA language workbench - www.oomega.net
VisibilityandScoping • VisibilityAn entity can reference another entity only if the other entity is either part of the same package or part of an imported package. • ScopingA package import leads to a scope expansion: if an entity of an imported package is referenced, then the package prefix can be omitted in the reference. The implementation of the features visibility and scoping takes only two lines of code. The OOMEGA language workbench - www.oomega.net
VisibilityandScoping • Association! refinesProp::>&type[1..1](Singleton) <-> usedBy : C:EntityprojectOn ((P:belongsTo.P:belongsTo.P:entities) union (P:belongsTo.P:belongsTo.P:importedPackages.P:entities)),&includedContext[0..*](Set) : C:EntityObject := (P:belongsTo.P:belongsTo.P:importedPackages) ; • The context sensitive domain of the “type” property realizes the visibilityfeature: an association cannot reference entities of foreign packages that have not been imported. • The inferred property “includedContext” implements the scoping feature: all imported packages are included into the scope of an association. Visibility Scoping The OOMEGA language workbench - www.oomega.net
Constrain property/value assignments within instances according to the type of the instance • This can be realized with a context sensitive domain. Let’s show the relevant part of the concept PropertyValue: • PropertyValue! refinesEntityObject::>(PK)&property[0..1](Singleton) : C:PropprojectOn (P:belongsTo.P:entity.P:properties), ... • The Edge Algebra statement ensures that the referenced property within a property/value assignment is a property that is defined within the type of the instance. The OOMEGA language workbench - www.oomega.net
Domain modelwithpackageimports The OOMEGA language workbench - www.oomega.net
Task 1.5 - Integrating manually written code (again in Java, C# or C++) • Challenge:Integrate derived attributes to entities.Note that if you want, you can also define or reuse an expression language that allows defining the algorithm for calculating the age directly in the model. Ideally, you will show both (manually written 3GL code as well as an expression language). entity Person { string name string firstname date birthdate Car ownedCar derived int age // somehow somewhere implement the code // to calculate age } The OOMEGA language workbench - www.oomega.net
Introducing a simple expressionlanguage • We have decided to implement a simple expression language that allows defining the algorithm for calculating the age directly in the model. • entityPerson{datebirthdatederived natural age = YearOf((Today - P(birthdate)))} The OOMEGA language workbench - www.oomega.net
The languagemodule„Expression“ The OOMEGA language workbench - www.oomega.net
The languagemodule „Expression“ • Today!! refinesDateExp ::> ; • DateSubtraction!! refinesDateExp::>leftOperand[1..1](Singleton) : C:DateExp,rightOperand[1..1](Singleton) : C:DateExp; • YearOf!! refinesNaturalExp::>dateExp[1..1](Singleton) : C:DateExp; • textualconcretesyntaxLWC{ <default> DateSubtraction: "(" (P:leftOperand) _ "-" _ (P:rightOperand) ")";<default> Today: "Today";<default> YearOf: "YearOf""(" (P:dateExp) ")";} The OOMEGA language workbench - www.oomega.net