1 /**
2  * This file is part of TelepathyQt
3  *
4  * @copyright Copyright (C) 2008-2009 Collabora Ltd. <http://www.collabora.co.uk/>
5  * @copyright Copyright (C) 2008-2009 Nokia Corporation
6  * @license LGPL 2.1
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21  */
22 
23 #ifndef _TelepathyQt_optional_interface_factory_h_HEADER_GUARD_
24 #define _TelepathyQt_optional_interface_factory_h_HEADER_GUARD_
25 
26 #ifndef IN_TP_QT_HEADER
27 #error IN_TP_QT_HEADER
28 #endif
29 
30 #include <TelepathyQt/Global>
31 
32 #include <QObject>
33 #include <QStringList>
34 #include <QtGlobal>
35 
36 namespace Tp
37 {
38 
39 class AbstractInterface;
40 
41 #ifndef DOXYGEN_SHOULD_SKIP_THIS
42 
43 class TP_QT_EXPORT OptionalInterfaceCache
44 {
45     Q_DISABLE_COPY(OptionalInterfaceCache)
46 
47 public:
48     explicit OptionalInterfaceCache(QObject *proxy);
49 
50     ~OptionalInterfaceCache();
51 
52 protected:
53     AbstractInterface *getCached(const QString &name) const;
54     void cache(AbstractInterface *interface) const;
55     QObject *proxy() const;
56 
57 private:
58     struct Private;
59     friend struct Private;
60     Private *mPriv;
61 };
62 
63 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
64 
65 template <typename DBusProxySubclass> class OptionalInterfaceFactory
66 #ifndef DOXYGEN_SHOULD_SKIP_THIS
67     : private OptionalInterfaceCache
68 #endif
69 {
70     Q_DISABLE_COPY(OptionalInterfaceFactory)
71 
72 public:
73     enum InterfaceSupportedChecking
74     {
75         CheckInterfaceSupported,
76         BypassInterfaceCheck
77     };
78 
OptionalInterfaceFactory(DBusProxySubclass * this_)79     inline OptionalInterfaceFactory(DBusProxySubclass *this_)
80         : OptionalInterfaceCache(this_)
81     {
82     }
83 
~OptionalInterfaceFactory()84     inline ~OptionalInterfaceFactory()
85     {
86     }
87 
interfaces()88     inline QStringList interfaces() const { return mInterfaces; }
89 
hasInterface(const QString & name)90     inline bool hasInterface(const QString &name) const
91     {
92         return mInterfaces.contains(name);
93     }
94 
95     template <class Interface>
96     inline Interface *optionalInterface(
97             InterfaceSupportedChecking check = CheckInterfaceSupported) const
98     {
99         // Check for the remote object supporting the interface
100         // Note that extra whitespace on "name" declaration is significant to avoid
101         // vexing-parse
102         QString name( (QLatin1String(Interface::staticInterfaceName())) );
103         if (check == CheckInterfaceSupported && !mInterfaces.contains(name)) {
104             return 0;
105         }
106 
107         // If present or forced, delegate to OptionalInterfaceFactory
108         return interface<Interface>();
109     }
110 
111     template <typename Interface>
interface()112     inline Interface *interface() const
113     {
114         AbstractInterface* interfaceMustBeASubclassOfAbstractInterface = static_cast<Interface *>(NULL);
115         Q_UNUSED(interfaceMustBeASubclassOfAbstractInterface);
116 
117         // If there is a interface cached already, return it
118         // Note that extra whitespace on "name" declaration is significant to avoid
119         // vexing-parse
120         QString name( (QLatin1String(Interface::staticInterfaceName())) );
121         AbstractInterface *cached = getCached(name);
122         if (cached)
123             return static_cast<Interface *>(cached);
124 
125         // Otherwise, cache and return a newly constructed proxy
126         Interface *interface = new Interface(
127                 static_cast<DBusProxySubclass *>(proxy()));
128         cache(interface);
129         return interface;
130     }
131 
132 protected:
setInterfaces(const QStringList & interfaces)133     inline void setInterfaces(const QStringList &interfaces)
134     {
135         mInterfaces = interfaces;
136     }
137 
138 private:
139     QStringList mInterfaces;
140 };
141 
142 } // Tp
143 
144 #endif
145