Adrian Kuhn wrote:
- generated code is not the only use-case
- there is legacy code that does not update opposites automatically
- some people use hardcoded mse exporters
- some people use hardcoded mse importers
right .. backwards compatibility.... the horror of microsoft nightmares
all over again
#(((#This fact would again strengthen my case
that the opposite of an
opposite should not necessarily be
#declared as an opposite in the MSE file. Nor should the type be in
either of them. If we find (prop (id: 2)
#(opposite (idref: 1))), then we should automatically do (objectAtId:
1).setOpposite(objectAtId: 2),
#which sets the owner of (objectAtId: 2) as it's type, sets the
type of
the (objectAtId: 2) as the owner of
#(objectAtId: 1); and then sets (objectAtId: 2) as the opposite of
(objectAtId: 1)
#
#---->> if you use an opposite-declaration for an attribute; you
have 1
statement instead of 5 for which 4 are
#redundant ----> less redundancy => better performance
#)))
Do you have a reference implementation?
Not yet, shouldn't be too difficult though...
What I -did- implement today in my python version is "onemany.py", which
is a implementation of a
One class and a Many class which are polymorphic "Opposite" descendants.
Which both have a
pointer to their owner instance. This allows me to use them as instance
variables of (their owner
instances), and instead of setting these instance variables and updating
the other side of a (one->one,
one->many or many->many relationship), these Opposite-descendants get a
new Opposite added.
This implements the 3 scenarios by using just 2 (polymorphic) classes.
Example of a use (this is generated code, I indicated the lines to read
with "%"):
class LocalVariable(StructuralEntity.StructuralEntity):
def __init__(self):
StructuralEntity.StructuralEntity.__init__(self)
% self.gen_parentBehaviouralEntity = onemany.One(self)
def getParentBehaviouralEntity(self):
# .value() returns the owner of the opposite Opposite descendant
% return self.gen_parentBehaviouralEntity.value()
def setParentBehaviouralEntity(self, gen_parentBehaviouralEntity):
import BehaviouralEntity
assert(isinstance(gen_parentBehaviouralEntity,
BehaviouralEntity.BehaviouralEntity))
%
self.gen_parentBehaviouralEntity.add(gen_parentBehaviouralEntity.gen_localVariables)
class BehaviouralEntity(ContainerEntity.ContainerEntity):
def __init__(self):
ContainerEntity.ContainerEntity.__init__(self)
self.gen_outgoingInvocations = onemany.Many(self)
% self.gen_localVariables = onemany.Many(self)
self.gen_parameters = onemany.Many(self)
self.gen_outgoingAccesses = onemany.Many(self)
self.gen_signature = None
% def getLocalVariables(self):
# values returns a [] of owners of the opposite Opposite descendants
% return self.gen_localVariables.values()
def setLocalVariables(self, gen_localVariables):
import LocalVariable
assert(isinstance(gen_localVariables, list))
for i in gen_localVariables:
assert(isinstance(i, LocalVariable.LocalVariable))
# On the setting of many-side you have to clear manually
since adding does not remove for Many
% self.gen_localVariables.clear()
% for i in gen_localVariables:
% self.gen_localVariables.add(i.gen_parentBehaviouralEntity)
((in the code I prepend gen_ to all instance variable names to avoid
conflicts with existing keywords))
if you want to run it yourself, do "python fm3codegenerator.py
FAMIX30.fm3.mse" (FAMIX30.fm3.mse not supplied
in that svn dir)
cheers,
Toon