Make official the syntax entityType:serializedEntity for EntityReferences

Hi everyone,

this proposal is about making official the support of the following serialized syntax for entity references:

entityType:serializedEntityReference

Example: OBJECT:xwiki:Main.WebHome^XWiki.StyleSheetExtension[0]

I’m talking about “making official” here because I discovered by accident that it’s already partially supported:

So IMO there’s several levels for making it official, and that would be different part of the proposal.

Proposal 1.

Document this syntax in https://extensions.xwiki.org/xwiki/bin/view/Extension/Model%20Module and maybe in https://www.xwiki.org/xwiki/bin/view/Documentation/DevGuide/FrontendResources/JavaScriptAPI/#HWorkwithEntityReferences

Proposal 2.

Create the dedicated script services methods in ModelScriptServices to allow using $services.model.resolve("OBJECT:xwiki:Main.WebHome^XWiki.StyleSheetExtension[0]") and to allow getting a serialization from it (see proposal 3 for implementation details).

Proposal 3.

Create the dedicated serializer and resolver component to be able to use that syntax directly in those components. For the serializer it would be easy to just create a serializer that would prefix the entity reference.
For the resolver it’s a bit more complicated since currently our EntityReferenceResolver interface contains the following signature:

EntityReference resolve(T entityReferenceRepresentation, EntityType type, Object... parameters);

I can see three solutions:

  • 3a. We provide a serializer but no resolver and we document to rely on the converter for this resolver
  • 3b. We add a new default method in the interface taking only the representation and the parameters, without the EntityType. And the default would be to throw an exception (maybe NotImplementedException or something more appropriate) unless we manage to provide an implem for all existing components.
  • 3c. We add a new resolver interface specifically for that representation.

Personally I’m in favor of 3b. And in favor of 1 and 2 of course.

WDYT?

I was not aware of this on my side. This looks like this could break backward compat and entityreference support. What if I have a document entity reference with OBJECT:Main.WebHome?

AFAIK an entityreference doesn’t contain its type so while serializing to a string isn’t a problem, it becomes one if we have code reading this string and parsing it. This seems to be what you suggest in proposal 2.

I personally don’t like these proposals because it means there would be 2 ways of serializing and parsing an entity reference and I think that’s confusing (you need to decide which one to use).

I’ve not yet fully read the proposal nor do I understand yet we have this need to have the type in the string. They’re supposed to be passed together as 2 separate values (one for the type and one for the reference). So right now I’m not super enthousiast since that would change too many things for me and have 2 separate APIs. I also need to understand the need vs passing 2 values.

Thanks

@surli is not proposing to change the standard entity reference syntax but to make this one another official syntax for other use cases along with the already existing ones. There is no compatibility to discuss here.

+1 for 1 and 2

Not sure what’s best for 3 yet.

yes I understood that but I don’t like it for the reasons I’ve explained.

First, I need to understand the need (the proposal doesn’t really explain why Simon needs this) and why passing the type + entity reference wouldn’t be enough. Then I really don’t like having 2 APIs for the same thing (again because it’s confusing for developers and you need to decide which one to use and why).

So to clarify, I’m bringing it up because I want to use this behaviour since it already exists in XWiki, I don’t strongly need it and I could live without it.
Why it exists is another story:

  • for EntityReferenceConverter, the answer is simple: it exists because we want to be able to convert a simple string to an EntityReference (so without having to use a couple of strings) to have seamless conversion in our script services
  • for the Javascript XWiki.Model.resolve() implementation, we’d have to ask @mflorea but I guess he got the same need and since it was already existing in the EntityReferenceConverter he used same syntax

Now my need is no different: I need to perform manipulation with entity references between frontend and backend, and I’d prefer to manipulate a single string on which I can perform equality checks, than to manipulate two strings.

Note that the fact we have defined a Converter for it, suggests that this syntax is already used in scripts anyway.

Another use case for the need to have a single String is EntityReference properties (macro parameters, filters, etc.) where you cannot really convert 2 values into one.

ok thanks. So from what I hear there’s no strong need and we could live with passing 2 piece of data (type and reference), and it’s just a handy way.

So what you’re proposing is a set of new Serializer/Resolver for EntityReference with different hints from the ones that exist. This is not easy since we have plenty of Serializer/Resolver already. What would be the plan: to replicate all existing ones and provide new hints prefixed, with, say, something like typed?

