Bidirectional References
Hi,
in EMF it is possible to make bidirectional references by setting their "opposite". For example, if A has a reference b to B ( A -b-> B ) and B -a-> A one can say that "a" and "b" are opposites and the underlying infrastructure will take care of maintaining the objects (e.g, if I have objects a->b and b->a and I set a new object b2 to a, I will get a->b2, b2->a, b->null). This also works if one of the sides has cardinality 0..1 and the other 0..n, which gives the same effect as children (many children, one parent) but without the containment property.
I don't think MPS has this concept of bidirectional references, does it?
In any case, I am trying to simmulate it with what MPS offers. Can you give a hint of the best way to approach it? Things I tried:
- using constraint language's referent set handler to manipulate the references. That works pretty well because I can manually manage the references when they change. The problem is that the set handler does not get called when I remove the target (in an editor) or set it to null. For example, if I have an editor for A and I delete the reference to B the set handler does not get called with null.
- creating new types BRef and ARef. This way I can use the Delete editor action to trigger the reference management code when the BRef gets deleted in an A editor. But then the code gets really ugly because everywhere I have this extra level of indirection.
- using TypeSytem NonTypeSystemRules and QuickFixes. The idea is that I can always check if the reference is correct and, if not, I can automatically trigger the quickfix. My problem with this is that it 1) it's not really clear when the rules will run and 2) if there are many of those rules it starts to impact performance because essentially every time you open the editor you have to check every reference.
Thanks for the help!
Thiago
-- edited --
PS - I know that you can't make 0-n references in MPS, but I never understood why. So if I want to have the effect of (many children, one parent), I need that the "many" side have specialized (smart) references as children...
Please sign in to leave a comment.
Hi Thiago,
you are right, i had the same problem before. See the discussion here
actually it is the way you describe ist. maybe it will be changed in the future (a call with null wouldn't help you here anyway, you would need the old node leading to a more complex interface (parameters!) here).
for performance-reason (as you explain) i wouldn't do that.
I'd use smart-references (Ref-Objects with a 1-card-ref; what is a good way to handle references anyway) to solve your problem. This is similar to what you explain in your second option... just create the reference-concept (you have even tool-support for that and can create a smart-reference (incl. the delegating editor) from within any AbstractConceptDeclaration-node via Intention!) and derive the TYPE from the referenced concept (so you introduce no new type into your model).
I think the reason for that is simply KISS and the smart-reference... :-)
Regards,
Mirko
Hi Mirko,
thanks for the answers!
Hi Thiago,
ah, ok... didn't realize that... so it actually looks like a bug. did you file one?
this indirection gives you also a bit more flexibility in cardinality (child vs. ref) and it is imho common practice in DSL-creation (for more flexibility and extensibility in structure/typesystem and the like). Another solution would it be to make the indirection "invisible" via some behavior (something like a.getB() instead of a.bref.b).
if "on demand" is suitable, this is a good solution, i think.
are you using findUsage-aspect for that?
Regards,
Mirko
Hi Mirko,