Add support for optional RDF properties
[qtcontacts-tracker:hasselmms-qtcontacts-tracker.git] / src / dao / contactdetailfield.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the Qt Mobility Components.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file.  Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #ifndef QTRACKERCONTACTDETAILFIELD_H
43 #define QTRACKERCONTACTDETAILFIELD_H
44
45 #include "subject.h"
46
47 #include <QtTracker/rdfunbound.h>
48 #include <QtTracker/ontologies/rdfs.h>
49
50 QTM_BEGIN_NAMESPACE;
51
52 ////////////////////////////////////////////////////////////////////////////////////////////////////
53
54 using SopranoLive::LiveResourceBridge;
55
56 using SopranoLive::RDFProperty;
57 using SopranoLive::RDFSelect;
58 using SopranoLive::RDFStrategy;
59 using SopranoLive::RDFStrategyFlags;
60 using SopranoLive::RDFVariable;
61
62 ////////////////////////////////////////////////////////////////////////////////////////////////////
63
64 class QTrackerContactDetail;
65
66 ////////////////////////////////////////////////////////////////////////////////////////////////////
67
68 class ResourceInfo {
69     Q_DISABLE_COPY(ResourceInfo);
70
71 public:
72     enum Flag {
73         Default =    0,
74         ReadOnly =  (1 << 0),
75         Shared =    (1 << 1),
76         Optional =  (1 << 2)
77     };
78
79     Q_DECLARE_FLAGS(Flags, Flag);
80
81 protected:
82     explicit ResourceInfo(const QVariant &value, Flags flags) :
83             mValue(value), mFlags(flags)
84     {
85     }
86
87 public:
88     virtual ~ResourceInfo()
89     {
90     }
91
92     const QString text() const { return value().toString(); }
93     const QVariant& value() const { return mValue; }
94
95     void modifyFlags(Flags mask, bool value);
96     void setFlags(Flags flags) { mFlags = flags; }
97     Flags flags() const { return mFlags; }
98
99     virtual const QUrl& iri() const = 0;
100
101 private:
102     QVariant mValue;
103     Flags    mFlags;
104 };
105
106 ////////////////////////////////////////////////////////////////////////////////////////////////////
107
108 template<class Class>
109 class ClassInfo : public ResourceInfo {
110     Q_DISABLE_COPY(ClassInfo);
111
112 public:
113     explicit ClassInfo(const QString &name, Flags flags = Default) :
114         ResourceInfo(name, flags)
115     {
116     }
117
118     const QUrl& iri() const { return Class::iri(); }
119 };
120
121 ////////////////////////////////////////////////////////////////////////////////////////////////////
122
123 template<class Class>
124 class InstanceInfo : public ResourceInfo {
125     Q_DISABLE_COPY(InstanceInfo);
126
127 public:
128     explicit InstanceInfo(const QVariant &value, Flags flags = Default) :
129         ResourceInfo(value, flags)
130     {
131     }
132
133     const QUrl& iri() const { return Class::iri(); }
134 };
135
136 ////////////////////////////////////////////////////////////////////////////////////////////////////
137
138 class PropertyInfoBase : public ResourceInfo
139 {
140     Q_DISABLE_COPY(PropertyInfoBase);
141
142 protected:
143     explicit PropertyInfoBase(const QString &name, Flags flags) :
144         ResourceInfo(name, flags)
145     {
146     }
147
148 public:
149     virtual RDFVariable bindProperty(const RDFVariable &source,
150                                      const RDFVariable &target = RDFVariable()) const = 0;
151
152     virtual const QUrl & range() const = 0;
153
154 protected:
155     static const QUrl & resourceIri(QDateTime *)
156     {
157         return SopranoLive::Ontologies::xsd::dateTime::iri();
158     }
159
160     static const QUrl & resourceIri(QString *)
161     {
162         return SopranoLive::Ontologies::xsd::string::iri();
163     }
164
165     template<class ResourceClass>
166     static const QUrl & resourceIri(ResourceClass *)
167     {
168         return ResourceClass::iri();
169     }
170 };
171
172 ////////////////////////////////////////////////////////////////////////////////////////////////////
173
174 template<class Class>
175 class PropertyInfo : public PropertyInfoBase {
176     Q_DISABLE_COPY(PropertyInfo);
177
178 public:
179     typedef typename Class::Domain Domain;
180     typedef typename Class::Range  Range;
181
182     explicit PropertyInfo(const QString &name = QString(), Flags flags = Default) :
183         PropertyInfoBase(name, flags)
184     {
185     }
186
187     RDFVariable bindProperty(const RDFVariable &subject, const RDFVariable &object) const
188     {
189         RDFProperty property(RDFProperty::fromObjectOf<Class>(object));
190         return subject.bindProperty(property);
191     }
192
193     const QUrl & domain() const { typename Class::Domain *p; return resourceIri(p); }
194     const QUrl & range() const { typename Class::Range *p; return resourceIri(p); }
195     const QUrl& iri() const { return Class::iri(); }
196 };
197
198 ////////////////////////////////////////////////////////////////////////////////////////////////////
199
200 typedef QHash<QString, RDFVariable>                     RDFVariableHash;
201 typedef RDFVariableHash::iterator                       RDFVariableHashIter;
202 typedef RDFVariableHash::const_iterator                 RDFVariableHashConstIter;
203
204 typedef QSharedPointer <ResourceInfo>                   ResourceInfoPtr;
205 typedef QList<ResourceInfoPtr>                          ResourceInfoList;
206 typedef ResourceInfoList::const_iterator                ResourceInfoListConstIter;
207
208 typedef QList<QUrl>                                     PredicateList;
209 typedef QMultiHash<PredicateList, class RDFVariable>    PredicateVariableHash;
210 typedef PredicateVariableHash::const_iterator           PredicateVariableHashConstIter;
211
212 ////////////////////////////////////////////////////////////////////////////////////////////////////
213
214 class QTrackerContactDetailField
215 {
216 public:
217     explicit QTrackerContactDetailField(const QString &name);
218     virtual ~QTrackerContactDetailField();
219
220     ////////////////////////////////////////////////////////////////////////////////////////////////
221
222     const QString& name() const { return mName; }
223
224     QTrackerContactDetailField& setDataType(QVariant::Type dataType);
225     QVariant::Type dataType() const { return mDataType; }
226
227     QTrackerContactDetailField& setDefaultValue(const QVariant &value);
228     const QVariant& defaultValue() const { return mDefaultValue; }
229     bool hasDefaultValue() const { return not defaultValue().isNull(); }
230
231     QTrackerContactDetailField& setSubjectDomain(QTrackerContactSubject::Domain domain);
232     QTrackerContactSubject::Domain subjectDomain() const { return mSubjectDomain; }
233     QUrl makeSubject(const QVariant &value) const;
234     bool hasSubjectDomain() const;
235
236     template<class Property> QTrackerContactDetailField& addProperty();
237     const ResourceInfoList& properties() const { return mProperties; }
238     bool hasProperties() const { return not properties().isEmpty(); }
239
240     template<class Resource> QTrackerContactDetailField& addSubType(const QString &name);
241     const ResourceInfoList& subTypes() const { return mSubTypes; }
242     bool hasSubTypes() const { return not subTypes().isEmpty(); }
243
244     template<class Resource> QTrackerContactDetailField& addInstance(const QVariant &name);
245     const ResourceInfoList& instances() const { return mInstances; }
246     bool hasInstances() const { return not instances().isEmpty(); }
247
248     QTrackerContactDetailField& setReadOnly(bool value = true);
249     QTrackerContactDetailField& setShared(bool value = true);
250     QTrackerContactDetailField& setOptional(bool value = true);
251
252     ////////////////////////////////////////////////////////////////////////////////////////////////
253
254     void bindProperties(const QTrackerContactDetail &detail, const RDFVariable &subject,
255                         const RDFVariableHash &variables, PredicateVariableHash &edges) const;
256     void bindColumns(const QTrackerContactDetail &detail, RDFSelect &query,
257                      RDFVariableHash &variables) const;
258
259     ////////////////////////////////////////////////////////////////////////////////////////////////
260
261     QContactDetailFieldDefinition describe() const;
262
263 protected:
264     template<class Resouce>
265     QTrackerContactDetailField& addSubType(const SopranoLive::Ontologies::rdfs::Class *const,
266                                            const QString &name);
267     template<class Resource>
268     QTrackerContactDetailField& addSubType(const SopranoLive::Ontologies::rdfs::Property *const,
269                                            const QString &name);
270
271 private:
272     QString                         mName;
273     QVariant::Type                  mDataType;
274     QVariant                        mDefaultValue;
275     ResourceInfoList                mProperties;
276     ResourceInfoList                mSubTypes;
277     ResourceInfoList                mInstances;
278     QTrackerContactSubject::Domain  mSubjectDomain;
279 };
280
281 ////////////////////////////////////////////////////////////////////////////////////////////////////
282
283 template<class Property>
284 QTrackerContactDetailField&
285 QTrackerContactDetailField::addProperty()
286 {
287     ResourceInfoPtr ptr(new PropertyInfo<Property>());
288     return mProperties.append(ptr), *this;
289 }
290
291 template<class Resource>
292 QTrackerContactDetailField&
293 QTrackerContactDetailField::addSubType(const QString &name)
294 {
295     static typename Resource::ResourceType *const typeHint = 0;
296     return addSubType<Resource>(typeHint, name);
297 }
298
299 template<class Resource>
300 QTrackerContactDetailField&
301 QTrackerContactDetailField::addSubType(const SopranoLive::Ontologies::rdfs::Class *const,
302                                        const QString &name)
303 {
304     ResourceInfoPtr ptr(new ClassInfo<Resource>(name));
305     return mSubTypes.append(ptr), *this;
306 }
307
308 template<class Resource>
309 QTrackerContactDetailField&
310 QTrackerContactDetailField::addSubType(const SopranoLive::Ontologies::rdfs::Property *const,
311                                        const QString &name)
312 {
313     ResourceInfoPtr ptr(new PropertyInfo<Resource>(name));
314     return mSubTypes.append(ptr), *this;
315 }
316
317 template<class Resource>
318 QTrackerContactDetailField&
319 QTrackerContactDetailField::addInstance(const QVariant &value)
320 {
321     ResourceInfoPtr ptr(new InstanceInfo<Resource>(value));
322     return mInstances.append(ptr), *this;
323 }
324
325 ////////////////////////////////////////////////////////////////////////////////////////////////////
326
327 QTM_END_NAMESPACE;
328
329 ////////////////////////////////////////////////////////////////////////////////////////////////////
330
331 template <class T>
332 inline uint qHash(const QList<T> &list)
333 {
334     return not list.isEmpty() ? qHash(list.first()) : 0;
335 }
336
337 ////////////////////////////////////////////////////////////////////////////////////////////////////
338
339 #endif // QTRACKERCONTACTDETAILFIELD_H