For ex, instead of compactwiki, there would be a new typed/compactwiki component?

That’s a lot and it’s not very scalable (every time you add a new resolver or seralizer you’ll also need to add new typed/* components.

Another option is to use the parameters from serialize/resolver to add support for a flag that says to use a typed prefix.

I see that your proposal 3 proposes to change the API. I don’t like this (-1), it weakens the current API and really feels like some badly designed API.

Honestly I don’t see any strong need for this. What is the problem of passing 2 strings from the client side to the server side? For ex: https://.../...?type=object&reference=reference. This is exactly how the Java API works (with type and reference being 2 different class variables).

Now if you really want to go this way, I would consider this new API to be just a helper API and it should not change the current APIs at all. I’d just introduce 2 components (one for the resolver helper and one for the serializer helper). The String resolver helper would generate 2 pieces of data : the type and the reference string (it would cut the passed string into 2 pieces). The API user would then use one of the existing String EntityResolver to get an EntityReference. Same for the serializer, it would take an entity type + a String and generate a single string (concatenate both).

Why not? It’s easy for a macro to have 2 parameters: one for the type and one for the reference ({{mymacro type="object" reference="someref"/}}). I’d even argue that it’s more self explicit and cleaner.

But then it’s two String that you have to parse in your macro and nobody can tell what they are by looking at the macro definition. You cannot define an EntityReference as parameter.

It makes a lot of sense for me to have the possibility to serialize as a single value something with is a single Java entity. Again I don’t think making this official suddently makes the other kind of serialization suddently deprecated, it’s just a usefull feature.

That’s only proposal 3b.

Not necessarily, with proposal 3c. you could imagine to only provide serializer/parser using the default serialization of the reference, so you’d always get the long serialization in this case. And you could only parse those too.

That’s not option for the resolver, since you need to specify a type.

Remember that I’m also talking about script services here: I have an SS API that takes an EntityReference as parameter, right now I benefitiate from the immediate conversion from a single string to the EntityReference. If I need to manipulate both the String of the type and the String of the reference, it means that I have to rebuild myself the proper String to get the conversion.
I repeat myself here but this syntax already exists, I just want to make it official so that we have no doubt when using it that it will work without any change.
You didn’t express your opinion about proposal 1 yet, which is the most important one.

So you’re +0 with proposal 3c?

ok, I see what you mean. You want an automatic conversion of the string to an EntityReference java object. Indeed you’d need a way to indicate that the data for the EntityReference is taken from 2 strings. For ex:

@EntityReferenceProperty("type", "reference")
private EntityReference er;

Now macros are exposed to users and I’m not sure forcing the user to learn yet another syntax to declare an entity reference is the best. It’s already hard enough. Also how do they know they have to prefix the reference with the type? A lot of macros don’t need that since they’re asking the user to enter a document reference (like the {{include}} macro). And if you use the new API you’ll confuse the wiki part entered with the reference type if the user doesn’t enter the type.

I think you need to read back the first post of this proposal…

Yes but it doesn’t make it good. As I said I wasn’t aware of it and I don’t recall any proposal about it in the past. I see some issues with it that I listed.

I did. I said I didn’t like it and I’ve tried explained why! :slight_smile:

To repeat what I said above: I find it confusing and I don’t like to have 2 non-compatible ways of defining an EntityReference as a string. They’re not compatible because if I give you for example something:whatever you have no way of knowing if something is a wiki part or an Entity Type.

Depends which users you are talking about. Having a property which is an EntityReference actually make a lot easier for the WYSIWYG to propose a picker for an entity reference, resulting in a better experience for the user.

This is why for example we cannot easily add support for a user: link type in link syntax for XWiki Syntax 2.1. It would prevent the ability to have a subwiki named user.

Well that’s the thing: this is the only way to define an EntityReference as a String. The other one describes only part of an EntityReference.

You can do doc:user:Space.Page in a link but I don’t see how this is related to the current discussion.

Just to clarify because maybe I’ve not been clear enough on that point, the idea is to reuse the same syntax already provided by the existing converter, meaning that the serializedEntityReference is only and always the full serialization provided by the DefaultStringEntityRereferenceSerializer so the wiki is explicit.

This API makes a lot of sense, but what do you have in mind for the serialize ? Hard to find something consistent since serialize(EntityReference, Object...) already exist in this script service but for a different syntax.

Only when the EntityReference has a wiki part.