This document describes the Enfinity Definition Language (EDL).
The syntax for each language element is described using railroad diagrams. See http://en.wikipedia.org/wiki/Syntax_diagramfor more information.
EDL defines 3 types of comments: single-line comments, multi-line comments and parser-agnostic comments.
// This is a single line comment. It ends with the line break. /** * This is a multi-line comment. It should be written using the typical Java syntax. */ /## # This is a parser-agnostic comment. It can be contained in an EDL file, but will # be ignored by the parser, so it will not be contained in the resulting EDL model # and cannot be processed further. #/
Any language element can have an associated description, which is reflected by a multi-line comment in front of it.
All references to types that are defined in a different EDL file must be explicitly declared using an import statement. The import consists of a URI to the EDL file containing the wished type. The URI points to a file, not a model element, so it must include the full path to the file and the file ending.
import "enfinity:/core/src/com/intershop/SomeEDLFile.edl";
Note
The enfinity: schema should be used for importing model files which can be located in a source cartridge or in a compiled cartridge in an Enfinity installation. It is also possible to use other URI schemas that are supported by EMF.
All primitive types that are used in an EDL model must be declared. There are no built-in primitive types in the language itself.
primitive boolean; primitive int; primitive string;
Basically, any primitive type can be declared. However, there are restrictions which primitive types the JGen code generator actually understands and is able to handle. Refer to the JGen documentation for details. The Core cartridge comes with some often-needed types that are supported by the JGen code generator. This file can be imported into own EDL models, so it is not necessary to declare the same primitive types again and again (though it would work, too).
import "enfinity:/core/edl/com/intershop/beehive/core/types.edl";
External types represent types that are used in EDL, but are not fully defined in EDL. They form an alias for an existing Java type, so that the type can be used in the model.
external Collection type "java.util.Collection";
A namespace can be compared with a Java package. It groups complex types into logical units. Namespaces can be nested. Alternatively, the name of the namespace can reflect the nesting by using a Java-like syntax. An EDL file can contain multiple namespaces.
namespace com { namespace intershop { } } namespace com.intershop { // this is equivalent }
Primitive and external types have no namespace, so they must be declared outside of the namespaces (e.g. in front of them). On the other hand, complex types such as ORM classes always must have a namespace, so they can only be declared within a namespace.
Namespaces contain the definitions of complex types. Currently, EDL supports ORM types, CAPI types, RAPI types and XML types.
All complex types in the EDL language follow roughly the same language structure. Which features are available for each type, depends on the specific sublanguage for the type (see later this document). Usually, they consist of:
A modifier is a single keyword that specifies the behavior of a complex type, attribute or relationship. It can be placed in front of the element (e.g. "abstract"), or behind the element. Which modifiers are supported depends on the sublanguage. Typical modifiers are:
Some complex types or members (ORM relationships, dependencies) can have a body with additional constraints. A body is contained within brackets ("{" and "}"). The constraint provides additional definitions that refer on the members of the element. Examples:
A property consists of a single keyword and a value, which is usually a literal, or sometimes a pre-defined keyword. It can be placed behind the element definition. Properties and modifiers can be mixed. Which properties are supported depends on the sublanguage. Typical properties are:
An attribute is a member that has a name, a type, and some sublanguage-specific additional features. The type of an attribute is usually a primitive type, or an external type.
A relation is a member whose type is another complex type. Depending on the sublanguage, different features of relationships are supported.
A dependency is a special kind of relation.
Operations are methods of a complex type. Usually, they take parameters, have a return type and may throw some exception.
There are a number of literals that can be used in EDL, e.g. for expressing default values or other values. Currently, EDL supports:
EDL comes with a number of reserved keywords that cannot be used as identifiers for classes, members and so on. If such an identifier collides with an existing keyword, the identifier must be escaped. Xtext supports the ^ character for this, e.g. the identifier must get ^ as prefix.
Example:
namespace com.intershop.^orm { }
Here is the list of the reserved keywords:
abstract, alternate, as, attribute, element, binary, block, cached, cartridge, class, column, component, constant, containment, default, delete, dependency, external, foreign, handler, localized, mapped, observable, orm, oca, operation, partitionable, pattern, primitive, readonly, remote, replicated, searchable, semantic, soap, soft, strong, table, tag, text, throws, timestamp, type, unique, weak, xml
An ORM class describes a type for the ORM object-relational-mapping layer of Enfinity. Its Java implementation can be generated by JGen.
An ORM class must be defined within a namespace.
Modifiers | |
---|---|
abstract | Declares an ORM class to be abstract, e.g., to serve as superclass for other ORM classes. |
oca | The code generator will create an additional OCA attribute, which is used for transaction control. This modifier can only be used on top-most superclasses. |
timestamp | The code generator will create an additional timestamp attribute which contains the last modification time of the object. This modifier can only be used on top-most superclasses. |
Properties | |
extends <superclass> | Defines the superclass from which the ORM class inherits. Must be another ORM class. |
implements <interfaces> | A comma-separated list of interfaces, which the ORM class implements. The interfaces can be CAPI interfaces or external types. |
table "tablename" | The name of the database table to which the ORM class is mapped. Only non-abstract ORM classes are mapped to a database table. The default value is the class name of the ORM class (without namespace names). |
cached <referencetype> | The reference type that is used for caching instances of the ORM class in the ORM cache. The type can be one of strong, soft, weak or none. Default is soft. |
Constraints | |
primary key(<orm attributes>); | Defines the primary key of the ORM class, consists of a comma-separated list of ORM attribute names. Due to restrictions in the ORM engine, a primary key can only be declared in the top-most superclasses. |
alternate key(<orm attributes>); | Defines the alternate key of the ORM class, consists of a comma-separated list of ORM attribute names. Due to restrictions in the ORM engine, an alternate key can only be declared once in the whole inheritance hierarchy of an ORM class. |
semantic key(<orm attributes>); | Defines the semantic key of the ORM class, consists of a comma-separated list of ORM attribute names. |
index(<orm attributes>); | Defines an index on ORM attributes, consists of a comma-separated list of ORM attribute names. The index constraint can have the unique modifier, which represents a unique index on the attributes. |
An ORM attribute is a member of an ORM class.
The type of an ORM attribute can either be a primitive or an external type.
The optional length of the attribute defines the length of the underlying database column. It must be an integer. If not specified, the default length of the code generator applies.
The attribute can have a default value, which is given as a literal.
Modifiers | |
---|---|
localized | The attribute is localized, e.g., it can have multiple values, one for each locale. Due to restrictions in the JGen code generator, localized attributes are currently only supported for ORM classes that inherit from |
mapped | The attribute is not stored in this object directly, but it is mapped to an extensible object attribute (as non-localized attribute). Due to restrictions in the JGen code generator, mapped attributes are currently only supported for ORM classes that inherit from |
observable | The code generator will create |
readonly | The attribute can only be read, but there will be no setter method. |
replicated | Holds the attribute twice, as a "normal" column and as an extensible object attribute. Due to restrictions in the JGen code generator, localized attributes are currently only supported for ORM classes that inherit from |
required | The attribute must have a non-null value. This will be reflected by a database NOT NULL constraint. |
searchable | The ORM objects can be searched by this attribute, e.g. the generated ORM factory will get an additional |
Properties | |
column "columname" | The name of the database column to which this attribute is mapped. |
type "columntype" | The type of the database column to which this attribute is mapped. |
cached <referencetype> | The reference type that is used for caching instances of the ORM attribute in the ORM cache. The type can be one of strong, soft, weak or none. Default is strong. |
handler "handlername" | The Java class name of an ORM attribute handler implementation that can read / write the attribute from / to JDBC. |
An ORM relation is a member of an ORM class.
An ORM relation always points to an ORM class, e.g. the type is an ORM class. Its cardinality can be one of 0..1, 1..1 or 0..n.
Modifiers | |
---|---|
readonly | The relation is readonly, e.g., there are no setter methods. |
pageable | The relation is pageable, e.g., there are special getter methods that return an IPageable iterator. |
Properties | |
inverse <orm relation> | Specifies the relationship in the target ORM class that represents the inverse relation of this relation. This can be used to implement bidirectional relations. The inverse relation must have this relation as inverse relation. |
implements <capi relation> | If set, this ORM relation represents the implementation of the specified CAPI relation. Special adapter methods will be generated. |
cached <referencetype> | The reference type that is used for caching instances of the ORM relation in the ORM cache. The type can be one of strong, soft, weak or none. Default is soft. |
delete <deleteaction> | Specifies the delete action of the relation, if the parent object is removed. Can be one of default, remove, block or propagate. The delete action:
The default delete action depends on the cardinality of the parent object. If the parent object has the cardinality 1..1 (i.e. a parent must exist for each child), then the default delete action is propagate. If the parent object has the cardinality 0..1, then the default delete action is remove. |
Constraints | |
foreign key (<orm source attributes>) -> (<orm target attributes>); | The foreign key mapping of the relation. It specifies the mapping of one or multiple source attributes (which must be defined in this class) to one or more target attributes (which must be the primary key of the target class). For bidirectional relationships, the foreign key mapping must be provided on only one side of the relationship, which is the class that defines the foreign key attributes. |
Note
Due to restrictions in the JGen code generator, ORM relations must currently always be bidirectional.
ORM dependencies represent so-called weak relations for ORM classes. The type of an ORM dependency can either be an ORM class, or a CAPI interface. Currently, there are no modifiers. The cardinality is always 0..1.
Properties | |
---|---|
handler "handlerclass" | The Java class name of a dependency handler that can resolve the referenced objects by the foreign key attribute. |
Constraints | |
foreign key (<orm source attribute>); | The foreign key mapping of the dependency. Currently, a dependency always maps to the UUID of the target type, therefore this attribute must always be a single local attribute of type |
Here is a small example for the definition of two ORM classes in EDL:
primitive uuid; primitive string; namespace com.intershop.example { abstract orm class BusinessObject oca timestamp { primary key(UUID); unique index(name); attribute UUID : uuid; attribute name: string<256> type "CLOB" required; } orm class Product extends BusinessObject table "PRODUCT_TABLE" { attribute bundleID : uuid; relation bundledProducts : Product[0..n] inverse productBundle { foreign key (bundleID) -> (UUID); } relation productBundle : Product[0..1] inverse bundledProducts; } }
The CAPI models define the Enfinity cartridge API (CAPI). Typically, this is just a thin interface layer that is implemented by ORM classes or other Java classes.
Members can be CAPI attributes, constants, relations or operations.
Properties | |
---|---|
extends <superinterfaces> | A comma separated list of CAPI interfaces from which this interface inherits. |
A CAPI Attribute is a member of a CAPI interface. The type of a CAPI attribute can be a primitive type or an external type. The optional dimension defines the dimensions for arrays of the type. For each dimension, a pair of brackets must be specified, e.g., [][] stands for a two-dimensional array.
Modifiers | |
---|---|
localized | The attribute is localized, e.g., it can have multiple values, one for each locale. |
mapped | The attribute is not stored in this object directly, but it is mapped to an extensible object attribute (as non-localized attribute). |
readonly | The attribute can only be read, but there will be no setter method. |
required | The attribute must have a non-null value. |
A CAPI constant is a member of a CAPI interface. It defines a public static final attribute. The type can be a primitive type or an external type. The value must be provided as a literal.
A CAPI relation is a member of a CAPI interface. The type of the relation must be another CAPI interface. The cardinality can be 0..n or 0..1.
Modifiers | |
---|---|
readonly | If the relation can only be read, e.g. there is no setter. |
pageable | The relation is pageable, e.g. there are special getter methods that return an IPageable instance. |
A CAPI operation is a member of a CAPI interface. The parameter types and the return type of an operation can be a primitive type, a CAPI interface or an external type.
The optional dimension defines the dimensions for arrays of the parameter or return type. For each dimension, a pair of brackets must be specified, e.g., [][] stands for a two-dimensional array.
Properties | |
---|---|
throws <exceptions> | A comma-separated list of exceptions that the method throws. Exceptions are always external types, as they can currently not be defined in EDL. |
Here is a small example for the definition of CAPI types in EDL:
primitive float; primitive string; primitive uuid; external IllegalArgumentException type "java.lang.IllegalArgumentException"; namespace com.intershop.example { cartridge interface Product { attribute UUID : uuid readonly; operation getPrice(currency: string) : float throws IllegalArgumentException; } }
XML classes define Java data structures that can be converted into / from an XML representation by a generated encoder / decoder. An XML class can be a value type, or an object type, depending on its inheritance from the DValue or DObject superclasses (see JGen documentation).
The members can be XML attributes or XML containments.
Modifiers | |
---|---|
abstract | The class represents an abstract superclass. |
Properties | |
extends <xml superclass> | The XML super class. |
implements <capi interfaces> | A comma-separated list of CAPI interfaces that the type implements. |
An XML attribute is a member of an XML class. The type can be a primitive type or an external type. The optional dimension defines the dimensions for arrays of the attribute type. For each dimension, a pair of brackets must be specified, e.g. [][] stands for a two-dimensional array. The default value can be a literal.
Properties | |
---|---|
tag | The name of the attribute in the XML document. |
type | Defines how the attribute is mapped to XML, one of element, attribute or text. |
pattern | A formatter pattern to express an XML string conversion for some types, e.g. for date values. |
An XML containment is a member of an XML class that represents a sub-tree in an XML document. The type must be an XML class. The cardinality can be 0..1 or 0..n.
Properties | |
---|---|
tag | The name of the XML tag to which the containment is mapped. Default is the containment name. |
type | Defines how the containment is mapped to XML, one of element or text. |
import "enfinity:/core/src/com/intershop/core/foundation/common/DObject.edl"; primitive string; namespace com.intershop.example { xml class DProduct extends DObject { attribute name : string tag "product-name" type element; containment bundledProducts : DProduct[0..n] tag "bundled-products" type text; } }
The RAPI model defines the Enfinity remote API. It consists of RAPI interfaces that represent a single remote service each. Members can be RAPI operations.
Modifiers | |
---|---|
abstract | If the generated implementation represents an abstract superclass from which other services inherit. |
soap | If present, an additional SOAP stub / skeleton will be generated for the interface. |
binary | If present, the contents of SOAP messages will be encoded in binary form. Default is an XML encoding. |
Properties | |
extends <rapi superinterface> | The super class from which this remote interface inherits. |
RAPI operations represent method declarations for remote interfaces. The parameter types and the return type of an operation can be a primitive type, an XML type, a CAPI interface or an external type. The optional dimension defines the dimensions for arrays of the parameters or the return type. For each dimension, a pair of brackets must be specified, e.g. [][] stands for a two-dimensional array.
Properties | |
---|---|
throws <exceptions> | A comma-separated list of exceptions that the method throws. Exceptions are always external types, as they can currently not be defined in EDL. |