Difference between revisions of "Developpement/Cpp/Component/RelectionHelper"

From Apache OpenOffice Wiki
Jump to: navigation, search
m (The ReflectionHelper class)
m (The ReflectionHelper class)
Line 2: Line 2:
 
This class is composed with two source files.  
 
This class is composed with two source files.  
 
<source lang="cpp">
 
<source lang="cpp">
 +
//******************************* Version 0.4 Jul 2009 ****************
 
#ifndef REFLECTIONHELPER_H
 
#ifndef REFLECTIONHELPER_H
 
#define REFLECTIONHELPER_H
 
#define REFLECTIONHELPER_H

Revision as of 13:53, 3 August 2009

The ReflectionHelper class

This class is composed with two source files.

//******************************* Version 0.4 Jul 2009 ****************
#ifndef REFLECTIONHELPER_H
#define REFLECTIONHELPER_H
#include <rtl/ustring.hxx>
#include <com/sun/star/uno/Sequence.hxx>
#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/lang/XMultiComponentFactory.hpp>
#include <com/sun/star/beans/XIntrospection.hpp>
#include <com/sun/star/beans/XIntrospectionAccess.hpp>
#include <com/sun/star/lang/XTypeProvider.hpp>
#include <com/sun/star/beans/MethodConcept.hpp>
#include <com/sun/star/reflection/XIdlMethod.hpp>
#include <com/sun/star/uno/Type.hxx>
#include <com/sun/star/beans/Property.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/reflection/ParamMode.hpp>
 
using rtl::OUString;
using namespace com::sun::star::reflection;
using namespace com::sun::star::beans;
using namespace com::sun::star::lang;
using namespace com::sun::star::uno;
 
class ReflectionHelper {
public:
	ReflectionHelper(Any toInspect,Reference< XMultiComponentFactory > const & oSVM, Reference< XComponentContext > const & xContext);
 
	Sequence < OUString > 	getMethods(),
				getTypes(),
				getServices(),
				getPropertiesWithoutValues(),
				getPropertiesWithValues();
	Sequence< Reference< XIdlMethod > > getIdlMethods();
	Reference< XIdlMethod > getXIdlMethodByName(OUString aName);
	void getTypeAndValue(Any toInspect);
	sal_Bool m_simpleObject;
	OUString m_OUStrAnyTypeAndValue; // for simple object data
// Print out
//	void printOut(); //perhaps const ?				
 
private:
	Any m_toInspect;
	Reference< XMultiComponentFactory > m_xServiceManager;
	Reference< XIntrospection >m_xIntrospection;
	Reference< XIntrospectionAccess > m_xIntrospec;
	Reference< XTypeProvider > m_xTypeProvider;
	Reference< XComponentContext > m_xContext;
	OUString getValueName(Any object);
	OUString getParamMode(ParamMode paramMode);
// methods
	Sequence< Reference< XIdlMethod > > mMethods;
// Interfaces
	Sequence< Type > types;
// Services
	Reference< XServiceInfo > m_xServiceInfo;
//	Sequence< OUString > services;
// Properties
	Sequence< Property > Properties;
// protected methods
protected:
	Sequence< OUString > convert2SeqOUStrInDEBUGMODE(Sequence < sal_Int8 > seqBytes);
// same as "convert2SeqOUStrInDEBUGMODE" but in one OUString
	OUString convert2OUStrInDEBUGMODE(Sequence < sal_Int8 > seqBytes);
};
#endif //REFLECTIONHELPER_H

And now the corresponding implementation :

// C++
// Serge Moutou
// with help of <OpenOffice1.1_SDK>/examples/java/Inspector
// and Bernard Marcelly XRay tool
// version 0.1 (22 Dec 2004)
// version 0.2 (4 Jun 2005) added printout in a dialog
// version 0.2.1 (4 Apr 2009) added name of parameters in methods
// version 0.3 (23 Apr 2009) added DEBUG MODE for []bytes properties
// version 0.4 (28 Jul 2009) changed to be used with a component: 
// ****** constructor uses XMultiComponentFactoty instead of XMultiServiceFactory
// To do : Exception Handling, to go further with properties values
//#include <org/openoffice/cpp/XInstanceIspector.hpp>
#include "./ReflectionHelper.hpp"
#include <com/sun/star/reflection/XIdlClass.hpp>
#include <com/sun/star/beans/PropertyConcept.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
//#include <com/sun/star/reflection/ParamMode.hpp> done in ReflectionHelper.hpp
#include <com/sun/star/container/XNameContainer.hpp>
//#include <cppuhelper/implbase1.hxx>
#include <com/sun/star/awt/XTextComponent.hpp>
//#include <com/sun/star/awt/XActionListener.hpp>
#include <com/sun/star/awt/XToolkit.hpp>
#include <com/sun/star/awt/XControlContainer.hpp>
//#include <com/sun/star/awt/PushButtonType.hpp>
//#include <com/sun/star/awt/XButton.hpp>
//#include <com/sun/star/awt/XWindow.hpp>
//#include <com/sun/star/awt/XDialog.hpp>
 
