Bug 299579 - [metadata] A proposal for an IExpression patch syntax
Summary: [metadata] A proposal for an IExpression patch syntax
Status: CLOSED WONTFIX
Alias: None
Product: Equinox
Classification: Eclipse Project
Component: p2 (show other bugs)
Version: 3.6   Edit
Hardware: All All
: P3 enhancement (vote)
Target Milestone: ---   Edit
Assignee: Thomas Hallgren CLA
QA Contact:
URL:
Whiteboard: stalebug
Keywords: api
Depends on:
Blocks: 298932 299506
  Show dependency tree
 
Reported: 2010-01-13 18:29 EST by Thomas Hallgren CLA
Modified: 2019-11-14 02:11 EST (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Thomas Hallgren CLA 2010-01-13 18:29:26 EST
With the new type of expression based IRequirement, I think we also need a new way to specify requirement changes. The current approach is to match on name, namespace, and intersecting ranges, and we need to be able to do something similar but for parts of expressions. Consider the following:

providedCapabilities.exists(x |
  x.name == 'EPL' && x.namespace == 'license' && x.version == '1.0.0') &&
providedCapabilities.exists(x |
  x.name == 'javax.servlet' && x.namespace == 'osgi.bundle' && x.version >= '2.4.0')

I.e. I want an IU that provides the javax.servlet bundle with an EPL license. The expression is fairly complex and will not allow that we extract one single name.

How do I change the version requirement for the 'javax.servlet' bundle to x.version >= '2.5.0'?

I think we need two things:

1. A way to identify exactly what part, or parts, it is that we want to change.
2. A way to specify how the change should be applied.

This can be achieved by a special variant of an expression and an expression tree visitor. Imagine a subtree that, when dropped at the top of the expression, tries to match itself to every node that it finds. When it finds a match, it performs some kind of replacement.

I will henceforth call this subtree an Expression Advice (EA). The EA can, in addition to any normal expression, also contain special patch expressions. An EA patch is something that matches an existing expression and can either remove or make changes to it. Consequently, it contains two parts, a match part and a replacement. This is the BNF that I have in mind:

EA-expression
  : patch '(' expression [ ',' expression ] ')'
  | patchEval '(' matchExpression [ ',' expression ] ')'
  ;

EA-operator
  : patchOp '(' op ',' op ')'
  ;

The EA-expression is allowed where any other expression is allowed and the EA-operator is allowed where any operator is allowed.

The difference between the 'patch' and the 'patchEval' notation is that the 'patch' performs an exact match where the match candidate is compared to the expression verbatim whereas the 'patchEval' uses a boolean expression that will be evaluated using the match candidate as input. The 'matchExpression' is just an expression but introduces an additional operator '$$' that represents the match candidate. When the matchExpression is used, the match candidate must be a literal.

Now let's return to the question: How do I change the version requirement for the 'javax.servlet' bundle to x.version >= '2.5.0'? Using the new syntax, this advice could be written like this (using newlines for clarity):

  x.name ==  'javax.servlet' && x.namespace == 'osgi.bundle' && x.version >= 
  patch('2.4.0', '2.5.0')

The advice processor would search for the and expression that contains the three comparisons. When found, it would replace the exact match for the '2.4.0' expression with '2.5.0'.

What if I want to replace the whole "x.version >= '2.4.0'" part with a range? Well, everything is just expressions, so it could be written as:

  x.name ==  'javax.servlet' && x.namespace == 'osgi.bundle' &&
  patch(x.version >= '2.4.0', x.version ~= [2.5.0,2.6.0))

Patching an operator can be done in a similar way:

  x.name == 'javax.servlet' && x.namespace == 'osgi.bundle' && x.version
  patchOp(>=, ==) '2.4.0'

Only expressions or operators can be patched so it's illegal to try and patch partial expressions. I.e.

  x.name == 'javax.servlet' && x.namespace == 'osgi.bundle' && x.version
  patch(>= '2.4.0',=='2.5.0')  <-- ILLEGAL

Let's alter the patch replacing 2.4.0 for 2.5.0 so that we replace everything in a certain range instead.

  x.name == 'javax.servlet' && x.namespace == 'osgi.bundle' && x.version >= 
  patchEval($$ >= '2.4.0' && $$ < '2.5.0', '2.5.1')

This means that all occurrences of "x.version >= <x>" where <x> is >= '2.4.0' and < '2.5.0' will be replaced by "x.version >= '2.5.1'"

But what if a range was present in the first place? I.e. the original expression is:

  x.name == 'javax.servlet' && x.namespace == 'osgi.bundle' && x.version ~= [2.4.0,2.5.0)

and I want to replace all ranges that intersect with a certain range? Easy, we just write:

  x.name == 'javax.servlet' && x.namespace == 'osgi.bundle' && x.version >= 
  patchEval($$ ~= ['2.4.0',2.5.0), ['2.5.0',2.6.0))

(assumes that "range ~= range" returns true when the ranges intersect, this is an addition to the current behavior)

If I simply want to remove an expression (would only be possible in OR and AND expression), I write:

  x.name == 'javax.servlet' && x.namespace == 'osgi.bundle' &&
  patch(x.version ~= [2.4.0,2.5.0))

Partial matches can be enabled by nesting patch and patchEval.

  x.name == 'javax.servlet' && x.namespace == 'osgi.bundle' &&
  patch(x.version ~= patchEval($$ ~= '[2.4.0,2.5.0)'), x.version == '2.5.1')

What do you think about this?
Comment 1 Pascal Rapicault CLA 2010-02-12 09:32:28 EST
The proposal is very interesting and the mechanism I was thinking to use (doing some intersection on the results of queries) would not have worked, so I think we should go with this. 

Before this, two questions:
- I think it is true, but can you confirm that we do have the ability to replace all the occurences of SWT to be SWT 3.6.
- Do we really need to introduce the ability to patch operator?
Comment 2 Thomas Hallgren CLA 2010-02-12 09:36:51 EST
(In reply to comment #1)
> The proposal is very interesting and the mechanism I was thinking to use (doing
> some intersection on the results of queries) would not have worked, so I think
> we should go with this. 
> 
> Before this, two questions:
> - I think it is true, but can you confirm that we do have the ability to
> replace all the occurences of SWT to be SWT 3.6.

Yes. That is possible.

> - Do we really need to introduce the ability to patch operator?

Perhaps not. I'll skip that part in the first implementation.
Comment 3 Pascal Rapicault CLA 2010-02-12 09:52:50 EST
When do you think you will start working on this?
Comment 4 Thomas Hallgren CLA 2010-02-12 11:12:01 EST
I can work on this in parallel with the query unification. Witch means I can start right away. To avoid having three tracks, it would be nice if I could check in the changes in bug 299506. I just updated my workspace and ran the tests again and it's all green. Is it OK to commit that or do you want to look at it a bit more?
Comment 5 Pascal Rapicault CLA 2010-03-11 21:40:47 EST
I was thinking about this and I think this format may be a bit of an annoyance during the slicing since at this point the IU being patched has not yet been identified.
Comment 6 Thomas Watson CLA 2010-03-30 11:05:08 EDT
This is still being considered for 3.6?  We should try to defer enhancements and new features until next release.
Comment 7 Pascal Rapicault CLA 2010-03-31 00:07:47 EDT
Thomas, what is the status on this?
Comment 8 Pascal Rapicault CLA 2010-04-05 21:21:30 EDT
Deferred to a future release.
Comment 9 Lars Vogel CLA 2019-11-14 02:11:52 EST
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet.

If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.

If the bug is still relevant, please remove the "stalebug" whiteboard tag.