Textual Modeling Framework


                            Sven Efftinge, Sebastian Zarnekow
                                            itemis




Donnerstag, 16. Juli 2009
Domain-Specific Language (DSL)




Donnerstag, 16. Juli 2009
Domain-Specific Language (DSL)
                 A DSL is a formal, processable language
                   targeting at a specific viewpoint or
                      aspect of a software system.




Donnerstag, 16. Juli 2009
Domain-Specific Language (DSL)
                 A DSL is a formal, processable language
                   targeting at a specific viewpoint or
                      aspect of a software system.
                It’s semantics, flexibility and notation is
                 designed in order to support working
                with that viewpoint as good as possible.


Donnerstag, 16. Juli 2009
Why DSLs?




Donnerstag, 16. Juli 2009
Why DSLs?
                            • higher abstractions




Donnerstag, 16. Juli 2009
Why DSLs?
                            • higher abstractions
                            • avoid redundancy




Donnerstag, 16. Juli 2009
Why DSLs?
                            • higher abstractions
                            • avoid redundancy
                            • separation of concerns




Donnerstag, 16. Juli 2009
Why DSLs?
                            • higher abstractions
                            • avoid redundancy
                            • separation of concerns
                            • use domain concepts
                             (Ubiquitous Language)




Donnerstag, 16. Juli 2009
The challenge




Donnerstag, 16. Juli 2009
Complicated
Donnerstag, 16. Juli 2009
Complicated & Expensive ?
Donnerstag, 16. Juli 2009
licensed by http://www.wordle.net/
Donnerstag, 16. Juli 2009
How we address this with




Donnerstag, 16. Juli 2009
Convenience
Donnerstag, 16. Juli 2009
grammar org.xtext.workshop.DomainModel
                            	   with org.eclipse.xtext.common.Terminals

                            generate domainModel "http://www.xtext.org/DomainModel"

                            Model :
                            	   (types+=Type)+;
                            	
                            Type :
                              Class | DataType;

                            DataType :
                              'datatype' name=ID;

                            Class :
                            	   (abstract?='abstract')? 'class' name=ID '{'
                                (features+=Feature)*	
                              '}';

                            Feature :
                              'attr' name=ID ':' type=[DataType];

                                                                                      9
Donnerstag, 16. Juli 2009
Grammar                   grammar org.xtext.workshop.DomainModel
  definition                	   with org.eclipse.xtext.common.Terminals

                            generate domainModel "http://www.xtext.org/DomainModel"

                            Model :
                            	   (types+=Type)+;
                            	
                            Type :
                              Class | DataType;

                            DataType :
                              'datatype' name=ID;

                            Class :
                            	   (abstract?='abstract')? 'class' name=ID '{'
                                (features+=Feature)*	
                              '}';

                            Feature :
                              'attr' name=ID ':' type=[DataType];

                                                                                      9
Donnerstag, 16. Juli 2009
Grammar                   grammar org.xtext.workshop.DomainModel             Grammar reuse
  definition                	   with org.eclipse.xtext.common.Terminals

                            generate domainModel "http://www.xtext.org/DomainModel"

                            Model :
                            	   (types+=Type)+;
                            	
                            Type :
                              Class | DataType;

                            DataType :
                              'datatype' name=ID;

                            Class :
                            	   (abstract?='abstract')? 'class' name=ID '{'
                                (features+=Feature)*	
                              '}';

                            Feature :
                              'attr' name=ID ':' type=[DataType];

                                                                                               9
Donnerstag, 16. Juli 2009
grammar org.xtext.workshop.DomainModel
                            	   with org.eclipse.xtext.common.Terminals

   Derived                  generate domainModel "http://www.xtext.org/DomainModel"
   metamodel
                            Model :
                            	   (types+=Type)+;
                            	
                            Type :
                              Class | DataType;

                            DataType :
                              'datatype' name=ID;

                            Class :
                            	   (abstract?='abstract')? 'class' name=ID '{'
                                (features+=Feature)*	
                              '}';

                            Feature :
                              'attr' name=ID ':' type=[DataType];

                                                                                      9
Donnerstag, 16. Juli 2009
grammar org.xtext.workshop.DomainModel
                            	   with org.eclipse.xtext.common.Terminals

                            generate domainModel "http://www.xtext.org/DomainModel"

                            Model :
                            	   (types+=Type)+;
  Parser                    	
  rules                     Type :
                              Class | DataType;

                            DataType :
                              'datatype' name=ID;

                            Class :
                            	   (abstract?='abstract')? 'class' name=ID '{'
                                (features+=Feature)*	
                              '}';

                            Feature :
                              'attr' name=ID ':' type=[DataType];

                                                                                      9
Donnerstag, 16. Juli 2009
grammar org.xtext.workshop.DomainModel
                            	   with org.eclipse.xtext.common.Terminals

                            generate domainModel "http://www.xtext.org/DomainModel"

                            Model :
                            	   (types+=Type)+;
  Parser                    	
  rules                     Type :
                              Class | DataType;

                            DataType :
                              'datatype' name=ID;

                            Class :
                            	   (abstract?='abstract')? 'class' name=ID '{'
                                (features+=Feature)*	
   Keywords                   '}';

                            Feature :
                              'attr' name=ID ':' type=[DataType];

                                                                                      9
Donnerstag, 16. Juli 2009
grammar org.xtext.workshop.DomainModel
                            	   with org.eclipse.xtext.common.Terminals

                            generate domainModel "http://www.xtext.org/DomainModel"

                                                  Multivalue assignment
                            Model :
                            	   (types+=Type)+;
                            	
                            Type :
                              Class | DataType;
                                                     Simple assigment
                            DataType :
                              'datatype' name=ID;
                                                    Boolean assigment
                            Class :
                            	   (abstract?='abstract')? 'class' name=ID '{'
                                (features+=Feature)*	
                              '}';

                            Feature :
                              'attr' name=ID ':' type=[DataType];

                                                                                      9
Donnerstag, 16. Juli 2009
grammar org.xtext.workshop.DomainModel
                            	   with org.eclipse.xtext.common.Terminals

                            generate domainModel "http://www.xtext.org/DomainModel"

                            Model :
                            	   (types+=Type)+;            Cardinality (one or more)
                            	
                            Type :
                              Class | DataType;

                            DataType :
                              'datatype' name=ID;

                            Class :                            Optional Element
                            	   (abstract?='abstract')? 'class' name=ID '{'
                                (features+=Feature)*	           Cardinality (zero or more)
                              '}';

                            Feature :
                              'attr' name=ID ':' type=[DataType];

                                                                                             9