//#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <rtl/ustring.hxx>
#include <rtl/string.hxx>
//#define DEBUG
 
using namespace com::sun::star::awt;
//using namespace com::sun::star::frame;
using namespace com::sun::star::lang;
using namespace com::sun::star::container;
 
 
// Inspector constructor
ReflectionHelper::ReflectionHelper(Any toInspect, Reference< XMultiComponentFactory > const & oSVM, 
					Reference< XComponentContext > const & xContext)
	: m_toInspect(toInspect), m_xServiceManager(oSVM), m_xContext(xContext) {
	m_xIntrospection = Reference< XIntrospection >( m_xServiceManager->createInstanceWithContext(
                                OUString::createFromAscii("com.sun.star.beans.Introspection" ),m_xContext), UNO_QUERY_THROW);
	getTypeAndValue(m_toInspect);
 
}
//FIXME:Bad idea to take a method of ReflectionHelper for that ?
//**** modify data member and then doesn't keep coherence in data ?
void ReflectionHelper::getTypeAndValue(Any toInspect){
// what kind of object object ?
	OUString OUStrAnyTypeAndValue, OUStrTypeValue;
	switch (toInspect.pType->eTypeClass)
		{
		// const defined in <OOo_SDK>/include/typelib/typeclass.h
		case typelib_TypeClass_VOID:
			OUStrAnyTypeAndValue = OUString::createFromAscii("(")+ OUStrAnyTypeAndValue+
				OUString::createFromAscii(")");
			m_simpleObject = sal_True;
			m_OUStrAnyTypeAndValue = OUStrAnyTypeAndValue;
			break;
		case typelib_TypeClass_BOOLEAN:
			sal_Bool MyBool;
			toInspect >>= MyBool;
			OUStrAnyTypeAndValue = OUString::createFromAscii("(")+ OUStrAnyTypeAndValue+
				OUString::createFromAscii(")=") + OUStrTypeValue.valueOf((sal_Bool) MyBool);
			m_simpleObject=sal_True;
			m_OUStrAnyTypeAndValue = OUStrAnyTypeAndValue;
			break;
		// all in a 32 bit data at the moment
		case typelib_TypeClass_BYTE:
		case typelib_TypeClass_CHAR:
		case typelib_TypeClass_SHORT:
		case typelib_TypeClass_UNSIGNED_SHORT:
		case typelib_TypeClass_UNSIGNED_LONG:
		case typelib_TypeClass_LONG:
			sal_Int32 *MyLong;
			MyLong = (sal_Int32*) toInspect.getValue();
			OUStrAnyTypeAndValue = OUString::createFromAscii("(")+ OUStrAnyTypeAndValue+
				OUString::createFromAscii(")=") + OUStrTypeValue.valueOf((sal_Int32) *MyLong);
			m_simpleObject = sal_True;
			m_OUStrAnyTypeAndValue = OUStrAnyTypeAndValue;
			break;
		// all in the double data at the moment
		case typelib_TypeClass_FLOAT:	
		case typelib_TypeClass_DOUBLE:
        		double *myDouble;
			myDouble = (double*) toInspect.getValue();
			OUStrAnyTypeAndValue = OUString::createFromAscii("(")+ OUStrAnyTypeAndValue+
				OUString::createFromAscii(")=") + OUStrTypeValue.valueOf((double) *myDouble);
			m_simpleObject = sal_True;
			m_OUStrAnyTypeAndValue = OUStrAnyTypeAndValue;
        		break;
	/*	case typelib_TypeClass_HYPER:
        		break;
		case typelib_TypeClass_ANY:
			break; */
		case typelib_TypeClass_STRING:
			toInspect >>= OUStrTypeValue;
			OUStrAnyTypeAndValue = OUString::createFromAscii("(")+ OUStrAnyTypeAndValue+
				OUString::createFromAscii(")=")+OUStrTypeValue;
			m_simpleObject = sal_True;
			m_OUStrAnyTypeAndValue = OUStrAnyTypeAndValue;
			break;
		case typelib_TypeClass_SEQUENCE:
		  if (toInspect.getValueTypeName() == OUString::createFromAscii("[]byte")) {
			Sequence< sal_Int8 > SeqByte;
			toInspect >>= SeqByte;
			OUString OUStr=OUString::createFromAscii("([]byte)");
/*			OUStr = OUString::createFromAscii("Length:");
			OUStr=OUStr.concat(OUStr.valueOf((sal_Int32) SeqByte.getLength())+
			OUString::createFromAscii(" : "));*/
			OUStrAnyTypeAndValue=OUStr + convert2OUStrInDEBUGMODE(SeqByte); //0.3 version
			m_simpleObject = sal_True;
			m_OUStrAnyTypeAndValue = OUStrAnyTypeAndValue;
		  } else
		  if (toInspect.getValueTypeName() == OUString::createFromAscii("[]string")) {
			Sequence< OUString > SeqOUStr;
			OUString OUStr;
			toInspect >>= SeqOUStr;
			OUStr = OUString::createFromAscii("Length:");
			OUStr=OUStr.concat(OUStr.valueOf((sal_Int32) SeqOUStr.getLength())+
			OUString::createFromAscii(" : "));
			for (sal_Int32 i=0; i<SeqOUStr.getLength(); i++){
				OUStr=OUStr.concat(OUString::createFromAscii("\"")
			                   +SeqOUStr[i]
					   + OUString::createFromAscii("\""));
			}
			OUStrAnyTypeAndValue = OUString::createFromAscii("([]string) ") + OUStr;
			m_simpleObject = sal_True;
			m_OUStrAnyTypeAndValue = OUStrAnyTypeAndValue;
		  } 
		  break;
		case typelib_TypeClass_INTERFACE: 
			m_xIntrospec = m_xIntrospection->inspect(toInspect);
			mMethods = m_xIntrospec -> getMethods(MethodConcept::ALL);
			m_xTypeProvider = Reference< XTypeProvider> (toInspect,UNO_QUERY);
			types = m_xTypeProvider->getTypes();
			m_xServiceInfo = Reference< XServiceInfo>(toInspect,UNO_QUERY);
			Properties = m_xIntrospec -> getProperties(PropertyConcept::ALL);
			m_simpleObject = sal_False;
			break; 
	/*	case typelib_TypeClass_TYPE: break;
		case typelib_TypeClass_ARRAY: break;
		case typelib_TypeClass_SERVICE: break;
		case typelib_TypeClass_INTERFACE_METHOD: break;
		case typelib_TypeClass_INTERFACE_ATTRIBUTE:break;
		case typelib_TypeClass_ENUM: break;
		case typelib_TypeClass_STRUCT:break; */
		//default:		
		} // switch
}
 
 
//OK
Sequence < OUString > ReflectionHelper::getServices() {
	return m_xServiceInfo->getSupportedServiceNames();
}
 
