EMF: How to set values for attributes of a Class?

197 Views Asked by At

I'm working on a project in EMF, where I have created a simple order system. A part of the system is presented on the picture below:

enter image description here

So an OrderItem object will have a reference to only one product and its price will be calculated by the quantity of OrderItem times the price of the Product. The attribute isValid must be set whenever OrderItem.quantity changes, e.g. if Product.quantity < OrderItem.quantity then set isValid=false else true.

My question is how can I achieve this, so when I am creating an instance of the model using the Editor or changing some instance variable, dependent variables are updated automatically? (Should I rewrite the generated code? Should I override the set() method using Annotation? Should I use AQL or Services?) Thank you!

1

There are 1 best solutions below

0
On

The scenario that you present touches on an important aspect of EMF and model-driven engineering in general, model validation.

Model validation, as the name suggests, is the process of checking whether a model is valid or not. EMF provides a convenient mechanism for this that can help you keep implementation complexity under control.

EMF defines two concepts related to model validation, invariants and constraints.

Invariants are assertions about your models that must be true at all times, whereas constraints are assertions about your models that must be true at some point in time (before executing a certain process perhaps). I cannot tell from your question whether you would like to check product quantities only before shipping for example or constantly check them. It is an application-specific decision that is up to you. I will explain invariants below.

In terms of Ecore model, invariants are defined as operations of the class whose instances you are validating. Here for example for the class OrderItem, you would add an Operation (named checkProduct quantity for example). Operations that represent invariants need to return EBoolean and accept two arguments, one EDiagnosticChain and one EMap argument.

Once you add the above to your Ecore model, the EMF generator will detect that you want to define an invariant and will generate a specific method, as well as a utility class YourDSLValidator. You need to manually modify the generated method based on the things you are validating. For example here, you would have something like the following.

/**
 * <!-- begin-user-doc -->
 * <!-- end-user-doc -->
 * @generated
 */
public boolean checkProductQuantities(DiagnosticChain diagnostics, Map<?, ?> context) {
    // TODO: implement this method
    // -> specify the condition that violates the invariant
    // -> verify the details of the diagnostic, including severity and message
    // Ensure that you remove @generated or mark it @generated NOT
    if (false) {
        if (diagnostics != null) {
            diagnostics.add
                (new BasicDiagnostic
                    (Diagnostic.ERROR,
                     PanoptesDSLValidator.DIAGNOSTIC_SOURCE,
                     PanoptesDSLValidator.BASE_ALGORITHM_EXECUTION__CHECK_PARAMETERS,
                     EcorePlugin.INSTANCE.getString("_UI_GenericInvariant_diagnostic", new Object[] { "checkParameters", EObjectValidator.getObjectLabel(this, context) }),
                     new Object [] { this }));
        }
        return false;
    }
    return true;
}

You would then basically modify the if(false) part to if(this.quantity < this.OrderItem.getQuantity)

With the above you can now validate your models programmatically but also validate them inside the generated eclipse editor.

There are a lot of extra functionality that EMF provides. If you would like to find out more about EMF internals, I would definitely recommend the EMF book https://www.informit.com/store/emf-eclipse-modeling-framework-9780321331885 as it has a lot of information that is not available with a simple google search.