Search code examples
eclipse-emfemfeclipse-emf-ecoreoclecore

Can derived attributes be persisted and derivation disabled in Ecore and OCL?


I want to port a legacy data format, which consists of concepts similar to Eclipse Modeling Framework (EMF) Ecore: Elements with Parameters which have different datatypes and default values.

A custom-made tool lets you edit such model instances by a fancy table-based GUI.

Also, a common feature for the Parameters is that a Derivation Rule can be added which specifies that the Parameter value gets computed automatically from other parameters. That also seems similar to Ecore derived Attributes which could be implemented by Java Code or OCLinEcore.

However, the automatic derivation of a Parameter in the legacy format is optional. I.e. a user can always select such a derived parameter and select that he or she wants to enter the value manually. Hence, even derived Parameter values are not transient but always persisted, including the state whether the parameter is in "auto" or "manual" mode.

Is there any way in Ecore (including extensions like OCLinEcore) to persist derived attributes and to selectively/temporarily enable/disable derivation at runtime?

Workaround could be not to use Ecore's derived Attribute feature but to implement the optional derivation in the client code manually. However, the declaration of the optional derivation rule would be no Standard way. Any way to reuse OCLinEcore or alike?


Solution

  • Here is how do I do it in Xcore:

    interface Identifier {
        id String uid
        boolean derive_enabled = "true"
        unsettable String uid_derived
    
        readonly String uid_generated get {  // this is the 'derived' parameter
            if (uid_derived == null || uid_derived.isEmpty) {
                uid_derived  = EcoreUtil.generateUUID().toString
            }
            if (derive_enabled) {
                uid = uid_derived
            }
            return uid
        }
    }
    

    You can easily implement it in Ecore/OCL-in-Ecore as well.

    I persist the derived value of the parameter, but I can always change it manually (if I like) by changing the value of the boolean parameter. Then, I implement this interface for any class I need, so I have this feature globally.