Domain-specific languages with Dr. Jan K�hnlein itemis AG Sonntag, 23. August 2009 Who`s that guy? Sonntag, 23. August 2009 Sonntag, 23. August 2009 Jan K�hnlein Sonntag, 23. August 2009 � Software Architect, Consultant, Coach at itemis Jan K�hnlein Sonntag, 23. August 2009 � Software Architect, Consultant, Coach at itemis � Several years of experience in the modeling world Jan K�hnlein Sonntag, 23. August 2009 � Software Architect, Consultant, Coach at itemis � Several years of experience in the modeling world source projects � Committer to several openJan K�hnlein Sonntag, 23. August 2009 itemis short facts Spezialist f�r modellbasierte Entwicklungsverfahren Gr�ndung im Jahr 2003 Niederlassungen in Deutschland, Frankreich, Schweiz und Kanada 140 Mitarbeiter Strategisches Mitglied der Eclipse Foundation Intensive Verzahnung im Bereich der Forschung Mitglied von ARTEMISIA Embedded Software Development Enterprise Application Development 1 Sonntag, 23. August 2009 What is a Domain Specific Language (DSL)? Sonntag, 23. August 2009 Sonntag, 23. August 2009 A domain-specific language (DSL) is a formal, processable language targeting at a specific viewpoint or aspect of a system. Sonntag, 23. August 2009 A domain-specific language (DSL) is a formal, processable language targeting at a specific viewpoint or aspect of a system. Its semantics, flexibility and notation is designed in order to support working with that viewpoint as good as possible. Sonntag, 23. August 2009 Boring! Don`t you have any examples? Sonntag, 23. August 2009 Rd2-c2 Sonntag, 23. August 2009 Rd2-c2 Sonntag, 23. August 2009 Queen to c7. " Check." Rd2-c2 , rook at d2 moves to c2. Sonntag, 23. August 2009 " " Using JPA Sonntag, 23. August 2009 Sonntag, 23. August 2009 @Entity public class Customer implements Serializable { private Long id; private String name; private Address address; private Collectionorders = new HashSet (); private Set phones = new HashSet (); public Customer() {} @Id public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } @OneToMany public Collection getOrders() { return orders; } public void setOrders(Collection orders) { this.orders = orders; } @ManyToMany public Set getPhones() { return phones; } public void setPhones(Set phones) { this.phones = phones; } } Sonntag, 23. August 2009 @Entity public class Customer implements Serializable { private Long id; private String name; private Address address; private Collection orders = new HashSet (); private Set phones = new HashSet (); public Customer() {} @Id public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } @OneToMany public Collection getOrders() { return orders; } public void setOrders(Collection orders) { this.orders = orders; } @ManyToMany public Set getPhones() { return phones; } public void setPhones(Set phones) { this.phones = phones; } } Sonntag, 23. August 2009 entity Customer { String name Address address Order* orders PhoneNumber** phones } Testing Testing a Parser Sonntag, 23. August 2009 Expr 2+3*7/8 Op + Parser Number 2 Op / Op * Number 8 Number 3 Sonntag, 23. August 2009 Number 7 public class ParserTests extends TestCase { public void testExampleExpression2() throws IOException { EObject ast = parse("2+3*7/8"); assertTrue(ast instanceof Expr); EObject ast_0 = child(ast, 0); assertTrue(ast_0 instanceof Op); assertEquals("+", ((Op) ast_0).getOperator()); } EObject ast_0_0 = child(ast_0, 0); assertTrue(ast_0_0 instanceof Number); assertEquals(2, ((Number) ast_0_0).getValue()); EObject ast_0_1 = child(ast_0, 1); assertTrue(ast_0_1 instanceof Op); assertEquals("/", ((Op) ast_0_1).getOperator()); EObject ast_0_1_0 = child(ast_0_1, 0); assertTrue(ast_0_1_0 instanceof Op); assertEquals("*", ((Op) ast_0_1_0).getOperator()); EObject ast_0_1_1 = child(ast_0_1, 1); assertTrue(ast_0_1_1 instanceof Number); assertEquals(8, ((Number) ast_0_1_1).getValue()); EObject ast_0_1_0_0 = child(ast_0_1_0, 0); assertTrue(ast_0_1_0_0 instanceof Number); assertEquals(3, ((Number) ast_0_1_0_0).getValue()); EObject ast_0_1_0_1 = child(ast_0_1_0, 1); assertTrue(ast_0_1_0_1 instanceof Number); assertEquals(7, ((Number) ast_0_1_0_1).getValue()); Sonntag, 23. August 2009 public class ParserTests extends ParserTestCase { } public void testExampleExpression() throws IOException { EObject ast = parse("2+3*7/8"); assertTrue(ast instanceof Expr); EObject ast_0 = child(ast, 0); assertOperator(ast_0, "+"); } EObject ast_0_0 = child(ast_0, 0); assertNumber(ast_0_0, 2); EObject ast_0_1 = child(ast_0, 1); assertOperator(ast_0_1, "/"); EObject ast_0_1_0 = child(ast_0_1, 0); assertOperator(ast_0_1_0, "*"); EObject ast_0_1_1 = child(ast_0_1, 1); assertNumber(ast_0_1_1,8); EObject ast_0_1_0_0 = child(ast_0_1_0, 0); assertNumber(ast_0_1_0_0, 3); EObject ast_0_1_0_1 = child(ast_0_1_0, 1); assertNumber(ast_0_1_0_1, 7); Sonntag, 23. August 2009 public class ParserTests extends ParserTestCase { } public void testExampleExpression() throws IOException { EObject ast = parse("2+3*7/8"); assertTrue(ast instanceof Expr); EObject ast_0 = child(ast, 0); test testExampleExpression assertOperator(ast_0, "+"); "2+3*7/8" } EObject ast_0_0 = child(ast_0, 0); assertNumber(ast_0_0, 2); EObject ast_0_1 = child(ast_0, 1); assertOperator(ast_0_1, "/"); EObject ast_0_1_0 = child(ast_0_1, 0); assertOperator(ast_0_1_0, "*"); EObject ast_0_1_1 = child(ast_0_1, 1); assertNumber(ast_0_1_1,8); EObject ast_0_1_0_0 = child(ast_0_1_0, 0); assertNumber(ast_0_1_0_0, 3); EObject ast_0_1_0_1 = child(ast_0_1_0, 1); assertNumber(ast_0_1_0_1, 7); Expr { Op operator="+" { Number value="2" Op operator="/" { Op operator="*" { Number value="3" Number value="7" } Number value="8" } } } Sonntag, 23. August 2009 What can I achieve with DSLs? Sonntag, 23. August 2009 Abstraction Sonntag, 23. August 2009 GPL vs DSL Sonntag, 23. August 2009 GPL vs DSL Sonntag, 23. August 2009 GPL vs DSL Sonntag, 23. August 2009 Why isn`t everybody using DSLs? Sonntag, 23. August 2009 Complicated Sonntag, 23. August 2009 Expensive licensed by http://www.wordle.net/ Sonntag, 23. August 2009 Sonntag, 23. August 2009 Sonntag, 23. August 2009 Sonntag, 23. August 2009 G ra m m ar Sonntag, 23. August 2009 G Reference Model ra m m ar Sonntag, 23. August 2009 G Reference Model ra m m ar Runtime Superclass Subclass Class ecore meta model LL(*) Parser G Reference Model ra m m ar editor Sonntag, 23. August 2009 Runtime Superclass Subclass Class ecore meta model LL(*) Parser editor Sonntag, 23. August 2009 Runtime Superclass Subclass Class ecore meta model LL(*) Parser editor Model Model Model Sonntag, 23. August 2009 Runtime Superclass Subclass Class ecore meta model LL(*) Parser editor Model Model Model Sonntag, 23. August 2009 Runtime Superclass Subclass Class ecore meta model LL(*) Parser editor AST Model Model Model Sonntag, 23. August 2009 Runtime Superclass Subclass Class ecore meta model LL(*) Parser editor AST Model Model Model Sonntag, 23. August 2009 Runtime Superclass Subclass Class ecore meta model LL(*) Parser editor Interpreter Code Generator AST Model Model Model Sonntag, 23. August 2009 Runtime Superclass Subclass Class ecore meta model LL(*) Parser editor Interpreter Code Generator AST Model Model Model Sonntag, 23. August 2009 Showtime Sonntag, 23. August 2009 Example Model type String entity Conference { property Name: String property Attendees: Person[] ] property Speakers: Speaker[ } entity Person { property Name: String } on { entity Speaker extends Pers property Sessions: Session[] } entity Session { property Title: String } Sonntag, 23. August 2009 Example Model type String entity Conference { property Name: String property Attendees: Person[] ] property Speakers: Speaker[ } entity Person { property Name: String } on { entity Speaker extends Pers property Sessions: Session[] } entity Session { property Title: String } Sonntag, 23. August 2009 entity Model types * Type name: EString SimpleType Entity extends properties * Property name: EString many: EBoolean type grammar org.xtext.webinar.Entity with org.eclipse.xtext.common.Terminals generate entity "http://www.xtext.org/webinar/Entity" Model: (elements+=Type)*; Type: SimpleType | Entity; SimpleType: 'type' name=ID; Entity: 'entity' name=ID ('extends' extends=[Entity])? '{' properties+=Property* '}'; Property: 'property' name=ID ':' type=[Type] (many?='[]')?; Sonntag, 23. August 2009 Grammar definition grammar org.xtext.webinar.Entity with org.eclipse.xtext.common.Terminals generate entity "http://www.xtext.org/webinar/Entity" Model: (elements+=Type)*; Type: SimpleType | Entity; SimpleType: 'type' name=ID; Entity: 'entity' name=ID ('extends' extends=[Entity])? '{' properties+=Property* '}'; Property: 'property' name=ID ':' type=[Type] (many?='[]')?; Sonntag, 23. August 2009 grammar org.xtext.webinar.Entity with org.eclipse.xtext.common.Terminals generate entity "http://www.xtext.org/webinar/Entity" Model: (elements+=Type)*; Type: SimpleType | Entity; SimpleType: 'type' name=ID; Entity: 'entity' name=ID ('extends' extends=[Entity])? '{' properties+=Property* '}'; Property: 'property' name=ID ':' type=[Type] (many?='[]')?; Grammar reuse Sonntag, 23. August 2009 grammar org.xtext.webinar.Entity with org.eclipse.xtext.common.Terminals Derived metamodel generate entity "http://www.xtext.org/webinar/Entity" Model: (elements+=Type)*; Type: SimpleType | Entity; SimpleType: 'type' name=ID; Entity: 'entity' name=ID ('extends' extends=[Entity])? '{' properties+=Property* '}'; Property: 'property' name=ID ':' type=[Type] (many?='[]')?; Sonntag, 23. August 2009 grammar org.xtext.webinar.Entity with org.eclipse.xtext.common.Terminals generate entity "http://www.xtext.org/webinar/Entity" Model: (elements+=Type)*; Type: SimpleType | Entity; Parser rules SimpleType: 'type' name=ID; Entity: 'entity' name=ID ('extends' extends=[Entity])? '{' properties+=Property* '}'; Property: 'property' name=ID ':' type=[Type] (many?='[]')?; Sonntag, 23. August 2009 grammar org.xtext.webinar.Entity with org.eclipse.xtext.common.Terminals generate entity "http://www.xtext.org/webinar/Entity" Model: (elements+=Type)*; Type: SimpleType | Entity; SimpleType: 'type' name=ID; Entity: 'entity' name=ID ('extends' extends=[Entity])? '{' properties+=Property* '}'; Property: 'property' name=ID ':' type=[Type] (many?='[]')?; Keywords Keywords Sonntag, 23. August 2009 grammar org.xtext.webinar.Entity with org.eclipse.xtext.common.Terminals generate entity "http://www.xtext.org/webinar/Entity" Model: (elements+=Type)*; Type: SimpleType | Entity; SimpleType: 'type' name=ID; Entity: 'entity' name=ID ('extends' extends=[Entity])? '{' properties+=Property* '}'; Property: 'property' name=ID ':' type=[Type] (many?='[]')?; Alternative Sonntag, 23. August 2009 grammar org.xtext.webinar.Entity with org.eclipse.xtext.common.Terminals generate entity "http://www.xtext.org/webinar/Entity" Model: (elements+=Type)*; Type: SimpleType | Entity; SimpleType: 'type' name=ID; Entity: 'entity' name=ID ('extends' extends=[Entity])? '{' properties+=Property* '}'; Property: 'property' name=ID ':' type=[Type] (many?='[]')?; Cardinality (zero or more) Cardinality (optional) Sonntag, 23. August 2009 grammar org.xtext.webinar.Entity with org.eclipse.xtext.common.Terminals generate entity "http://www.xtext.org/webinar/Entity" Model: (elements+=Type)*; Type: SimpleType | Entity; SimpleType: 'type' name=ID; Entity: 'entity' name=ID ('extends' extends=[Entity])? '{' properties+=Property* '}'; Property: 'property' name=ID ':' type=[Type] (many?='[]')?; Unassigned rulecall Assigned rulecall Sonntag, 23. August 2009 grammar org.xtext.webinar.Entity with org.eclipse.xtext.common.Terminals generate entity "http://www.xtext.org/webinar/Entity" Model: (elements+=Type)*; Type: SimpleType | Entity; SimpleType: 'type' name=ID; Entity: 'entity' name=ID ('extends' extends=[Entity])? '{' properties+=Property* '}'; Property: 'property' name=ID ':' type=[Type] (many?='[]')?; Multivalue assignment Simple assigment Boolean assigment Sonntag, 23. August 2009 grammar org.xtext.webinar.Entity with org.eclipse.xtext.common.Terminals generate entity "http://www.xtext.org/webinar/Entity" Model: (elements+=Type)*; Type: SimpleType | Entity; SimpleType: 'type' name=ID; Entity: 'entity' name=ID ('extends' extends=[Entity])? '{' properties+=Property* '}'; Property: 'property' name=ID ':' type=[Type] (many?='[]')?; Cross reference Sonntag, 23. August 2009 grammar org.xtext.webinar.Entity with org.eclipse.xtext.common.Terminals generate entity "http://www.xtext.org/webinar/Entity" Model: (elements+=Type)*; Type: SimpleType | Entity; SimpleType: 'type' name=ID; Entity: 'entity' name=ID ('extends' extends=[Entity])? '{' properties+=Property* '}'; Property: 'property' name=ID ':' type=[Type] (many?='[]')?; Sonntag, 23. August 2009 grammar org.xtext.webinar.Entity with org.eclipse.xtext.common.Terminals generate entity "http://www.xtext.org/webinar/Entity" Model: (elements+=Type)*; Type: SimpleType | Entity; SimpleType: 'type' name=ID; Entity: 'entity' name=ID ('extends' extends=[Entity])? '{' properties+=Property* '}'; Property: 'property' name=ID ':' type=[Type] (many?='[]')?; entity Model types * Type name: EString SimpleType Entity extends properties * Property name: EString many: EBoolean type Sonntag, 23. August 2009 grammar org.xtext.webinar.Entity with org.eclipse.xtext.common.Terminals generate entity "http://www.xtext.org/webinar/Entity" Model: (elements+=Type)*; Type: SimpleType | Entity; SimpleType: 'type' name=ID; Entity: 'entity' name=ID ('extends' extends=[Entity])? '{' properties+=Property* '}'; Property: 'property' name=ID ':' type=[Type] (many?='[]')?; entity Model types * Type name: EString SimpleType Entity extends properties * Property name: EString many: EBoolean type Sonntag, 23. August 2009 grammar org.xtext.webinar.Entity with org.eclipse.xtext.common.Terminals generate entity "http://www.xtext.org/webinar/Entity" Model: (elements+=Type)*; Type: SimpleType | Entity; SimpleType: 'type' name=ID; Entity: 'entity' name=ID ('extends' extends=[Entity])? '{' properties+=Property* '}'; Property: 'property' name=ID ':' type=[Type] (many?='[]')?; entity Model types * Type name: EString SimpleType Entity extends properties * Property name: EString many: EBoolean type Sonntag, 23. August 2009 grammar org.xtext.webinar.Entity with org.eclipse.xtext.common.Terminals generate entity "http://www.xtext.org/webinar/Entity" Model: (elements+=Type)*; Type: SimpleType | Entity; SimpleType: 'type' name=ID; Entity: 'entity' name=ID ('extends' extends=[Entity])? '{' properties+=Property* '}'; Property: 'property' name=ID ':' type=[Type] (many?='[]')?; entity Model types * Type name: EString SimpleType Entity extends properties * Property name: EString many: EBoolean type Sonntag, 23. August 2009 grammar org.xtext.webinar.Entity with org.eclipse.xtext.common.Terminals generate entity "http://www.xtext.org/webinar/Entity" Model: (elements+=Type)*; Type: SimpleType | Entity; SimpleType: 'type' name=ID; Entity: 'entity' name=ID ('extends' extends=[Entity])? '{' properties+=Property* '}'; Property: 'property' name=ID ':' type=[Type] (many?='[]')?; entity Model types * Type name: EString SimpleType Entity extends properties * Property name: EString many: EBoolean type Sonntag, 23. August 2009 grammar org.xtext.webinar.Entity with org.eclipse.xtext.common.Terminals generate entity "http://www.xtext.org/webinar/Entity" Model: (elements+=Type)*; Type: SimpleType | Entity; SimpleType: 'type' name=ID; Entity: 'entity' name=ID ('extends' extends=[Entity])? '{' properties+=Property* '}'; Property: 'property' name=ID ':' type=[Type] (many?='[]')?; entity Model types * Type name: EString SimpleType Entity extends properties * Property name: EString many: EBoolean type Sonntag, 23. August 2009 grammar org.xtext.webinar.Entity with org.eclipse.xtext.common.Terminals generate entity "http://www.xtext.org/webinar/Entity" Model: (elements+=Type)*; Type: SimpleType | Entity; SimpleType: 'type' name=ID; Entity: 'entity' name=ID ('extends' extends=[Entity])? '{' properties+=Property* '}'; Property: 'property' name=ID ':' type=[Type] (many?='[]')?; entity Model types * Type name: EString SimpleType Entity extends properties * Property name: EString many: EBoolean type Sonntag, 23. August 2009 grammar org.xtext.webinar.Entity with org.eclipse.xtext.common.Terminals generate entity "http://www.xtext.org/webinar/Entity" Model: (elements+=Type)*; Type: SimpleType | Entity; SimpleType: 'type' name=ID; Entity: 'entity' name=ID ('extends' extends=[Entity])? '{' properties+=Property* '}'; Property: 'property' name=ID ':' type=[Type] (many?='[]')?; entity Model types * Type name: EString SimpleType Entity extends properties * Property name: EString many: EBoolean type Sonntag, 23. August 2009 Isn`t text a little bit oldfashioned? Sonntag, 23. August 2009 Graphics } protected String getErrorMessage() { return errorMessage.toString(); } public boolean isSameStructure(EObject left, EObject right) { counter = 0; return internalIsSameStructure(left, right); } public boolean internalIsSameStructure(EObject left, EObject right) { ++counter; if (!isSameClass(left.eClass(), right.eClass())) { errorMessage.append("Classes are not equal: " + left + " != " + ri return false; } List leftChildren = getRelevantChildren(left); List rightChildren = getRelevantChildren(right); if(leftChildren.size() != rightChildren.size()) { errorMessage.append("Number of children differs " + left + " " + r return false; } for (int i = 0; i < leftChildren.size(); ++i) { if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get errorMessage.append("Children differ " + left + " " + right + return false; } } } return true; protected boolean isSameClass(EClass left, EClass right) { return left.getName().equals(right.getName()) && left.getEPackage().getNsURI().equals(right.getEPackage().g } Text protected List getRelevantChildren(EObject _this) { List relevantChildren = new ArrayList (_this.eContents( for (Iterator i = relevantChildren.iterator(); i.hasNext();) { EObject next = i.next(); if (!isRelevantChild(_this, next)) { i.remove(); } } return relevantChildren; } protected boolean isRelevantChild(EObject container, EObject child) { return true; } Sonntag, 23. August 2009 Graphics � High-level views } protected String getErrorMessage() { return errorMessage.toString(); } public boolean isSameStructure(EObject left, EObject right) { counter = 0; return internalIsSameStructure(left, right); } public boolean internalIsSameStructure(EObject left, EObject right) { ++counter; if (!isSameClass(left.eClass(), right.eClass())) { errorMessage.append("Classes are not equal: " + left + " != " + ri return false; } List leftChildren = getRelevantChildren(left); List rightChildren = getRelevantChildren(right); if(leftChildren.size() != rightChildren.size()) { errorMessage.append("Number of children differs " + left + " " + r return false; } for (int i = 0; i < leftChildren.size(); ++i) { if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get errorMessage.append("Children differ " + left + " " + right + return false; } } } return true; protected boolean isSameClass(EClass left, EClass right) { return left.getName().equals(right.getName()) && left.getEPackage().getNsURI().equals(right.getEPackage().g } Text protected List getRelevantChildren(EObject _this) { List relevantChildren = new ArrayList (_this.eContents( for (Iterator i = relevantChildren.iterator(); i.hasNext();) { EObject next = i.next(); if (!isRelevantChild(_this, next)) { i.remove(); } } return relevantChildren; } protected boolean isRelevantChild(EObject container, EObject child) { return true; } Sonntag, 23. August 2009 Graphics � High-level views } protected String getErrorMessage() { return errorMessage.toString(); } public boolean isSameStructure(EObject left, EObject right) { counter = 0; return internalIsSameStructure(left, right); } public boolean internalIsSameStructure(EObject left, EObject right) { ++counter; if (!isSameClass(left.eClass(), right.eClass())) { errorMessage.append("Classes are not equal: " + left + " != " + ri return false; } List leftChildren = getRelevantChildren(left); List rightChildren = getRelevantChildren(right); if(leftChildren.size() != rightChildren.size()) { errorMessage.append("Number of children differs " + left + " " + r return false; } for (int i = 0; i < leftChildren.size(); ++i) { if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get errorMessage.append("Children differ " + left + " " + right + return false; } } } return true; protected boolean isSameClass(EClass left, EClass right) { return left.getName().equals(right.getName()) && left.getEPackage().getNsURI().equals(right.getEPackage().g } � Detailed views Text protected List getRelevantChildren(EObject _this) { List relevantChildren = new ArrayList (_this.eContents( for (Iterator i = relevantChildren.iterator(); i.hasNext();) { EObject next = i.next(); if (!isRelevantChild(_this, next)) { i.remove(); } } return relevantChildren; } protected boolean isRelevantChild(EObject container, EObject child) { return true; } Sonntag, 23. August 2009 Graphics � High-level views � Suggests non-formalism } protected String getErrorMessage() { return errorMessage.toString(); } public boolean isSameStructure(EObject left, EObject right) { counter = 0; return internalIsSameStructure(left, right); } public boolean internalIsSameStructure(EObject left, EObject right) { ++counter; if (!isSameClass(left.eClass(), right.eClass())) { errorMessage.append("Classes are not equal: " + left + " != " + ri return false; } List leftChildren = getRelevantChildren(left); List rightChildren = getRelevantChildren(right); if(leftChildren.size() != rightChildren.size()) { errorMessage.append("Number of children differs " + left + " " + r return false; } for (int i = 0; i < leftChildren.size(); ++i) { if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get errorMessage.append("Children differ " + left + " " + right + return false; } } } return true; protected boolean isSameClass(EClass left, EClass right) { return left.getName().equals(right.getName()) && left.getEPackage().getNsURI().equals(right.getEPackage().g } � Detailed views Text protected List getRelevantChildren(EObject _this) { List relevantChildren = new ArrayList (_this.eContents( for (Iterator i = relevantChildren.iterator(); i.hasNext();) { EObject next = i.next(); if (!isRelevantChild(_this, next)) { i.remove(); } } return relevantChildren; } protected boolean isRelevantChild(EObject container, EObject child) { return true; } Sonntag, 23. August 2009 Graphics � High-level views � Suggests non-formalism } protected String getErrorMessage() { return errorMessage.toString(); } public boolean isSameStructure(EObject left, EObject right) { counter = 0; return internalIsSameStructure(left, right); } public boolean internalIsSameStructure(EObject left, EObject right) { ++counter; if (!isSameClass(left.eClass(), right.eClass())) { errorMessage.append("Classes are not equal: " + left + " != " + ri return false; } List leftChildren = getRelevantChildren(left); List rightChildren = getRelevantChildren(right); if(leftChildren.size() != rightChildren.size()) { errorMessage.append("Number of children differs " + left + " " + r return false; } for (int i = 0; i < leftChildren.size(); ++i) { if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get errorMessage.append("Children differ " + left + " " + right + return false; } } } return true; protected boolean isSameClass(EClass left, EClass right) { return left.getName().equals(right.getName()) && left.getEPackage().getNsURI().equals(right.getEPackage().g } protected List getRelevantChildren(EObject _this) { List relevantChildren = new ArrayList (_this.eContents( for (Iterator i = relevantChildren.iterator(); i.hasNext();) { EObject next = i.next(); if (!isRelevantChild(_this, next)) { i.remove(); } } return relevantChildren; } protected boolean isRelevantChild(EObject container, EObject child) { return true; } � Detailed views � Formal Text Sonntag, 23. August 2009 Graphics � High-level views � Suggests non-formalism � Individual tools } protected String getErrorMessage() { return errorMessage.toString(); } public boolean isSameStructure(EObject left, EObject right) { counter = 0; return internalIsSameStructure(left, right); } public boolean internalIsSameStructure(EObject left, EObject right) { ++counter; if (!isSameClass(left.eClass(), right.eClass())) { errorMessage.append("Classes are not equal: " + left + " != " + ri return false; } List leftChildren = getRelevantChildren(left); List rightChildren = getRelevantChildren(right); if(leftChildren.size() != rightChildren.size()) { errorMessage.append("Number of children differs " + left + " " + r return false; } for (int i = 0; i < leftChildren.size(); ++i) { if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get errorMessage.append("Children differ " + left + " " + right + return false; } } } return true; protected boolean isSameClass(EClass left, EClass right) { return left.getName().equals(right.getName()) && left.getEPackage().getNsURI().equals(right.getEPackage().g } protected List getRelevantChildren(EObject _this) { List relevantChildren = new ArrayList (_this.eContents( for (Iterator i = relevantChildren.iterator(); i.hasNext();) { EObject next = i.next(); if (!isRelevantChild(_this, next)) { i.remove(); } } return relevantChildren; } protected boolean isRelevantChild(EObject container, EObject child) { return true; } � Detailed views � Formal Text Sonntag, 23. August 2009 Graphics � High-level views � Suggests non-formalism � Individual tools } protected String getErrorMessage() { return errorMessage.toString(); } public boolean isSameStructure(EObject left, EObject right) { counter = 0; return internalIsSameStructure(left, right); } public boolean internalIsSameStructure(EObject left, EObject right) { ++counter; if (!isSameClass(left.eClass(), right.eClass())) { errorMessage.append("Classes are not equal: " + left + " != " + ri return false; } List leftChildren = getRelevantChildren(left); List rightChildren = getRelevantChildren(right); if(leftChildren.size() != rightChildren.size()) { errorMessage.append("Number of children differs " + left + " " + r return false; } for (int i = 0; i < leftChildren.size(); ++i) { if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get errorMessage.append("Children differ " + left + " " + right + return false; } } } return true; protected boolean isSameClass(EClass left, EClass right) { return left.getName().equals(right.getName()) && left.getEPackage().getNsURI().equals(right.getEPackage().g } protected List getRelevantChildren(EObject _this) { List relevantChildren = new ArrayList (_this.eContents( for (Iterator i = relevantChildren.iterator(); i.hasNext();) { EObject next = i.next(); if (!isRelevantChild(_this, next)) { i.remove(); } } return relevantChildren; } protected boolean isRelevantChild(EObject container, EObject child) { return true; } � Detailed views � Formal � Well established tools Text Sonntag, 23. August 2009 Graphics � � � � High-level views Suggests non-formalism Individual tools Hard to evolve } protected String getErrorMessage() { return errorMessage.toString(); } public boolean isSameStructure(EObject left, EObject right) { counter = 0; return internalIsSameStructure(left, right); } public boolean internalIsSameStructure(EObject left, EObject right) { ++counter; if (!isSameClass(left.eClass(), right.eClass())) { errorMessage.append("Classes are not equal: " + left + " != " + ri return false; } List leftChildren = getRelevantChildren(left); List rightChildren = getRelevantChildren(right); if(leftChildren.size() != rightChildren.size()) { errorMessage.append("Number of children differs " + left + " " + r return false; } for (int i = 0; i < leftChildren.size(); ++i) { if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get errorMessage.append("Children differ " + left + " " + right + return false; } } } return true; protected boolean isSameClass(EClass left, EClass right) { return left.getName().equals(right.getName()) && left.getEPackage().getNsURI().equals(right.getEPackage().g } protected List getRelevantChildren(EObject _this) { List relevantChildren = new ArrayList (_this.eContents( for (Iterator i = relevantChildren.iterator(); i.hasNext();) { EObject next = i.next(); if (!isRelevantChild(_this, next)) { i.remove(); } } return relevantChildren; } protected boolean isRelevantChild(EObject container, EObject child) { return true; } � Detailed views � Formal � Well established tools Text Sonntag, 23. August 2009 Graphics � � � � High-level views Suggests non-formalism Individual tools Hard to evolve } protected String getErrorMessage() { return errorMessage.toString(); } public boolean isSameStructure(EObject left, EObject right) { counter = 0; return internalIsSameStructure(left, right); } public boolean internalIsSameStructure(EObject left, EObject right) { ++counter; if (!isSameClass(left.eClass(), right.eClass())) { errorMessage.append("Classes are not equal: " + left + " != " + ri return false; } List leftChildren = getRelevantChildren(left); List rightChildren = getRelevantChildren(right); if(leftChildren.size() != rightChildren.size()) { errorMessage.append("Number of children differs " + left + " " + r return false; } for (int i = 0; i < leftChildren.size(); ++i) { if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get errorMessage.append("Children differ " + left + " " + right + return false; } } } return true; protected boolean isSameClass(EClass left, EClass right) { return left.getName().equals(right.getName()) && left.getEPackage().getNsURI().equals(right.getEPackage().g } protected List getRelevantChildren(EObject _this) { List relevantChildren = new ArrayList (_this.eContents( for (Iterator i = relevantChildren.iterator(); i.hasNext();) { EObject next = i.next(); if (!isRelevantChild(_this, next)) { i.remove(); } } return relevantChildren; } protected boolean isRelevantChild(EObject container, EObject child) { return true; } � � � � Text Detailed views Formal Well established tools Easy to evolve Sonntag, 23. August 2009 Graphics � � � � � High-level views Suggests non-formalism Individual tools Hard to evolve Editing with mouse } protected String getErrorMessage() { return errorMessage.toString(); } public boolean isSameStructure(EObject left, EObject right) { counter = 0; return internalIsSameStructure(left, right); } public boolean internalIsSameStructure(EObject left, EObject right) { ++counter; if (!isSameClass(left.eClass(), right.eClass())) { errorMessage.append("Classes are not equal: " + left + " != " + ri return false; } List leftChildren = getRelevantChildren(left); List rightChildren = getRelevantChildren(right); if(leftChildren.size() != rightChildren.size()) { errorMessage.append("Number of children differs " + left + " " + r return false; } for (int i = 0; i < leftChildren.size(); ++i) { if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get errorMessage.append("Children differ " + left + " " + right + return false; } } } return true; protected boolean isSameClass(EClass left, EClass right) { return left.getName().equals(right.getName()) && left.getEPackage().getNsURI().equals(right.getEPackage().g } protected List getRelevantChildren(EObject _this) { List relevantChildren = new ArrayList (_this.eContents( for (Iterator i = relevantChildren.iterator(); i.hasNext();) { EObject next = i.next(); if (!isRelevantChild(_this, next)) { i.remove(); } } return relevantChildren; } protected boolean isRelevantChild(EObject container, EObject child) { return true; } � � � � Text Detailed views Formal Well established tools Easy to evolve Sonntag, 23. August 2009 Graphics � � � � � High-level views Suggests non-formalism Individual tools Hard to evolve Editing with mouse } protected String getErrorMessage() { return errorMessage.toString(); } public boolean isSameStructure(EObject left, EObject right) { counter = 0; return internalIsSameStructure(left, right); } public boolean internalIsSameStructure(EObject left, EObject right) { ++counter; if (!isSameClass(left.eClass(), right.eClass())) { errorMessage.append("Classes are not equal: " + left + " != " + ri return false; } List leftChildren = getRelevantChildren(left); List rightChildren = getRelevantChildren(right); if(leftChildren.size() != rightChildren.size()) { errorMessage.append("Number of children differs " + left + " " + r return false; } for (int i = 0; i < leftChildren.size(); ++i) { if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get errorMessage.append("Children differ " + left + " " + right + return false; } } } return true; protected boolean isSameClass(EClass left, EClass right) { return left.getName().equals(right.getName()) && left.getEPackage().getNsURI().equals(right.getEPackage().g } protected List getRelevantChildren(EObject _this) { List relevantChildren = new ArrayList (_this.eContents( for (Iterator i = relevantChildren.iterator(); i.hasNext();) { EObject next = i.next(); if (!isRelevantChild(_this, next)) { i.remove(); } } return relevantChildren; } protected boolean isRelevantChild(EObject container, EObject child) { return true; } � � � � � Text Detailed views Formal Well established tools Easy to evolve Editing with keyboard Sonntag, 23. August 2009 How about customization? Sonntag, 23. August 2009 Convention over Configuration Sonntag, 23. August 2009 http://www.wordle.net/ Sonntag, 23. August 2009 Configured with Google Guice class MyDslRuntimeModule extends DefaultRuntimeModule { Class extends ServiceInterface> bindService() { return MyServiceImplementation.class; } } Sonntag, 23. August 2009 Bird's Eye View Sonntag, 23. August 2009 Extensible Language Generator � Generates a lot of Java code � Composed of fragments � Customizable � Add your own fragments! Sonntag, 23. August 2009 Does Xtext integrate with other technologies? Sonntag, 23. August 2009 Integration with EMF Sonntag, 23. August 2009 Integration with EMF Code Generator GMF Editor Any EMF-based Component modeling P R O J E C T eclipse Sonntag, 23. August 2009 Integration with EMF Code Generator GMF Editor Any EMF-based Component modeling P R O J E C T eclipse < > Resource XMIResource Sonntag, 23. August 2009 Integration with EMF Code Generator GMF Editor Any EMF-based Component modeling P R O J E C T eclipse < > Resource XMIResource Sonntag, 23. August 2009 Integration with EMF Code Generator GMF Editor Any EMF-based Component modeling P R O J E C T eclipse < > Resource XMIResource XMI Sonntag, 23. August 2009 Integration with EMF Code Generator GMF Editor Any EMF-based Component modeling P R O J E C T eclipse < > Resource XMIResource XMI Sonntag, 23. August 2009 Integration with EMF Code Generator GMF Editor Any EMF-based Component modeling P R O J E C T eclipse < > Resource XMIResource XMI XtextResource Sonntag, 23. August 2009 Integration with EMF Code Generator GMF Editor Any EMF-based Component modeling P R O J E C T eclipse < > Resource XMIResource XMI XtextResource Sonntag, 23. August 2009 Integration with EMF Code Generator GMF Editor Any EMF-based Component modeling P R O J E C T eclipse < > Resource XMIResource XMI XtextResource Text Sonntag, 23. August 2009 Integration with EMF Code Generator GMF Editor Any EMF-based Component modeling P R O J E C T eclipse < > Resource XMIResource XMI XtextResource Text Parser Linker Serializer ValueConverter ScopeProvider Formatter Sonntag, 23. August 2009 converging editors (Xtext and GMF) koehnlein.blogspot.com Sonntag, 23. August 2009 converging editors (Xtext and GMF) koehnlein.blogspot.com Sonntag, 23. August 2009 Questions? find out more at http://www.xtext.org Sonntag, 23. August 2009 Sonntag, 23. August 2009 Aktuelle Veranstaltungen LOP und DSLs - K�ln, 15:00 25. August 2009: Deutsches Zentrum f�r Luft- und Raumfahrt - Falko Riemenschneider, NRWConf. 2009 27-28. August 2009: Wolkenburg 100, 42119 Wuppertal Dom�nenspezifische Sprachen - Lars Corneliussen 12.15 Uhr - 12.45 Uhr Die 10 Gebote der Architektur - Georg Pietrek 15.20 Uhr - 16.20 Uhr Scrum: Vom Businessneed zum hochwertigen Produktbacklog, Bonn, 18:30 31.August 2009 - Konferenzhotel Bonn - Sebastian Neus / Dr. Martin Wrangel Tagung: Mensch und Computer 2009, Berlin, 09:00 07. September 2009 - Leichtgewichtigkeit als Prinzip � Gestaltung der Webanwendung myPIM durch UCD, FDD und Xtext � Torsten Krohn Praktische Anwendung von EMF Compare, Dortmund 18:30 14. September 2009 - Harenberg City Center - Dr. Lothar Wendehals Alle aktuellen Veranstaltungen und weiterf�hrende Informationen auf: http://www.itemis.de/veranstaltungen Sonntag, 23. August 2009