bidirectional n:m relationship
Hi,
I created a DSL where I need an bidirectional n:m relationship between nodes. I was able to create it by using a concept whose only content is a reference to a node. One A-node has children of type BRef, that references one B-node. But I also need to navigate from B-nodes backwards and to edit them on both sides. I can't believe that I'm the first one, who want's to do this. However I can't find a straight forward way to do this.
So my question is, how would you do this? Please bear with me, if this is a trivial question. I just started experimenting with MPS. I found a post from 2010, but surely some things have change since then.
-- Axel
Please sign in to leave a comment.
Hello Axel,
Why don't you create an equivalent ARef children in B and handle the "bidirectionality" in a setter?
Something like (pseudo-code):
A:setB(b) {
if(bRef != b) { // Beware the infinite loop :-)
bRef = b
b.setA(this)
}
}
B:setA(a) {
if(aRef != a) {
aRef = a
a.setB(this)
}
}
You could also handle this from the "referent constraints" section of the Concepts Constraints using the same code.
Regards,
Sérgio Ribeiro
Porto - Portugal
Hi Sérgio,
thank you for this suggestion. It sounds promising. I will test it. However I wonder how to tell my editor to use a setter. Is this done automatically?
-- Axel
Hi Axel,
I think the "referent constraints" should give you what you want easy.
I've created two simple concepts with your scenario: AAA and BBB (each is an INamedConcept with a reference to the other concept).
I've added a simple editor to them and the code that does what I said in my previous post.
Here it is:
This is just something I've coded very quickly, it may not work well for all scenarios but I think you can get an idea from it.
After compiling the language with these concepts, create a few AAA's and BBB's and play with them selecting a reference for any of those instances.
Imagine you have "aaa1" and "bbb1", If in the editor of "aaa1" you select "bbb1" as ref; you should (if all went well and I made no mistakes) see "aaa1" as ref of "bbb1".
Hope this helps you.
Regards,
Sérgio Ribeiro
Porto - Portugal
Hi Sérgio,
thank you for your efforts. It gave me an idea where to start. However I'm long from being there. What I need is an n:m relationship. So I would need to create a child at the BBB-node. This is probably possible, but takes quite some coding and testing. I'm still trying to get it done, but maybe this shows that MPS is not my tool, since I have n:m relationships all over my intended language. Maybe I can create an abstract concept, that will be inherited by all my n:m relations, but I'm not sure whether this is feasible.
Thanks again for you great example.
regards,
Axel
Could you describe in more detail the parts of your language that require n:m relationships? Maybe there's a better way to implement the desired structure.
Vaclav
Hi Axel,
In my example, I've used a [0..1] cardinality for the references but the code could be refactored to use a [0..n] cardinality...
However, as Vaclav says, it depends on what you really want to do.
Regards,
Sérgio Ribeiro
Porto - Portugal
Hi Vaclav,
I'm trying to create an editor for the Business Motivation Model. So the n:m relationships are given. This might be an untypical use case for MPS, since the only code I want to generate is an html-page. It is just a pet project that I wanted to use to get to know MPS.
Hi Sérgio,
Well, if that was so easy. I thought references can only be 0..1? That's why I created the ARef and BRef nodes that can be children of B respectivly A-nodes. What you have shown me, is how to make sure that ARef and BRef nodes know each other. However I need to make sure, that an ARef knows a BRef owned by the A-node referenced by the ARef. Or course I could go via the owner directly (ARef.bRef.owner). I don't know how easy it is to create an editor for this, that makes it as comfortable as editing children directly.
Thank you for your patience with a novice MPS user.
--Axel
Axel,
You're right in me being wrong: references can't be [0..n], just [0..1] or [1] (that's what one gets replying directly without checking things out).
If I have some time, I'll try to check your scenario.
Regards,
Sérgio Ribeiro
Porto - Portugal