src/publishsubscribe/qvaluespacepublisher.cpp
changeset 0 876b1a06bc25
equal deleted inserted replaced
-1:000000000000 0:876b1a06bc25
       
     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 #include "qvaluespacepublisher.h"
       
    43 #include "qvaluespace.h"
       
    44 #include "qvaluespace_p.h"
       
    45 #include "qvaluespacemanager_p.h"
       
    46 
       
    47 #include <QtCore/qcoreapplication.h>
       
    48 
       
    49 #include <QtCore/qdebug.h>
       
    50 
       
    51 QTM_BEGIN_NAMESPACE
       
    52 
       
    53 /*!
       
    54     \class QValueSpacePublisher
       
    55 
       
    56     \brief The QValueSpacePublisher class allows applications to publish values in the Value Space.
       
    57 
       
    58     \ingroup publishsubscribe
       
    59 
       
    60     When multiple Value Space layers are available QValueSpacePublisher only publishes values to
       
    61     the layer with the highest order.  The layers that QValueSpacePublisher can access can be
       
    62     limited by specifying either a \l {QValueSpace::LayerOption}{filter} or a QUuid at construction
       
    63     time.
       
    64 
       
    65     The lifetime of values published in the Value Space is specified by the particular Value Space
       
    66     layer that the value is published in.  For details on the different behaviors see
       
    67     QValueSpace::LayerOption.
       
    68 
       
    69     Once a value is published all applications in the system will have read access to it via the
       
    70     QValueSpaceSubscriber class.
       
    71 
       
    72     Although, logically, the Value Space is a simple collection of
       
    73     hierarchical paths, these paths can conceptually be visualized as a set of
       
    74     objects with attributes.  For example, rather than viewing the following list
       
    75     as 12 distinct Value Space paths:
       
    76 
       
    77     \code
       
    78     /Device/Network/Interfaces/eth0/Name
       
    79     /Device/Network/Interfaces/eth0/Type
       
    80     /Device/Network/Interfaces/eth0/Status
       
    81     /Device/Network/Interfaces/eth0/BytesSent
       
    82     /Device/Network/Interfaces/eth0/BytesReceived
       
    83     /Device/Network/Interfaces/eth0/Time
       
    84     /Device/Network/Interfaces/ppp0/Name
       
    85     /Device/Network/Interfaces/ppp0/Type
       
    86     /Device/Network/Interfaces/ppp0/Status
       
    87     /Device/Network/Interfaces/ppp0/BytesSent
       
    88     /Device/Network/Interfaces/ppp0/BytesReceived
       
    89     /Device/Network/Interfaces/ppp0/Time
       
    90     \endcode
       
    91 
       
    92     it can be thought of as describing two Value Space objects,
       
    93     \c { { /Device/Network/Interfaces/eth0, /Device/Network/Interfaces/ppp0 } },
       
    94     each with the six attributes \c { {Name, Type, Status, BytesSent,
       
    95     BytesReceived, Time} }.  The QValueSpacePublisher class encapsulates this
       
    96     abstraction.
       
    97 
       
    98     For performance reasons the setting of and removing of attributes is buffered
       
    99     internally by the QValueSpacePublisher and applied as a batch sometime later.
       
   100     Normally this occurs the next time the application enters the Qt event loop,
       
   101     but this behavior should not be relied upon.  If an application must
       
   102     synchronize with others, the QValueSpacePublisher::sync() and QValueSpacePublisher::syncAll()
       
   103     functions can be used to force the application of changes.  This call is generally unnecessary,
       
   104     and should be used sparingly to prevent unnecessary load on the system.
       
   105 
       
   106     \sa QValueSpaceSubscriber
       
   107 */
       
   108 
       
   109 /*!
       
   110     \fn void QValueSpacePublisher::interestChanged(const QString &attribute,
       
   111                                                    bool interested)
       
   112 
       
   113     Signal that is emitted when interest in \a attribute changes.  If \a interested is true at
       
   114     least on QValueSpaceSubscriber is interested in the value of \a attribute.
       
   115 */
       
   116 
       
   117 class QValueSpacePublisherPrivate
       
   118 {
       
   119 public:
       
   120     QValueSpacePublisherPrivate(const QString &_path,
       
   121                                QValueSpace::LayerOptions filter = QValueSpace::UnspecifiedLayer);
       
   122     QValueSpacePublisherPrivate(const QString &_path, const QUuid &uuid);
       
   123 
       
   124     QString path;
       
   125 
       
   126     QAbstractValueSpaceLayer *layer;
       
   127     QAbstractValueSpaceLayer::Handle handle;
       
   128 
       
   129     bool hasSet;
       
   130     bool hasWatch;
       
   131 };
       
   132 
       
   133 QValueSpacePublisherPrivate::QValueSpacePublisherPrivate(const QString &_path,
       
   134                                                        QValueSpace::LayerOptions filter)
       
   135 :   layer(0), handle(QAbstractValueSpaceLayer::InvalidHandle), hasSet(false), hasWatch(false)
       
   136 {
       
   137     path = qCanonicalPath(_path);
       
   138 
       
   139     if ((filter & QValueSpace::PermanentLayer &&
       
   140          filter & QValueSpace::TransientLayer) ||
       
   141         (filter & QValueSpace::WritableLayer &&
       
   142          filter & QValueSpace::ReadOnlyLayer)) {
       
   143         return;
       
   144     }
       
   145 
       
   146     QList<QAbstractValueSpaceLayer *> layers = QValueSpaceManager::instance()->getLayers();
       
   147 
       
   148     for (int ii = 0; ii < layers.count(); ++ii) {
       
   149         if (filter == QValueSpace::UnspecifiedLayer ||
       
   150             layers.at(ii)->layerOptions() & filter) {
       
   151             QAbstractValueSpaceLayer::Handle h =
       
   152                     layers.at(ii)->item(QAbstractValueSpaceLayer::InvalidHandle, path);
       
   153 
       
   154             if (h != QAbstractValueSpaceLayer::InvalidHandle) {
       
   155                 layer = layers.at(ii);
       
   156                 handle = h;
       
   157                 break;
       
   158             }
       
   159         }
       
   160     }
       
   161 }
       
   162 
       
   163 QValueSpacePublisherPrivate::QValueSpacePublisherPrivate(const QString &_path, const QUuid &uuid)
       
   164 :   layer(0), handle(QAbstractValueSpaceLayer::InvalidHandle), hasSet(false), hasWatch(false)
       
   165 {
       
   166     path = qCanonicalPath(_path);
       
   167 
       
   168     QList<QAbstractValueSpaceLayer *> layers = QValueSpaceManager::instance()->getLayers();
       
   169 
       
   170     for (int ii = 0; ii < layers.count(); ++ii) {
       
   171         if (layers.at(ii)->id() == uuid) {
       
   172             layer = layers.at(ii);
       
   173             handle = layer->item(QAbstractValueSpaceLayer::InvalidHandle, path);
       
   174             break;
       
   175         }
       
   176     }
       
   177 }
       
   178 
       
   179 /*!
       
   180     Constructs a QValueSpacePublisher with the specified \a parent that publishes values under
       
   181     \a path.
       
   182 */
       
   183 QValueSpacePublisher::QValueSpacePublisher(const QString &path, QObject *parent)
       
   184 :   QObject(parent), d(new QValueSpacePublisherPrivate(path))
       
   185 {
       
   186     QValueSpaceManager::instance()->init();
       
   187 }
       
   188 
       
   189 /*!
       
   190     Constructs a QValueSpacePublisher with the specified \a parent that publishes values under
       
   191     \a path.  The \a filter parameter is used to limit which layer this QValueSpacePublisher will
       
   192     access.
       
   193 
       
   194     The constructed Value Space publisher will access the \l {QAbstractValueSpaceLayer}{layer} with
       
   195     the highest \l {QAbstractValueSpaceLayer::order()}{order} that matches \a filter and for which
       
   196     \a path is a valid path.
       
   197 
       
   198     If no suitable \l {QAbstractValueSpaceLayer}{layer} is found, the constructed
       
   199     QValueSpacePublisher will be unconnected.
       
   200 
       
   201     \sa isConnected()
       
   202 */
       
   203 QValueSpacePublisher::QValueSpacePublisher(QValueSpace::LayerOptions filter,
       
   204                                            const QString &path,
       
   205                                            QObject *parent)
       
   206 :   QObject(parent), d(new QValueSpacePublisherPrivate(path, filter))
       
   207 {
       
   208     QValueSpaceManager::instance()->init();
       
   209 }
       
   210 
       
   211 /*!
       
   212     Constructs a QValueSpacePublisher with the specified \a parent that publishes values under
       
   213     \a path.  Only the layer identified by \a uuid will be accessed by this publisher.
       
   214 
       
   215     Use of this constructor is not platform agnostic.  If possible use one of the constructors that
       
   216     take a QAbstractValueSpaceLayer::LayerOptions parameter instead.
       
   217 
       
   218     If a layer with a matching \a uuid is not found, the constructed QValueSpacePublisher will be
       
   219     unconnected.
       
   220 
       
   221     \sa isConnected()
       
   222 */
       
   223 
       
   224 QValueSpacePublisher::QValueSpacePublisher(const QUuid &uuid, const QString &path, QObject *parent)
       
   225 :   QObject(parent), d(new QValueSpacePublisherPrivate(path, uuid))
       
   226 {
       
   227     QValueSpaceManager::instance()->init();
       
   228 }
       
   229 
       
   230 /*!
       
   231     Destroys the QValueSpacePublisher.  This will remove all values published by this publisher in
       
   232     \l {QValueSpace::TransientLayer}{non-permanent} layers.
       
   233 */
       
   234 QValueSpacePublisher::~QValueSpacePublisher()
       
   235 {
       
   236     if (!d->layer)
       
   237         return;
       
   238 
       
   239     if (d->hasSet && !(d->layer->layerOptions() & QValueSpace::PermanentLayer))
       
   240         d->layer->removeSubTree(this, d->handle);
       
   241 
       
   242     if (d->hasWatch)
       
   243         d->layer->removeWatches(this, d->handle);
       
   244 
       
   245     delete d;
       
   246 }
       
   247 
       
   248 /*!
       
   249     Returns the path that this QValueSpacePublisher refers to.
       
   250 */
       
   251 QString QValueSpacePublisher::path() const
       
   252 {
       
   253     return d->path;
       
   254 }
       
   255 
       
   256 /*!
       
   257     Returns true if this QValueSpacePublisher is connected to an available layer; otherwise returns
       
   258     false.
       
   259 */
       
   260 bool QValueSpacePublisher::isConnected() const
       
   261 {
       
   262     return (d->layer && d->handle != QAbstractValueSpaceLayer::InvalidHandle);
       
   263 }
       
   264 
       
   265 /*!
       
   266     Forcibly sync all Value Space publisher using the same layer as this publisher.
       
   267 
       
   268     For performance reasons attribute changes are batched internally by QValueSpacePublisher
       
   269     instances.  In cases where the visibility of changes must be synchronized with other processes,
       
   270     calling this function will flush these batches.  By the time this function returns, all other
       
   271     processes in the system will be able to see the attribute changes.
       
   272 
       
   273     Generally, calling this function is unnecessary.
       
   274 */
       
   275 void QValueSpacePublisher::sync()
       
   276 {
       
   277     if (!d || !d->layer)
       
   278         return;
       
   279 
       
   280     d->layer->sync();
       
   281 }
       
   282 
       
   283 /*!
       
   284     Sets the value \a name on the publisher to \a data.  If name is empty, this call will set the
       
   285     value of this publisher's path.
       
   286 
       
   287     For example:
       
   288 
       
   289     \code
       
   290         QValueSpacePublisher publisher("/Device");
       
   291         publisher.setValue("State", "Starting");
       
   292         publisher.sync();
       
   293 
       
   294         // QValueSpaceSubscriber("/Device/State").value() == QVariant("Starting")
       
   295     \endcode
       
   296 */
       
   297 void QValueSpacePublisher::setValue(const QString &name, const QVariant &data)
       
   298 {
       
   299     if (!isConnected()) {
       
   300         qWarning("setAttribute called on unconnected QValueSpacePublisher.");
       
   301         return;
       
   302     }
       
   303 
       
   304     d->hasSet = true;
       
   305     d->layer->setValue(this, d->handle, qCanonicalPath(name), data);
       
   306 }
       
   307 
       
   308 /*!
       
   309     Removes the value \a name and all sub-attributes from the system.
       
   310 
       
   311     For example:
       
   312     \code
       
   313         QValueSpacePublisher publisher("/Device");
       
   314         publisher.setValue("State", "Starting");
       
   315         publisher.setValue("State/Memory", "1000");
       
   316         publisher.sync();
       
   317         // QValueSpaceSubscriber("/Device/State").value() == QVariant("Starting")
       
   318         // QValueSpaceSubscriber("/Device/State/Memory").value() == QVariant("1000")
       
   319 
       
   320         publisher.resetValue("State");
       
   321         publisher.sync();
       
   322         // QValueSpaceSubscriber("/Device/State").value() == QVariant();
       
   323         // QValueSpaceSubscriber("/Device/State/Memory").value() == QVariant();
       
   324     \endcode
       
   325 */
       
   326 void QValueSpacePublisher::resetValue(const QString &name)
       
   327 {
       
   328     if (!isConnected()) {
       
   329         qWarning("removeAttribute called on unconnected QValueSpacePublisher.");
       
   330         return;
       
   331     }
       
   332 
       
   333     d->layer->removeValue(this, d->handle, qCanonicalPath(name));
       
   334 }
       
   335 
       
   336 /*!
       
   337     \reimp
       
   338 
       
   339     Registers this QValueSpacePublisher for notifications when QValueSpaceSubscribers are
       
   340     interested in values under path().
       
   341 
       
   342     Generally you do not need to call this function as it is automatically called when
       
   343     connections are made to this classes signals.  \a member is the signal that has been connected.
       
   344 
       
   345     If you reimplement this virtual function it is important that you call this implementation from
       
   346     your implementation.
       
   347 
       
   348     \sa interestChanged()
       
   349 */
       
   350 void QValueSpacePublisher::connectNotify(const char *member)
       
   351 {
       
   352     if (!d->hasWatch && d->layer && (*member - '0') == QSIGNAL_CODE) {
       
   353         d->layer->addWatch(this, d->handle);
       
   354         d->hasWatch = true;
       
   355     }
       
   356 
       
   357     QObject::connectNotify(member);
       
   358 }
       
   359 
       
   360 #include "moc_qvaluespacepublisher.cpp"
       
   361 QTM_END_NAMESPACE