//OK
Sequence < OUString > ReflectionHelper::getMethods(){
	Sequence< OUString > methods(mMethods.getLength());
	for (int i=0;i<mMethods.getLength();i++){
		OUString params;
		params=OUString::createFromAscii("(");
		Sequence< ParamInfo > ParamInfos = mMethods[i]->getParameterInfos();
		if (ParamInfos.getLength() > 0) {
			for (int j=0;j<ParamInfos.getLength();j++){
				Reference< XIdlClass > xIdlClass = ParamInfos[j].aType;
				if (j == 0)
				// first parameter has no leading comma
				params += OUString::createFromAscii("[") + getParamMode(ParamInfos[j].aMode)+
				OUString::createFromAscii("]") +
				xIdlClass->getName() + OUString::createFromAscii(" ") + ParamInfos[j].aName;
				else
				params += OUString::createFromAscii(",[") + getParamMode(ParamInfos[j].aMode)+
				OUString::createFromAscii("]")+
				xIdlClass->getName() + OUString::createFromAscii(" ") + ParamInfos[j].aName;
			}
		}
		params += OUString::createFromAscii(")");
		methods[i] = mMethods[i]->getReturnType()->getName()+OUString::createFromAscii(" ")+
			mMethods[i]->getName()+params;
	}
	return methods;
}
 