Donnerstag, 16. Juli 2009
grammar org.xtext.workshop.DomainModel
                            	   with org.eclipse.xtext.common.Terminals

                            generate domainModel "http://www.xtext.org/DomainModel"

                            Model :
                            	   (types+=Type)+;            Cardinality (one or more)
                            	
                                                    Alternative
                            Type :
                              Class | DataType;

                            DataType :
                              'datatype' name=ID;

                            Class :                            Optional Element
                            	   (abstract?='abstract')? 'class' name=ID '{'
                                (features+=Feature)*	           Cardinality (zero or more)
                              '}';

                            Feature :
                              'attr' name=ID ':' type=[DataType];

                                                                                             9
Donnerstag, 16. Juli 2009
grammar org.xtext.workshop.DomainModel
                            	   with org.eclipse.xtext.common.Terminals

                            generate domainModel "http://www.xtext.org/DomainModel"

                            Model :
                            	   (types+=Type)+;
                            	
                            Type :
                              Class | DataType;

                            DataType :
                              'datatype' name=ID;          Assignment with rulecall

                            Class :
                            	   (abstract?='abstract')? 'class' name=ID '{'
                                (features+=Feature)*	
                              '}';

                            Feature :
                              'attr' name=ID ':' type=[DataType];

                                                                                      9
Donnerstag, 16. Juli 2009
grammar org.xtext.workshop.DomainModel
                            	   with org.eclipse.xtext.common.Terminals

                            generate domainModel "http://www.xtext.org/DomainModel"

                            Model :
                            	   (types+=Type)+;
                            	
                            Type :
                              Class | DataType;               Unassigned rulecall


                            DataType :
                              'datatype' name=ID;          Assignment with rulecall

                            Class :
                            	   (abstract?='abstract')? 'class' name=ID '{'
                                (features+=Feature)*	
                              '}';

                            Feature :
                              'attr' name=ID ':' type=[DataType];

                                                                                      9
Donnerstag, 16. Juli 2009
grammar org.xtext.workshop.DomainModel
                            	   with org.eclipse.xtext.common.Terminals

                            generate domainModel "http://www.xtext.org/DomainModel"

                            Model :
                            	   (types+=Type)+;
                            	
                            Type :
                              Class | DataType;               Unassigned rulecall


                            DataType :
                              'datatype' name=ID;          Assignment with rulecall

                            Class :
                            	   (abstract?='abstract')? 'class' name=ID '{'
                                (features+=Feature)*	
                              '}';                   Containment

                            Feature :
                              'attr' name=ID ':' type=[DataType];

                                                                                      9
Donnerstag, 16. Juli 2009
grammar org.xtext.workshop.DomainModel
                            	   with org.eclipse.xtext.common.Terminals

                            generate domainModel "http://www.xtext.org/DomainModel"

                            Model :
                            	   (types+=Type)+;
                            	
                            Type :
                              Class | DataType;               Unassigned rulecall


                            DataType :
                              'datatype' name=ID;          Assignment with rulecall

                            Class :
                            	   (abstract?='abstract')? 'class' name=ID '{'
                                (features+=Feature)*	
                              '}';                   Containment
                                                                    Cross reference
                            Feature :
                              'attr' name=ID ':' type=[DataType];

                                                                                      9
Donnerstag, 16. Juli 2009
Metamodel Inference
      grammar org.xtext.workshop.DomainModel
      	   with org.eclipse.xtext.common.Terminals

      generate domainModel
        "http://www.xtext.org/workshop/DomainModel"

      Model :
      	   (types+=Type)+;
      	
      Type :
        Class | DataType;

      DataType :
        'datatype' name=ID;

      Class :
      	   (abstract?='abstract')? 'class' name=ID '{'
          (features+=Feature)*	
        '}';

      Feature :
        'attr' name=ID ':' type=[DataType];

                                                        10
Donnerstag, 16. Juli 2009
Metamodel Inference
      grammar org.xtext.workshop.DomainModel
      	   with org.eclipse.xtext.common.Terminals

      generate domainModel
        "http://www.xtext.org/workshop/DomainModel"

      Model :
      	   (types+=Type)+;
      	
      Type :
        Class | DataType;

      DataType :
        'datatype' name=ID;

      Class :
      	   (abstract?='abstract')? 'class' name=ID '{'
          (features+=Feature)*	
        '}';

      Feature :
        'attr' name=ID ':' type=[DataType];

                                                        10
Donnerstag, 16. Juli 2009
Metamodel Inference
      grammar org.xtext.workshop.DomainModel
      	   with org.eclipse.xtext.common.Terminals

      generate domainModel
        "http://www.xtext.org/workshop/DomainModel"

      Model :
      	   (types+=Type)+;
      	
      Type :
        Class | DataType;

      DataType :
        'datatype' name=ID;

      Class :
      	   (abstract?='abstract')? 'class' name=ID '{'
          (features+=Feature)*	
        '}';

      Feature :
        'attr' name=ID ':' type=[DataType];

                                                        10
Donnerstag, 16. Juli 2009
Metamodel Inference
      grammar org.xtext.workshop.DomainModel
      	   with org.eclipse.xtext.common.Terminals

      generate domainModel
        "http://www.xtext.org/workshop/DomainModel"

      Model :
      	   (types+=Type)+;
      	
      Type :
        Class | DataType;

      DataType :
        'datatype' name=ID;

      Class :
      	   (abstract?='abstract')? 'class' name=ID '{'
          (features+=Feature)*	
        '}';

      Feature :
        'attr' name=ID ':' type=[DataType];

                                                        10
Donnerstag, 16. Juli 2009
Metamodel Inference
      grammar org.xtext.workshop.DomainModel
      	   with org.eclipse.xtext.common.Terminals

      generate domainModel
        "http://www.xtext.org/workshop/DomainModel"

      Model :
      	   (types+=Type)+;
      	
      Type :
        Class | DataType;

      DataType :
        'datatype' name=ID;

      Class :
      	   (abstract?='abstract')? 'class' name=ID '{'
          (features+=Feature)*	
        '}';

      Feature :
        'attr' name=ID ':' type=[DataType];

                                                        10
Donnerstag, 16. Juli 2009
Metamodel Inference
      grammar org.xtext.workshop.DomainModel
      	   with org.eclipse.xtext.common.Terminals

      generate domainModel
        "http://www.xtext.org/workshop/DomainModel"

      Model :
      	   (types+=Type)+;
      	
      Type :
        Class | DataType;

      DataType :
        'datatype' name=ID;

      Class :
      	   (abstract?='abstract')? 'class' name=ID '{'
          (features+=Feature)*	
        '}';

      Feature :
        'attr' name=ID ':' type=[DataType];

                                                        10
