Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Programming
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Databases
Mail Systems
openSolaris
Eclipse Documentation
Techotopia.com
Virtuatopia.com

How To Guides
Virtualization
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Windows
Problem Solutions
Privacy Policy

  




 

 

Eclipse EMF Validation Framework
Previous Page Home Next Page

Tutorial: EMF Validation Adapter

Contents

Overview

The EMF Validation Framework provides a generic and extensible framework for defining constraints on EMF metamodels and for checking models against those constraints. It differs from the EValidator API in EMF in several important respects:

  • support for automatic validation on transaction boundaries: constraints can indicate that they are evaluated in "live" mode, as changes are made in a model, rather than by user demand.
  • dynamic extensibility: the framework is not based on code generation.
  • pluggable support for constraint languages such as OCL.

This tutorial will illustrate how a client application performs model validation using the Validation Framework. In particular, it will show you how to create an EValidator implementation that delegates to the validation framework, to provide user-demand "batch mode" validation from an EMF editor.

[ back to top]

References

This tutorial assumes that the reader is familiar with the Eclipse extension point architecture. There is an abundance of on-line help in Eclipse for those unfamiliar with extension points.

To see the complete source code for the examples shown in this tutorial, install the Validation Adapter Example plug-in into your workspace.

Other references:

[ back to top]

Creating the EValidator Implementation

Our EValidator implementation will delegate to the EMF Validation Framework to evaluate all active constraints on a sub-tree of a model. The metamodel that will target is the Library Metamodel example.

The EValidator API requires us to implement three methods, as shown:

    boolean validate(EObject eObject, DiagnosticChain diagnostics, Map context);

    boolean validate(EClass eClass, EObject eObject, DiagnosticChain diagnostics, Map context);

    boolean validate(EDataType eDataType, Object value, DiagnosticChain diagnostics, Map context);

We will extend the EObjectValidator class from the EMF API to inherit the basic EObject constraints. Then, we will concentrate our efforts on implementing the second of the EValidator methods, above, implementing the first by delegating to the second. The EMF Validation Framework does not validate EDataType values directly; it relies on constraints on EClasses to validate the EAttributes of their instances.

public class EValidatorAdapter
    extends EObjectValidator {

    private final IBatchValidator batchValidator;
    
    public EValidatorAdapter() {
        super();
        
        batchValidator =
            (IBatchValidator) ModelValidationService.getInstance().newValidator(
                EvaluationMode.BATCH);
        batchValidator.setIncludeLiveConstraints(true);
        batchValidator.setReportSuccesses(false);
    }

    public boolean validate(EObject eObject, DiagnosticChain diagnostics,
            Map context) {
        return validate(eObject.eClass(), eObject, diagnostics, context);
    }

The snippet above shows how we use the ModelValidationService to create a validator object to perform batch (user-triggered) validation. We want to include any constraints that also run in live mode, and are not interested in receiving informational statuses indicating which constraints pass.

First, we perform the superclass's validation (whatever that might be), then delegate to our IBatchValidator instance to evaluate constraints contributed to the EMF Validation Framework and convert the results to EMF Diagnostic s:

    public boolean validate(EClass eClass, EObject eObject,
            DiagnosticChain diagnostics, Map context) {
        super.validate(eClass, eObject, diagnostics, context);
        
        IStatus status = Status.OK_STATUS;
        
        if (diagnostics != null) {
            if (!hasProcessed(eObject, context)) {
                status = batchValidator.validate(
                    eObject,
                    new NullProgressMonitor());
                
                processed(eObject, context, status);
                
                appendDiagnostics(status, diagnostics);
            }
        }
        
        return status.isOK();
    }

When EMF's Diagnostician invokes our validator, it will assume that we are evaluating only a single object (not an entire content tree). The EMF Validation Framework takes the opposite approach: by default, batch validation is recursive over the object's content tree (though this can be changed by a client or a metamodel provider). This allows constraints to detect and avoid redundancy in evaluation on related elements and to implement other kinds of optimizations. Because of this difference, we need to ensure that our validator does not re-validate objects already reached from their containers, using the context map provided by the diagnostician:

    private void processed(EObject eObject, Map context, IStatus status) {
        if (context != null) {
            context.put(eObject, status);
        }
    }
    
    private boolean hasProcessed(EObject eObject, Map context) {
        boolean result = false;
        
        if (context != null) {
            while (eObject != null) {
                if (context.containsKey(eObject)) {
                    result = true;
                    eObject = null;
                } else {
                    eObject = eObject.eContainer();
                }
            }
        }
        
        return result;
    }

Finally, we need to convert the IStatus objects reported by the IBatchValidator to represent constraint violations to Diagnostic s:

    private void appendDiagnostics(IStatus status, DiagnosticChain diagnostics) {
        if (status.isMultiStatus()) {
            IStatus[] children = status.getChildren();
            
            for (int i = 0; i < children.length; i++) {
                appendDiagnostics(children[i], diagnostics);
            }
        } else if (status instanceof IConstraintStatus) {
            diagnostics.add(new BasicDiagnostic(
                status.getSeverity(),
                status.getPlugin(),
                status.getCode(),
                status.getMessage(),
                ((IConstraintStatus) status).getResultLocus().toArray()));
        }
    }

[ back to top]

Registering the EValidator Implementation

EMF provides extension points on which to register resource factories for file extensions and EPackages for namespace URIs. However, there is no extension point on which we can register our EValidator implementation for the Library Metamodel. Instead, we will create an org.eclipse.ui.startup extension to register our validator when the Eclipse platform launches. A real application would probably have some better trigger point than this. In our plugin.xml we define:

   <extension point="org.eclipse.ui.startup">
      <startup class="org.eclipse.emf.validation.examples.adapter.Startup"/>
   </extension>

Our start-up class then just needs to instantiate our validator and add it to the EValidator.Registry:

public class Startup
	implements IStartup {

	public void earlyStartup() {
		EValidator.Registry.INSTANCE.put(
			LibraryPackage.eINSTANCE,
			new EValidatorAdapter());
	}
}

Now, any invocation of EMF's "Validate" menu in the Library Editor will invoke the EMF Validation Framework to perform the validation.

[ back to top]

Summary

To illustrate how to implement an EMF Validation Framework client, we

  1. Created an EMF validator that performs validation using the model validation service.
  2. Registered the validator with an EMF metamodel to install the validator in the editor.

[ back to top]


Copyright (c) 2000,2005 IBM Corporation and others. All Rights Reserved.


 
 
  Published under the terms of the Eclipse Public License Version 1.0 ("EPL") Design by Interspire