Custom EObject fields
1. Intro
To create a new EMF-based project derived from an existing one, the typical approach involves:
-
Creating a new datamodel bundle that inherits from the parent project’s datamodel.
-
Adding new EClasses as children of the parent datamodel EClasses.
-
Defining additional fields in the new EClasses for child project-specific information.
However, this process requiring an entirely new datamodel bundle just for minor extensions can feel excessive, especially when only a single new field is needed.
The Amalgama Platform offers a more flexible alternative:
instead of extending the datamodel, you can inherit your EClass from CustomFieldContainer
.
This allows objects of your EClass to support custom fields—key-value pairs that can be dynamically assigned to individual EObjects.
In this article, we’ll explore how custom EObject fields work.
To follow along, ensure you have an Eclipse project with a bundle of 'Ecore Modeling Project' type containing a valid datamodel (.ecore
and .genmodel
files).
2. Adding ecoreutils
to your source code
The ecoreutils
bundle in the Amalgama Platform provides essential EClasses and utility classes to work with custom fields.
You will need to do the following steps to make ecoreutils
functionality available in your code.
2.1. Integrating ecoreutils
into your datamodel
If your datamodel doesn’t yet use ecoreutils
, follow these steps to enable its functionality:
-
Update MANIFEST.MF Dependencies:
-
Open the MANIFEST.MF file of your datamodel bundle.
-
Navigate to the Dependencies tab and add the following to the Required Bundles list:
com.amalgamasimulation.ecoreutils
,org.apache.commons.math3
-
-
Reference
ecoreutils
in your Ecore Model:-
Open your datamodel’s .ecore file in the Ecore editor.
-
Right-click in the editor and select "Load Resource…" from the context menu.
-
In the dialog that appears, click "Browse Target Platform Packages…".
-
Locate and double-click the
https://amalgamasimulation.com/ecoreutils
item. -
Click OK to confirm.
-
After completing the previous steps, you should now see the ecoreutils item appear in your datamodel’s .ecore file editor. This confirms that the ecoreutils EClasses are now available for use in your project.
You can now add CustomFieldContainer
EClass to the list of parent classes of any of your ECore classes that you’d like to have custom fields.
2.2. Updating the Genmodel After First Use of ecoreutils
After using any ecoreutils
EClasses in your datamodel for the first time, perform these one-time configuration steps:
-
Locate and open your datamodel’s .genmodel file in the editor The editor will look like this (note that 'datamodel' and 'ecoreutils' icons look similar):
-
In 'genmodel' file editor, open the context menu and click 'Reload'.
-
In the 'Model importers' list, select 'Ecore model' and click 'Next'.
-
In the 'Ecore Import' page, do not change anything , just click 'Next'.
-
In the 'Package Selection' page:
-
In the 'Root packages' list, only select one package - that of your datamodel.
-
In the 'Referenced generator models' list, select the 'Ecoreutils' item.
-
-
Click 'Finish' to complete the configuration.
Now the genmodel should look like this:

Note that 'Ecoreutils' icon has changed - now this is a referenced datamodel.
Since custom fields are managed programmatically,
you will need to add
the com.amalgamasimulation.ecoreutils
dependency to any bundle that contains Java code for working with custom fields.
|
2.3. Updating EMFExcelTransform
The EMFExcelTransform
singleton object is typically created in the 'datamodel' bundle.
It contains references to used datamodel packages and other settings, such as custom names of Excel sheets in the scenario files.
In your application, locate the EMFExcelTransform
creation code and augment its construction with the following instruction:
.addPackage(EcoreutilsPackage.eINSTANCE)
Now that you have done so, custom fields (based on ecoreutils
classes) will be saved to and read from a scenario file.
If the EcoreutilsPackage is not added to the EMFExcelTransform object, custom fields will not be included in the scenario file and will be lost without warning.
To prevent this, ensure the EcoreutilsPackage is added when constructing the EMFExcelTransform object
|
3. Custom Fields Usage
3.1. CustomFieldContainer
EClass
To enable custom fields for any of your EClasses:
-
In your .ecore file, select the EClass that should support custom fields.
-
Add
CustomFieldContainer
EClass fromecoreutils
to its list of parent EClasses.
This inheritance grants all instances of your EClass the ability to store dynamic custom fields without requiring datamodel extensions.
3.2. Custom value fields
Custom value fields are similar to EMF EAttributes.
-
All primitive Java types and their wrapper classes;
-
String
; -
java.awt.Color
; -
LocalDateTime
,LocalTime
,DayOfWeek
;
All such value fields are serialized to a String
when stored to an Excel, ZIP, or XML file.
To add a custom value field, call the CustomFields.putValue() method.
To read a custom value field, use various get…()
methods in the CustomFields
class: getDouble()
, getInt()
, etc.
To remove a custom value field, call CustomFields.removeCustomField()
.
Custom value fields are represented by the CustomValueField
EClass from ecoreutils
.
When a scenario is saved to a file, all custom value fields from all its EObjects are stored to the 'CustomValueField' sheet.
3.3. Custom reference fields
Custom value fields are similar to EMF EReferences - this is a reference to some EObject.
To add a custom reference field, call the CustomFields.putReference() method.
To read a custom reference field, use the getReference() method of CustomFields
class.
To remove a custom reference field, call CustomFields.removeCustomField()
- the same method as for custom value fields.
Custom reference fields are represented by the CustomReferenceField
EClass from ecoreutils
.
When a scenario is saved to a file, all custom references from all its EObjects are stored to the 'CustomReferenceField' sheet.
3.4. A Note on EMF Containment
In EMF, all EObjects must have a container (in the EMF sense) and be contained — directly or indirectly — within the root EObject
. If an EObject
is not properly contained, it will be lost when the data model is saved to a file.
To support custom references to non-contained EObjects
, a special rule applies:
-
When adding a custom reference field to an
EObject
that is not yet contained, the reference field itself becomes the EObject’s container (in the EMF sense). -
You can safely change the EObject’s containment later.
There are two special cases you neet to keep in mind.
Case 1: Custom reference field EObject has an empty container reference
If:
-
The
EClass
of the custom reference fieldEObject
declares anEReference
to anotherEClass
(intended as the container), and -
This
EReference
is empty in theEObject
being added as a custom reference field,
then a console warning is generated, indicating that the EObject
expects its container field to be filled.
If you see a warning - ensure the EObject
is properly contained (in the EMF sense) before adding it as a custom reference field.
Case 2: Root EClass has a collection-type field of custom reference field EObject’s EClass
If the root EClass
of your datamodel has a field that:
-
is an
EReference
to custom reference field EObject’sEClass
, -
is an array (can contain many references),
-
has 'Containment=true' property,
then all EObjects of custom reference field EObject’s EClass
must be properly contained (in EMF sense)
only by the root EObject
.
Ensure you make such EObjects contained (in EMF sense) by the root EObject
of your data model — either before or after adding them as the custom reference fields.
Consequences of improper containment:
-
During save operation: the custom reference field
EObject
will not be saved to the file because it was expected (but failed) to be contained by the rootEObject
. -
During load operation: an error will occur because the custom reference field points to a now-missing
EObject
.