Donnerstag, 16. Juli 2009
Metamodel Inference
      grammar org.xtext.workshop.DomainModel
      	   with org.eclipse.xtext.common.Terminals

      generate domainModel
        "http://www.xtext.org/workshop/DomainModel"

      Model :
      	   (types+=Type)+;
      	
      Type :
        Class | DataType;

      DataType :
        'datatype' name=ID;

      Class :
      	   (abstract?='abstract')? 'class' name=ID '{'
          (features+=Feature)*	
        '}';

      Feature :
        'attr' name=ID ':' type=[DataType];

                                                        10
Donnerstag, 16. Juli 2009
Metamodel Inference
      grammar org.xtext.workshop.DomainModel
      	   with org.eclipse.xtext.common.Terminals

      generate domainModel
        "http://www.xtext.org/workshop/DomainModel"

      Model :
      	   (types+=Type)+;
      	
      Type :
        Class | DataType;

      DataType :
        'datatype' name=ID;

      Class :
      	   (abstract?='abstract')? 'class' name=ID '{'
          (features+=Feature)*	
        '}';

      Feature :
        'attr' name=ID ':' type=[DataType];

                                                        10
Donnerstag, 16. Juli 2009
licensed by http://www.wordle.net/
Donnerstag, 16. Juli 2009
Based on
              the grammar and Ecore models,
              Xtext provides you with sensible
                  default implementations.


                                          licensed by http://www.wordle.net/
Donnerstag, 16. Juli 2009
Flexibility
Donnerstag, 16. Juli 2009
licensed by http://www.wordle.net/
Donnerstag, 16. Juli 2009
Dependency management




                            licensed by http://www.wordle.net/
Donnerstag, 16. Juli 2009
Dependency management




                            licensed by http://www.wordle.net/
Donnerstag, 16. Juli 2009
Dependency management




                            licensed by http://www.wordle.net/
Donnerstag, 16. Juli 2009
Dependency management




                            licensed by http://www.wordle.net/
Donnerstag, 16. Juli 2009
Dependency management




                            licensed by http://www.wordle.net/
Donnerstag, 16. Juli 2009
MyCustomLabelProvider




                                        licensed by http://www.wordle.net/
Donnerstag, 16. Juli 2009
Dependency Injection
                     with Google fGuice




Donnerstag, 16. Juli 2009
Dependency Injection
                     with Google fGuice




Donnerstag, 16. Juli 2009
Dependency Injection
                     with Google fGuice




           ‣No dependency to concrete implementation



Donnerstag, 16. Juli 2009
Dependency Injection
                     with Google fGuice




           ‣No dependency to concrete implementation
           ‣No explicit construction


Donnerstag, 16. Juli 2009
Dependency Injection
                     with Google fGuice




           ‣No dependency to concrete implementation
           ‣No explicit construction
           ‣Easy testing

Donnerstag, 16. Juli 2009
Dependency Injection
                     with Google fGuice




           ‣No dependency to concrete implementation
           ‣No explicit construction
           ‣Easy testing
           ‣Easy composition
Donnerstag, 16. Juli 2009
Configuration of
                      Components in Xtext
         /**
           * used to register components to be used within the IDE.
           */
         public class DomainmodelUiModule
         	 	 extends GeneratedDomainmodelUiModule {
         	
         	 @Override
         	 public Class<? extends ILabelProvider> bindILabelProvider() {
         	 	 return MySpecialLabelProvider.class;
         	 }
         }




Donnerstag, 16. Juli 2009
Composable
                                Code Generator
                            ‣ Generator is composed of “fragments”




Donnerstag, 16. Juli 2009
Composable
                                Code Generator
                            ‣ Generator is composed of “fragments”
                            ‣ Fragments can contribute to:




Donnerstag, 16. Juli 2009
Composable
                                Code Generator
                            ‣ Generator is composed of “fragments”
                            ‣ Fragments can contribute to:
                             ‣ Manifest.MF



Donnerstag, 16. Juli 2009
Composable
                                Code Generator
                            ‣ Generator is composed of “fragments”
                            ‣ Fragments can contribute to:
                             ‣ Manifest.MF
                             ‣ plugin.xml


Donnerstag, 16. Juli 2009
Composable
                                Code Generator
                            ‣ Generator is composed of “fragments”
                            ‣ Fragments can contribute to:
                             ‣ Manifest.MF
                             ‣ plugin.xml
                             ‣ Guice modules

Donnerstag, 16. Juli 2009
Composable
                                Code Generator
                            ‣ Generator is composed of “fragments”
                            ‣ Fragments can contribute to:
                             ‣ Manifest.MF
                             ‣ plugin.xml
                             ‣ Guice modules
                            ‣ Add your own fragments
Donnerstag, 16. Juli 2009
UseCase
                            Migrating existing Apps




Donnerstag, 16. Juli 2009
Starting point



         • DB-Application
         • Oracle DB
         • OracleForms
Donnerstag, 16. Juli 2009
Target



          • Oracle DB
          • Java Rich Client
          • JPA
          • Spring
          • Swing / JGoodies Forms
Donnerstag, 16. Juli 2009
Quantities




Donnerstag, 16. Juli 2009
Quantities
                • 1700++ Tables




Donnerstag, 16. Juli 2009
Quantities
                • 1700++ Tables
                • 19500++ Columns




Donnerstag, 16. Juli 2009
Quantities
                • 1700++ Tables
                • 19500++ Columns
                • 300++ Forms




Donnerstag, 16. Juli 2009
Quantities
                • 1700++ Tables
                • 19500++ Columns
                • 300++ Forms

            Task


Donnerstag, 16. Juli 2009
Quantities
                • 1700++ Tables
                • 19500++ Columns
                • 300++ Forms

            Task
                 • Find abstractions

Donnerstag, 16. Juli 2009
Quantities
                • 1700++ Tables
                • 19500++ Columns
                • 300++ Forms

            Task
                 • Find abstractions
                 • Simplify code
Donnerstag, 16. Juli 2009
@SuppressWarnings("serial")
          @Entity
           Entity
          @Table(name = "BUCHUNGSKREISE_F")
                         BUCHUNGSKREISE_F
          public class BuchungskreiseF extends AbstractEntity implements Serializable {
          	

          	     @SuppressWarnings("unused")
          	     @Id
                 Id
          	     @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "bkrIdSeq")
          	     @SequenceGenerator(name = "bkrIdSeq", sequenceName = "BKR_SEQ", allocationSize = 1)
                                                                      BKR_SEQ
          	     @Column(name = "BKR_ID", nullable = false
                                BKR_ID              false)
          	     private Long bkrId
                             bkrId;

          	     public Long getBkrId() {
          	     	   return bkrId;
          	     }

          	     public void setBkrId(final Long bkrId) {
          	     	   this.bkrId = bkrId;
          	     }

          	     @Column(name = "KONTO_NR", nullable = false length = 45
                                KONTO_NR              false,         45)
          	     private String kontoNr;
                               kontoNr

          	     public String getKontoNr() {
          	     	   return kontoNr;
          	     }

          	     public void setKontoNr(final String kontoNr) {
          	     	   String oldValue = this.kontoNr;
          	     	   this.kontoNr = kontoNr;
          	     	   firePropertyChangeEvent("kontoNr", oldValue, this.kontoNr);
          	     }
Donnerstag, 16. Juli 2009
@SuppressWarnings("serial")
          @Entity
           Entity
          @Table(name = "BUCHUNGSKREISE_F")
                         BUCHUNGSKREISE_F
          public class BuchungskreiseF extends AbstractEntity implements Serializable {
          	

          	     @SuppressWarnings("unused")
          	     @Id
                 Id
          	     @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "bkrIdSeq")
          	     @SequenceGenerator(name = "bkrIdSeq", sequenceName = "BKR_SEQ", allocationSize = 1)
                                                                      BKR_SEQ
          	     @Column(name = "BKR_ID", nullable = false
                                BKR_ID              false)
          	     private Long bkrId
                             bkrId;

          	     public Long getBkrId() {
          	     	   return bkrId;
          	     }

          	     public void setBkrId(final Long bkrId) {
          	     	   this.bkrId = bkrId;
          	     }

          	     @Column(name = "KONTO_NR", nullable = false length = 45
                                KONTO_NR              false,         45)
          	     private String kontoNr;
                               kontoNr

          	     public String getKontoNr() {
          	     	   return kontoNr;
          	     }

          	     public void setKontoNr(final String kontoNr) {
          	     	   String oldValue = this.kontoNr;
          	     	   this.kontoNr = kontoNr;
          	     	   firePropertyChangeEvent("kontoNr", oldValue, this.kontoNr);
          	     }
Donnerstag, 16. Juli 2009
External DSL for Entities

               entity BuchungskreiseF
                (id=bkrId sequenceName=BKR_SEQ) {

                   String kontoNr   (notNull, length=45)

                   Long rgNrBkrIdentifikator    (notNull, length=1)

                   String referenzcodeKontoNr (notNull, length=45)

               }


Donnerstag, 16. Juli 2009
External DSL for Entities

               entity BuchungskreiseF
                (id=bkrId sequenceName=BKR_SEQ) {

                   String kontoNr

                   Long rgNrBkrIdentifikator

                   String referenzcodeKontoNr

               }


Donnerstag, 16. Juli 2009
External DSL for Entities
                                              BUCHUNGSKREISE_F

               entity BuchungskreiseF
                (id=bkrId sequenceName=BKR_SEQ) {

                   String kontoNr
                                                  RG_NR_BKR_IDENTIFIKATOR

                   Long rgNrBkrIdentifikator

                   String referenzcodeKontoNr

               }


