reuseLogoDevBooststLogo
gearsBG
Reuseware Composition Framework
Components, Modules, Aspects or something new?
Introduce new Composition Techniques into your Language of Choice with Reuseware!

Contents

Screencasts for releases 0.8.x

Screencasts for releases 0.5.x

Reuse Extension Language Reference

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.

Examples

Several examples can be found in the Applications section. Here are some direct links to rex files:

REX File Structure

Header

The header of a reuse extension has the following schema:

 componentmodel ID
 implements     compositionSystemID
 epackages      <epackage> +
 rootclass      rootelementMetaclass     
 { fragmentRoleBindings + }

Fragment Role Bindings

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

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$ ?
 }


Advanced Topics

OCL: Operations on Strings

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

OCL: Refer to Container

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)

OCL: Metamodel Packages

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.

OCL: Handle Enumerations

To refer to a Literal of an Enumeration, use the following schema:

 EPackageNsPrefix :: EEnumName :: EEnumLiteralName

Language Grammars(0.5x)

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:

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].

Abstract Syntax Definition Language

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   ::= "?"; 


Concrete Syntax Definition Language

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 ::= "?"; 

Java Tutorial

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

Core language

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.


Defining components

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.


Reuse language

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.



Execution composition

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.bcbc (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.

Xcerptware: Query Composition

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.

Background: Xcerpt

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 in Xcerpt

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.

Xcerptware: Tool

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.


Modular Xcerpt in Eclipse



Bibliography

Retrieved from "http://www.reuseware.org/index.php/Reuseware_OldDocumentation"

This page has been accessed 2,091 times. This page was last modified 15:37, 11 February 2011.