Developpement/Cpp/Component/RelectionHelper

From Apache OpenOffice Wiki
Revision as of 13:57, 3 August 2009 by SergeMoutou (Talk | contribs)

Jump to: navigation, search

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

The component IDL file is as follows

TO DO

The corresponding c++ code is :

/***************************************************************************************************
 ***************************************************************************************************
 *
 * service implementation:	 foo.Counter
 * exported interfaces:		 foo.XCounter
 *
 * simple example component implementing a counter
 *
 ***************************************************************************************************
 **************************************************************************************************/
 
#include <rtl/ustring.hxx>
#include <rtl/string.hxx>
#include <cppuhelper/queryinterface.hxx> // helper for queryInterface() impl
#include <cppuhelper/factory.hxx> // helper for component factory
// New
#include <cppuhelper/implbase3.hxx> // "3" implementing three interfaces
#include <cppuhelper/implementationentry.hxx>
#include <com/sun/star/awt/XDialog.hpp>
#include <com/sun/star/awt/XNumericField.hpp>
#include <com/sun/star/awt/XControl.hpp>
#include <com/sun/star/awt/XControlContainer.hpp>
#include <com/sun/star/awt/XDialogEventHandler.hpp>
#include <com/sun/star/awt/XDialogProvider2.hpp>
#include <com/sun/star/awt/XTextComponent.hpp>
#include <com/sun/star/awt/tree/XTreeControl.hpp>
#include <com/sun/star/awt/tree/XMutableTreeDataModel.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
// generated c++ interfaces
//#include <com/sun/star/lang/XSingleServiceFactory.hpp>
//#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/lang/XMultiComponentFactory.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/frame/XDesktop.hpp>
#include <com/sun/star/frame/XFrame.hpp>
#include <com/sun/star/frame/XModel.hpp>
//#include <com/sun/star/lang/WrappedTargetException.hpp>
//#include <com/sun/star/reflection/XIdlClass.hpp>
//#include <com/sun/star/reflection/XIdlMethod.hpp>
#include <com/sun/star/registry/XRegistryKey.hpp>
#include <com/sun/star/uno/Any.hxx>
#include <foo/XCountable.hpp>
// Java Inspector
//#include <org/openoffice/XInstanceInspector.hpp>
 
//ReflectionHelper
#include "ReflectionHelper.hpp"
// FIXME : change the service name
#define SERVICENAME "foo.Counter"
#define IMPLNAME "com.sun.star.comp.example.cpp.Counter"
 
using namespace ::rtl;
using namespace ::osl;
using namespace ::cppu;
using namespace ::com::sun::star::awt;
using namespace ::com::sun::star::awt::tree;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::registry;
using namespace ::com::sun::star::frame;
using namespace ::com::sun::star::beans;
//using namespace ::com::sun::star::relflection;
using namespace ::foo;
//using namespace ::org::openoffice;
//==================================================================================================
namespace my_sc_impl
{
static Sequence< OUString > getSupportedServiceNames_MyCounterImpl()
{
	static Sequence < OUString > *pNames = 0;
	if( ! pNames )
	{
//		MutexGuard guard( Mutex::getGlobalMutex() );
		if( !pNames )
		{
			static Sequence< OUString > seqNames(1);
			seqNames.getArray()[0] = OUString(RTL_CONSTASCII_USTRINGPARAM(SERVICENAME));
			pNames = &seqNames;
		}
	}
	return *pNames;
}
 
static OUString getImplementationName_MyCounterImpl()
{
	static OUString *pImplName = 0;
	if( ! pImplName )
	{
//		MutexGuard guard( Mutex::getGlobalMutex() );
		if( ! pImplName )
		{
			static OUString implName( RTL_CONSTASCII_USTRINGPARAM(IMPLNAME) );
			pImplName = &implName;
		}
	}
	return *pImplName;
}
 
// New
class MyCounterImpl : public ::cppu::WeakImplHelper3<
      XCountable, XServiceInfo, XDialogEventHandler >
{
	// to obtain other services if needed
	Reference< XMultiComponentFactory > m_xMCF;
	Reference< XComponentContext > m_xContext;
//	Reference< XInstanceInspector > m_xInspector;
//	sal_Int32 m_nCount;
	Reference< XMutableTreeDataModel > m_xMutTreeDatMod;
	Reference< XDialog > m_xDialog;
	Any m_toInspect;
public:
// added this constructor 06/06/09 
    inline MyCounterImpl( Reference< XComponentContext > const & xContext) throw ()
        : m_xContext( xContext ) {
	m_xMCF=m_xContext->getServiceManager();
 
//	Reference< XMutableTreeDataModel > xTreeMutDatMod(xTreeControl,UNO_QUERY); //NO NO NO:hangs the office : see below
	m_xMutTreeDatMod = Reference< XMutableTreeDataModel > (m_xMCF->createInstanceWithContext(
			OUString::createFromAscii("com.sun.star.awt.tree.MutableTreeDataModel"),m_xContext),UNO_QUERY_THROW);
	Reference< XDialogProvider2 > xDialog2(m_xMCF->createInstanceWithContext( 
            					OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.DialogProvider2" ) ),
						m_xContext),
						UNO_QUERY_THROW );
	m_xDialog=xDialog2->createDialogWithHandler(
		OUString::createFromAscii( "vnd.sun.star.script:Standard.SimpleTreeDialog?location=application" ),
		(XCountable *)this);
// If you want to use java Inspector
//	m_xInspector = Reference< XInstanceInspector > (m_xMCF->createInstanceWithContext( 
//            					OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.InstanceInspector" ) ),
//						m_xContext),
//						UNO_QUERY_THROW );
 
 
	}
    virtual ~MyCounterImpl() {}
 
    // XServiceInfo specification
    virtual OUString SAL_CALL getImplementationName(  ) throw(RuntimeException);
    virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) throw(RuntimeException);
    virtual Sequence< OUString > SAL_CALL getSupportedServiceNames(  ) throw(RuntimeException);
    static Sequence< OUString > SAL_CALL getSupportedServiceNames_Static(  );
 
