1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #ifndef _COMPHELPER_IMPLEMENTATIONREFERENCE_HXX
25 #define _COMPHELPER_IMPLEMENTATIONREFERENCE_HXX
26 
27 #include <com/sun/star/uno/Reference.hxx>
28 #include <com/sun/star/uno/XInterface.hpp>
29 
30 namespace comphelper
31 {
32 
33     /** Holds a uno::Reference alongside a C++ implementation pointer
34 
35     	This template is useful to accomplish the following task: the
36     	client needs an implementation pointer to an object providing
37     	UNO interfaces. It is unsafe to simply store a C++ pointer,
38     	because of the automatic UNO lifetime control. It is
39     	inconvenient to always cast the UNO interface to the C++
40     	implementation, and what's more, it's mostly unclear to the
41     	casual code reader.
42 
43         Thus, this template nicely encapsulate the stated intention,
44         by holding a uno::Reference internally, and providing simple
45         C++ pointer semantics to the outside. As a differentiator to
46         ::rtl::Reference, this template features a getRef() method,
47         giving you friction-less access to the internal UNO interface,
48         without extra querying.
49 
50         By the way, the pointer semantic of this template include
51         transitive constness. That means, if this template's instance
52         is const (e.g. because it is a member of a class which is
53         accessed in a const method), the pointer returned is also
54         const.
55 
56         As this template is geared towards fast, internal pointer
57         access, validity of the UNO reference is _not_ checked for
58         every pointer access. The client of this template is
59         responsible to check that, whereever necessary, via the is()
60         method.
61 
62         @tpl CppType
63         The C++ type this class should mimick a pointer to (not the
64         pointer type itself!).
65 
66         @tpl UnoType
67         The UNO interface type of the object (a uno::Reference to this
68         type is held internally).
69 
70         @tpl XIfType
71         An unambiguous derivative of UnoType. This is defaulted to
72         the second template parameter (UnoType), which should normally
73         just work, since one typically has only single inheritance in
74         UNO.<p>
75         Alternatively, when using the
76         ImplementationReference::createFromQuery() method to create an
77         instance, this type can serve a different need: if the
78         provided CppType only derives from XInterface (generally
79         speaking, derives from a UNO interface above UnoType in the
80         class hierarchy), then the default XIfType constitutes a
81         possibly invalid downcast to UnoType. Setting XIfType equal to
82         CppTypes's most derived UNO interface type then solves this
83         problem (which is not as arcane as it seems to be. Just
84         imagine you're providing a C++ abstract interface, which must
85         provide UNO reference semantics. Naturally, you will derive
86         this C++ interface only from XInterface, to reduce the number
87         of ambiguous classes. Even more naturally, it is reasonable to
88         have UnoType be something different from XInterface, governed
89         by the usage of the C++ interface)
90 
91         @sample ImplementationReference< MyCppType, XMyInterface >
92 
93         @sample ImplementationReference< MyAbstractCppType, XMyInterface, XInterface >
94         for an abstract C++ class
95 
96         @see ::rtl::Reference
97 
98      */
99     template < class CppType,
100                class UnoType,
101                class XIfType=UnoType > class ImplementationReference
102     {
103     public:
104 
105         typedef UnoType UnoInterfaceType;
106         typedef CppType ImplementationType;
107         typedef XIfType UnambiguousXInterfaceType;
108 
109         /** Default-construct an ImplementationReference
110 
111         	Uno reference will be invalid, implementation pointer will
112         	be NULL.
113          */
ImplementationReference()114         ImplementationReference() :
115             mxRef(),
116             mpImpl( NULL )
117         {
118         }
119 
120         /** Create an ImplementationReference from C++ pointer.
121 
122         	This constructor does not perform an explicit
123         	QueryInterface on the provided implementation object, but
124         	constructs the UNO reference directly from the given
125         	pointer. This is the fastest, and most often the best way
126         	to create an ImplementationReference. If the conversion
127         	between the implementation object and the required UNO
128         	interface is ambiguous, provide the third template
129         	parameter with a type that can be unambiguously upcasted
130         	to the UNO interface (the second template parameter).
131 
132             There are cases, however, where performing a
133             QueryInterface is the better, albeit slower choice. In
134             these cases, createFromQuery() should be used.
135 
136             @param pImpl
137             Pointer to the C++ implementation type
138 
139             @see createFromQuery()
140         */
ImplementationReference(ImplementationType * pImpl)141         explicit ImplementationReference( ImplementationType* pImpl ) :
142             mxRef( static_cast<UnambiguousXInterfaceType*>(pImpl) ),
143             mpImpl( pImpl )
144         {
145         }
146 
147         struct CreateFromQuery { };
148         /** Create an ImplementationReference from C++ pointer
149 
150         	@param pImpl
151             The pointer to the C++ implementation type, which is
152             queried for the template-parameterized UNO type.
153 
154             @param dummy
155             Dummy parameter, to distinguish this contructor from the
156             default unary one (which does not perform a
157             QueryInterface)
158          */
ImplementationReference(ImplementationType * pImpl,CreateFromQuery)159         ImplementationReference( ImplementationType* pImpl, CreateFromQuery ) :
160             mxRef( static_cast<UnambiguousXInterfaceType*>(pImpl),
161                    ::com::sun::star::uno::UNO_QUERY ),
162             mpImpl( pImpl )
163         {
164         }
165 
166         /** Factory method to create an ImplementationReference from
167             C++ pointer.
168 
169             This is a static version of the constructor which creates
170             an instance of an implementation type which is explicitely
171             queried for the ImplementationReference's
172             template-parameterized UNO type.
173 
174             @sample
175                 mpRef = mpRef.createFromQuery( new ImplementationType );
176         */
createFromQuery(ImplementationType * pImpl)177         static ImplementationReference createFromQuery( ImplementationType* pImpl )
178         {
179             return ImplementationReference( pImpl, CreateFromQuery() );
180         }
181 
182         /** Query whether the pointer is still valid.
183 
184         	Hands off also from the implementation pointer if this
185         	returns false!
186          */
is() const187         bool is() const { return mxRef.is(); }
188 
189         /** Get a pointer to the implementation object
190 
191 			Compatibility method to get an auto_ptr-compatible
192 			interface
193          */
get()194         ImplementationType* 		get() { return mpImpl; }
get() const195         const ImplementationType* 	get() const { return mpImpl; }
196 
197         /** Release all references
198 
199 			Compatibility method to get an auto_ptr-compatible
200 			interface
201          */
reset()202         void						reset() { dispose(); }
203 
204         /** Release all references
205 
206         	This method releases the UNO interface reference, and
207         	clears the C++ pointer to NULL.
208          */
dispose()209         void						dispose() { mxRef = NULL; mpImpl=NULL; }
210 
operator ->()211         ImplementationType* 		operator->() { return mpImpl; }
operator ->() const212         const ImplementationType* 	operator->() const { return mpImpl; }
213 
operator *()214         ImplementationType& 		operator*() { return *mpImpl; }
operator *() const215         const ImplementationType& 	operator*() const { return *mpImpl; }
216 
217         /// Access to the underlying UNO reference, without extra querying
getRef()218         ::com::sun::star::uno::Reference< UnoInterfaceType > getRef() { return mxRef; }
219 
220         /// Access to the underlying UNO reference, without extra querying
getRef() const221         const ::com::sun::star::uno::Reference< UnoInterfaceType >& getRef() const { return mxRef; }
222 
223         // default destructor, copy constructor and assignment will do
224         // ~ImplementationReference();
225         // ImplementationReference( const ImplementationReference& );
226         // ImplementationReference& operator= ( const ImplementationReference& );
227 
228         /** Comparison operator
229 
230         	Object identity is defined to be identity of the
231         	implementation pointers. This is in general invalid when
232         	comparing pointers to UNO objects (ambiguous class
233         	hierarchies, optimizations in the bridges, etc.), but okay
234         	for raw C++ pointers (which is what's compared herein).
235         */
operator ==(const ImplementationReference & rhs) const236         bool operator==( const ImplementationReference& rhs ) const
237         {
238             return mpImpl == rhs.mpImpl;
239         }
240 
241         /** less-than operator
242 
243         	Object order is defined to be the ordering of the
244         	implementation pointers. This is in general invalid when
245         	comparing pointers to UNO objects (ambiguous class
246         	hierarchies, optimizations in the bridges, etc.), but okay
247         	for raw C++ pointers (which is what's used herein).
248 
249             This ordering complies with STL's strict weak ordering
250             concept.
251         */
operator <(const ImplementationReference & rhs) const252         bool operator<( const ImplementationReference& rhs ) const
253         {
254             return mpImpl < rhs.mpImpl;
255         }
256 
257     private:
258 
259         // the interface, hard reference to prevent object from vanishing
260         ::com::sun::star::uno::Reference< UnoInterfaceType > 	mxRef;
261 
262         // the c++ object, for our internal stuff
263         ImplementationType* 									mpImpl;
264 
265     };
266 
267 }
268 
269 #endif // _COMPHELPER_IMPLEMENTATIONREFERENCE_HXX
270