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

8 comments
Comment actions Permalink

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

 

1
Comment actions Permalink

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

1
Comment actions Permalink

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

 

1
Comment actions Permalink

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

 

1
Comment actions Permalink

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

 

1
Comment actions Permalink

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

 

0
Comment actions Permalink

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

0
Comment actions Permalink

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

0

Please sign in to leave a comment.