Home » Modeling » OCL » Ignoring OCL during Ecore validation possible ?
| |
Re: Ignoring OCL during Ecore validation possible ? [message #1826399 is a reply to message #1826394] |
Fri, 24 April 2020 11:51 |
Andrzej Wąsowski Messages: 21 Registered: November 2019 |
Junior Member |
|
|
Intersting. Would it be something like:
org.eclipse.emf.ecore.EValidator.ValidationDelegate.Registry.INSTANCE.remove(
org.eclipse.ocl.pivot.utilities.PivotConstants.OCL_DELEGATE_URI_PIVOT)
Actually this (almost) works. Obviously, It brings me back to the point were I was struggling with OCL not being validated :). An error that a delegate is missing. So apparently a dummy OCL is needed. I understand that I need to implement it myself, right? What is the type that it should extend?
[Updated on: Fri, 24 April 2020 12:10] Report message to a moderator
|
|
| |
Re: Ignoring OCL during Ecore validation possible ? [message #1826466 is a reply to message #1826403] |
Sat, 25 April 2020 10:59 |
Andrzej Wąsowski Messages: 21 Registered: November 2019 |
Junior Member |
|
|
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 11:44] Report message to a moderator
|
|
| |
Re: Ignoring OCL during Ecore validation possible ? [message #1826472 is a reply to message #1826469] |
Sat, 25 April 2020 14:09 |
Andrzej Wąsowski Messages: 21 Registered: November 2019 |
Junior Member |
|
|
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 14:10] Report message to a moderator
|
|
| | |
Goto Forum:
Current Time: Sun May 05 11:35:20 GMT 2024
Powered by FUDForum. Page generated in 0.04164 seconds
|