
Contents |
The Reuse Extension Language provides means to bind composition systems defined in the Composition System Specification Language to a concrete language that is defined by an Ecore metamodel. They are specified in files with the extension rex.
Several examples can be found in the Applications section. Here are some direct links to rex files:
The header of a reuse extension has the following schema:
componentmodel ID
implements compositionSystemID
epackages <epackage> +
rootclass rootelementMetaclass
{ fragmentRoleBindings + }
A reuse extension consists of a set of fragment role bindings which again consist of a set of port type bindings which define the addressable point derivation rules.
fragment role roleName {
portTypeBinding +
}
port portTypeName {
addressablePointDerivationRule +
}
Addressable point derivation rules define how addressable points (i.e, Hooks, Slots, Prototypes and Anchors) that lay behind each port are found in a fragment. They are defined using the following schema:
metaclass.feature? is addressablePointType if $OCLExpression$? {
point expr = $OCLExpression$ ?
port expr = $OCLExpression$ ?
value expr = $OCLExpression$ ?
begin expr = $OCLExpression$ ?
end expr = $OCLExpression$ ?
}
In addition to the standard OCL String API, the flavor of OCL in reuse extensions supports the complete Java String API. This means that operations like startsWith() or indexOf() can be used on Strings. Refer to the Javadoc for Strings to learn about the supported methods: Java String API
Sometimes one needs to navigate from an element to its container in an OCL expression. The OCL flavor used in reuse extensions supports the eContainer() method to obtain a container. After using that method, the container needs to be manually casted to the correct type using oclAsType(). The following could be used to obtain the UML Package that contains the UML Class myClass:
myClass.eContainer().oclAsType(UML::Package)
Inside OCL expressions, you can refer to a class defined in a different EPackage than the one identified in the header. This might be required when using oclIsTypeOf() or oclIsKindOf().
EPackageNsPrefix :: EClassName
For example...
myElement.oclIsTypeOf(uml::Class)
...checks if myElement is an UML Class.
To refer to a Literal of an Enumeration, use the following schema:
EPackageNsPrefix :: EEnumName :: EEnumLiteralName
This is a collection of language descriptions. For each language, there are defined the abstract syntax and one concrete syntax. The abstract syntax definition language is oriented at the one used in [Mey90]. In the language, there are four kinds of grammar rules:
is a rule that is an aggregation of references to other rules. It corresponds to the definition of references in a metamodel.
is a rule defining a set of alternatives. It corresponds to the subclass-of relationship in a metamodel where all subclasses (i.e., alternatives) can substitute their superclass.
defines that a rule inherits all properties from a super-rule. It also corresponds to the subclass-of relationship in a metamodel. Here, it expresses that a subclass inherits all references from its superclass. Such expressiveness is usually not supported by grammar languages and only available in metamodels. Note that the rules super-rule = alternative-rule ";" and alternative rule ==> super rule ";" technically express the same thing. The distinction exists to express the different usages of subclass-of in distinct ways, which enhances readability.
Empty rules (i.e., classes without references) act as terminal symbols. A special case is the terminal rule S, which is predefined. It denotes the infinite set of strings and is mapped to an attribute of the primitive type String in metamodels.
It is possible to refer to rules defined in other grammars to extend an existing language:
The concrete syntax definition language is used to write concrete syntax grammars for a previously defined abstract syntax. For one abstract syntax, different concrete syntaxes may exist. Composition works solely on the abstract syntax. Thus, fragments written in different concrete syntaxes can be composed. A concrete syntax grammar has a header line and rules oriented at EBNF rules [Int96].
defines for which abstract syntax this concrete syntax is defined.
The rule name corresponds to the name of an aggregation rule in the abstract syntax. The rule can contain nested sequences and alternatives of elements. An element is either part of the concrete syntax, of a concrete string encapsulated in quote symbols (" or ’), or of a reference defined in the abstract syntax. References that have a multiplicity greater than one may be used several times in a concrete syntax definition. They will be merged to one reference in the abstract syntax tree.
Note that a concrete syntax has to be defined for each abstract syntax aggregation rule. This includes referenced rules defined in other abstract syntax grammars. In cases where a concrete syntax for such rules should be reused (e.g., in a reuse language) a simple mechanism to extend concrete syntax grammars is provided.
All the definitions that exist in the super-grammar are imported but may be overridden.
Abstract syntax grammar
AbstractSyntax = rules:Rule+; Rule = name:Identifier, definition:Definition?; Identifier = identifier:S; Definition = Aggregation | Choice; Choice = options:Identifier+; Aggregation = reference:Reference+; Reference = name:Identifier, rule:Identifier, cardinality:Cardinality?; Cardinality = PLUS | STAR | QUESTIONMARK; PLUS; STAR; QUESTIONMARK;
Concrete syntax grammar
CONCRETESYNTAX as FOR abstractsyntax
AbstractSyntax ::= rules+;
Rule ::= (name ("=" definition)? ";") | (definition "==>" name ";");
Identifier ::= identifier[((’A’..’Z’|’a’..’z’|’0’..’9’)+ ’.’)?(’A’..’Z’|’a’..’z’|’0’..’9’)+];
Choice ::= options ( "|" options)* ;
Aggregation ::= reference ( "," reference )*;
Reference ::= (name ":" rule cardinality?) ;
PLUS ::= "+";
STAR ::= "*";
QUESTIONMARK ::= "?";
Abstract syntax grammar
ConcreteSyntax = name:S, languageName:S, superGrammar:S?, rules:Rule+; Rule = name:Metaidentifier, definition:Choice; Metaidentifier = identifier:S; Choice = options:Aggregation+; Aggregation = parts:SingleDefinition+; SingleDefinition = body:DefinitionBody, cardinality:Cardinality?; DefinitionBody = SubDefinition | Reference | CsString; SubDefinition = definition:Choice; Reference = name:S, regex:S?; CsString = value:S; Cardinality = PLUS | STAR | QUESTIONMARK; PLUS; STAR; QUESTIONMARK;
Concrete syntax grammar
CONCRETESYNTAX cs FOR concretesyntax
ConcreteSyntax ::= "EBNF" name[((’A’..’Z’|’a’..’z’|’0’..’9’)+ ’.’ )?(’A’..’Z’|’a’..’z’|’0’..’9’)+]
"FOR" languageName[((’A’..’Z’|’a’..’z’|’0’..’9’)+ ’.’ )?
(’A’..’Z’|’a’..’z’|’0’..’9’)+]
"EXTENDS" superGrammar[((’A’..’Z’|’a’..’z’|’0’..’9’)+ ’.’ )?
(’A’..’Z’|’a’..’z’|’0’..’9’)+])? rules+;
Rule ::= name "::=" definition ";";
Metaidentifier ::= identifier[((’A’..’Z’|’a’..’z’|’0’..’9’)+ ’.’ )?
(’A’..’Z’|’a’..’z’|’0’..’9’)+];
Aggregation ::= parts+;
Choice ::= options ("|" options)*;
SingleDefinition ::= body cardinality?;
Reference ::= name[((’A’..’Z’|’a’..’z’|’0’..’9’)+ ’.’ )? (’A’..’Z’|’a’..’z’|’0’..’9’)+]
regex[’[’ ( ’ ’|’(’|’)’|’|’|’?’|’*’|’+’|’~’|’.’|
(’\’’ ( ~(’\’’|’\\’) | (’\\’ .))* ) ’\’’ )* ’]’]?;
CsString ::= value[(’\"’ (~’\"’)* ’\"’) | (’\’’ (~’\’’)* ’\’’)];
SubDefinition ::= "(" definition ")";
PLUS ::= "+";
STAR ::= "*";
QUESTIONMARK ::= "?";
This tutorial works with a subset of the Java programming language, here referred to as Java-. In order to create a composition environment for the Java- language, we first need a description of the Java- language itself, i.e. a grammar description of the language. We aim at having a clear separation between the abstract and concrete syntax of any language. In that way, several concrete syntaxes can be defined for a single abstract syntax. Thus, first we need to define the abstract syntax of Java- in a way that is readable by the tool. The Reuseware Framework understands two input formats: an EBNF-like syntax, but also a description in a more modeling-like language, Ecore. Here we provide the abstract syntax description of Java- in the EBNF-like syntax
See also: Language Grammers
CompilationUnit = packageDeclaration:PackageDeclaration?,
importDeclarations:ImportDeclaration*,
classDeclarations:ClassDeclaration*;
PackageDeclaration = name:QualifiedName;
ImportDeclaration = name:QualifiedName;
ClassDeclaration = modifier:Modifier,
name:Identifier,
extends:QualifiedName?,
implements:QualifiedName*,
classBody:MemberDeclaration*;
MemberDeclaration = AttributeDeclaration | MethodDeclaration;
AttributeDeclaration = modifier:Modifier,
type:QualifiedName,
name:Identifier,
value:Value?;
MethodDeclaration = modifier:Modifier,
type:QualifiedName,
name:Identifier,
arguments:VariableDeclaration*,
statements:Statement*;
Statement = MethodCall | VariableDeclaration | VariableAssignment;
VariableDeclaration = type:QualifiedName, name:Identifier, value:Value?;
VariableAssignment = name:Identifier,
value:Value;
MethodCall = method:QualifiedName,
arguments:Value*,
succeedingCall:MethodCall?;
Value = StringValue | IntegerValue | Identifier | MethodCall;
Modifier = PrivateModifier | PublicModifier | ProtectedModifier;
QualifiedName = elements:Identifier+;
PrivateModifier;
PublicModifier;
ProtectedModifier;
StringValue = value:S;
IntegerValue = value:S;
Identifier = value:S;
A valid Java- program is an instance of the CompilationUnit description in the grammar above. The first production rule of the grammar says that a CompilationUnit optionally (?) has a PackageDeclaration followed by any number (*) of ImportDeclarations and then any number (*) of ClassDeclarations.
The EBNF syntax for describing a language is mostly a shorthand for the Ecore variant. Thus, it is possible to automatically generate an Ecore model from any valid description in the EBNF syntax.
In order to use the grammar above, create a folder in your Eclipse workspace and copy the grammar description into a file called java.as ('as' for abstract syntax). Right-click on the grammar file (java.as) and click the Map to Ecore option. A new file will be created called java.ecore and its contents can be browsed, as shown below.
The next task is to define the concrete syntax for the Java- language.
The abstract syntax grammar above is accompanied by a concrete syntax, referring to the abstract syntax.
CONCRETESYNTAX java FOR java
CompilationUnit ::= packageDeclaration? ";" (importDeclarations ";")* classDeclarations*;
PackageDeclaration ::= "package" name;
ImportDeclaration ::= "import" name;
ClassDeclaration ::= modifier "class" name ("extends" extends)? ("implements" implements+)?
"{" classBody* "}";
AttributeDeclaration ::= modifier type name ("=" value)? ";";
MethodDeclaration ::= modifier type name "(" (arguments ("," arguments)*)? ")"
"{" (statements ";")* "}";
VariableDeclaration ::= type name ("=" value)?;
VariableAssignment ::= name "=" value;
MethodCall ::= method "(" (arguments ("," arguments)*)? ")" ("." succeedingCall)?;
QualifiedName ::= elements ("." elements)*;
PrivateModifier ::= "private";
PublicModifier ::= "public";
ProtectedModifier ::= "protected";
StringValue ::= value['\"' (~('\"'|'\\') | '\\' . )* '\"'];
IntegerValue ::= value[('-')? ('0'..'9')+];
Identifier ::= value[('a'..'z'|'A'..'Z') ('a'..'z'|'A'..'Z'|'0'..'9')*];
For example, the first rule says that a CompilationUnit consists of first its optional package declaration followed by a semicolon (";"), a list of import declarations separated by semicolons (";") and finally any number of class declarations.
TODO: explain the use of roles.
The concrete syntax above can be put in the file java.cs ('cs' for concrete syntax) in the same folder as the abstract syntax description.
We will now write some example components in Java- in order see what we would like to achieve with respect to composition. In particular, in what way we should extend Java- in order to cover the introduced examples.
Suppose we want to define the following fragment component, being a valid Java- CompilationUnit.
package org.foo.vehicles;
import java.util.Collection;
public class Car implements Comparable {
private String name;
private Engine engine;
<<myMethod : java.MemberDeclaration>>
public void startEngine() {
engine.start();
}
public void stopEngine() {
engine.stop();
}
}
The fragment components consists of one package declaration, one package import statement and one class definition defining the class Car. The class in turn has two member attributes and two methods specified. Further more, the fragment components is declared to be underspecified by the use of the statement:
<<myMethod : java.MemberDeclaration>>
The intention of this statement is to allow a yet unknown method definition to be bound in its place at a later time. The statement declares a slot, which can be bound to some suitable fragment component at composition time. The slot has the name myMethod and its type is declared to be java.MemberDeclaration. The type MemberDeclaration is reused from the java language (Java-). The typing ensures that the fragment component bound in its place is of a valid construct to replace the slot, in this case a member declaration. Possibly, the following fragment component could be bound there during composition:
public void drive(int direction) {
turn(direction);
}
We will now see how to extend the Java- language to support this simple kind of composition.
Now that the core language Java- has been is given, and we have seen a simple example we will now need to extend it to support composition. This step can also be automated using the CoMoGen subsystem of the composition framework. Here, however, we show how to do this manually.
For this example we will extend Java- by allowing the specification of Java- components of the type MemberDeclaration, i.e. components containing method declarations.
java.MemberDeclaration = MemberDeclarationSlot; MemberDeclarationSlot; MemberDeclarationSlot ==> componentmodel.slot;
This little language extension is the extension of the Java- abstract syntax and will be called a Java- reuse language. The extension definition can be put in the file reusejava.as in the same directory as the other Java- grammar files.
The description above says (line 1) that what previously (in Java-, hence the "java." usage) could be MemberDeclarations can now also be a new construct called MemberDeclarationSlot, introduced to describe the construct used for declaring slots (in this case as representatives for member declarations). The two remaining statements in the description above introduces the construct as a concept in the language description and says that the new construct is a subclass (==>) of the concept slot in a common component model.
This description can also be mapped to an Ecore model by right-clicking on the description and selecting Map to Ecore.
For the language extension above we also need to define a concrete syntax.
CONCRETESYNTAX rjava FOR reusejava EXTENDS java
java.CompilationUnit ::= packageDeclaration? ";" (importDeclarations ";")*
classDeclarations*;
MemberDeclarationSlot ::= "<<" name ":" type ">>";
componentmodel.VariationPointName ::= name[('a'..'z'|'A'..'Z') ('a'..'z'|'A'..'Z'|'0'..'9')*];
componentmodel.FragmentType ::= language[('a'..'z'|'A'..'Z') ('a'..'z'|'A'..'Z'|'0'..'9')*] "."
construct[('a'..'z'|'A'..'Z') ('a'..'z'|'A'..'Z'|'0'..'9')*];
The most interesting definition in the concrete syntax is the third statement saying that the newly introduced construct MemberDeclarationSlot is written using first "<<" token, then a name for the slot followed by a colon (":") and a type of the slot and finally the closing ">>" token.
The definition above can be put in the file rjava.cs ('r' for reuse) in the same folder as the other language descriptions.
It is now time to generate our composition environment for our extended Java- language. This involves two steps, first, generating the language plug-in for the reuse language (on the abstract grammar or the Ecore model) and generating a parser for the reuse language. These steps are shown below.
Once this is done, we must launch a reuse language composition environment. This is done by selecting the Eclipse menu option Run -> Run... and creating a new Eclipse Application like shown below and then clicking Run to launch it.
See also: Composition Language
Once our composition environment is launched, we need to create a Reuseware Project, into which our components and composition programs will go. A new Reuseware project can be created by the following Eclipse menu selection File -> New -> Project... -> Reuseware -> Reuseware Project -> Next
Once this is done we need to write a composition program which describes how our components written above will be put together.
The following composition program could be used to execute the composition:
composition program fragmentlist java.CompilationUnit myCar = /Car.rjava; fragmentlist java.MethodDeclaration driveMethod = /DriveMethod.rjava; bind myMethod on myCar with driveMethod; print myCar to /CoolCar.java;
The composition program is put in the composition program folder in the file CarComposition.bc — bc (basic composition) is the extension for composition programs. The components are put in the components folder in the files Car.rjava and DriveMethod.rjava
Tip: use the Reuseware Text Editor inside Eclipse to obtain code highlighting for components and composition programs:
If Project -> Build Automatically is selected, the file CoolCar.java should appear in the out folder of your newly created Reuseware project. As expected, the result looks like this:
package org.foo.vehicles;
import java.util.Collection;
public class Car {
private String name;
private Engine engine;
public void drive(int direction)
turn(direction);
}
public void startEngine() {
engine.start();
}
public void stopEngine() {
engine.stop();
}
}
You have now successfully completed the first Reuseware Composition Framework tutorial. Please give your feedback for possible improvements.
This page contains information about the Reuseware application "Xcerptware". Xcerptware provides the language Xcerpt with additional reuse possibilities. More precisely, it provides Xcerpt programmers with the opportunity to develop, and design, programs using the 'module' concept.
Xcerpt is an XML query and transformation language. For an introduction into Xcerpt, please refer to Querying the Web Reconsidered: A Practical Introduction to Xcerpt. Xcerpt is a rule-based language and is closely related to other logic programming languages, such as Prolog, in that it is a declarative rule-based language. Xcerpt differs from other XML query languages, such as, e.g., XQuery, in clearly separating between query and construct parts of its rules.
Xcerpt rules come in two forms: goal rules, which make up the output of programs, and construct rules, which are used to construct intermediate results in a program. Goal rules look like this:
GOAL <construct term> FROM <query> END
And construct rules look like this:
CONSTRUCT <construct term> FROM <query> END
Rules without a FROM-part (query part) are called facts. An example of a one-rule Xcerpt program is shown below:
GOAL
result [ title [ var X ] ]
FROM
in { resource { "file:biblio.xml", "xml" },
books [
book [
author [ var Y ],
title [ var X ]
]
]
}
END
The above program queries the XML file biblio.xml. The data structure of the file is assumed to consists of a root node labeled 'books', containing, possibly, several 'book' labeled nodes. Each book node in turn contains an author and a title entry. The result of the program is a list of all the book titles in the XML file, structured as indicated in the construct term of the rule.
Modules enable the separation and encapsulation of reusable functionality, such that several different applications can integrate and take advantage of such entities in an easy way. Xcerpt modules are very similar to modules as used in other logic programming systems, such as XSB etc.
Module programmers already familiar with Xcerpt have very little to learn before being able to define reusable modules. An Xcerpt module is simply a set of Xcerpt rules that provides the intended functionality. The rules of a module are grouped together using the following construct:
MODULE [name] <module imports*> <rules+>
As can be noticed, a module can in its turn import other modules. An example of a simple module is given below:
MODULE moduleB CONSTRUCT public bookTitleFromB [ "White Mughals" ] END CONSTRUCT bookTitleFromB [ "Stanley" ] END
The module is given the name moduleB and defines two rules. The two rules here are facts, and define two titles. As can be seen, in the first rule, the constructed data is proceeded by the public keyword. This keyword is used to specify that the data constructed by this rule may be accessed by programs or modules importing this module. The second rule is not specified with the public keyword, and hence, the data it constructs should not be accessible from the outside.
In order to import and reuse modules, the import-construct is used:
IMPORT [module] AS [prefix]
There is a prefix associated with the module so as to make it easier to refer to the module later. The following shows a program importing the above-defined module, assumed to be located at /moduleB.mxcerpt.
IMPORT /moduleB.mxcerpt AS mB GOAL finalResult [ all var Data ] FROM in mB ( bookTitleFromB [ var Data ] ) END
In addition to importing a module, the program makes use of the in-module construct to access data provided by the importing module.
in [module prefix] ( <query> )
The execution of the above program results in the output:
finalResult [ "White Mughals" ]
Changing the used module to the following:
MODULE moduleB CONSTRUCT public bookTitleFromB [ "White Mughals" ] END CONSTRUCT public bookTitleFromB [ "Stanley" ] END
causes the output of the program to instead be:
finalResult [ "White Mughals", "Stanley" ]
Obviously, removing both the public keywords in the module makes the output empty.
This has been a short introduction to the basic concepts of the Xcerpt module system.
The following shows a screenshot of the Modular Xcerpt environment running in Eclipse. To the left the available Xcerpt modules are shown (under folder components), together with Modular Xcerpt programs that import and make use of the modules (under folder compositionPrograms). As can be seen, syntax highlighting is for example supported.