[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