I delivered this presentation at the Eclipse Modeling Days in NYC and Toronto, Ca: http://wiki.eclipse.org/Eclipse_Modeling_Day in November 2009.
The slides are based on the ones Jan Koehnlein presented at the Eclipse Summit Europe 09.
5. Modeling?
Should we model or code?
Real programmers write code!
Modeling is something the architect does.
6. Modeling?
Should we model or code?
Real programmers write code!
Modeling is something the architect does.
Models are graphical!
7. Modeling?
Should we model or code?
Real programmers write code!
Modeling is something the architect does.
Models are graphical!
I model on my whiteboard.
8. Modeling?
Should we model or code?
Real programmers write code!
Modeling is something the architect does.
Models are graphical!
I model on my whiteboard.
This doesn’t lead us anywhere!
10. Let’s take a step back
It’s about having the right notation for the job.
11. Let’s take a step back
It’s about having the right notation for the job.
It would be nice if we could just run it.
12. Let’s take a step back
sounds like a
language
It’s about having the right notation for the job.
It would be nice if we could just run it.
13. Let’s take a step back
sounds like a sounds like it is specific to
language the job’s domain
It’s about having the right notation for the job.
It would be nice if we could just run it.
14. Let’s take a step back
sounds like a sounds like it is specific to
language the job’s domain
It’s about having the right notation for the job.
It would be nice if we could just run it.
it needs to be
formal!
16. The Right Notation
The Right Notation
• Whether we call it a model or not doesn’t matter
17. The Right Notation
The Right Notation
• Whether we call it a model or not doesn’t matter
• However, tools from Eclipse Modeling help to build
tooling for this notation
18. The Right Notation
The Right Notation
• Whether we call it a model or not doesn’t matter
• However, tools from Eclipse Modeling help to build
tooling for this notation
• Instances of this notation are a primary artifact of your
software
19. The Right Notation
The Right Notation
• Whether we call it a model or not doesn’t matter
• However, tools from Eclipse Modeling help to build
tooling for this notation
• Instances of this notation are a primary artifact of your
software
• If it has syntax and semantics, it is a language
20. The Right Notation
The Right Notation
• Whether we call it a model or not doesn’t matter
• However, tools from Eclipse Modeling help to build
tooling for this notation
• Instances of this notation are a primary artifact of your
software
• If it has syntax and semantics, it is a language
• The focus on a certain kind of tasks makes it domain
specific. It becomes a DSL or DSML
21. Qualities for an effective development process
and a high-quality product
Language Tooling
• Support for a few, • Content Assist
Writable
orthogonal concepts • Quickfixes
• Appropriate, concise
syntax • Navigation
Readable • Hide technical details • Syntax highlighting
• Outline
• Reuse established
Communicable
syntax/semantics
• Instant feedback
Error-preventing • Statically typed
• Short roundtrips
22. Qualities for an effective development process
and a high-quality product
Language Tooling
• Support for a few, • Content Assist
Writable
orthogonal concepts • Quickfixes
• Appropriate, concise
syntax • Navigation
Readable • Hide technical details • Syntax highlighting
• Outline
• Reuse established
Communicable
syntax/semantics
• Instant feedback
Error-preventing • Statically typed
• Short roundtrips
23. Qualities for an effective development process
and a high-quality product
Language Tooling
• Support for a few, • Content Assist
Writable
orthogonal concepts • Quickfixes
• Appropriate, concise
syntax • Navigation
Readable • Hide technical details • Syntax highlighting
• Outline
• Reuse established
Communicable
syntax/semantics
• Instant feedback
Error-preventing • Statically typed
• Short roundtrips
24. Qualities for an effective development process
and a high-quality product Where?
Language Tooling
• Support for a few, • Content Assist
Writable
orthogonal concepts • Quickfixes
• Appropriate, concise
syntax • Navigation
Readable • Hide technical details • Syntax highlighting
• Outline
• Reuse established
Communicable
syntax/semantics
• Instant feedback
Error-preventing • Statically typed
• Short roundtrips
25. Qualities for an effective development process
and a high-quality product
Language Tooling
• Support for a few, • Content Assist
Writable
orthogonal concepts • Quickfixes
• Appropriate, concise
syntax • Navigation
Readable • Hide technical details • Syntax highlighting
• Outline
• Reuse established
Communicable
syntax/semantics
• Instant feedback
Error-preventing • Statically typed
• Short roundtrips
31. textual Examples?
graphical
forms/tables
You name it! mathematical
The limit to design
notations is available
tooling and creativity.
32. textual Examples?
graphical
forms/tables
You name it! mathematical
The limit to design
notations is available
tooling and creativity.
Multiple notations can be combined.
33. public void assertSameStructure(EObject left, EObject right) {
if(!isSameStructure(left, right)) {
Text
log.error(getErrorMessage());
Graphics
Assert.fail(getErrorMessage());
}
//logger.debug("" + counter + " elements compared");
}
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 + " != " + right).append('n');
return false;
}
List<EObject> leftChildren = getRelevantChildren(left);
List<EObject> rightChildren = getRelevantChildren(right);
if(leftChildren.size() != rightChildren.size()) {
errorMessage.append("Number of children differs " + left + " " + right + " " + leftChildren.size() + " <> " + rightChildren.size()).append('n')
return false;
}
for (int i = 0; i < leftChildren.size(); ++i) {
if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get(i))) {
errorMessage.append("Children differ " + left + " " + right + " with children " + leftChildren.get(i) + " " + rightChildren.get(i)).append
return false;
}
}
return true;
}
protected boolean isSameClass(EClass left, EClass right) {
return left.getName().equals(right.getName())
&& left.getEPackage().getNsURI().equals(right.getEPackage().getNsURI());
}
protected List<EObject> getRelevantChildren(EObject _this) {
List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents());
for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) {
EObject next = i.next();
if (!isRelevantChild(_this, next)) {
i.remove();
34. public void assertSameStructure(EObject left, EObject right) {
if(!isSameStructure(left, right)) {
Text
log.error(getErrorMessage());
Graphics
Assert.fail(getErrorMessage());
}
//logger.debug("" + counter + " elements compared");
}
• Detailed 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 + " != " + right).append('n');
return false;
}
List<EObject> leftChildren = getRelevantChildren(left);
List<EObject> rightChildren = getRelevantChildren(right);
if(leftChildren.size() != rightChildren.size()) {
errorMessage.append("Number of children differs " + left + " " + right + " " + leftChildren.size() + " <> " + rightChildren.size()).append('n')
return false;
}
for (int i = 0; i < leftChildren.size(); ++i) {
if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get(i))) {
errorMessage.append("Children differ " + left + " " + right + " with children " + leftChildren.get(i) + " " + rightChildren.get(i)).append
return false;
}
}
return true;
}
Information that is not in the text,
protected boolean isSameClass(EClass left, exists.
doesn’t EClass right) {
return left.getName().equals(right.getName())
&& left.getEPackage().getNsURI().equals(right.getEPackage().getNsURI());
}
protected List<EObject> getRelevantChildren(EObject _this) {
List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents());
for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) {
EObject next = i.next();
if (!isRelevantChild(_this, next)) {
i.remove();
35. public void assertSameStructure(EObject left, EObject right) {
if(!isSameStructure(left, right)) {
Text
log.error(getErrorMessage());
Graphics
Assert.fail(getErrorMessage());
}
//logger.debug("" + counter + " elements compared");
}
• Detailed views
protected String getErrorMessage() {
return errorMessage.toString();
• High-level views
}
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 + " != " + right).append('n');
return false;
}
List<EObject> leftChildren = getRelevantChildren(left);
List<EObject> rightChildren = getRelevantChildren(right);
if(leftChildren.size() != rightChildren.size()) {
errorMessage.append("Number of children differs " + left + " " + right + " " + leftChildren.size() + " <> " + rightChildren.size()).append('n')
return false;
}
for (int i = 0; i < leftChildren.size(); ++i) {
if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get(i))) {
errorMessage.append("Children differ " + left + " " + right + " with children " + leftChildren.get(i) + " " + rightChildren.get(i)).append
return false;
}
}
return true;
The diagram is the big picture, details are
}
Information that is not in the text, in property dialogs.
protected boolean isSameClass(EClass left, exists.
doesn’t EClass right) { Graphical notations are commonly used
return left.getName().equals(right.getName())
&& left.getEPackage().getNsURI().equals(right.getEPackage().getNsURI()); at higher levels of abstractions.
}
protected List<EObject> getRelevantChildren(EObject _this) {
List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents());
for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) {
EObject next = i.next();
if (!isRelevantChild(_this, next)) {
i.remove();
36. public void assertSameStructure(EObject left, EObject right) {
if(!isSameStructure(left, right)) {
Text
log.error(getErrorMessage());
Graphics
Assert.fail(getErrorMessage());
}
//logger.debug("" + counter + " elements compared");
}
• Detailed views
protected String getErrorMessage() { • High-level views
•
return errorMessage.toString();
}
Very formal syntax
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 + " != " + right).append('n');
return false;
}
List<EObject> leftChildren = getRelevantChildren(left);
List<EObject> rightChildren = getRelevantChildren(right);
if(leftChildren.size() != rightChildren.size()) {
errorMessage.append("Number of children differs " + left + " " + right + " " + leftChildren.size() + " <> " + rightChildren.size()).append('n')
return false;
}
for (int i = 0; i < leftChildren.size(); ++i) {
if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get(i))) {
errorMessage.append("Children differ " + left + " " + right + " with children " + leftChildren.get(i) + " " + rightChildren.get(i)).append
return false;
}
}
return true;
} Non-Formal Elements
whitespace, line-breaks, comments
protected boolean isSameClass(EClass left, EClass right) {
return left.getName().equals(right.getName())
&& left.getEPackage().getNsURI().equals(right.getEPackage().getNsURI());
}
protected List<EObject> getRelevantChildren(EObject _this) {
List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents());
for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) {
EObject next = i.next();
if (!isRelevantChild(_this, next)) {
i.remove();
37. public void assertSameStructure(EObject left, EObject right) {
if(!isSameStructure(left, right)) {
Text
log.error(getErrorMessage());
Graphics
Assert.fail(getErrorMessage());
}
//logger.debug("" + counter + " elements compared");
}
• Detailed views
protected String getErrorMessage() { • High-level views
• •
return errorMessage.toString();
}
Very formal syntax Suggests non-formalism
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 + " != " + right).append('n');
return false;
}
List<EObject> leftChildren = getRelevantChildren(left);
List<EObject> rightChildren = getRelevantChildren(right);
if(leftChildren.size() != rightChildren.size()) {
errorMessage.append("Number of children differs " + left + " " + right + " " + leftChildren.size() + " <> " + rightChildren.size()).append('n')
return false;
}
for (int i = 0; i < leftChildren.size(); ++i) {
if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get(i))) {
errorMessage.append("Children differ " + left + " " + right + " with children " + leftChildren.get(i) + " " + rightChildren.get(i)).append
return false;
}
}
return true;
Non-Formal Elements
} Non-Formal Elements
Modify: position, size, shape, color, font, icon
whitespace, line-breaks, comments
protected boolean isSameClass(EClass left, EClass right) {
return left.getName().equals(right.getName()) Add: note-box, custom shapes, comments
&& left.getEPackage().getNsURI().equals(right.getEPackage().getNsURI());
}
protected List<EObject> getRelevantChildren(EObject _this) {
List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents());
for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) {
EObject next = i.next();
if (!isRelevantChild(_this, next)) {
i.remove();
38. public void assertSameStructure(EObject left, EObject right) {
if(!isSameStructure(left, right)) {
Text
log.error(getErrorMessage());
Graphics
Assert.fail(getErrorMessage());
}
//logger.debug("" + counter + " elements compared");
}
• Detailed views
protected String getErrorMessage() { • High-level views
• •
return errorMessage.toString();
}
Very formal syntax Suggests non-formalism
• Standard text editor
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 + " != " + right).append('n');
return false;
}
List<EObject> leftChildren = getRelevantChildren(left);
List<EObject> rightChildren = getRelevantChildren(right);
if(leftChildren.size() != rightChildren.size()) {
errorMessage.append("Number of children differs " + left + " " + right + " " + leftChildren.size() + " <> " + rightChildren.size()).append('n')
return false;
}
for (int i = 0; i < leftChildren.size(); ++i) {
if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get(i))) {
errorMessage.append("Children differ " + left + " " + right + " with children " + leftChildren.get(i) + " " + rightChildren.get(i)).append
return false;
}
}
return true;
}
The editor can be language-aware, but is
protected boolean isSameClass(EClass required to.
not left, EClass right) {
return left.getName().equals(right.getName())
&& left.getEPackage().getNsURI().equals(right.getEPackage().getNsURI());
}
protected List<EObject> getRelevantChildren(EObject _this) {
List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents());
for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) {
EObject next = i.next();
if (!isRelevantChild(_this, next)) {
i.remove();
39. public void assertSameStructure(EObject left, EObject right) {
if(!isSameStructure(left, right)) {
Text
log.error(getErrorMessage());
Graphics
Assert.fail(getErrorMessage());
}
//logger.debug("" + counter + " elements compared");
}
• Detailed views
protected String getErrorMessage() { • High-level views
• •
return errorMessage.toString();
}
Very formal syntax Suggests non-formalism
• Standard text editor • Custom editor
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 + " != " + right).append('n');
return false;
}
List<EObject> leftChildren = getRelevantChildren(left);
List<EObject> rightChildren = getRelevantChildren(right);
if(leftChildren.size() != rightChildren.size()) {
errorMessage.append("Number of children differs " + left + " " + right + " " + leftChildren.size() + " <> " + rightChildren.size()).append('n')
return false;
}
for (int i = 0; i < leftChildren.size(); ++i) {
if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get(i))) {
errorMessage.append("Children differ " + left + " " + right + " with children " + leftChildren.get(i) + " " + rightChildren.get(i)).append
return false;
}
}
return true;
}
The editor can be language-aware, but is Each language requires a special
protected boolean isSameClass(EClass required to.
not left, EClass right) { (or generic) editor.
return left.getName().equals(right.getName())
&& left.getEPackage().getNsURI().equals(right.getEPackage().getNsURI());
}
protected List<EObject> getRelevantChildren(EObject _this) {
List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents());
for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) {
EObject next = i.next();
if (!isRelevantChild(_this, next)) {
i.remove();
40. public void assertSameStructure(EObject left, EObject right) {
if(!isSameStructure(left, right)) {
Text
log.error(getErrorMessage());
Graphics
Assert.fail(getErrorMessage());
}
//logger.debug("" + counter + " elements compared");
}
• Detailed views
protected String getErrorMessage() { • High-level views
• •
return errorMessage.toString();
}
Very formal syntax Suggests non-formalism
• Standard text editor • Custom editor
public boolean isSameStructure(EObject left, EObject right) {
counter = 0;
return internalIsSameStructure(left, right);
}
• Standard versioning /
public boolean internalIsSameStructure(EObject left, EObject right) {
multi-user support
++counter;
if (!isSameClass(left.eClass(), right.eClass())) {
errorMessage.append("Classes are not equal: " + left + " != " + right).append('n');
return false;
}
List<EObject> leftChildren = getRelevantChildren(left);
List<EObject> rightChildren = getRelevantChildren(right);
if(leftChildren.size() != rightChildren.size()) {
errorMessage.append("Number of children differs " + left + " " + right + " " + leftChildren.size() + " <> " + rightChildren.size()).append('n')
return false;
}
for (int i = 0; i < leftChildren.size(); ++i) {
if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get(i))) {
errorMessage.append("Children differ " + left + " " + right + " with children " + leftChildren.get(i) + " " + rightChildren.get(i)).append
return false;
}
}
return true;
}
SVN, CVS, GIT, GNU diff/patch, etc.
protected boolean isSameClass(EClass left, EClass right) {
return left.getName().equals(right.getName())
&& left.getEPackage().getNsURI().equals(right.getEPackage().getNsURI());
}
protected List<EObject> getRelevantChildren(EObject _this) {
List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents());
for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) {
EObject next = i.next();
if (!isRelevantChild(_this, next)) {
i.remove();
41. public void assertSameStructure(EObject left, EObject right) {
if(!isSameStructure(left, right)) {
Text
log.error(getErrorMessage());
Graphics
Assert.fail(getErrorMessage());
}
//logger.debug("" + counter + " elements compared");
}
• Detailed views
protected String getErrorMessage() { • High-level views
• •
return errorMessage.toString();
}
Very formal syntax Suggests non-formalism
• Standard text editor • Custom editor
public boolean isSameStructure(EObject left, EObject right) {
counter = 0;
return internalIsSameStructure(left, right);
}
• Standard versioning /
public boolean internalIsSameStructure(EObject left, EObject right) {
• Custom versioning /
multi-user support
++counter;
if (!isSameClass(left.eClass(), right.eClass())) {
multi-user support
errorMessage.append("Classes are not equal: " + left + " != " + right).append('n');
return false;
}
List<EObject> leftChildren = getRelevantChildren(left);
List<EObject> rightChildren = getRelevantChildren(right);
if(leftChildren.size() != rightChildren.size()) {
errorMessage.append("Number of children differs " + left + " " + right + " " + leftChildren.size() + " <> " + rightChildren.size()).append('n')
return false;
}
for (int i = 0; i < leftChildren.size(); ++i) {
if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get(i))) {
errorMessage.append("Children differ " + left + " " + right + " with children " + leftChildren.get(i) + " " + rightChildren.get(i)).append
return false;
}
}
return true;
}
Model repositories, diff/merge needs to
SVN, CVS, GIT, GNU diff/patch, etc.
protected boolean isSameClass(EClass left, EClass right) {
return left.getName().equals(right.getName())
be language-aware
&& left.getEPackage().getNsURI().equals(right.getEPackage().getNsURI());
}
protected List<EObject> getRelevantChildren(EObject _this) {
List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents());
for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) {
EObject next = i.next();
if (!isRelevantChild(_this, next)) {
i.remove();
42. public void assertSameStructure(EObject left, EObject right) {
if(!isSameStructure(left, right)) {
Text
log.error(getErrorMessage());
Graphics
Assert.fail(getErrorMessage());
}
//logger.debug("" + counter + " elements compared");
}
• Detailed views
protected String getErrorMessage() { • High-level views
• •
return errorMessage.toString();
}
Very formal syntax Suggests non-formalism
• Standard text editor • Custom editor
public boolean isSameStructure(EObject left, EObject right) {
counter = 0;
return internalIsSameStructure(left, right);
}
• Standard versioning /
public boolean internalIsSameStructure(EObject left, EObject right) {
• Custom versioning /
multi-user support
++counter;
if (!isSameClass(left.eClass(), right.eClass())) { multi-user support
•
errorMessage.append("Classes are not equal: " + left + " != " + right).append('n');
} Editing with keyboard
return false;
List<EObject> leftChildren = getRelevantChildren(left);
List<EObject> rightChildren = getRelevantChildren(right);
if(leftChildren.size() != rightChildren.size()) {
errorMessage.append("Number of children differs " + left + " " + right + " " + leftChildren.size() + " <> " + rightChildren.size()).append('n')
return false;
}
for (int i = 0; i < leftChildren.size(); ++i) {
if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get(i))) {
errorMessage.append("Children differ " + left + " " + right + " with children " + leftChildren.get(i) + " " + rightChildren.get(i)).append
return false;
}
}
return true;
}
protected boolean isSameClass(EClass left, EClass right) {
return left.getName().equals(right.getName())
&& left.getEPackage().getNsURI().equals(right.getEPackage().getNsURI());
}
protected List<EObject> getRelevantChildren(EObject _this) {
List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents());
for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) {
EObject next = i.next();
if (!isRelevantChild(_this, next)) {
i.remove();
43. public void assertSameStructure(EObject left, EObject right) {
if(!isSameStructure(left, right)) {
Text
log.error(getErrorMessage());
Graphics
Assert.fail(getErrorMessage());
}
//logger.debug("" + counter + " elements compared");
}
• Detailed views
protected String getErrorMessage() { • High-level views
• •
return errorMessage.toString();
}
Very formal syntax Suggests non-formalism
• Standard text editor • Custom editor
public boolean isSameStructure(EObject left, EObject right) {
counter = 0;
return internalIsSameStructure(left, right);
}
• Standard versioning /
public boolean internalIsSameStructure(EObject left, EObject right) {
• Custom versioning /
multi-user support
++counter;
if (!isSameClass(left.eClass(), right.eClass())) { multi-user support
• •
errorMessage.append("Classes are not equal: " + left + " != " + right).append('n');
} Editing with keyboard
return false;
Editing with mouse
List<EObject> leftChildren = getRelevantChildren(left);
List<EObject> rightChildren = getRelevantChildren(right);
if(leftChildren.size() != rightChildren.size()) {
errorMessage.append("Number of children differs " + left + " " + right + " " + leftChildren.size() + " <> " + rightChildren.size()).append('n')
return false;
}
for (int i = 0; i < leftChildren.size(); ++i) {
if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get(i))) {
errorMessage.append("Children differ " + left + " " + right + " with children " + leftChildren.get(i) + " " + rightChildren.get(i)).append
return false;
}
}
return true;
}
protected boolean isSameClass(EClass left, EClass right) {
return left.getName().equals(right.getName())
&& left.getEPackage().getNsURI().equals(right.getEPackage().getNsURI());
}
protected List<EObject> getRelevantChildren(EObject _this) {
List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents());
for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) {
EObject next = i.next();
if (!isRelevantChild(_this, next)) {
i.remove();
44. public void assertSameStructure(EObject left, EObject right) {
if(!isSameStructure(left, right)) {
Text
log.error(getErrorMessage());
Graphics
Assert.fail(getErrorMessage());
}
//logger.debug("" + counter + " elements compared");
}
• Detailed views
protected String getErrorMessage() { • High-level views
• •
return errorMessage.toString();
}
Very formal syntax Suggests non-formalism
• Standard text editor • Custom editor
public boolean isSameStructure(EObject left, EObject right) {
counter = 0;
return internalIsSameStructure(left, right);
}
• Standard versioning /
public boolean internalIsSameStructure(EObject left, EObject right) {
• Custom versioning /
multi-user support
++counter;
if (!isSameClass(left.eClass(), right.eClass())) { multi-user support
• •
errorMessage.append("Classes are not equal: " + left + " != " + right).append('n');
} Editing with keyboard
return false;
Editing with mouse
• Expressions, Lists
List<EObject> leftChildren = getRelevantChildren(left);
List<EObject> rightChildren = getRelevantChildren(right);
if(leftChildren.size() != rightChildren.size()) {
errorMessage.append("Number of children differs " + left + " " + right + " " + leftChildren.size() + " <> " + rightChildren.size()).append('n')
return false;
}
for (int i = 0; i < leftChildren.size(); ++i) {
if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get(i))) {
errorMessage.append("Children differ " + left + " " + right + " with children " + leftChildren.get(i) + " " + rightChildren.get(i)).append
return false;
}
}
return true;
Mathematical Expressions,
}
Imperative Command Lists,
Hierarchical Data,
protected boolean isSameClass(EClass left, EClass right) {
return left.getName().equals(right.getName())
etc.
&& left.getEPackage().getNsURI().equals(right.getEPackage().getNsURI());
}
protected List<EObject> getRelevantChildren(EObject _this) {
List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents());
for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) {
EObject next = i.next();
if (!isRelevantChild(_this, next)) {
i.remove();
45. public void assertSameStructure(EObject left, EObject right) {
if(!isSameStructure(left, right)) {
Text
log.error(getErrorMessage());
Graphics
Assert.fail(getErrorMessage());
}
//logger.debug("" + counter + " elements compared");
}
• Detailed views
protected String getErrorMessage() { • High-level views
• •
return errorMessage.toString();
}
Very formal syntax Suggests non-formalism
• Standard text editor • Custom editor
public boolean isSameStructure(EObject left, EObject right) {
counter = 0;
return internalIsSameStructure(left, right);
}
• Standard versioning /
public boolean internalIsSameStructure(EObject left, EObject right) {
• Custom versioning /
multi-user support
++counter;
if (!isSameClass(left.eClass(), right.eClass())) { multi-user support
• •
errorMessage.append("Classes are not equal: " + left + " != " + right).append('n');
} Editing with keyboard
return false;
Editing with mouse
• Expressions, Lists • Flow, Structure
List<EObject> leftChildren = getRelevantChildren(left);
List<EObject> rightChildren = getRelevantChildren(right);
if(leftChildren.size() != rightChildren.size()) {
errorMessage.append("Number of children differs " + left + " " + right + " " + leftChildren.size() + " <> " + rightChildren.size()).append('n')
return false;
}
for (int i = 0; i < leftChildren.size(); ++i) {
if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get(i))) {
errorMessage.append("Children differ " + left + " " + right + " with children " + leftChildren.get(i) + " " + rightChildren.get(i)).append
return false;
}
}
Visual Pattern-Matching
Mathematical Expressions,
return true;
Flow: Workflow, State-Machine,
}
Imperative Command Lists,
Process Chain
Hierarchical Data,
protected boolean isSameClass(EClass left, EClass right) {
return left.getName().equals(right.getName()) Structure: Class Diagram, Entity
etc.
&& left.getEPackage().getNsURI().equals(right.getEPackage().getNsURI());
} Relationship Diagram
protected List<EObject> getRelevantChildren(EObject _this) {
List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents());
for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) {
EObject next = i.next();
if (!isRelevantChild(_this, next)) {
i.remove();
46. public void assertSameStructure(EObject left, EObject right) {
if(!isSameStructure(left, right)) {
Text
log.error(getErrorMessage());
Graphics
Assert.fail(getErrorMessage());
}
//logger.debug("" + counter + " elements compared");
}
• Detailed views
protected String getErrorMessage() { • High-level views
• •
return errorMessage.toString();
}
Very formal syntax Suggests non-formalism
• Standard text editor • Custom editor
public boolean isSameStructure(EObject left, EObject right) {
counter = 0;
return internalIsSameStructure(left, right);
}
• Standard versioning /
public boolean internalIsSameStructure(EObject left, EObject right) {
• Custom versioning /
multi-user support
++counter;
if (!isSameClass(left.eClass(), right.eClass())) { multi-user support
• •
errorMessage.append("Classes are not equal: " + left + " != " + right).append('n');
} Editing with keyboard
return false;
Editing with mouse
• Expressions, Lists • Flow, Structure
List<EObject> leftChildren = getRelevantChildren(left);
List<EObject> rightChildren = getRelevantChildren(right);
if(leftChildren.size() != rightChildren.size()) {
errorMessage.append("Number of children differs " + left + " " + right + " " + leftChildren.size() + " <> " + rightChildren.size()).append('n')
return false;
}
for (int i = 0; i < leftChildren.size(); ++i) {
if(!internalIsSameStructure(leftChildren.get(i), rightChildren.get(i))) {
errorMessage.append("Children differ " + left + " " + right + " with children " + leftChildren.get(i) + " " + rightChildren.get(i)).append
return false;
}
}
Why not have both?
return true;
}
protected boolean isSameClass(EClass left, EClass right) {
return left.getName().equals(right.getName())
&& left.getEPackage().getNsURI().equals(right.getEPackage().getNsURI());
}
protected List<EObject> getRelevantChildren(EObject _this) {
List<EObject> relevantChildren = new ArrayList<EObject>(_this.eContents());
for (Iterator<EObject> i = relevantChildren.iterator(); i.hasNext();) {
EObject next = i.next();
if (!isRelevantChild(_this, next)) {
i.remove();
47. Xtext vs GMF
A textual concrete syntax and a graphical concrete syntax
on top of the same abstract syntax.
61. Xtext
EObject element
eAdapters
NodeAdapter
node
children AbstractNode
offset: int
length: int
CompositeNode LeafNode
text: String
parent
62. Xtext GMF
EObject element EObject
element
eAdapters
NodeAdapter View
node
children AbstractNode Node Edge
offset: int
length: int
layoutConstraints bendpoints
CompositeNode LeafNode Bounds Bendpoints
text: String x: int
parent y: int
width: int
height: int
121. Summary
• Think about the notation, the language, that
would be ideal to get your work done.
• Textual and graphical syntax can be combined.
• To integrate Xtext into GMF, exchange the
XMIResource with an XtextResource -> GMF
operates on a model persisted in textual syntax.
• Some integration code is helpful, too.
• itemis provides professional assistance.
Moritz Eysholdt