~ubuntu-branches/ubuntu/gutsy/soprano/gutsy

« back to all changes in this revision

Viewing changes to soprano/iterator.h

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2007-10-12 14:43:48 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20071012144348-yajzi51v4k23ahxf
Tags: 1.95.0~beta2-1ubuntu1
* Sync with Debian
* Add versioned build-dep on raptor

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This file is part of Soprano Project.
 
3
 *
 
4
 * Copyright (C) 2006 Daniele Galdi <daniele.galdi@gmail.com>
 
5
 * Copyright (C) 2007 Sebastian Trueg <trueg@kde.org>
 
6
 *
 
7
 * This library is free software; you can redistribute it and/or
 
8
 * modify it under the terms of the GNU Library General Public
 
9
 * License as published by the Free Software Foundation; either
 
10
 * version 2 of the License, or (at your option) any later version.
 
11
 *
 
12
 * This library is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
 * Library General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU Library General Public License
 
18
 * along with this library; see the file COPYING.LIB.  If not, write to
 
19
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 
20
 * Boston, MA 02110-1301, USA.
 
21
 */
 
22
 
 
23
#ifndef SOPRANO_ITERATOR_H
 
24
#define SOPRANO_ITERATOR_H
 
25
 
 
26
#include <QtCore/QSharedDataPointer>
 
27
#include <QtCore/QList>
 
28
 
 
29
#include "iteratorbackend.h"
 
30
#include "error.h"
 
31
 
 
32
namespace Soprano {
 
33
 
 
34
    /**
 
35
     * \class Iterator iterator.h Soprano/Iterator
 
36
     *
 
37
     * \brief The basic %Soprano iterator class.
 
38
     *
 
39
     * Iterators in %Soprano are very easy to use through two methods
 
40
     * next() and current(). Instead of the latter operator*() can also be used.
 
41
     * Both can be called subsequetially to retrieve the current element
 
42
     * until next() has been called again.
 
43
     *
 
44
     * \code
 
45
     * Soprano::Iterator<X> it;
 
46
     * while( it.next() ) {
 
47
     *    doSomething( *it );
 
48
     *    doSomethingElse( it.current() );
 
49
     * }
 
50
     * \endcode
 
51
     *
 
52
     * Many backends do lock the underlying Model during iteration. Thus, 
 
53
     * it is always a good idea to cache the results if they are to be used
 
54
     * to modify the model:
 
55
     *
 
56
     * \code
 
57
     * Soprano::StatementIterator it = model->listStatements();
 
58
     * QList<Statement> allStatements = it.allElements();
 
59
     * Q_FOREACH( Soprano::Statement s, allStatements ) {
 
60
     *    modifyTheModel( model, s );
 
61
     * }
 
62
     * \endcode
 
63
     *
 
64
     * Also, Iterators have to be closed.
 
65
     * This can either be achieved by deleting the iterator, finishing it (next() does return \p false),
 
66
     * or calling close(). Before that other operations on the Model may block.
 
67
     *
 
68
     * Iterators are not thread-safe. Two threads using the same iterator at the same time may result
 
69
     * in undefined behaviour and even crashes.
 
70
     *
 
71
     * \warning Be aware that iterators in Soprano are shared objects which means
 
72
     * that copies of one iterator object work on the same data.
 
73
     * 
 
74
     * \author Daniele Galdi <daniele.galdi@gmail.com><br>Sebastian Trueg <trueg@kde.org>
 
75
     */
 
76
    template<typename T> class Iterator : public Error::ErrorCache
 
77
    {
 
78
    public:
 
79
        /**
 
80
         * Creates and empty, invalid iterator.
 
81
         */
 
82
        Iterator();
 
83
 
 
84
        /**
 
85
         * Create a new Iterator instance that uses sti as backend.
 
86
         * Iterator will take ownership of the backend.
 
87
         */
 
88
        Iterator( IteratorBackend<T> *sti );
 
89
 
 
90
        Iterator( const Iterator &sti );
 
91
 
 
92
        virtual ~Iterator();
 
93
 
 
94
        Iterator& operator=( const Iterator& );
 
95
 
 
96
        /**
 
97
         * Close the iterator and release any locks on the underlying Model.
 
98
         */
 
99
        void close();
 
100
 
 
101
        /**
 
102
         * Advances to the next element in the iterator.
 
103
         *\return true if another element can be read from the iterator,
 
104
         * false if the end has been reached.
 
105
         */
 
106
        bool next();
 
107
 
 
108
        /**
 
109
         * Get the element the iterator currently points to. Be aware that
 
110
         * a valid current element is only available if next() returned \p true.
 
111
         *
 
112
         *\return the current element.
 
113
         */
 
114
        T current() const;
 
115
 
 
116
        /**
 
117
         * Retrieve the current element in the iterator.
 
118
         *
 
119
         * This is equivalent to current().
 
120
         *
 
121
         * \return The element the iterator currently points to or
 
122
         * an invalid one if next has never been called.
 
123
         */
 
124
        T operator*() const;
 
125
 
 
126
        /**
 
127
         * \return \p true if the Iterator is valid, \p false otherwise. (An invalid iterator
 
128
         * has no backend.)
 
129
         */
 
130
        bool isValid() const;
 
131
 
 
132
        /**
 
133
         * Convenience method which extracts all elements (this does not include the
 
134
         * elements that have already been read from the iterator) from the iterator
 
135
         * and returns them in a list.
 
136
         *
 
137
         * Be aware that after calling this method the iterator will be invalid.
 
138
         *
 
139
         * \return A list of all elements that rest in the iterator.
 
140
         */
 
141
        QList<T> allElements();
 
142
 
 
143
    protected:
 
144
        /**
 
145
         * Set the backend to read the actual data from.
 
146
         * A previous backend will be deleted if there are no other Iterator
 
147
         * instances using it.
 
148
         */
 
149
        void setBackend( IteratorBackend<T>* b );
 
150
 
 
151
        IteratorBackend<T>* backend() const;
 
152
 
 
153
    private:
 
154
        class Private;
 
155
        QSharedDataPointer<Private> d;
 
156
    };
 
157
}
 
