Home » Modeling » OCL » Ignoring OCL during Ecore validation possible ?
Ignoring OCL during Ecore validation possible ? [message #1826389] |
Fri, 24 April 2020 05:11  |
Eclipse User |
|
|
|
I have an Ecore model with Pivot OCL constraints embedded (using OCLInEcore). I am validating instances loaded from ecore using
Diagnostician.INSTANCE.validate (eObject)
where eObject is the root element in the instance. Validation fails (rightly so!) because some of my constraints are violated. My question is, is it possible to somehow deactivate validation of OCL constraints in such case? (for education reasons I would like to be able to run validation with and without OCL, using the same meta-model).
|
|
| | | |
Re: Ignoring OCL during Ecore validation possible ? [message #1826466 is a reply to message #1826403] |
Sat, 25 April 2020 06:59   |
Eclipse User |
|
|
|
This lazy loading and reloading seems to be chasing me. I had no success with EValidator.Registry.INSTANCE. Whether I put a dummy there, or simply removed, it seemed to have no effect. I suspect that things got reloaded before I managed to see the difference. So I tried EValidator.ValidationDelegate.Registry. I created (apologies for Scala syntax):
private class DummyDelegate extends EValidator.ValidationDelegate {
override def validate (
eClass: EClass,
eObject: EObject,
context: java.util.Map[java.lang.Object, java.lang.Object],
invariant: EOperation,
expression: java.lang.String): Boolean = true
override def validate(
eClass: EClass,
eObject: EObject,
context: java.util.Map[java.lang.Object, java.lang.Object],
constraint: java.lang.String,
expression: java.lang.String): Boolean = true
override def validate(
eDataType: EDataType,
value: java.lang.Object,
context: java.util.Map[java.lang.Object, java.lang.Object],
constraint: java.lang.String,
expression: java.lang.String): Boolean = true
}
and then registered it as follows:
private val dummyDelegate = new DummyDelegate
EValidator.ValidationDelegate.Registry.INSTANCE .put (OCL_DELEGATE_URI_PIVOT, dummyDelegate)
I am doing this dynamically (registering a dummy delegate, or whatever was there before) depending whether I need a test-case to check OCL or not. This does seem to work. To an extent. If I run few test cases, OCL seems to deactivate nicely, and I see behavior as I want (as if the constraints were not in the Ecore file).
When I run many tests, I am starting to see some Heisenbugs. Once in a while one of the tests fails due to lack of delegate for OCL. So magically OCL managed to activate. I get various errors, for example "org.eclipse.ocl.pivot.internal.utilities.IllegalLibraryException: No OCL Standard Library content available" or some classes missing. It is a different test that fails and often a different runtime error each time. It seems that OCL somehow manages to activate partially once in a while, even if I do not want it to. Something in the background (the lazy initialization?) must be kicking in.
I also tried do a dummy substitution in EValidator.Registry.INSTANCE. Even though, it did not prevent OCL validation in the first place, Perhaps it will improve stability. My present validation code looks roughly like this:
val oclDelegate =
EValidator.ValidationDelegate.Registry.INSTANCE.get (OCL_DELEGATE_URI_PIVOT)
val oclValidator =
EValidator.Registry.INSTANCE.get (org.eclipse.ocl.pivot.PivotPackage.eINSTANCE)
val essentialValidator =
EValidator.Registry.INSTANCE.get (org.eclipse.ocl.xtext.essentialoclcs.EssentialOCLCSPackage.eINSTANCE)
val baseValidator =
EValidator.Registry.INSTANCE.get (org.eclipse.ocl.xtext.basecs.BaseCSPackage.eINSTANCE)
EValidator.ValidationDelegate.Registry.INSTANCE
.put (OCL_DELEGATE_URI_PIVOT, dummyDelegate)
EValidator.Registry.INSTANCE
.put (org.eclipse.ocl.pivot.PivotPackage.eINSTANCE, dummyValidator)
EValidator.Registry.INSTANCE
.put (org.eclipse.ocl.xtext.essentialoclcs.EssentialOCLCSPackage.eINSTANCE, dummyValidator)
EValidator.Registry.INSTANCE
.put (org.eclipse.ocl.xtext.basecs.BaseCSPackage.eINSTANCE, dummyValidator)
val diagnostic = Diagnostician.INSTANCE.validate (root)
EValidator.ValidationDelegate.Registry.INSTANCE
.put (OCL_DELEGATE_URI_PIVOT, oclDelegate)
EValidator.Registry.INSTANCE
.put (org.eclipse.ocl.pivot.PivotPackage.eINSTANCE, oclValidator)
EValidator.Registry.INSTANCE
.put (org.eclipse.ocl.xtext.essentialoclcs.EssentialOCLCSPackage.eINSTANCE, essentialValidator)
EValidator.Registry.INSTANCE
.put (org.eclipse.ocl.xtext.basecs.BaseCSPackage.eINSTANCE, baseValidator)
DummyValidator is an instance of a class very similar to the DummyDelegate above. Unfortunately, this does not work either. The OCL validator would activate for a random check with the above procedure once in a while. Usually just 1 per probably 2-3 dozens of tests I have, but different one each time. What does seem to help (still testing), is to remove the put commands after the check of diagnostics, but I thought I need that (in case, I wanted to validate OCL later in the code).
Frankly, I do not know what I am doing. Any further hint, or thought would be invaluable.
[Updated on: Sat, 25 April 2020 07:44] by Moderator
|
|
| |
Re: Ignoring OCL during Ecore validation possible ? [message #1826472 is a reply to message #1826469] |
Sat, 25 April 2020 10:09   |
Eclipse User |
|
|
|
I dug a bit deeper. The only explanation why it does not work that I could sniff on the Internet, is that I am running in Standalone mode outside Eclipse. I do not understand what delegators do, but they seem to be crucial in such setup. So my solution still uses delegators.
I found the error somewhere else in my setup. Basically, this idea of switching delegators/validators around as per validation call (depending whether I need OCL or not) is not thread safe. I realized that my testing framework (scalatest) was running my two test suites in parallel, and the two threads competed for switching validators. This is why I was seeing the validation activated and at random moments of time. So this way does not work, unless we synchronize for the time of validation. I chose to switch off parallel testing instead. It is good enough for me.
This is my final simples solution I could figure out (for anybody that would like to control whether OCL is validated or not):
private class DummyDelegate extends EValidator.ValidationDelegate {
override def validate (
eClass: EClass,
eObject: EObject,
context: java.util.Map[java.lang.Object, java.lang.Object],
invariant: EOperation,
expression: java.lang.String): Boolean = true
override def validate(
eClass: EClass,
eObject: EObject,
context: java.util.Map[java.lang.Object, java.lang.Object],
constraint: java.lang.String,
expression: java.lang.String): Boolean = true
override def validate(
eDataType: EDataType,
value: java.lang.Object,
context: java.util.Map[java.lang.Object, java.lang.Object],
constraint: java.lang.String,
expression: java.lang.String): Boolean = true
}
private val dummyDelegate = new DummyDelegate
// OCL de-activated for a single validation run:
val oclDelegate =
EValidator.ValidationDelegate.Registry.INSTANCE.get (OCL_DELEGATE_URI_PIVOT)
EValidator.ValidationDelegate.Registry.INSTANCE
.put (OCL_DELEGATE_URI_PIVOT, dummyDelegate)
val diagnostic = Diagnostician.INSTANCE.validate (root)
EValidator.ValidationDelegate.Registry.INSTANCE
.put (OCL_DELEGATE_URI_PIVOT, oclDelegate)
The code is in Scala, but easy to translate to anything JVM-ish.
Thanks for helping!
[Updated on: Sat, 25 April 2020 10:10] by Moderator
|
|
| |
Re: Ignoring OCL during Ecore validation possible ? [message #1826504 is a reply to message #1826489] |
Sun, 26 April 2020 01:02  |
Eclipse User |
|
|
|
Quote:The EValidator..Registry.INSTANCE is the first point of attack.
Correction.
The EValidator.Registry.INSTANCE is the correct point of attack to interfere with validation of OCL EObjects such as ExpressionInOCL, IfExp.
The EValidator..ValidationDelegate.Registry.INSTANCE is the correct point of attack to interfere with validation of OCL embedded within Ecore EObjects.
InvocationDelegate/InvocationDelegeate will only be relevant if your primary Ecore models have operations/derived properties with OCL implementations. You probably ould want this OCL to continue.
Whether the EValidator suppression is needed may be a side effect of whether you have previously executed the OCL and so caused its AST to be cached under the Ecore EObject. If your model is freshly loaded, the OCL should be solely in String form.
Regards
Ed Willink
|
|
|
Goto Forum:
Current Time: Sun Jul 06 00:07:30 EDT 2025
Powered by FUDForum. Page generated in 0.05620 seconds
|