As well as addressing resources and resource paths, in OData we apparently have the ability to invoke "service operations" as well.
From what I see, these are addressed in a pretty much identical manner to actual resources like so
/ProductsByColor?color='red'
Or
/ProductsByColor(3)/Category/Name?color='red'
The invocation on the server is the same in each of these cases, however in the second case we're addressing into the collection returned by the invocation.
Now, a simple solution to this will be to carry on using the existing parser, and supply these custom params as part of the overall model:
So, with the following test:
test("/method(1)/child?foo=bar", function(result) {
it("should have the resource specified", function() {
assert.equal(result.resource, 'method')
})
it("The result should be addressed", function() {
assert.equal(result.key, '1')
})
it("should have the path specified", function() {
assert.equal(result.next.resource, 'Child')
})
it("should have the argument specified", function() {
assert.equal(result.args.foo, 'bar')
})
})
I might then solve it by simply adding this to the end of my main expression
OData = (
(
PathSegment:model
(
'?'
OperationParam:param
)?
Where
OperationParam =
Text:name '=' Text:value -> { name: name, value: value }
,
(Text is a hack so I'm not putting that here until I've defined what it actually is - similar to my kerfuffle over resource names earlier)
To build up the model we can do some inline code like so:
OData = (
(
PathSegment:model
(
'?'
OperationParam:param
)?
) -> {
if(param) {
model.args = {}
model.args[param.name] = param.value;
}
return model
}
| '/'
)
This will have the desired effect to an extent, of course it won't pass this test:
test("/method(1)/child?foo=bar&foz=baz", function(result) {
it("should have 'foo' specified", function() {
assert.equal(result.args.foo, 'bar')
})
it("should have 'foz' specified", function() {
assert.equal(result.args.foz, 'baz')
})
})
This is where the built-in 'listOf' comes in useful:
OData = (
(
PathSegment:model
(
'?'
listOf(`OperationParam, '&'):params
)?
With an appropriate loop to build up the list
OData = (
(
PathSegment:model
(
'?'
listOf(`OperationParam, '&'):params
)?
) -> {
if(params) {
model.args = {}
for(var i in params)
model.args[params[i].name] = params[i].value;
}
return model
}
| '/'
)
Now, a few things getting wrong with this whole implementation so far...
I can live most of this for now - but I've made a note that they're making me uncomfortable so when my progress is at a suitable point I can deal with them.
2020 © Rob Ashton. ALL Rights Reserved.