Elda: configuring multiple URL rewrite rules

26 views
Skip to first unread message

Brian McBride

unread,
Jun 2, 2015, 8:51:51 AM6/2/15
to linked-data...@googlegroups.com
I have a need to have the velocity HTML renderer transform the URLs used in some hrefs.  Currently, it is possible to specify one rewrite pattern using rewriteURLFrom and rewriteURLTo api variables. I want to be able to define multiple pairs of rewrite patterns.

The natural way to express the rewrite patterns in an api-config would be to use a list of from/to pairs, e.g.

  api:spec api:variable [
    api:name "rewriteURLList"        ;
    api:value (
      [ api:first "http://from1" ; api:second "http://to1" ]
      [ api:first "http://from2" ; api:second "http:/to2" ]
    )
  ] .

On investigation, it is currently not possible to pass such a list to the renderer.  API variable values are represented as Objects of type Value that consist of three strings (valueString, typeString, langString).

I have a working solution that encodes a list of rewrite patterns as a string  The literal consists of an even number of space separated tokens with no other punctuation, e.g.

  """
       from1 to1
       from2 to2
       from3 to3
  """

Other syntaxes are possible; this one is easy to parse.

However, I think it is better to express the list in turtle rather than encode it as a string.

It may be that this can be accomplished by adding the RDFNode that represents an api variable value in the api configuration to the Value object that Elda uses internally.  A value object would become (valueString, typeString, langString, valueRDFNode), or similar.

If this is a reasonable approach, then I'd be happy to try implementing such a change.

Brian

chris dollin

unread,
Jun 2, 2015, 9:18:59 AM6/2/15
to linked-data-api-discuss
I had a poke around in the code and a think.

We have the internal mechanism for allowing variables to be bound to arbitrary
Java values [[retrieved by calling Bindings.getAny(name) as opposed to the
more usual get()]]. (Calling get() on such a binding returns null, just as if it
were not bound at all.)

The problem is in initialising such a variable from the API spec. At the moment
the code (in VariableExtract.findVariables) doesn't permit bnodes at all.

RDF lists are represented (usually) with bnodes.

So we could allow an api:value which was a bnode (presumed to be)
representing a list to create a variable binding whose value was
a Java list whose elements were the RDF values of that list.

This is backwards compatible, since lists as operands of api:value
are currently illegal, and does not introduce a new way of breaking
Bindings, since it uses existing machinery for arbitrary Java values.
Of course it might expose already-existing problems with those values,
but that's different.

Chris
> --
> You received this message because you are subscribed to the Google Groups
> "linked-data-api-discuss" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to linked-data-api-d...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.



--
Chris "allusive" Dollin

Brian McBride

unread,
Jun 2, 2015, 9:51:21 AM6/2/15
to linked-data...@googlegroups.com
Hi Chris,

You are suggesting that RDF lists be translated to Java lists. I'm
wondering what the elements of those lists would be. For my use case,
I'm looking for an object that is a pair of strings. How would that
work? A list of lists?

Brian

chris dollin

unread,
Jun 2, 2015, 10:15:33 AM6/2/15
to linked-data-api-discuss
Brian says: I'm wondering what the elements of those lists would be

RDF Literals, RDF Resources, or Lists.

Or we might turn Literals into their actual values. Really it depends on what's
nicest for the user of the list value, which at the moment, is any programmer
of the velocity renderer.

Yes for the case you're most interested in it would be a one-element
list whose element was a
two-element lists whose elements were ... as above.

Chris
--
Chris "allusive" Dollin

Brian McBride

unread,
Jun 3, 2015, 3:16:21 AM6/3/15
to linked-data...@googlegroups.com
Hi Chris,

Interesting idea.

On 02/06/15 15:15, chris dollin wrote:
> Brian says: I'm wondering what the elements of those lists would be
>
> RDF Literals, RDF Resources, or Lists.
That seems a little odd to me, but I may be not understanding the
underlying design principle that applies here.

If the idea is that the values of bindings should be Java 'natural'
objects (strings, integers, Lists etc) so that they are easier to
process than RDF structures then it would be more consistent to have the
members of the lists be Value objects. There might be pragmatic 'one
level is good enough' consideration.