Sequence< Reference< XIdlMethod > > ReflectionHelper::getIdlMethods(){
	return mMethods;
}
// added for 0.4 version
Reference< XIdlMethod > ReflectionHelper::getXIdlMethodByName(OUString aName){
	Reference< XIdlMethod > xIdlMethod = m_xIntrospec->getMethod(aName,MethodConcept::ALL);
	return xIdlMethod; 
} 
// OK
Sequence < OUString > ReflectionHelper::getTypes(){
	Sequence< OUString > interfaces(types.getLength());
	for (int i=0;i<types.getLength();i++){
		interfaces[i] = types[i].getTypeName();
	}
	return interfaces;
}
 
// to improve : change all the tests with getCppuType : probably quicker than a string test
OUString ReflectionHelper::getValueName(Any object){
	OUString OUStr;
	OUStr = OUString::createFromAscii("!! Unable to compute values !!");
	if (object.hasValue()) {
		if (object.isExtractableTo(getCppuBooleanType())){
			sal_Bool MyBool;
			object >>= MyBool;
			return OUStr.valueOf((sal_Bool) MyBool);
		} else
		if (object.getValueTypeName() == OUString::createFromAscii("string")) {
			OUString *MyOUStr;
			MyOUStr = (OUString *) object.getValue();
			OUStr = OUString::createFromAscii("\"");
			return OUStr + *MyOUStr + OUString::createFromAscii("\"");
		} else
		if (object.getValueTypeName() == OUString::createFromAscii("long")) {
			sal_Int32 *MyLong;
			MyLong = (sal_Int32*) object.getValue();
			return OUStr.valueOf((sal_Int32) *MyLong);
		} else
		if (object.getValueTypeName() == OUString::createFromAscii("short")) {
			sal_Int16 *MyShort;
			MyShort = (sal_Int16*) object.getValue();
			return OUStr.valueOf((sal_Int32) *MyShort);
		} else
		if (object.getValueTypeName() == OUString::createFromAscii("[]byte")) {
			Sequence< sal_Int8 > SeqByte;
			object >>= SeqByte;
			OUString OUStr=convert2OUStrInDEBUGMODE(SeqByte); //0.3 version
			return OUStr;
		} else
		if (object.getValueTypeName() == OUString::createFromAscii("[]string")) {
			Sequence< OUString > SeqOUStr;
			object >>= SeqOUStr;
			OUStr = OUString::createFromAscii("Length:");
			OUStr=OUStr.concat(OUStr.valueOf((sal_Int32) SeqOUStr.getLength())+
			OUString::createFromAscii(" : "));
			for (sal_Int32 i=0; i<SeqOUStr.getLength(); i++){
				OUStr=OUStr.concat(OUString::createFromAscii("\"")
				                   +SeqOUStr[i]
						   + OUString::createFromAscii("\""));
			}
			return OUStr;
		} else return OUStr;
	} else return OUStr;
}
 
// OK
// Get properties with values : only those computed in getValueName
// améliorer avec :
// voir SDK2.3.1 portable IUT <SDK>/examples/cpp/extensions/source/objectbrowser/uno_lang.cxx
Sequence < OUString > ReflectionHelper::getPropertiesWithValues(){
	Sequence< OUString > propWithVal(Properties.getLength());
	for (int i=0;i<Properties.getLength();i++){
		Type typ =  getCppuType( (const Reference< XPropertySet > *)0);
		Reference< XPropertySet > rPropertySet(m_xIntrospec->queryAdapter(typ),UNO_QUERY);
		Reference< XPropertySetInfo > rPropertySetInfo=rPropertySet->getPropertySetInfo();
		Any object;
		if (rPropertySetInfo->hasPropertyByName(Properties[i].Name)){
			object <<= rPropertySet->getPropertyValue(Properties[i].Name);
			//if (object.hasValue()) printf("Valeur trouvee : \n");
			propWithVal[i] = Properties[i].Name + OUString::createFromAscii(" = (")+
				Properties[i].Type.getTypeName() + OUString::createFromAscii(") ")
				+ getValueName(object);
				//+ object.getValueTypeName();
		}
	}
	return propWithVal;
}
 