    // XCountable specification
    virtual void SAL_CALL myInspect(const Any &toInspect) throw (RuntimeException);
 
// XDialogEventHandler specification
    virtual sal_Bool SAL_CALL callHandlerMethod(const Reference< XDialog >& xDialog,const Any& EventObject,const OUString& MethodName )
throw(WrappedTargetException, RuntimeException);
    virtual Sequence< OUString > SAL_CALL getSupportedMethodNames() throw (RuntimeException);
};
// XCountable implementation
//*************************************************************************
void SAL_CALL MyCounterImpl::myInspect(const Any &toInspect) throw (RuntimeException){
// use of ReflectionHelper
	ReflectionHelper RefHelp(toInspect,m_xMCF,m_xContext);
// Constructing the Tree 24th Jul 2009 (dynamic Tree)
	m_toInspect = toInspect;
	Reference< XControlContainer > xControlContainer(m_xDialog,UNO_QUERY);
	Reference< XControl > xControl = xControlContainer->getControl(OUString::createFromAscii("TreeControl"));
	Reference< XServiceInfo > xServiceInfo(toInspect,UNO_QUERY);
	OUString implName(xServiceInfo->getImplementationName());
	Any any;
	any <<= implName;
	Reference< XMutableTreeNode > xMTN=m_xMutTreeDatMod->createNode(any,sal_True);
	m_xMutTreeDatMod->setRoot(xMTN);
	any <<= OUString::createFromAscii("Methods");
	Reference< XMutableTreeNode > xChildNode = m_xMutTreeDatMod->createNode(any,sal_True);
	xMTN->appendChild(xChildNode);
	Sequence< OUString > SeqMethods = RefHelp.getMethods();
	for (sal_Int32 i=0;i<SeqMethods.getLength();i++) {
		any <<= SeqMethods[i];
		Reference< XMutableTreeNode > xChildNode2 = m_xMutTreeDatMod->createNode(any,sal_True);
		xChildNode->appendChild(xChildNode2);
	}
	any <<= OUString::createFromAscii("Interfaces");
	xChildNode = m_xMutTreeDatMod->createNode(any,sal_True);
	xMTN->appendChild(xChildNode);
	Sequence< OUString > SeqTypes = RefHelp.getTypes();
	for (sal_Int32 i=0;i<SeqTypes.getLength();i++) {
		any <<= SeqTypes[i];
		Reference< XMutableTreeNode > xChildNode2 = m_xMutTreeDatMod->createNode(any,sal_True);
		xChildNode->appendChild(xChildNode2);
	}
	any <<= OUString::createFromAscii("Services");
	xChildNode = m_xMutTreeDatMod->createNode(any,sal_True);
	xMTN->appendChild(xChildNode);
	Sequence< OUString > SeqServices = RefHelp.getServices();
	for (sal_Int32 i=0;i<SeqServices.getLength();i++) {
		any <<= SeqServices[i];
		Reference< XMutableTreeNode > xChildNode2 = m_xMutTreeDatMod->createNode(any,sal_True);
		xChildNode->appendChild(xChildNode2);
	}
	any <<= OUString::createFromAscii("Properties");
	xChildNode = m_xMutTreeDatMod->createNode(any,sal_True);
	xMTN->appendChild(xChildNode);
	Sequence< OUString > SeqProperties = RefHelp.getPropertiesWithValues();
	for (sal_Int32 i=0;i<SeqProperties.getLength();i++) {
		any <<= SeqProperties[i];
		Reference< XMutableTreeNode > xChildNode2 = m_xMutTreeDatMod->createNode(any,sal_True);
		xChildNode->appendChild(xChildNode2);
	}
// set the model to see the tree in control (two hours to find four lines below)
// translation of oTreeModel = oTreeCtrl.Model and oTreeModel.DataModel = oMutableTreeDataModel
        Reference< XControlModel > xControlModel=xControl->getModel();
	Reference< XPropertySet > xPropertySet( xControlModel,UNO_QUERY);
	any <<= m_xMutTreeDatMod;
	xPropertySet->setPropertyValue(OUString::createFromAscii("DataModel"),any);
	// put the new node name in text control
	OUString OUStrMethodName = m_toInspect.getValueTypeName();
	xControl = xControlContainer->getControl(OUString::createFromAscii("lbDescription"));
        Reference< XTextComponent > xTextComponent(xControl,UNO_QUERY);
	xTextComponent->setText(OUStrMethodName);
// execute dialog
	m_xDialog->execute();
 
}
 
// XDialogEventHandler implementation
sal_Bool SAL_CALL MyCounterImpl::callHandlerMethod(const Reference< XDialog >& xDialog,const Any& EventObject,const OUString & MethodName ) throw(WrappedTargetException, RuntimeException ){
  if (MethodName.equalsAscii("LosingFocus")){//When Losing Focus in Tree control
	// not used in this example
	return sal_True;
  }
  if (MethodName.equalsAscii("Invoke")){//add a child to the selected node -- not done
// First retrieve the selection
        Reference< XControlContainer > xControlContainer(xDialog,UNO_QUERY);
	Reference< XControl > xControl = xControlContainer->getControl(OUString::createFromAscii("TreeControl"));	
	// com.sun.star.awt.tree.XTreeControl
        Reference< XTreeControl > xTreeControl(xControl,UNO_QUERY);
	Any any=xTreeControl->getSelection();
	// Parent
	Reference< XMutableTreeNode > xParentNode;
	any >>= xParentNode;	
// adding invoke result
 
//	sal_Int32 nb=xParentNode->getChildCount();
	// Child
	OUString OUStr,OUStrMethodName(OUString::createFromAscii("notFound"));
 
	any=xParentNode->getDisplayValue();
	any >>= OUStr;
//FIXME: parsing is too simple	
//	if ( OUStr.match(OUString::createFromAscii("()"),OUStr.getLength()-2) ) { // zero arguments
	if ( OUStr.endsWithAsciiL("()",2) ) { // zero arguments
//FIXME check if parent Node is really a "method"
		sal_Int32 beginIndex=OUStr.indexOfAsciiL(" ",1);
		sal_Int32 length = OUStr.indexOfAsciiL("()",1)-beginIndex;
		OUStr = OUStr.copy(beginIndex+1,length-1);
//FIXME: keep this data in a member field to avoid constructor call for a second time
		ReflectionHelper RefHelp(m_toInspect,m_xMCF,m_xContext);
//FIXME: hangs the office with exception if bad method name
//****** it occurs when invoke a method with parameter !!!
//****** because of bad parsing
		Reference < XIdlMethod > xIdlMethod = RefHelp.getXIdlMethodByName(OUStr);
// FIXME: is this check good enough ?
		if (xIdlMethod.is()) { 
		//Sequence<Reference <XIdlClass> > seqXIdlClass = xIdlMethod->getParameterTypes();
		//	OUStrMethodName = xIdlMethod->getName(); 
			Sequence < Any >SeqAny(0);
			any=xIdlMethod->invoke(m_toInspect,SeqAny);
			OUStrMethodName = any.getValueTypeName();
		//any >>= OUStrMethodName;
			RefHelp.getTypeAndValue(any);
			if (RefHelp.m_simpleObject)
				OUStrMethodName = RefHelp.m_OUStrAnyTypeAndValue;
			else
				OUStrMethodName = any.getValueTypeName();
		} // if (xIdlMethod.is())
	} //if ( OUStr.endsWithAsciiL("()",2) ) { // zero arguments
 
// put the new node name in text control
	xControl = xControlContainer->getControl(OUString::createFromAscii("lbDescription"));
        Reference< XTextComponent > xTextComponent(xControl,UNO_QUERY);
	xTextComponent->setText(OUStrMethodName);
/*	any <<= OUStr;
	Reference< XMutableTreeNode > xChildMutTreeNode = m_xMutTreeDatMod->createNode(any ,sal_True);
// Java Introspection
//	any <<= xChildMutTreeNode;
//	m_xInspector->inspect(any,OUString::createFromAscii("Inspector"));        
	xParentNode->appendChild(xChildMutTreeNode); */
	return sal_True;
  }
  return sal_False;
}
Sequence< OUString > SAL_CALL MyCounterImpl::getSupportedMethodNames() throw (RuntimeException){
  Sequence< OUString > SeqOUStr(2);
  SeqOUStr[0]=OUString::createFromAscii("LosingFocus");
  SeqOUStr[1]=OUString::createFromAscii("Invoke");
  return SeqOUStr;
}
// XServiceInfo	implementation
//*************************************************************************
OUString SAL_CALL MyCounterImpl::getImplementationName(  )
	throw(RuntimeException)
{
	return OUString( RTL_CONSTASCII_USTRINGPARAM(IMPLNAME) );
}
 
//*************************************************************************
sal_Bool SAL_CALL MyCounterImpl::supportsService( const OUString& ServiceName )
	throw(RuntimeException)
{
	return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(SERVICENAME) );
}	
 
//*************************************************************************
Sequence<OUString> SAL_CALL MyCounterImpl::getSupportedServiceNames(  )
	throw(RuntimeException)
{
	return getSupportedServiceNames_Static();
}
 
//*************************************************************************
Sequence<OUString> SAL_CALL MyCounterImpl::getSupportedServiceNames_Static(  )
{
	Sequence<OUString> names(1);
    names[0] = OUString(RTL_CONSTASCII_USTRINGPARAM(SERVICENAME));
    return names;
}
 
//*****New vesion with context management
Reference< XInterface > SAL_CALL MyCounterImpl_createInstance(
    Reference< XComponentContext > const & xContext )
    SAL_THROW( () )
{
    return static_cast< ::cppu::OWeakObject * >( new MyCounterImpl( xContext ) );
}
}
 
//##################################################################################################
//#### EXPORTED ####################################################################################
//##################################################################################################
 
/* New ****/
/* shared lib exports implemented without helpers in service_impl1.cxx */
 
namespace my_sc_impl
{
static struct ::cppu::ImplementationEntry s_component_entries [] =
{
    { // MyCounterImpl_create replaced by MyCounterImpl_createInstance 19/05/09
        MyCounterImpl_createInstance, getImplementationName_MyCounterImpl,
        getSupportedServiceNames_MyCounterImpl, ::cppu::createSingleComponentFactory,
        0, 0
    },
    { 0, 0, 0, 0, 0, 0 }
};
}
 
extern "C"
{
void SAL_CALL component_getImplementationEnvironment(
    sal_Char const ** ppEnvTypeName, uno_Environment ** ppEnv )
{
    *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
}
sal_Bool SAL_CALL component_writeInfo(
    XMultiServiceFactory * xMgr, XRegistryKey * xRegistry )
{
    return ::cppu::component_writeInfoHelper(
        xMgr, xRegistry, ::my_sc_impl::s_component_entries );
}
void * SAL_CALL component_getFactory(
    sal_Char const * implName, XMultiServiceFactory * xMgr,
    XRegistryKey * xRegistry )
{
    return ::cppu::component_getFactoryHelper(
        implName, xMgr, xRegistry, ::my_sc_impl::s_component_entries );
}
}
Personal tools