EEX Specification
Version: 0.5 2017.09.15 AET
"EEX" is acronym for EDM EXPRESS Extension Schema, and is also the file extension used for such files.
EXPRESS_EXTENSION_SCHEMA Declaration
EXPRESS_EXTENSION_SCHEMA extensionSchemaName FOR expressSchemaName; <body> END_EXPRESS_EXTENSION_SCHEMA;
EXPRESS_EXTENSION_SCHEMA extensionSchemaName {‘GUID’} FOR expressSchemaName;<body> END_EXPRESS_EXTENSION_SCHEMA;
The reason for the optional GUID is to be able to track/label one particular version of an extension schema and population(data).
Example: exporting a population including “extension schema data” on a step file package. When importing such step file package, the GUID is used to ensure that the extension schemata in the importing DB is exactly the same as in the exporting DB. There will be an option in write/read step file package to include exporting/defining of the extension schemata.
ENTITY Declaration
ENTITY declarations in an extension schema have the same syntax as in an Express schema except the following:
- Declarations not supported: UNIQUE , WHERE
- Extension: GENERIC_ENTITY is allowed as domain for all attribute types.
- Extension: INVERSE attribute may be declared: ALL_LOCAL_REFS_TO_ME : SET OF GENERIC_ENTITY; -- no “ FOR ‘attributeName’ “
- The attribute will return a set containing all instances that refers this instance within the same model
- Extension: INVERSE attribute may be declared: ALL_CROSS_MODEL_REFS_TO_ME : SET OF GENERIC_ENTITY; -- no “ FOR ‘attributeName’ “
- The attribute will return a set containing all instances that refers this instance within the same database - all models
ENTITY_EXTENSION Declaration
The ENTITY_EXTENSION – END_ENTITY_EXTENSION as earlier agreed, plus the same extensions for attribute declarations as for ENTITY.
ENTITY_EXTENSION ‘entity_extension_name’ FOR ‘expressEntityName’; <body> END_ENTITY_EXTENSION;
ENTITY_EXTENSION ‘entity_extension_name’ FOR SUBTYPES ‘expressEntityName’; <body> END_ENTITY_EXTENSION;
Additional rules:
- EESR #22: A name of an ENTITY_ EXTENSION declaration must only be unique in the collection of all ENTITY_EXTENSION declarations in the actual extension schema. (22)
- Technically there is no problem to allow an ENTITY_EXTENSION name to have the same name as other declarations (ENTITY, TYPE, FUNCTION …etc), but for “readability” we may not permit it.
- EESR #23: There must be only one ENTITY_ EXTENSION declaration for the same entity in one extension schema
- With the use of SUBTYPES declaration, there may be implicitly more than one ENTITY_ EXTENSION that extends the same entity:
We can discuss how many of the ”extension schema rules checking” we implement in the compiler and how many we implement in the edmCloseExtensionSchemaCompilerModel() (similar as edmCloseCompilerModel()).
Supported EXPRESS Declarations
The following Express declarations are supported:
- TYPE - without the WHERE
- ENTITY – with the above listed restrictions and extensions
- Subtype_constraint – to be decided???
- CONSTANT
- FUNCTION
- PROCEDURE
Not supported EXPRESS Declarations
The following Express declarations are not supported:
- SCHEMA
- RULE (Rules can be written in separate RULE_SCHEMA)
New tokens (reserved words):
ALL_CROSS_MODEL_REFS_TO_ME
ALL_LOCAL_REFS_TO_ME
END_ENTITY_EXTENSION
ENTITY_EXTENSION
END_EXPRESS_EXTENSION_SCHEMA
EXPRESS_EXTENSION_SCHEMA
Compiler checking
In addition to the “standard compilation time checking” during defining (compilation) of an extension schema, the following will be checked:
- EESR #31: NumberOfExtensionSchema for ExpressSchema < MAX_EXTENSION_SCHEMATA for an Express schema
- EESR #32: ExtensionSchema name already exist for the particular Express schema
- EESR #33: All ENTITY names must be unique in the collection of Express schema and all extension schemata for the actual Express schema.
- EESR #34: In addition to the rule in the Express language for “unique attribute names in an Entity declaration” , attribute names must be unique in the collection of all ENTITY_EXTENSION for a particular entity in all extension schemata for the actual Express schema.
- The ALL_CROSS_MODEL_REFS_TO_ME and ALL_LOCAL_REFS_TO_ME are exceptions to this constraint. When a combination of extension schemata results in more duplicates of these attributes, this “problem” will be resolved when the actual model will be created, such that the actual entity instances will have only one occurrence of each of these attributes;
We can discuss how many of the ”extension schema rules checking” we implement in the compiler and how many we implement in the edmCloseExtensionSchemaCompilerModel() (similar as edmCloseCompilerModel()).
Syntax Illustration 0.5
(** Check basic elements for EXTENSION_SCHEMA Should compile with no errors *) EXPRESS_EXTENSION_SCHEMA EEX_1011 FOR IFC4; GLOBAL gGeneric : GENERIC; gGenericEntity : GENERIC_ENTITY; geexEntity : eexEntity; END_GLOBAL; CONSTANT cInteger : INTEGER := 1; END_CONSTANT; ENTITY eexEntity; explicitAttr1 : INTEGER; explicitAttr2 : GENERIC_ENTITY; DERIVE derivedAttr1 : STRING := foo1(SELF); derivedAttr2 : STRING := foo2(SELF); INVERSE cross_references : SET OF GENERIC_ENTITY FOR ALL_CROSS_MODEL_REFERENCES_TO_ME; local_refs: SET OF GENERIC_ENTITY FOR ALL_LOCAL_REFS_TO_ME; END_ENTITY; ENTITY eexTask SUBTYPE OF(ifcTask); explicitAttr1 : INTEGER; END_ENTITY; ENTITY_EXTENSION extToIfcSpace FOR IfcSpace; (* Attribute name must be unique within the extended entity (ifcxx1), may be same as attribute names in super type Entity. When so, this extended attribute must be accessed by name using "full qualified attribute name". The attribute domains can be any domain in the actual schema or domain (instance type) defined in the current extension schema *) extendedExplicitAttr1 : STRING; -- any simple data type can be used, not defined types extendedExplicitAttr2 : GENERIC_ENTITY; --sdaiINSTANCE of any type. can be used as link to instance in any other model. extendedExplicitAttr3 : SET OF GENERIC_ENTITY; DERIVE extendedDeriveAttr : SET OF GENERIC_ENTITY := foo4(SELF); INVERSE cross_references : SET OF GENERIC_ENTITY FOR ALL_CROSS_MODEL_REFERENCES_TO_ME; local_refs : SET OF GENERIC_ENTITY FOR ALL_LOCAL_REFS_TO_ME; -- extendedInverseAttr : SET OF GENERIC_ENTITY FOR (entityx.explicitAttr1, entityx.explicitAttr2, ...entityz.explicitAttr5); END_ENTITY_EXTENSION; ENTITY_EXTENSION extToIfcElementSubtypes FOR SUBTYPE IfcElement; (* same as ENTITY_EXTENSION except that all extensions will be valid for all subtypes of the extended entity, i.e., all subtypes of IfcElement *) extendedExplicitAttr1 : STRING; -- any simple data type can be used, not defined types -- INVERSE -- extendedInverseAttr : SET OF GENERIC_ENTITY FOR (entityx.explicitAttr1, entityx.explicitAttr2, ...entityz.explicitAttr5); END_ENTITY_EXTENSION; FUNCTION foo1(arg : GENERIC) : STRING; RETURN('typename'); END_FUNCTION; FUNCTION foo2(arg : GENERIC_ENTITY) : STRING; RETURN('typename'); END_FUNCTION; FUNCTION foo4(arg : GENERIC_ENTITY) : SET OF GENERIC_ENTITY; LOCAL result : SET OF GENERIC_ENTITY := []; END_LOCAL; RETURN(?); END_FUNCTION; PROCEDURE poo1(arg1 : GENERIC;VAR arg2: GENERIC); arg1.explicitAttr1 := 2; arg2.explicitAttr1 := 2; END_PROCEDURE; PROCEDURE poo2(arg1 : GENERIC_ENTITY;VAR arg2: GENERIC_ENTITY); arg1.explicitAttr1 := 2; arg2.explicitAttr1 := 2; END_PROCEDURE; -- AET 20181101 - proposal for methods in entities: -- enhance DERIVE to allow parameters - then the "attribute" becomes a method: -- there are several possible variants of syntax, see this as an example -- Example: add MOVE method to cartesian point ENTITY_EXTENSION ext2IfcCartesianPointSpace FOR IfcCartesianPoint; DERIVE -- move the point in direction given by x,y,z return the updated point Move(x,y,z: IfcLengthMeasure) : IfcCartesianPoint := IfcCartesianPoint_Move(SELF,x,y,z); END_ENTITY_EXTENSION; -- note that VAR must be allowed here, if no VAR we would just move a copy of the point FUNCTION IfcCartesianPoint_Move(VAR p: IfcCartesianPoint; x,y,z: IfcLengthMeasure): IfcCartesianPoint; p.Coordinates[1] := p.Coordinates[1] + x; p.Coordinates[2] := p.Coordinates[2] + y; p.Coordinates[3] := p.Coordinates[3] + z; RETURN(p); END_FUNCTION; -- variant: declare method directly as "function" - the term "FOR <entity> indicates it is a method FUNCTION Move(x,y,z: IfcLengthMeasure) FOR IfcCartesianPoint: IfcCartesianPoint; SELF.Coordinates[1] := SELF.Coordinates[1] + x; SELF.Coordinates[2] := SELF.Coordinates[2] + y; SELF.Coordinates[3] := SELF.Coordinates[3] + z; RETURN(SELF); END_FUNCTION; -- easier to read but defines new operator "scope resolution" = '::' -- Arnes Favourite :) FUNCTION IfcCartesianPoint::Move(x,y,z: IfcLengthMeasure): IfcCartesianPoint; SELF.Coordinates[1] := SELF.Coordinates[1] + x; SELF.Coordinates[2] := SELF.Coordinates[2] + y; SELF.Coordinates[3] := SELF.Coordinates[3] + z; RETURN(SELF); END_FUNCTION; -- variant: declare method inside entity - uses BEGIN and END keywords. Arne does not like it :( ENTITY_EXTENSION ext2IfcCartesianPointSpace FOR IfcCartesianPoint; DERIVE Move : IfcCartesianPoint(x,y,z: IfcLengthMeasure) : IfcCartesianPoint; BEGIN SELF.Coordinates[1] := SELF.Coordinates[1] + x; SELF.Coordinates[2] := SELF.Coordinates[2] + y; SELF.Coordinates[3] := SELF.Coordinates[3] + z; RETURN(SELF); END; END_ENTITY_EXTENSION; -- END_AET 20181101 - proposal for methods in entities: END_EXPRESS_EXTENSION_SCHEMA;
Historical: