FR/Documentation/XIntrospection Interface

From Apache OpenOffice Wiki
Jump to: navigation, search

Nous préférons utiliser la technique de l'Inspector Java : inspecter un objet réel. Vous pouvez trouver les valeurs des propriétés par exemple (<OpenOffice.org1.1_SDK>/examples/java/Inspector). De nouveau nous décrivons sommairement les interfaces que nous allons rencontrer. Commençons d'abord par l'interface com.sun.star.beans.XIntrospection :

// IDL
module com {  module sun {  module star {  module beans {
 
interface XIntrospection: com::sun::star::uno::XInterface
{ 
	com::sun::star::beans::XIntrospectionAccess inspect( [in] any aObject );
};
}; }; }; };

où nous voyons que nous devons nous concentrer sur l'autre interface com.sun.star.beans.XIntrospectionAccess :

// IDL
module com {  module sun {  module star {  module beans {
interface XIntrospectionAccess: com::sun::star::uno::XInterface
{ 
	long getSuppliedMethodConcepts(); 
	long getSuppliedPropertyConcepts();
	com::sun::star::beans::Property getProperty( [in] string aName,
			 [in] long nPropertyConcepts ) 
			raises( com::sun::star::container::NoSuchElementException );
	boolean hasProperty( [in] string aName,
			 [in] long nPropertyConcepts ); 
	sequence<com::sun::star::beans::Property> getProperties(  
				[in] long nPropertyConcepts );
	com::sun::star::reflection::XIdlMethod getMethod( [in] string aName, 
			 [in] long nMethodConcepts )
			raises( com::sun::star::lang::NoSuchMethodException ); 
	boolean hasMethod( [in] string aName, 
			 [in] long nMethodConcepts );
	sequence<com::sun::star::reflection::XIdlMethod> getMethods(
			[in] long nMethodConcepts ); 
	sequence<type> getSupportedListeners(); 
	com::sun::star::uno::XInterface queryAdapter( [in] type aInterfaceType ) 
			raises( com::sun::star::beans::IllegalTypeException ); 
};
}; }; }; };

S'il vous plait, prenez seul votre envol et regardez attentivement les autres fichiers IDL invoqués : com.sun.star.beans.Property et com.sun.star.uno.XInterface.

Obtenir des informations sur les méthodes

Nous présentons maintenant comment construire l'information d'introspection à l'aide d'un schéma.

XIntrospectionMethodInfo.png

La figure ci-dessus explique comment obtenir l'information sur les méthodes comme, le type retourné, le nom même de la méthode, et tout ce que vous voulez savoir sans oser le demander sur les paramètres. S'il vous plaît notez que getParamMode n'est pas fourni par le SDK, mais est mon propre code (inspiré très fortement de l'Inspector Java). Voir aussi l'énumération com.sun.star.reflection.ParamMode.

Documentation caution.png Comme vous le verrez dans le code C++, il y a une faute dans la figure ci-dessus pour le type retourné. La méthode est getReturnType au lieu de getReturnedType. Je corrigerai cela plus tard dans la figure.

Commençons par donner le code correspondant à la fonction getParamMode :

//Listing 12 getParamMode function
// C++
// Ne pas oublier d'ajouter : #include <com/sun/star/reflection/ParamMode.hpp>
// Ne pas oublier d'ajouter : "com.sun.star.reflection.ParamMode \" in the makefile
OUString getParamMode(ParamMode paramMode) {
// comes from <OpenOffice1.1_SDK>/examples/java/Inspector
  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;
}

Et maintenant l'implémentation complète est donnée : partant de la figure ci-dessus, c'est facile de voir que nous avons besoin de deux paramètres, une interface com.sun.star.lang.XMultiServiceFactory (qui est la racine de notre arbre IDL) et un type Any (dans lequel nous mettons l'objet à introspecter) :

//Listing 13 getMethods function
//C++
// translated in C++ from <OpenOffice1.1_SDK>/examples/java/Inspector
 
// Don't forget to add : using namespace com::sun::star::beans;
// Don't forget to add : #include <com/sun/star/beans/XIntrospection.hpp>
// Don't forget to add "com.sun.star.beans.XIntrospection \" in the makefile
 
Sequence <OUString> getMethods(Any any,Reference< XMultiServiceFactory > rSVM)
	Reference< XIntrospection >xIntrospection = Reference< XIntrospection >
					( rSVM->createInstance(
                                 OUString( RTL_CONSTASCII_USTRINGPARAM(
                                      "com.sun.star.beans.Introspection" ))), UNO_QUERY );
 
// ********* get all methods for the given object *********************
 
	Reference< XIntrospectionAccess > xIntrospec = xIntrospection->inspect(any);
 
// Don't forget to add : #include <com/sun/star/beans/MethodConcept.hpp>
// Don't forget to add "com.sun.star.beans.MethodConcept \" in the makefile
	Sequence< Reference < XIdlMethod > > mMethods = xIntrospec -> getMethods(MethodConcept::ALL);
	Sequence<OUString> OUStrs(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(")");
		OUStrs[i]= mMethods[i]->getName()+params;
	}
	return OUStrs;
}

Voir aussi les constantes UNO com.sun.star.beans.MethodConcept, et l'interface com.sun.star.beans.XIntrospection.

Obtenir toutes les interfaces

Obtenir tous les types (ou interfaces) est un travail assez simple comme montré dans la figure ci-dessous :

XIntrospectionInterfInfo.png

Jeter un oeil sur l'interface com.sun.star.lang.XTypeProvider semble aussi très utile.

Le Listing 14 ci-dessous montre, parmi d'autres choses, le code C++ correspondant.

Obtenir tous les services

Obtenir tous les services est encore une tâche plus aisée avec l'interface com.sun.star.lang.XServiceInfo :

XIntrospectionServicesInfo.png

Et de nouveau le Listing 14 ci-après nous montre encore une fois le code C++ correspondant.

Obtenir toutes les propriétés

Si vous avez une bonne connaissance de Java regardez dans le SDK dans le répertoire : <OpenOffice.org1.1_SDK>/examples/java/Inspector/InstanceInspector.java et voyez le code Java correspondant.

Documentation caution.png Quand j'ai écrit ce chapitre j'utilisais le SDK 1.1 pour lequel l'inspecteur java avait une taille raisonnable. Maintenant l'inspecteur a beaucoup évolué puisqu'il est capable de générer du code et il est donc certainement plus difficile (mais pas impossible) d'y trouver des informations utiles comme au bon vieux temps.

Le problème de l'obtention des valeurs des propriétés est donné dans le code C++ sous forme d'une classe dans la section suivante.

Une classe complete pour l'introspection

Avant de lire la suite, prenez le temps de consulter Constructing Helpers section (non encore traduite). Voici en attendant un exemple de code avec les interfaces com.sun.star.reflection.XIdlClass, com.sun.star.beans.XIntrospection, com.sun.star.lang.XTypeProvider, com.sun.star.lang.XServiceInfo et com.sun.star.beans.XPropertySet, avec les contantes UNO com.sun.star.beans.PropertyConcept et les énumérations UNO com.sun.star.reflection.ParamMode.


//Listing 14 Implementation of the reflection helper
// C++
// with help of <OpenOffice1.1_SDK>/examples/java/Inspector
// and Bernard Marcelly XRay tool
// version 0.1 (22 Dec 2004)
// To do : Exception Handling, to go further with properties values
#include "/home/smoutou/OpenOffice.org1.1_SDK/examples/DevelopersGuide/ProfUNO/CppBinding/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
 
// constructor
ReflectionHelper::ReflectionHelper(Any any,Reference< XMultiServiceFactory > oSVM)
	: toInspect(any), xServiceManager(oSVM){
	xIntrospection = Reference< XIntrospection >( xServiceManager->createInstance(
                                OUString( RTL_CONSTASCII_USTRINGPARAM(
                                "com.sun.star.beans.Introspection" ))), UNO_QUERY );
	xIntrospec = xIntrospection->inspect(toInspect);
	mMethods = xIntrospec -> getMethods(MethodConcept::ALL);
	xTypeProvider = Reference< XTypeProvider> (toInspect,UNO_QUERY);
	types = xTypeProvider->getTypes();
	xServiceInfo = Reference< XServiceInfo>(toInspect,UNO_QUERY);
	Properties = xIntrospec -> getProperties(PropertyConcept::ALL);
}
 
Sequence < OUString > ReflectionHelper::getServices() {
	return xServiceInfo->getSupportedServiceNames();
}
 
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 < 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("!! No computed value !!");
	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;
			OUStr = OUString::createFromAscii("Length:");
			OUStr=OUStr.concat(OUStr.valueOf((sal_Int32) SeqByte.getLength()));
			for (sal_Int32 i=0; i<SeqByte.getLength(); i++){
				OUStr=OUStr.concat(OUStr.valueOf((sal_Int32) SeqByte[i]));
				OUStr=OUStr.concat(OUString::createFromAscii(" "));
			}
			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;
}
 
// Get properties with values : only those computed in getValueName
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(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);
		}
	}
	return propWithVal;
}
 
// 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(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;
}
Documentation caution.png

Parcequ'il est difficile de maintenir du code plusieurs fois répété, j'ai ajouté le code complet de la Classe C++ ici. Je ne metterai à jour désormais que cette classe et elle correspondra donc à la version la plus récente de ce code.

Cela représente beaucoup de code. Donnons-en donc une représentation schématique pour les parties manquantes, à savoir, l'obtention des propriétés.

Représentation schématique des propriétés

Obtenir les propriétés avec les valeurs n'est pas chose aisée. J'espère que la figure ci-dessous vous sera d'un grand secours pour comprendre le code.

PropertiesIntrospection.png

Documentation caution.png Après vérification les points d'interrogation après XInterface peuvent être retirés. Je remettrai l'image à jour un de ces jours.

Voir aussi les interfaces com.sun.star.lang.XMultiServiceFactory, com.sun.star.beans.XIntrospection, com.sun.star.beans.XIntrospectionAccess, com.sun.star.beans.XPropertySet et com.sun.star.beans.XPropertySetInfo.

Documentation caution.png

Ce code utilise la méthode getValueName pour le moment à cause des difficultés que j'ai rencontrées pour résoudre le problème d'affichage des valeurs des propriétés. Je ne pense malheureusement pas utiliser le chemin le plus simple pour résoudre cela : ce problème devrait probablement être mieux résolu en utilisant d'avantage getCppuType ou en cherchant une autre manière pour les types Any.

Retour à Fichiers IDL et C++

See also

Personal tools