I can see the point of translating to java structures if there is likely
to be other cases like mine.

From a pragmatic point of view, all I really want is direct access to
the head of an epi:variable value that is a list from the renderer. If
that is a general requirement then putting in some general purpose
machinery seems appropriate. If not, a simpler solution that does not
preclude adding general machinery later if needed, might be best.

Brian

Stuart Williams

unread,
Jun 3, 2015, 7:06:12 AM6/3/15
to Chris Dollin, Brian McBride, Linked Data API Discuss
Hi Chris, Brian,

Before we head of too far down a path that changes the nature of an ELDA
variable I'd like to urge some caution to think through the more general cases
of where references to such variables might be made and what they might be
intended to mean. Here's and entirely bogus api endpoint spec intended simply to
surface some ugly corners that might arise if we allow api:Variable to bear
values that reference specifically rdf:List nodes in the api configuration graphs.

spec:alistEndpoint
api:uriTemplate "/stem/{field1}/{field2}/{field3}" ;
api:variable [ api:name "r1" ;
api:value "http://{site_prefix}/{field1}" ;
api:type rdfs:Resource ] ;
api:variable [ api:name "v1" ;
api:value ( "{r1}" "infixed {field2} value" "postfix {field3}" (
"{field1}" [ ex:prop2 "{field3"} ] ) )
api:selector [
api:where "?item ex:prop ?v1 ."
api:filter "prop={v1}"
] ;

Questions this poses are:

- does the elda variable substitition mechanism work (recursively?) over the
members of a list?
- does variable substition apply to the objects of rdf statements further down a
nested structure?
- what would it mean for an rdf:List valued variable to be used in an api:Selector?

I am not claiming that there are useful ways that list valued variables could be
used, though there might be. More I'm suggesting that opening up the possiblity
results in questions of intention and utility that ought to be addressed before
committing to a design. In particular, if list values (or indeed any direct rdf
node expressions - eg. api:value "2015-06-03"^^xsd:date ; or api:value
"{date}"^^xsd:date) may simply not allow the variable substitution and rdf:List
expression would follow suit. This might make for a simple easily communicated
restriction - variable substitution only applies plain literal values of ali:value.

There is clear utility for rdf node expression in general in api:Selectors, but
it's less clear that lists in particular are useful - but there are sparql
extensions that may use lists with (magic) property functions where such list
constructors may be useful.

Anyway... the main point is to think through the cases where references to
api:Variables can occur; which are useful; what are they intended to
express/mean; which are not and *how* the error cases are communicated to an
api: config developer so that they can usefully correct or avoid a mistake.

Stuart
--
Epimorphics Ltd www.epimorphics.com
Court Lodge, 105 High Street, Portishead, Bristol BS20 6PT
Tel: 01275 399069

Epimorphics Ltd. is a limited company registered in England (number 7016688)
Registered address: Court Lodge, 105 High Street, Portishead, Bristol BS20 6PT, UK

chris dollin

unread,
Jun 3, 2015, 10:52:27 AM6/3/15
to linked-data-api-discuss, Chris Dollin, Brian McBride
I'm still thinking about generalised api@variables and their
values but won't get to any sort of decision today.

Stuart's musings on substitutions mean that it's harder
to define what a structured api:value would mean and
how general it would (not) be.

Having a structured value map to a Java object as the
bound value now seems unsatisfactory to me.

Attaching the RDFNode value of the api:value to the
internal Value object now seems to me to be a useful
approach but that assumes that we allow structured
values and have then to answer the substitution questions.

Chris

--
Chris "allusive" Dollin

chris dollin

unread,
Jun 4, 2015, 7:49:26 AM6/4/15
to linked-data-api-discuss
OK, I think I have a position I'm not completely unhappy
with; it turns out to be pretty much Brian's original
"put RDF Node in Value" with ancillary background and
detail.

Givens:

* we wish to be able to transmit configuration information
from the API config to renderers (specifically we wish to
be able to configure lists of pairs of (partial) URIs for
renaming purposes, but we do not wish this to have a one-off
ad-hoc solution)

* we don't know what the type and structure of this
information is in advance other than "expressible in RDF"

