-
Notifications
You must be signed in to change notification settings - Fork 1
EXPRESS 2 Xcore
This page holds a documentation concerning the transformation.
- Principle description
- Specific rules
- Annotations
EXPRESS is a standardized language (ISO 10303-11) which is used to model product data. It has an object flavour rather than a strict OO character. This means, that it supports the meaning of types and inheritance but does not follow strictly the meaning of type safety or a model-driven approach.
Actually, an EXPRESS scheme is a mixture of a model-driven workflow during design phase and an individual reasoning process during life-time. This fact sets up a challenge for any programmer of OO languages. Up to now, there are different approaches to provide OO APIs.
- JSDAI
- BIM server
The structural part of EXPRESS distinguishes to basic named concepts called ENTITY and TYPE. The only distinction between TYPE and ENTITY is caused by additional properties and the ability of inheritance.
In principle each ENTITY corresponds to a class definition. Abstract entities are mapped to abstract classes. Sub classes are always disjoint (i.e. ONE OF).
Each TYPE represents a datatype. A TYPE might be an alias for a builtin datatype (i.e. REAL) or an entity. In principle the M2M method recognizes pure aliases and will replace a TYPE reference by its transitive referenced basic datatype. Special types are SELECT and any type of aggregation (ARRAY, LIST, SET and BAG).
The schema creates a container for all entities and types. This is to declare a containment for individual in the schema.
SCHEMA IFC4;
...
ENTITY IfcWall ... END_ENTITY;
...
END_SCHEMA;
becomes
@XpressModel(kind="new", pattern="container")
class IFC4 {
// ...
contains IfcWall[] ifcWall
// ...
}Simple data types in EXPRESS are NUMBER, REAL, INTEGER, LOGICAL, BOOLEAN, STRING and BINARY. These are transformed to the build-in Java primitives, except for LOGICAL and BINARY.
| EXPRESS | Xcore |
|---|---|
NUMBER |
Double |
REAL |
Double |
INTEGER |
Integer |
LOGICAL |
enum Logical { TRUE = 0, FALSE = 1, UNKNOWN = 2 } |
BOOLEAN |
Boolean |
STRING |
String |
BINARY |
type Binary wraps java.util.BitSet |
Alias types simply rename an existing concept (i.e. REAL). These aliased types are resolved to their base type. This behaviour will be optional in future.
TYPE IfcAreaMeasure = REAL;
END_TYPE;
ENTITY IfcQuantityArea
AreaValue : IfcAreaMeasure;
END_ENTITY;
becomes
class IfcQuantityArea {
@P21 double areaValue
}First, there are four kinds of aggregation namely ARRAY, LIST, SET and BAG. Since all aggregations are mapped to lists in Ecore, only the properties of order and uniqueness control which insertion behaviour is implemented.
| EXPRESS | Xcore |
|---|---|
A = ARRAY[0:?] |
A[*] |
A = LIST[0:?] |
A[*] |
A = SET[0:?] |
unordered unique A[*] |
A = BAG[0:?] |
unordered A[*] |
Multiple cardinalities always map to an unbound upper range. Aggregation with 0 or 1 reference map to single reference types without aggregation.
Enumerations are mapped to enums in Xcore by numbering literals starting with 0. The first literal in the list is always the default one in EMF.
TYPE A = ENUMERATION OF (
Literal1, Literal2
);
END_TYPE;
becomes
enum A {
Literal1 = 0, Literal2 = 1
}There are two different kinds of alternative branching types called SELECT. First forms up an alternative which is aggregated into a single reference which is further called a referenced select type. The other opportunity is denoted as inverse relational select where a select acts as a branch of back references. As a result the relation becomes non-unique on the declaring side of inverse.
- Referenced selects are mapped to special additional classes which are comprised of an attribute to identify the current type of value and a bundle of unique types.
TYPE SimpleDoubleA = REAL;
END_TYPE;
TYPE SimpleDoubleB = REAL;
END_TYPE;
ENTITY Person;
END_ENTITY;
TYPE DoubleOrPersonSelect = SELECT (
SimpleDoubleA, SimpleDoubleB, Person
);
END_TYPE;
becomes
enum EnumDoubleOrPersonSelect {
SIMPLEDOUBLEA=0, SIMPLEDOUBLEB=1, PERSON=2
}
class Person {
}
class DoubleOrPersonSelect {
EnumDoubleOrPersonSelect select
double doubleValue
refers Person person
// ... additional operations
}- Inverse relational selects are mapped to a inheritance driven class graph where additional classes serve as delegates between both inverse bundled entities. Since non-unique relations cannot be embedded into Xcore directly, this normalization behaviour is needed. The pattern is denoted as relational delegation (see below).
An entity concept of EXPRESS is mapped to a class in Xcore. Abstract entities are mapped to abstract classes. Inheritance is mapped directly to Xcore. Multiple inheritance is and will be not supported. There are 3 types of attributes, explicit, derived and inverse attributes. Derived attributes are currently not handled. Inverse relations are handled by the opposite mechanism of Xcore.
ENTITY Organization;
ThePerson : Person;
END_ENTITY;
ENTITY Person;
GivenName : STRING;
FamilyName : STRING;
INVERSE
EngagedIn : Organization FOR ThePerson;
DERIVE
FullName : STRING := GivenName + ' ' + FamilyName;
END_ENTITY;
ENTITY Male SUBTYPE OF (Person);
END_ENTITY;
ENTITY Female SUBTYPE OF (Person);
END_ENTITY;
becomes
class Organization{
@P21 refers Person thePerson opposite engagedIn
}
class Person {
String givenName
String familyName
refers Organization engagedIn opposite thePerson
}
class Male extends Person {
}
class Female extends Person {
}EXPRESS has the possbility to define nested lists / multi-dimensional arrays. To support this in Xcore we need to introduce wrapper classes for the contained lists. An aggregration aggregates a class with another aggregration. :)
sectors : ARRAY [ 1 : 10 ] OF -- first dimension
ARRAY [ 11 : 14 ] OF -- second dimension
Something;
complex_list : LIST[0:10] OF UNIQUE ARRAY[1:10] OF INTEGER;
becomes
class XYZ {
@XpressModel(pattern="delegate")
@P21
contains SomethingInList [] sectors
@XpressModel(pattern="delegate")
@P21
contains IntInList[] complex_list
}
@XpressModel(kind="new", pattern="nested")
class SomethingInList {
refers Something[] aList
}
@XpressModel(kind="new", pattern="nested")
class IntInList {
int[] aList
}Relational properties of a pair of entities
ENTITY IfcBSplineSurface
ABSTRACT SUPERTYPE OF (ONEOF(IfcBSplineSurfaceWithKnots))
SUBTYPE OF (IfcBoundedSurface);
UDegree : IfcInteger;
VDegree : IfcInteger;
ControlPointsList : LIST [2:?] OF LIST [2:?] OF IfcCartesianPoint;
SurfaceForm : IfcBSplineSurfaceForm;
UClosed : IfcLogical;
VClosed : IfcLogical;
SelfIntersect : IfcLogical;
DERIVE
UUpper : IfcInteger := SIZEOF(ControlPointsList) - 1;
VUpper : IfcInteger := SIZEOF(ControlPointsList[1]) - 1;
ControlPoints : ARRAY [0:UUpper] OF ARRAY [0:VUpper] OF IfcCartesianPoint := IfcMakeArrayOfArray(ControlPointsList,
0,UUpper,0,VUpper);
END_ENTITY;
ENTITY IfcBSplineSurfaceWithKnots
SUPERTYPE OF (ONEOF(IfcRationalBSplineSurfaceWithKnots))
SUBTYPE OF (IfcBSplineSurface);
UMultiplicities : LIST [2:?] OF IfcInteger;
VMultiplicities : LIST [2:?] OF IfcInteger;
UKnots : LIST [2:?] OF IfcParameterValue;
VKnots : LIST [2:?] OF IfcParameterValue;
KnotSpec : IfcKnotType;
DERIVE
KnotVUpper : IfcInteger := SIZEOF(VKnots);
KnotUUpper : IfcInteger := SIZEOF(UKnots);
END_ENTITY;
becomes
@XpressModel(name="IfcBSplineSurface",kind="generated")
abstract class IfcBSplineSurface extends IfcBoundedSurface {
@P21 int uDegree
@P21 int vDegree
@XpressModel(pattern="delegate") @P21 contains IfcCartesianPointInList[] controlPointsList
@P21 IfcBSplineSurfaceForm surfaceForm
@P21 Logical uClosed
@P21 Logical vClosed
@P21 Logical selfIntersect
}
@XpressModel(name="IfcBSplineSurfaceWithKnots",kind="generated")
class IfcBSplineSurfaceWithKnots extends IfcBSplineSurface {
@P21 int[] uMultiplicities
@P21 int[] vMultiplicities
@P21 double[] uKnots
@P21 double[] vKnots
@P21 IfcKnotType knotSpec
}
IfcAnnotation, IfcGrid and IfcElement (not shown here) declare an inverse relation ContainedInStructure to the attribute RelatedElements of the objectified relation IfcRelContainedInSpatialStructure. This attribute itself declares the type of the attribute to be IfcProject the suppertype of IfcAnnotation, IfcGrid and IfcElement. The inverse relation opens a triangle of involved entities through the inheritance graph. This can not be reflected in Xcore directly and need helper classes to resolve the inverse relations correctly.
ENTITY IfcAnnotation
SUBTYPE OF (IfcProduct);
INVERSE
ContainedInStructure : SET [0:1] OF IfcRelContainedInSpatialStructure FOR RelatedElements;
END_ENTITY;
ENTITY IfcGrid
SUBTYPE OF (IfcProduct);
UAxes : LIST [1:?] OF UNIQUE IfcGridAxis;
VAxes : LIST [1:?] OF UNIQUE IfcGridAxis;
WAxes : OPTIONAL LIST [1:?] OF UNIQUE IfcGridAxis;
PredefinedType : OPTIONAL IfcGridTypeEnum;
INVERSE
ContainedInStructure : SET [0:1] OF IfcRelContainedInSpatialStructure FOR RelatedElements;
END_ENTITY;
ENTITY IfcRelContainedInSpatialStructure
SUBTYPE OF (IfcRelConnects);
RelatedElements : SET [1:?] OF IfcProduct;
RelatingStructure : IfcSpatialElement;
END_ENTITY;
becomes
@XpressModel(name="IfcAnnotation",kind="generated")
class IfcAnnotation extends IfcProduct {
@XpressModel(pattern="delegate")
contains unordered unique DelegateIfcAnnotationIfcRelContainedInSpatialStructure[] containedInStructure opposite relatedElements
}
@XpressModel(name="IfcGrid",kind="generated")
class IfcGrid extends IfcProduct {
// ...
@XpressModel(pattern="delegate")
contains unordered unique DelegateIfcGridIfcRelContainedInSpatialStructure[] containedInStructure opposite relatedElements
}
@XpressModel(name="IfcRelContainedInSpatialStructure",kind="generated")
class IfcRelContainedInSpatialStructure extends IfcRelConnects {
@XpressModel(pattern="delegate")
@P21 refers unordered unique DelegateIfcRelContainedInSpatialStructureIfcProduct[] relatedElements opposite ifcRelContainedInSpatialStructure
// ...
}
@XpressModel(kind="new", pattern="delegate")
interface DelegateIfcRelContainedInSpatialStructureIfcProduct {
// Inverse super type
op IfcProduct getRelatedElements()
// Non-unique counter part, using concept QN as reference name
refers IfcRelContainedInSpatialStructure ifcRelContainedInSpatialStructure opposite relatedElements
}
@XpressModel(kind="new", pattern="delegate")
class DelegateIfcAnnotationIfcRelContainedInSpatialStructure extends DelegateIfcRelContainedInSpatialStructureIfcProduct {
// Containment on declaring side of IfcAnnotation
container IfcAnnotation relatedElements opposite containedInStructure
}
@XpressModel(kind="new", pattern="delegate")
class DelegateIfcGridIfcRelContainedInSpatialStructure extends DelegateIfcRelContainedInSpatialStructureIfcProduct {
// Containment on declaring side of IfcGrid
container IfcGrid relatedElements opposite containedInStructure
}Version 0.2
- No WHERE rules are embedded
- No Functions are embedded
- Derived attributes are marked as derived but will not be computed (since this feature is based on functions)
During the process of transformation the generator creates annotations to mark decisions made by the procedure. Since not all features of EXPRESS can be handled by an OO language like Java, additional information are needed to support the P21 reading and writing process. Only explicit attributes are exchanged through P21 files and the appear in the order of their declaration inside of the entity. The @P21 annotation marks attributes which are exchanged to garranty the correct mapping.
The namespace of XpressModel-annotations is http://www.bitub.de/express/XpressModel.
The namespace of P21-annotations is http://www.bitub.de/express/P21.
| Key | Values | Context | Description |
|---|---|---|---|
| name | text | class, method, property | Name of original entity or type |
| type | {mapped, delegate, nested} | class, method, property | Type of approach |