158
 
 
159
 
 
160
/** \cond iterator_implementation */
 
161
template<typename T> class Soprano::Iterator<T>::Private : public QSharedData
 
162
{
 
163
public:
 
164
    Private()
 
165
        : backend( 0 ) {
 
166
    }
 
167
        
 
168
    ~Private() {
 
169
        if( backend ) {
 
170
            backend->close();
 
171
            delete backend;
 
172
        }
 
173
    }
 
174
    
 
175
    IteratorBackend<T>* backend;
 
176
};
 
177
 
 
178
 
 
179
template<typename T> Soprano::Iterator<T>::Iterator()
 
180
    : Error::ErrorCache(),
 
181
      d( new Private() )
 
182
    
 
183
{
 
184
}
 
185
 
 
186
template<typename T> Soprano::Iterator<T>::Iterator( IteratorBackend<T> *sti )
 
187
    : Error::ErrorCache(),
 
188
      d( new Private() )
 
189
{
 
190
    d->backend = sti;
 
191
}
 
192
 
 
193
template<typename T> Soprano::Iterator<T>::Iterator( const Iterator<T> &other )
 
194
    : Error::ErrorCache(),
 
195
      d( other.d )
 
196
{
 
197
}
 
198
 
 
199
template<typename T> Soprano::Iterator<T>::~Iterator()
 
200
{
 
201
}
 
202
 
 
203
template<typename T> Soprano::Iterator<T>& Soprano::Iterator<T>::operator=( const Iterator<T>& other )
 
204
{
 
205
    d = other.d;
 
206
    return *this;
 
207
}
 
208
 
 
209
template<typename T> void Soprano::Iterator<T>::setBackend( IteratorBackend<T>* b )
 
210
{
 
211
    if ( d->backend != b ) {
 
212
        // now we want it to detach
 
213
        d->backend = b;
 
214
    }
 
215
}
 
216
 
 
217
template<typename T> Soprano::IteratorBackend<T>* Soprano::Iterator<T>::backend() const
 
218
{
 
219
    return d->backend;
 
220
}
 
221
 
 
222
template<typename T> void Soprano::Iterator<T>::close()
 
223
{
 
224
    // some evil hacking to avoid detachment of the shared data
 
225
    if( isValid() ) {
 
226
        const Private* cd = d.constData();
 
227
        cd->backend->close();
 
228
        setError( cd->backend->lastError() );
 
229
    }
 
230
    else {
 
231
        setError( QString::fromLatin1( "Invalid iterator." ) );
 
232
    }
 
233
}
 
234
 
 
235
template<typename T> bool Soprano::Iterator<T>::next()
 
236
{
 
237
    // some evil hacking to avoid detachment of the shared data
 
238
    const Private* cd = d.constData();
 
239
    if( isValid() ) {
 
240
        bool hasNext = cd->backend->next();
 
241
        setError( cd->backend->lastError() );
 
242
        if( !hasNext ) {
 
243
            cd->backend->close();
 
244
        }
 
245
        return hasNext;
 
246
    }
 
247
    else {
 
248
        setError( QString::fromLatin1( "Invalid iterator." ) );
 
249
        return false;
 
250
    }
 
251
}
 
252
 
 
253
template<typename T> T Soprano::Iterator<T>::current() const
 
254
{
 
255
    if( isValid() ){
 
256
        T c = d->backend->current();
 
257
        setError( d->backend->lastError() );
 
258
        return c;
 
259
    }
 
260
    else {
 
261
        setError( QString::fromLatin1( "Invalid iterator." ) );
 
262
        return T();
 
263
    }
 
264
}
 
265
 
 
266
template<typename T> T Soprano::Iterator<T>::operator*() const
 
267
{
 
268
    return current();
 
269
}
 
270
 
 
271
template<typename T> bool Soprano::Iterator<T>::isValid() const
 
272
{
 
273
    return d->backend != 0;
 
274
}
 
275
 
 
276
 
 
277
template<typename T> QList<T> Soprano::Iterator<T>::allElements()
 
278
{
 
279
    QList<T> sl;
 
280
    while ( next() ) {
 
281
        sl.append( current() );
 
282
    }
 
283
    close();
 
284
    return sl;
 
285
}
 
286
/** \endcond */
 
287
 
 
288
#endif
 
289