* we currently do this by exploiting api:variables whose values
represent [typed/languages] literals and URI resources;
an api:value can be created from an RDF literal or resource
or a string, but NOT a bnode. Structured values such as lists
and anonymous resources with properties cannot be specified
using this mechanism.

* api:variables value strings may contain substitution markers
{name}; when the value of the variable is demanded the string
is (recursively) expanded.

* the value of an api:variable named X may be injected into a
query using the SPARQL syntax ?X, where it is replaced by
the SPARQL rendering of the variable's value; currently either
a literal or a URI resource.

* if we add a feature now we would very much prefer to not
remove it later.

* it is not required that all of a feature be added at once.

Proposal:

* to use api:variables to transmit this new configuration
information (as opposed to specialised new features of
an API[Endpoint]Spec, etc).

* to transmit this information as an RDFNode embedded in
the API config model, allowing for list and record structures
in the usual way, rather than attempting to build some
parallel data structure (eg Java lists), and leaving it to the
user of the config information to walk the RDF graph as
they require.

* to specify this RDFNode as the object of the api:value
statement, and further allowing blank nodes as these objects eg

api:variable [api:name "Adam"; api:value [my:from 1; my:to 2]]

* to embed this RDF node as a new field of the Value object
which represents the api:value in a Bindings structure (which
is already available to the code of the velocity renderer) via
an accessor eg getSpecNode().

* to define that

(A) no {} text substitution applies to any strings forming part
of the api:value; they are what they are. If the code that exploits
the RDFNode cares it can request that strings are expanded
according to its own whim.

(B) if the variable is injected into a SPARQL query then
the query fails with status 500. (Sometimes it might be a bad
request but it's not obvious how to tell and we have to pick
one.) Rejecting any injection of the variable means that we
don't have to decide what it might mean right now and can supply
a definition later if we wish.

Note that this proposal is independant of the existing code
that allows arbitrary Java values (such as servlet requests)
to be bound as the value of an api:variable.

Chris
--
Chris "allusive" Dollin

Stuart Williams

unread,
Jun 4, 2015, 8:14:21 AM6/4/15
to Chris Dollin, linked-data...@googlegroups.com
Broadly happy with what you suggest... but one small question:

On 04/06/2015 12:49, chris dollin wrote:
> * to embed this RDF node as a new field of the Value object
> which represents the api:value in a Bindings structure (which
> is already available to the code of the velocity renderer) via
> an accessor eg getSpecNode().

the Bindings are also passed into the XSLT renderer as parameters of the transform.

Will and how will these RDFNodes values be presented to the XSLT renderer -
specifically the xsl transform - eg. so that it can implement equivalent URL
rewriting based on a common set of parameters?

Stuart

chris dollin

unread,
Jun 4, 2015, 8:40:39 AM6/4/15
to linked-data-api-discuss, Chris Dollin
On 4 June 2015 at 13:14, Stuart Williams <s...@epimorphics.com> wrote:
> Broadly happy with what you suggest... but one small question:
>
> the Bindings are also passed into the XSLT renderer as parameters of the
> transform.
>
> Will and how will these RDFNodes values be presented to the XSLT renderer -
> specifically the xsl transform - eg. so that it can implement equivalent URL
> rewriting based on a common set of parameters?

Good question. I don't know how to feed Java structures to XSLT.
We could apply some common translation of RDFNOde-Values to
all the bindings before running the XSLT engine but I don't know
what the right choice would be -- any takers?

chris dollin

unread,
Jun 4, 2015, 9:55:57 AM6/4/15
to linked-data-api-discuss, Chris Dollin
OK, here's where I'm at.

* the proposal doesn't address the issue of renderers written
in languages other than Velocity; specifically our XSLT renderers.

* the motivating example (lists of rewrite pairs) can be addressed
by representing them as strings and using trivial parsers to
turn them into whatever's needed to rewrite.

* XSLT engines can do string manipulation so the same route is
open to our XSLT renders when necessary.

= The proposal remains in the historical record in case we want
to reboot it later, but will not be actioned.

Thanks to Stuart and Brian for discussions.
Reply all
Reply to author
Forward
0 new messages