[Uml-devel] Re: Umbrello design (was UML XML tree viewer)
Luis De la Parra Blum
lparrab at gmx.net
Mon Nov 11 15:17:02 UTC 2002
ok, so I've been reading a little about reflection and such things for the
last couple of nights, and I think I'm starting to get it (finally!! =))
first some comments, then some links I think are worth looking at:
after having done some reading, there are some points I'd like to mention:
If we could get "normal" C++ objects to have some degree or
reflection-capabilities, it would be really great since it coud simplify
things like saving/ loading a lot. however, I dont think that *having* to
access the objects "only" through the reflective interface is something very
nice...
being able to write obj->setAttribute("attname","attvalue") is surely a nice
thing for the load / save functions, but for other parts it is much easir to
write obj->setAttXX(valueX) so I think our objects shoule offer both
interfaces, the "normal C++ object" and the "reflective object"
I mention this because in the pages I've read in these two days, I found
basically two ways of brining reflection to C++
1 ) write "normal" c++ classes, and then write extra code (or define some nice
macros) to "register" the attributes of the class, and finally implement the
methods for getting/setting these through the "reflection" API.
(This soundls like the QT "properties" stuff...)
2 ) making the objects "pure reflective" .. this option is (I think) the
easiest to implement... something like this would be almost all we need:
/*----start reflection objects ---------------*/
class Object;
class MetaClass
{public:
MetaClass(string className);
Object* createObject();
void insertAttribute(string attname);
list<string> getAttList();
void setAttribute(string attname, string attvalue)
string getAttrbute(string attname)
protected:
string className;
list<pair<string /*attname*/,string /*value*/>> attributeList;
};
class Object: public MetaClass
{
/* we cannot modify the structure of an object.. modify the class instead.
you cannot intantiate an object from an object.. you should do it from a
class, so we just hide these functions*/
private:
Object* createObject();
void insertAttribute(string);
};
/*------------------------end reflection objects-------------------------*/
but having to modify the objects this way just doesnt seem natural... not to
mention we would loose compiler type checking (since all classes would be
really MetaClass objects, and they would differentiate from each other only
through the "className" attribute, which is really just a string)
-
I also made a search to find some existing code. (if this is really something
that good, I just couldnt believe no one had come up with an implementation
of this for C++).. a simple search in google for "reflection c++" or "mop
c++" will give you some results (mop = meta object protocol... seems to be
the "real".. or better said, the "original" name for this thing.. then java
came and renamed it to "reflection")
I found some interesting stuff, but not really what I was looking for.
There is an interesting project called OpenC++. it seems it was started as a
reasearch project by Xerox and now is mantained by a group of developers at
sourceforge (open source). I think this could give us what we are looking
for, but I dont know if using this thing would be too complicated, since
OpenC++ is really supposed to give you much more than just the reflection
part of the MOP, so it would probably make things too complicated (note that
I said *probably*.. I havent really looked at at this close enougth)
so... after looking at other "reflection libraries" outthere (most of them
based on Macros to register the attributes of classes), I think the best
approach would be to hack the moc and generate the reflection code for our
classes. we could either extend QT's MetaObject, or create our own
MetaObject. The thing is that I would like to get the reflection
"automatically" ie, without having to register all the methods and attributes
manually... but I think we could take the moc as a basis and make our
"reflection code generator" out of that.
since C++ doesnt support this in a native way, I only see two options:
1- doing "pure reflective" objects (I am sure there are cases for which this
would be a good option, but not for us)
2- writing the reflection code ourselves -- as I said, I would suggest going
for this approach, but have the moc analyse and genereate the code for us.
ok, and now the links:
here are a few that I found very interesting:
++++++++++++++++++++++++++++++++++++++
http://www.garret.ru/~knizhnik/cppreflection/docs/reflect.html
--> gives a good introduction on reflection, and describes the ways that
reflection can be realized in C++
-----------------------------------------------------------------------------
http://www.vollmann.ch/en/pubs/meta/meta/meta.html
--> probably the best page I found last night... it gives a very good
introduction to reflection, and then takes you step by step through creating
some "reflective" objects.. very nice, but long (it was too late last night
so I skiped some parts towards the end)
------------------------------------------------------------------------------
http://oopsla.acm.org/oopsla2k/fp/tutorials/tut22.html
--> This sounds very interesting... but I could only find the description for
the tutorial. dont know where the text is.
-----------------------------------------------------------------------------
http://www.csg.is.titech.ac.jp/~chiba/openc++.html
--> OpenC++ home page. This is really a C++-based-language with support for
MOP. very interesting... but I dont know if this would be "too much" for what
we need.
++++++++++++++++++++++++++++++++++++++++++
so, to summarize:
I suggest having a simple reflective interface (abstract class, API) and then
have our objects implement this interface (if possible code autogenerated)
then, for the libXMI and friends, I would suggest
1- making a dom out of the file
2- for each object found, make a
obj = Factory::makeObject(objtype)
where objtype is the type read from the file (MOF::Package, UML::Class, etc)
the object returned would be a "real" object (ie, not a dumb, reflective only
object)
3- since the object returned would also implement the "reflection interface",
the next step is to read all attributs and do some
obj -> setAttribute("attname", "attvalue")
There are only two things worth mentioning:
the Factory would have to know all the objects we support (MOF::*, UML::* )
and create and return the appropiate object based on the "objype" string
passes as argument (see the WriterFactory... it gets a string asking for a
specific language, and it returns an object of that type)
of course when we want to support other objects (ie, add support for CWM) the
factory would have to be changed.. but I think this code could also be in
great part automatically generated. and we could load the factory dinamically
so that we dont have to recompile the basic XML reader/writer
the second thing is that we need to provide functions like "stringToInt",
"stringToFloat" and so on for all basic data types, which can be used for all
the object in the "setAttribute" methods (providing this functions is not
complicated.. we just have to remember that we have to convert everything
from /to string, since it is the format stored in the XML.
luis
More information about the umbrello-devel
mailing list