Donnerstag, 16. Juli 2009
Validation
Donnerstag, 16. Juli 2009
Donnerstag, 16. Juli 2009
addValidator(new Validator<Institutionen>() {
     	 	 	 @Override
     	 	 	 public ValidationResult validate(final Institutionen institution) {
     	 	 	 	 final ValidationResult result = new ValidationResult();
     	 	 	 	 if (institution != null
                       && institution.getEsrNr() != null
     	 	 	 	 	          && !CheckUtils.checkPcKontoNrPruefziffer(
                             Long.parseLong(institution.getEsrNr())) {
     	 	 	 	 	 result.add(new SimpleValidationMessage(
                             getResourceMap().getString("validation.esr.msg"),
                             Severity.ERROR, getModel(Institutionen.DESC.esrNr())));
     	 	 	 	 }
     	 	 	 	 return result;
     	 	 	 }
     	 	 });




Donnerstag, 16. Juli 2009
Framework-Code




     addValidator(new Validator<Institutionen>() {
     	 	 	 @Override
     	 	 	 public ValidationResult validate(final Institutionen institution) {
     	 	 	 	 final ValidationResult result = new ValidationResult();
     	 	 	 	 if (institution != null
                       && institution.getEsrNr() != null
     	 	 	 	 	          && !CheckUtils.checkPcKontoNrPruefziffer(
                             Long.parseLong(institution.getEsrNr())) {
     	 	 	 	 	 result.add(new SimpleValidationMessage(
                             getResourceMap().getString("validation.esr.msg"),
                             Severity.ERROR, getModel(Institutionen.DESC.esrNr())));
     	 	 	 	 }
     	 	 	 	 return result;
     	 	 	 }
     	 	 });




Donnerstag, 16. Juli 2009
Framework-Code
     Nullpointer abfragen



     addValidator(new Validator<Institutionen>() {
     	 	 	 @Override
     	 	 	 public ValidationResult validate(final Institutionen institution) {
     	 	 	 	 final ValidationResult result = new ValidationResult();
     	 	 	 	 if (institution != null
                       && institution.getEsrNr() != null
     	 	 	 	 	          && !CheckUtils.checkPcKontoNrPruefziffer(
                             Long.parseLong(institution.getEsrNr())) {
     	 	 	 	 	 result.add(new SimpleValidationMessage(
                             getResourceMap().getString("validation.esr.msg"),
                             Severity.ERROR, getModel(Institutionen.DESC.esrNr())));
     	 	 	 	 }
     	 	 	 	 return result;
     	 	 	 }
     	 	 });




Donnerstag, 16. Juli 2009
Framework-Code
     Nullpointer abfragen
     Static imports

     addValidator(new Validator<Institutionen>() {
     	 	 	 @Override
     	 	 	 public ValidationResult validate(final Institutionen institution) {
     	 	 	 	 final ValidationResult result = new ValidationResult();
     	 	 	 	 if (institution != null
                       && institution.getEsrNr() != null
     	 	 	 	 	          && !CheckUtils.checkPcKontoNrPruefziffer(
                             Long.parseLong(institution.getEsrNr())) {
     	 	 	 	 	 result.add(new SimpleValidationMessage(
                             getResourceMap().getString("validation.esr.msg"),
                             Severity.ERROR, getModel(Institutionen.DESC.esrNr())));
     	 	 	 	 }
     	 	 	 	 return result;
     	 	 	 }
     	 	 });




Donnerstag, 16. Juli 2009
Framework-Code
     Nullpointer abfragen
     Static imports
     Bibliotheks Methoden definieren und benutzen
     addValidator(new Validator<Institutionen>() {
     	 	 	 @Override
     	 	 	 public ValidationResult validate(final Institutionen institution) {
     	 	 	 	 final ValidationResult result = new ValidationResult();
     	 	 	 	 if (institution != null
                       && institution.getEsrNr() != null
     	 	 	 	 	          && !CheckUtils.checkPcKontoNrPruefziffer(
                             Long.parseLong(institution.getEsrNr())) {
     	 	 	 	 	 result.add(new SimpleValidationMessage(
                      error("validation.esr.msg", desc.esrNr());
                             getResourceMap().getString("validation.esr.msg"),
                             Severity.ERROR, getModel(Institutionen.DESC.esrNr())));
     	 	 	 	 }
     	 	 	 	 return result;
     	 	 	 }
     	 	 });




Donnerstag, 16. Juli 2009
Internal DSL with Java
       	     @Check
             void checkEsrMsg() {
       	     	 if (!checkKontoNrPruefziffer(parseLong(_this.getEsrNr())))
       	     	 	 error("validation.esr.msg",desc.esrNr());
       	     }


                      • JUnit-like
                      • Ignore Nullpointer-Exceptions



Donnerstag, 16. Juli 2009
Future Plans
Donnerstag, 16. Juli 2009
Eclipse Helios




Donnerstag, 16. Juli 2009
Eclipse Helios
        •       Model Index




Donnerstag, 16. Juli 2009
Eclipse Helios
        •       Model Index
        • Grammar Mixins




Donnerstag, 16. Juli 2009
Eclipse Helios
        •       Model Index
        • Grammar Mixins
        • Base Language




Donnerstag, 16. Juli 2009
Eclipse Helios
        •       Model Index
        • Grammar Mixins
        • Base Language
        • UI Features



Donnerstag, 16. Juli 2009
Eclipse Helios
        •       Model Index
        • Grammar Mixins
        • Base Language
        • UI Features
        • Documentation

Donnerstag, 16. Juli 2009
Donnerstag, 16. Juli 2009
Thank you very much for listening

       Visit the project’s web site :
              www.xtext.org


                            Copyright 2009 by itemis




Donnerstag, 16. Juli 2009
Thank you very much for listening

       Visit the project’sWebinar :
                    Xtext web site
              www.xtext.org19:00
                   Tomorrow
                      http://live.eclipse.org/node/705


                            Copyright 2009 by itemis




Donnerstag, 16. Juli 2009

Textual Modeling Framework Xtext

  • 1.
    Textual Modeling Framework Sven Efftinge, Sebastian Zarnekow itemis Donnerstag, 16. Juli 2009
  • 2.
  • 3.
    Domain-Specific Language (DSL) A DSL is a formal, processable language targeting at a specific viewpoint or aspect of a software system. Donnerstag, 16. Juli 2009
  • 4.
    Domain-Specific Language (DSL) A DSL is a formal, processable language targeting at a specific viewpoint or aspect of a software system. It’s semantics, flexibility and notation is designed in order to support working with that viewpoint as good as possible. Donnerstag, 16. Juli 2009
  • 5.
  • 6.
    Why DSLs? • higher abstractions Donnerstag, 16. Juli 2009
  • 7.
    Why DSLs? • higher abstractions • avoid redundancy Donnerstag, 16. Juli 2009
  • 8.
    Why DSLs? • higher abstractions • avoid redundancy • separation of concerns Donnerstag, 16. Juli 2009
  • 9.
    Why DSLs? • higher abstractions • avoid redundancy • separation of concerns • use domain concepts (Ubiquitous Language) Donnerstag, 16. Juli 2009
  • 10.
  • 11.
  • 12.
    Complicated & Expensive? Donnerstag, 16. Juli 2009
  • 13.
  • 14.
    How we addressthis with Donnerstag, 16. Juli 2009
  • 15.
  • 16.
    grammar org.xtext.workshop.DomainModel with org.eclipse.xtext.common.Terminals generate domainModel "http://www.xtext.org/DomainModel" Model : (types+=Type)+; Type : Class | DataType; DataType : 'datatype' name=ID; Class : (abstract?='abstract')? 'class' name=ID '{' (features+=Feature)* '}'; Feature : 'attr' name=ID ':' type=[DataType]; 9 Donnerstag, 16. Juli 2009
  • 17.
    Grammar grammar org.xtext.workshop.DomainModel definition with org.eclipse.xtext.common.Terminals generate domainModel "http://www.xtext.org/DomainModel" Model : (types+=Type)+; Type : Class | DataType; DataType : 'datatype' name=ID; Class : (abstract?='abstract')? 'class' name=ID '{' (features+=Feature)* '}'; Feature : 'attr' name=ID ':' type=[DataType]; 9 Donnerstag, 16. Juli 2009
  • 18.
    Grammar grammar org.xtext.workshop.DomainModel Grammar reuse definition with org.eclipse.xtext.common.Terminals generate domainModel "http://www.xtext.org/DomainModel" Model : (types+=Type)+; Type : Class | DataType; DataType : 'datatype' name=ID; Class : (abstract?='abstract')? 'class' name=ID '{' (features+=Feature)* '}'; Feature : 'attr' name=ID ':' type=[DataType]; 9 Donnerstag, 16. Juli 2009
  • 19.
    grammar org.xtext.workshop.DomainModel with org.eclipse.xtext.common.Terminals Derived generate domainModel "http://www.xtext.org/DomainModel" metamodel Model : (types+=Type)+; Type : Class | DataType; DataType : 'datatype' name=ID; Class : (abstract?='abstract')? 'class' name=ID '{' (features+=Feature)* '}'; Feature : 'attr' name=ID ':' type=[DataType]; 9 Donnerstag, 16. Juli 2009
  • 20.
    grammar org.xtext.workshop.DomainModel with org.eclipse.xtext.common.Terminals generate domainModel "http://www.xtext.org/DomainModel" Model : (types+=Type)+; Parser rules Type : Class | DataType; DataType : 'datatype' name=ID; Class : (abstract?='abstract')? 'class' name=ID '{' (features+=Feature)* '}'; Feature : 'attr' name=ID ':' type=[DataType]; 9 Donnerstag, 16. Juli 2009
  • 21.
    grammar org.xtext.workshop.DomainModel with org.eclipse.xtext.common.Terminals generate domainModel "http://www.xtext.org/DomainModel" Model : (types+=Type)+; Parser rules Type : Class | DataType; DataType : 'datatype' name=ID; Class : (abstract?='abstract')? 'class' name=ID '{' (features+=Feature)* Keywords '}'; Feature : 'attr' name=ID ':' type=[DataType]; 9 Donnerstag, 16. Juli 2009
  • 22.
    grammar org.xtext.workshop.DomainModel with org.eclipse.xtext.common.Terminals generate domainModel "http://www.xtext.org/DomainModel" Multivalue assignment Model : (types+=Type)+; Type : Class | DataType; Simple assigment DataType : 'datatype' name=ID; Boolean assigment Class : (abstract?='abstract')? 'class' name=ID '{' (features+=Feature)* '}'; Feature : 'attr' name=ID ':' type=[DataType]; 9 Donnerstag, 16. Juli 2009
  • 23.
    grammar org.xtext.workshop.DomainModel with org.eclipse.xtext.common.Terminals generate domainModel "http://www.xtext.org/DomainModel" Model : (types+=Type)+; Cardinality (one or more) Type : Class | DataType; DataType : 'datatype' name=ID; Class : Optional Element (abstract?='abstract')? 'class' name=ID '{' (features+=Feature)* Cardinality (zero or more) '}'; Feature : 'attr' name=ID ':' type=[DataType]; 9 Donnerstag, 16. Juli 2009
  • 24.
    grammar org.xtext.workshop.DomainModel with org.eclipse.xtext.common.Terminals generate domainModel "http://www.xtext.org/DomainModel" Model : (types+=Type)+; Cardinality (one or more) Alternative Type : Class | DataType; DataType : 'datatype' name=ID; Class : Optional Element (abstract?='abstract')? 'class' name=ID '{' (features+=Feature)* Cardinality (zero or more) '}'; Feature : 'attr' name=ID ':' type=[DataType]; 9 Donnerstag, 16. Juli 2009
  • 25.
    grammar org.xtext.workshop.DomainModel with org.eclipse.xtext.common.Terminals generate domainModel "http://www.xtext.org/DomainModel" Model : (types+=Type)+; Type : Class | DataType; DataType : 'datatype' name=ID; Assignment with rulecall Class : (abstract?='abstract')? 'class' name=ID '{' (features+=Feature)* '}'; Feature : 'attr' name=ID ':' type=[DataType]; 9 Donnerstag, 16. Juli 2009
  • 26.
    grammar org.xtext.workshop.DomainModel with org.eclipse.xtext.common.Terminals generate domainModel "http://www.xtext.org/DomainModel" Model : (types+=Type)+; Type : Class | DataType; Unassigned rulecall DataType : 'datatype' name=ID; Assignment with rulecall Class : (abstract?='abstract')? 'class' name=ID '{' (features+=Feature)* '}'; Feature : 'attr' name=ID ':' type=[DataType]; 9 Donnerstag, 16. Juli 2009
  • 27.
    grammar org.xtext.workshop.DomainModel with org.eclipse.xtext.common.Terminals generate domainModel "http://www.xtext.org/DomainModel" Model : (types+=Type)+; Type : Class | DataType; Unassigned rulecall DataType : 'datatype' name=ID; Assignment with rulecall Class : (abstract?='abstract')? 'class' name=ID '{' (features+=Feature)* '}'; Containment Feature : 'attr' name=ID ':' type=[DataType]; 9 Donnerstag, 16. Juli 2009
  • 28.
    grammar org.xtext.workshop.DomainModel with org.eclipse.xtext.common.Terminals generate domainModel "http://www.xtext.org/DomainModel" Model : (types+=Type)+; Type : Class | DataType; Unassigned rulecall DataType : 'datatype' name=ID; Assignment with rulecall Class : (abstract?='abstract')? 'class' name=ID '{' (features+=Feature)* '}'; Containment Cross reference Feature : 'attr' name=ID ':' type=[DataType]; 9 Donnerstag, 16. Juli 2009
  • 29.
    Metamodel Inference grammar org.xtext.workshop.DomainModel with org.eclipse.xtext.common.Terminals generate domainModel "http://www.xtext.org/workshop/DomainModel" Model : (types+=Type)+; Type : Class | DataType; DataType : 'datatype' name=ID; Class : (abstract?='abstract')? 'class' name=ID '{' (features+=Feature)* '}'; Feature : 'attr' name=ID ':' type=[DataType]; 10 Donnerstag, 16. Juli 2009
  • 30.
    Metamodel Inference grammar org.xtext.workshop.DomainModel with org.eclipse.xtext.common.Terminals generate domainModel "http://www.xtext.org/workshop/DomainModel" Model : (types+=Type)+; Type : Class | DataType; DataType : 'datatype' name=ID; Class : (abstract?='abstract')? 'class' name=ID '{' (features+=Feature)* '}'; Feature : 'attr' name=ID ':' type=[DataType]; 10 Donnerstag, 16. Juli 2009
  • 31.
    Metamodel Inference grammar org.xtext.workshop.DomainModel with org.eclipse.xtext.common.Terminals generate domainModel "http://www.xtext.org/workshop/DomainModel" Model : (types+=Type)+; Type : Class | DataType; DataType : 'datatype' name=ID; Class : (abstract?='abstract')? 'class' name=ID '{' (features+=Feature)* '}'; Feature : 'attr' name=ID ':' type=[DataType]; 10 Donnerstag, 16. Juli 2009
  • 32.
    Metamodel Inference grammar org.xtext.workshop.DomainModel with org.eclipse.xtext.common.Terminals generate domainModel "http://www.xtext.org/workshop/DomainModel" Model : (types+=Type)+; Type : Class | DataType; DataType : 'datatype' name=ID; Class : (abstract?='abstract')? 'class' name=ID '{' (features+=Feature)* '}'; Feature : 'attr' name=ID ':' type=[DataType]; 10 Donnerstag, 16. Juli 2009
  • 33.
    Metamodel Inference grammar org.xtext.workshop.DomainModel with org.eclipse.xtext.common.Terminals generate domainModel "http://www.xtext.org/workshop/DomainModel" Model : (types+=Type)+; Type : Class | DataType; DataType : 'datatype' name=ID; Class : (abstract?='abstract')? 'class' name=ID '{' (features+=Feature)* '}'; Feature : 'attr' name=ID ':' type=[DataType]; 10 Donnerstag, 16. Juli 2009
  • 34.
    Metamodel Inference grammar org.xtext.workshop.DomainModel with org.eclipse.xtext.common.Terminals generate domainModel "http://www.xtext.org/workshop/DomainModel" Model : (types+=Type)+; Type : Class | DataType; DataType : 'datatype' name=ID; Class : (abstract?='abstract')? 'class' name=ID '{' (features+=Feature)* '}'; Feature : 'attr' name=ID ':' type=[DataType]; 10 Donnerstag, 16. Juli 2009
  • 35.
    Metamodel Inference grammar org.xtext.workshop.DomainModel with org.eclipse.xtext.common.Terminals generate domainModel "http://www.xtext.org/workshop/DomainModel" Model : (types+=Type)+; Type : Class | DataType; DataType : 'datatype' name=ID; Class : (abstract?='abstract')? 'class' name=ID '{' (features+=Feature)* '}'; Feature : 'attr' name=ID ':' type=[DataType]; 10 Donnerstag, 16. Juli 2009
  • 36.
    Metamodel Inference grammar org.xtext.workshop.DomainModel with org.eclipse.xtext.common.Terminals generate domainModel "http://www.xtext.org/workshop/DomainModel" Model : (types+=Type)+; Type : Class | DataType; DataType : 'datatype' name=ID; Class : (abstract?='abstract')? 'class' name=ID '{' (features+=Feature)* '}'; Feature : 'attr' name=ID ':' type=[DataType]; 10 Donnerstag, 16. Juli 2009
  • 37.
  • 38.
    Based on the grammar and Ecore models, Xtext provides you with sensible default implementations. licensed by http://www.wordle.net/ Donnerstag, 16. Juli 2009
  • 39.
  • 40.
  • 41.
    Dependency management licensed by http://www.wordle.net/ Donnerstag, 16. Juli 2009
  • 42.
    Dependency management licensed by http://www.wordle.net/ Donnerstag, 16. Juli 2009
  • 43.
    Dependency management licensed by http://www.wordle.net/ Donnerstag, 16. Juli 2009
  • 44.
    Dependency management licensed by http://www.wordle.net/ Donnerstag, 16. Juli 2009
  • 45.
    Dependency management licensed by http://www.wordle.net/ Donnerstag, 16. Juli 2009
  • 46.
    MyCustomLabelProvider licensed by http://www.wordle.net/ Donnerstag, 16. Juli 2009
  • 47.
    Dependency Injection with Google fGuice Donnerstag, 16. Juli 2009
  • 48.
    Dependency Injection with Google fGuice Donnerstag, 16. Juli 2009
  • 49.
    Dependency Injection with Google fGuice ‣No dependency to concrete implementation Donnerstag, 16. Juli 2009
  • 50.
    Dependency Injection with Google fGuice ‣No dependency to concrete implementation ‣No explicit construction Donnerstag, 16. Juli 2009
  • 51.
    Dependency Injection with Google fGuice ‣No dependency to concrete implementation ‣No explicit construction ‣Easy testing Donnerstag, 16. Juli 2009
  • 52.
    Dependency Injection with Google fGuice ‣No dependency to concrete implementation ‣No explicit construction ‣Easy testing ‣Easy composition Donnerstag, 16. Juli 2009
  • 53.
    Configuration of Components in Xtext /** * used to register components to be used within the IDE. */ public class DomainmodelUiModule extends GeneratedDomainmodelUiModule { @Override public Class<? extends ILabelProvider> bindILabelProvider() { return MySpecialLabelProvider.class; } } Donnerstag, 16. Juli 2009
  • 54.
    Composable Code Generator ‣ Generator is composed of “fragments” Donnerstag, 16. Juli 2009
  • 55.
    Composable Code Generator ‣ Generator is composed of “fragments” ‣ Fragments can contribute to: Donnerstag, 16. Juli 2009
  • 56.
    Composable Code Generator ‣ Generator is composed of “fragments” ‣ Fragments can contribute to: ‣ Manifest.MF Donnerstag, 16. Juli 2009
  • 57.
    Composable Code Generator ‣ Generator is composed of “fragments” ‣ Fragments can contribute to: ‣ Manifest.MF ‣ plugin.xml Donnerstag, 16. Juli 2009
  • 58.
    Composable Code Generator ‣ Generator is composed of “fragments” ‣ Fragments can contribute to: ‣ Manifest.MF ‣ plugin.xml ‣ Guice modules Donnerstag, 16. Juli 2009
  • 59.
    Composable Code Generator ‣ Generator is composed of “fragments” ‣ Fragments can contribute to: ‣ Manifest.MF ‣ plugin.xml ‣ Guice modules ‣ Add your own fragments Donnerstag, 16. Juli 2009
  • 60.
    UseCase Migrating existing Apps Donnerstag, 16. Juli 2009
  • 61.
    Starting point • DB-Application • Oracle DB • OracleForms Donnerstag, 16. Juli 2009
  • 62.
    Target • Oracle DB • Java Rich Client • JPA • Spring • Swing / JGoodies Forms Donnerstag, 16. Juli 2009
  • 63.
  • 64.
    Quantities • 1700++ Tables Donnerstag, 16. Juli 2009
  • 65.
    Quantities • 1700++ Tables • 19500++ Columns Donnerstag, 16. Juli 2009
  • 66.
    Quantities • 1700++ Tables • 19500++ Columns • 300++ Forms Donnerstag, 16. Juli 2009
  • 67.
    Quantities • 1700++ Tables • 19500++ Columns • 300++ Forms Task Donnerstag, 16. Juli 2009
  • 68.
    Quantities • 1700++ Tables • 19500++ Columns • 300++ Forms Task • Find abstractions Donnerstag, 16. Juli 2009
  • 69.
    Quantities • 1700++ Tables • 19500++ Columns • 300++ Forms Task • Find abstractions • Simplify code Donnerstag, 16. Juli 2009
  • 70.
    @SuppressWarnings("serial") @Entity Entity @Table(name = "BUCHUNGSKREISE_F") BUCHUNGSKREISE_F public class BuchungskreiseF extends AbstractEntity implements Serializable { @SuppressWarnings("unused") @Id Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "bkrIdSeq") @SequenceGenerator(name = "bkrIdSeq", sequenceName = "BKR_SEQ", allocationSize = 1) BKR_SEQ @Column(name = "BKR_ID", nullable = false BKR_ID false) private Long bkrId bkrId; public Long getBkrId() { return bkrId; } public void setBkrId(final Long bkrId) { this.bkrId = bkrId; } @Column(name = "KONTO_NR", nullable = false length = 45 KONTO_NR false, 45) private String kontoNr; kontoNr public String getKontoNr() { return kontoNr; } public void setKontoNr(final String kontoNr) { String oldValue = this.kontoNr; this.kontoNr = kontoNr; firePropertyChangeEvent("kontoNr", oldValue, this.kontoNr); } Donnerstag, 16. Juli 2009
  • 71.
    @SuppressWarnings("serial") @Entity Entity @Table(name = "BUCHUNGSKREISE_F") BUCHUNGSKREISE_F public class BuchungskreiseF extends AbstractEntity implements Serializable { @SuppressWarnings("unused") @Id Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "bkrIdSeq") @SequenceGenerator(name = "bkrIdSeq", sequenceName = "BKR_SEQ", allocationSize = 1) BKR_SEQ @Column(name = "BKR_ID", nullable = false BKR_ID false) private Long bkrId bkrId; public Long getBkrId() { return bkrId; } public void setBkrId(final Long bkrId) { this.bkrId = bkrId; } @Column(name = "KONTO_NR", nullable = false length = 45 KONTO_NR false, 45) private String kontoNr; kontoNr public String getKontoNr() { return kontoNr; } public void setKontoNr(final String kontoNr) { String oldValue = this.kontoNr; this.kontoNr = kontoNr; firePropertyChangeEvent("kontoNr", oldValue, this.kontoNr); } Donnerstag, 16. Juli 2009
  • 72.
    External DSL forEntities entity BuchungskreiseF (id=bkrId sequenceName=BKR_SEQ) { String kontoNr (notNull, length=45) Long rgNrBkrIdentifikator (notNull, length=1) String referenzcodeKontoNr (notNull, length=45) } Donnerstag, 16. Juli 2009
  • 73.
    External DSL forEntities entity BuchungskreiseF (id=bkrId sequenceName=BKR_SEQ) { String kontoNr Long rgNrBkrIdentifikator String referenzcodeKontoNr } Donnerstag, 16. Juli 2009
  • 74.
    External DSL forEntities BUCHUNGSKREISE_F entity BuchungskreiseF (id=bkrId sequenceName=BKR_SEQ) { String kontoNr RG_NR_BKR_IDENTIFIKATOR Long rgNrBkrIdentifikator String referenzcodeKontoNr } Donnerstag, 16. Juli 2009
  • 75.
  • 76.
  • 77.
    addValidator(new Validator<Institutionen>() { @Override public ValidationResult validate(final Institutionen institution) { final ValidationResult result = new ValidationResult(); if (institution != null && institution.getEsrNr() != null && !CheckUtils.checkPcKontoNrPruefziffer( Long.parseLong(institution.getEsrNr())) { result.add(new SimpleValidationMessage( getResourceMap().getString("validation.esr.msg"), Severity.ERROR, getModel(Institutionen.DESC.esrNr()))); } return result; } }); Donnerstag, 16. Juli 2009
  • 78.
    Framework-Code addValidator(new Validator<Institutionen>() { @Override public ValidationResult validate(final Institutionen institution) { final ValidationResult result = new ValidationResult(); if (institution != null && institution.getEsrNr() != null && !CheckUtils.checkPcKontoNrPruefziffer( Long.parseLong(institution.getEsrNr())) { result.add(new SimpleValidationMessage( getResourceMap().getString("validation.esr.msg"), Severity.ERROR, getModel(Institutionen.DESC.esrNr()))); } return result; } }); Donnerstag, 16. Juli 2009
  • 79.
    Framework-Code Nullpointer abfragen addValidator(new Validator<Institutionen>() { @Override public ValidationResult validate(final Institutionen institution) { final ValidationResult result = new ValidationResult(); if (institution != null && institution.getEsrNr() != null && !CheckUtils.checkPcKontoNrPruefziffer( Long.parseLong(institution.getEsrNr())) { result.add(new SimpleValidationMessage( getResourceMap().getString("validation.esr.msg"), Severity.ERROR, getModel(Institutionen.DESC.esrNr()))); } return result; } }); Donnerstag, 16. Juli 2009
  • 80.
    Framework-Code Nullpointer abfragen Static imports addValidator(new Validator<Institutionen>() { @Override public ValidationResult validate(final Institutionen institution) { final ValidationResult result = new ValidationResult(); if (institution != null && institution.getEsrNr() != null && !CheckUtils.checkPcKontoNrPruefziffer( Long.parseLong(institution.getEsrNr())) { result.add(new SimpleValidationMessage( getResourceMap().getString("validation.esr.msg"), Severity.ERROR, getModel(Institutionen.DESC.esrNr()))); } return result; } }); Donnerstag, 16. Juli 2009
  • 81.
    Framework-Code Nullpointer abfragen Static imports Bibliotheks Methoden definieren und benutzen addValidator(new Validator<Institutionen>() { @Override public ValidationResult validate(final Institutionen institution) { final ValidationResult result = new ValidationResult(); if (institution != null && institution.getEsrNr() != null && !CheckUtils.checkPcKontoNrPruefziffer( Long.parseLong(institution.getEsrNr())) { result.add(new SimpleValidationMessage( error("validation.esr.msg", desc.esrNr()); getResourceMap().getString("validation.esr.msg"), Severity.ERROR, getModel(Institutionen.DESC.esrNr()))); } return result; } }); Donnerstag, 16. Juli 2009
  • 82.
    Internal DSL withJava @Check void checkEsrMsg() { if (!checkKontoNrPruefziffer(parseLong(_this.getEsrNr()))) error("validation.esr.msg",desc.esrNr()); } • JUnit-like • Ignore Nullpointer-Exceptions Donnerstag, 16. Juli 2009
  • 83.
  • 84.
  • 85.
    Eclipse Helios • Model Index Donnerstag, 16. Juli 2009
  • 86.
    Eclipse Helios • Model Index • Grammar Mixins Donnerstag, 16. Juli 2009
  • 87.
    Eclipse Helios • Model Index • Grammar Mixins • Base Language Donnerstag, 16. Juli 2009
  • 88.
    Eclipse Helios • Model Index • Grammar Mixins • Base Language • UI Features Donnerstag, 16. Juli 2009
  • 89.
    Eclipse Helios • Model Index • Grammar Mixins • Base Language • UI Features • Documentation Donnerstag, 16. Juli 2009
  • 90.
  • 91.
    Thank you verymuch for listening Visit the project’s web site : www.xtext.org Copyright 2009 by itemis Donnerstag, 16. Juli 2009
  • 92.
    Thank you verymuch for listening Visit the project’sWebinar : Xtext web site www.xtext.org19:00 Tomorrow http://live.eclipse.org/node/705 Copyright 2009 by itemis Donnerstag, 16. Juli 2009