Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 318489

Summary: Interface in EPackage with Classes with validation produces uncompilable ValidationClass
Product: [Modeling] EMF Reporter: Axel Uhl <eclipse>
Component: CoreAssignee: Ed Merks <Ed.Merks>
Status: RESOLVED WORKSFORME QA Contact:
Severity: normal    
Priority: P3 CC: ed
Version: unspecified   
Target Milestone: ---   
Hardware: PC   
OS: Windows XP   
Whiteboard:
Attachments:
Description Flags
Project reproducing the problem none

Description Axel Uhl CLA 2010-06-30 11:43:03 EDT
Build Identifier: 20100527-0614

For an EPackage, a ValidationClass is generated when there is at least one class inside that has a validation rule specified. However, when a validation class is generated, all classifiers including interfaces are used to generate validation methods for each of them. For interfaces this produces uncompilable code because the interfaces don't extend EObject but a call to EObjectValidator.validate_EveryDefaultConstraint is generated.

Workaround: put interfaces in a separate package that does not contain any classes with validation methods

Reproducible: Always

Steps to Reproduce:
1. create an Ecore model with an EPackage with an interface and a class
2. add an operation to the class, with an EBoolean operation taking an EDiagnosticChain and an EMap<EJavaObject, EJavaObject> argument
3. generate model code and try to compile the generated validator class
Comment 1 Ed Merks CLA 2010-07-01 10:20:51 EDT
I'm getting

  public boolean validateA(Serializable a, DiagnosticChain diagnostics, Map<Object, Object> context)
  {
    return validate_EveryDefaultConstraint((EObject)a, diagnostics, context);
  }

I.e., the instance is cast to EObject.

Please attach a test case rather than a description of how to produce one.

Note that I'm testing with EMF 2.6.
Comment 2 Axel Uhl CLA 2010-07-04 11:50:10 EDT
Created attachment 173374 [details]
Project reproducing the problem

I assume the problem originates from a specific set-up of a class in the OCL.ecore model: Visitor. It is configured as an interface, its generated version does for some reason not extend EObject.
Comment 3 Ed Merks CLA 2010-07-04 12:05:19 EDT
The generator expects Visitor to extend EObject (it's a generated interface and it's GenModel specifies EObject as the Root Extends Interface) but the actual source code blocks merging so that's not actually the case.
Comment 4 Ed Merks CLA 2010-07-04 12:56:01 EDT
Of course a simple workaround is to specialize the generated code like this.

    /**
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @generated not
     */
    public boolean validateB(B<?, ?, ?, ?, ?, ?, ?, ?, ?, ?> b, DiagnosticChain diagnostics, Map<Object, Object> context) {
        return validate_EveryDefaultConstraint((EObject)b, diagnostics, context);
    }
Comment 5 Axel Uhl CLA 2010-07-04 16:15:48 EDT
When a package only contains interfaces, no validator seems to be generated at all. I was wondering why validation code is generated into the validator for interfaces if they appear in a package also containing non-interface classes.
Comment 6 Ed Merks CLA 2010-07-05 09:11:01 EDT
When there is at least one constraint on at least one of the classes (even pure interfaces can have constraints) a validator that covers all classes in the package is generated. This generated validator "overrides" the default validator (EObjectValidator) that's otherwise used and otherwise covers all classes in the package.