eclipse-ocl / org.eclipse.ocl

Eclipse Public License 2.0
0 stars 0 forks source link

[pivot] Rationalize Standard Library / Pivot Metamodel loading #2216

Open eclipse-ocl-bot opened 1 month ago

eclipse-ocl-bot commented 1 month ago

| --- | --- | | Bugzilla Link | 577825 | | Status | NEW | | Importance | P3 normal | | Reported | Dec 15, 2021 09:35 EDT | | Modified | Mar 24, 2023 05:55 EDT | | Blocks | 581543 | | See also | 574430, 526813 | | Reporter | Ed Willink |

Description

After activating full Pivot Validation of ExpressionInOCL bodies, potentially triggering nested parses, testOCLstdlib_AS fails with unresolved proxies when run after testOCLstdlib.

The problem is that testOCLstdlib loads a custom Standard Library that occludes the complete-merged built-in Standard Library. OperationCallExp's within the built-in Standard Library resolve to the custom Standard Library. At the end of the test when the custom Standard Library is unloaded, the 'immutable' built-in Standard Library acquires proxies that fail to resolve in the following test.

1) Why was the built-in Standard Library loaded at all?

2) Should the parser operation resolution break the choice between equally good candidates to favour the not-saveable built-in Standard Library version?

3) Should the proxy have resolved anyway in the next test?

4) Does this problem go away or just change once CompleteClasses go away?

eclipse-ocl-bot commented 1 month ago

By Ed Willink on Dec 16, 2021 04:31

(In reply to Ed Willink from comment #0)

1) Why was the built-in Standard Library loaded at all?

It shouldn't have been. Two tweaks can avoid the premature load and break 12 other tests instead.


Fundamentally we have potentially nine permutations of:

{read-only-built-in / complemented-cloned-built-in / custom} standard library\ {read-only-built-in / complemented-cloned-built-in / custom} pivot metamodel

Not all permutations are safe - must only reference non-read-only from non-read-only to avoid proxies.

The 99% use case of all read-only-built-in works fine. The other use cases lack clear definition and so there are too many APIs with magic lazy deduction of load needs/progress.

Need to clarify

A) How to declare a custom model

B) How to import a custom model

C) How lo load the custom/built-in models for use

A) Declaration by re-use of the URIs or Library rather than Package is too magic so we have Annotations that are inconsistently used for pivot metamodel / standard library. Need to make these annotations consistent in .ecore and .oclas.

B) Import could use a distinct library rather than import keyword, but it's all a bit magic. Should be able to import anything and react to the distinction annotation.

C) (Re-)loading should occur at a precise instant, so that asserts can diagnose too-soon / too-late coding errors.

For CS2AS, a suitable instant could be after the containment visitor has created all the primary AS tree (and probably before the containment continuations). Imports can be similarly containment-parsed so that the top level packages/libraries and their annotations are available. Pre-instant use of metamodel/library is forbidden.

For ES2AS, a suitable instant could be after XMI load, since top level EPackage and EAnnotations should be available from the outset.

It is not necessary to analyze imports transitively. If a specialized library needs a specialized metamodel, the consumer can and probably should specify both.

Once (re-)loading occurs at a single instant we should only need a single API. The diverse get/install/Library/Metamodel MetaModelmanager APIs and magic fields can mostly be deprecated in favour of a single clear EnvironmentFactory API.


For now just one test fails because validating the built-in standard library in the prior presence of a custom library leads to proxies. Just suppress validation of the built-in standard library for now.

2) Should the parser operation resolution break the choice between equally good candidates to favour the not-saveable built-in Standard Library version?

No. Fix the problem rather than mitigate its presence.

3) Should the proxy have resolved anyway in the next test?

Probably not. We're dealing with custom test projects.

4) Does this problem go away or just change once CompleteClasses go away?

It's an orthogonal issue.

eclipse-ocl-bot commented 1 month ago

By Ed Willink on Mar 15, 2022 10:57

Bug 574430 advocates that CompleteClass and PartialClass extend (Abstract)Class to simplify non-loading usage and to allow a PartialModel rather than CompleteModel to be used for the very very common use case that there is no merging.

Unfortunately the current design with distinct OCLmetmodeljava and OCLstdlib.java provide efficient loading when just one is customized but incurs complexitoies as mltipe models are merged for the overlap in the '99'9%' use case.

Better to have a single OCLbuiltinModel.java for the normal case allowing usage directly without merging overheads.

Only for the '0.1%' usecase in which a standard model is extended need some Complete structures be created.

And for another '0.1%' usecase with fully custom models they can be loaded from CS.

For QVT too we can have a single pre-merged standard QVTxBuiltinModel.java for the uncustomized case.

Perhaps, Bug 526813, we can have and OCL4UMLbuiltinModel.java that can avoid unnecessary UML overheads using the pre-load transitove import analysis to detect the need for UML support.

eclipse-ocl-bot commented 1 month ago

By Ed Willink on Mar 20, 2023 10:54

Once again we have an unfortunate design following OCL specification suggestions too closely.

Logically there is a parse-time metamodel as defined by Pivot.ecore/Pivot.ocl and a run-time model defined by the OCL-2.5.oclstdlib. But they are each heavily cross-dependent.

In Java, no one questions that java.lang.Class and java.lang.Integer are the same meta-level. java.reflect.Field is just a different package for modularity.

In Ecore, EInt and EReference are at the same meta-level although there is some hidden magic to accommodate the self-definition of EInt etc.

In OCL, once we rescue omitted classes, we have both BooleanType and Boolean but in different (meta-)models. (Java has no such BooleanType, just the one Class<?> for all meta-types.

So today's Pivot OCL metamodels are a mess with considerable difficulties from the potential ability of a user to replace one or other or both by custom variants.

If instead Pivot.ecore also defines all fundamental types (e.g. Boolean, Integer, OclAny, OclElement etc but perhaps not Map, MapType), and also unavoidable operations (e.g. OclAny::=(), OclComparable::compareTo()) the OCL language core comes from one (replaceable) model. At build-time we may add-in Collections.oclinecore, Iterations.oclinecore, Numerics.oclinecore, Maps.oclinecore, Strings.oclinecore etc to define a single appropriate Pivot. (QVT might omit Messages.oclinecore). Users can statically rebuild with more or less. Users can dynamically load more (e.g. Maths.oclinecore) but cannot replace/remove.

eclipse-ocl-bot commented 1 month ago

By Ed Willink on Mar 24, 2023 05:29

(In reply to Ed Willink from comment #3)

So today's Pivot OCL metamodels are a mess with considerable difficulties from the potential ability of a user to replace one or other or both by custom variants.

Worse. Attempting to streamline FlatClass construction for Bug 581543 hits a problem with the CGed test_oclIsKindOf because Real and Integer have both OCLstdlib and OCLstdlibTables contributions mandating the use of a CompleteFlatClass. So it seems that a lightweight execution using only the built-in OCL functionality is currently impossible.

If instead Pivot.ecore also defines all fundamental types

We would only have one Real and one Integer - problem solved.