// OK
// Get properties without values but types
Sequence < OUString > ReflectionHelper::getPropertiesWithoutValues(){
	Sequence< OUString > propWithVal(Properties.getLength());
	for (int i=0;i<Properties.getLength();i++){
		Type typ =  getCppuType( (const Reference< XPropertySet > *)0);
		Reference< XPropertySet > xPropertySet(m_xIntrospec->queryAdapter(typ),UNO_QUERY);
		Reference< XPropertySetInfo > xPropertySetInfo=xPropertySet->getPropertySetInfo();
		if (xPropertySetInfo->hasPropertyByName(Properties[i].Name)){
			propWithVal[i] = Properties[i].Name + OUString::createFromAscii(" = (")+
				Properties[i].Type.getTypeName() + OUString::createFromAscii(")");
		}
	}
	return propWithVal;
}
 
// Don't forget to add : #include <com/sun/star/reflection/ParamMode.hpp>
// Don't forget to add "com.sun.star.reflection.ParamMode \" in the makefile
OUString ReflectionHelper::getParamMode(ParamMode paramMode) {
  OUString toReturn;
  toReturn = OUString::createFromAscii("");
  if (paramMode == ParamMode_IN) toReturn = OUString::createFromAscii("IN"); else
    if (paramMode == ParamMode_OUT) toReturn = OUString::createFromAscii("OUT"); else
      if (paramMode == ParamMode_INOUT) toReturn = OUString::createFromAscii("INOUT");
  return toReturn;
}
// added for 0.3 version
Sequence< OUString > ReflectionHelper::convert2SeqOUStrInDEBUGMODE(Sequence < sal_Int8 > seqBytes){
  sal_Int8 Hexa[16]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
  sal_Int32 lin,col;
  sal_Char line[80];
  sal_Int32 len,sequenceSize,index;
  len=seqBytes.getLength();
  sequenceSize=(len>>4)+2;
  if ((len&0XFFF0)==len) sequenceSize--; //if len%16==0
  Sequence< OUString > SeqOUStr(sequenceSize);
  // First line with length 
  SeqOUStr[0] = OUString::createFromAscii("Length:")+
                OUString::valueOf((sal_Int32) seqBytes.getLength())+
		OUString::createFromAscii(" ");
  len = len&0XFFF0; // remove the modulo 16
  for(lin=0;lin<len;lin=lin+16){
      for(col=0;col<16;col++){
        line[3*col]=Hexa[((unsigned char)seqBytes[lin+col])>>4];
	line[3*col+1]=Hexa[seqBytes[lin+col]&0x0F];
	line[3*col+2]=' ';
        if ((seqBytes[lin+col]<128)&&(seqBytes[lin+col]>20)) line[50+col]=seqBytes[lin+col];
        else line[50+col]='.';
      } /* end of for */
      line[66]=0; /* end of cstring...*/
      line[48]=' ';line[49]=' ';
  // ready to add the OUString in Sequence
      if ((lin%16)==0) index = lin/16+1; else index=lin/16+2;
      SeqOUStr[index]=OUString::createFromAscii(line);
  } /* end of for */ 
  // the last line is more complicated because not complete
  // we only keep modulo
  len=seqBytes.getLength()&0x000F;
  if (len>0) { // only a line here if non-empty
  for (lin=0;lin<len;lin++){
    col=lin;
    line[3*col]=Hexa[((unsigned char)seqBytes[lin])>>4];
    line[3*col+1]=Hexa[seqBytes[lin]&0x0F];
    line[3*col+2]=' ';
    if ((seqBytes[lin]<128)&&(seqBytes[lin]>20)) line[50+col]=seqBytes[lin];
    else line[50+col]='.';
  }
  // we complete the line
  for (++col;col<16;col++){
	line[3*col]=' ';line[3*col+1]=' ';line[3*col+2]=' ';line[50+col]=' ';
  }
  line[66]=0; /* end of string...*/
  line[48]=' ';line[49]=' ';
  // ready to add the OUString in Sequence
  SeqOUStr[lin/16+2]=OUString::createFromAscii(line);
  } //end if
  return SeqOUStr;
}
 
// added for 0.3 version
OUString ReflectionHelper::convert2OUStrInDEBUGMODE(Sequence < sal_Int8 > seqBytes){
  Sequence <OUString> SeqOUStr = convert2SeqOUStrInDEBUGMODE(seqBytes);
  OUString OUStr;
  for(sal_Int32 i=0;i<SeqOUStr.getLength();i++)
    OUStr = OUStr+SeqOUStr[i]+OUString::createFromAscii("\n");
  return OUStr;
}

The Component Code

Personal tools