/usr/include/dataquay/objectmapper/ObjectStorer.h is in libdataquay-dev 0.9.1-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 | /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
/*
Dataquay
A C++/Qt library for simple RDF datastore management.
Copyright 2009-2012 Chris Cannam.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Chris Cannam
shall not be used in advertising or otherwise to promote the sale,
use or other dealings in this Software without prior written
authorization.
*/
#ifndef _DATAQUAY_OBJECT_STORER_H_
#define _DATAQUAY_OBJECT_STORER_H_
#include "../Node.h"
#include "ObjectMapperDefs.h"
#include <QHash>
class QObject;
namespace Dataquay
{
class Store;
class TypeMapping;
/**
* \class ObjectStorer ObjectStorer.h <dataquay/objectmapper/ObjectStorer.h>
*
* ObjectStorer is a storage handler capable of turning objects
* derived from QObject into RDF triples in a Store, such that under
* the right conditions the original objects can be recreated from the
* store by ObjectLoader.
*
* See also ObjectMapper, for a class which manages a set of objects
* and uses ObjectStorer and ObjectLoader to map changes
* bidirectionally between object hierarchy and datastore.
*
* ObjectStorer typically creates a new URI for each object it stores,
* based on the object's class name with a unique suffix. (In some
* cases -- where an object only exists as the value of a property of
* another object and is not referred to elsewhere in the hierarchy --
* it will by default be given a blank node instead of a URI.) The
* URI created for an object will be stored in that object as a user
* property named "uri" of type Dataquay::Uri. If that property
* already exists, ObjectStorer will use its value instead of creating
* a new URI; you can exploit this if you wish to override the
* generated URI. Note that ObjectStorer cannot handle objects having
* a uri property of any type other than Dataquay::Uri.
*
* For each object, ObjectStorer will write an rdf:type; an RDF
* property for each of the QObject properties of the object that have
* STORED set to true; and RDF properties identifying the parent and
* sibling objects if the object is part of a QObject hierarchy. The
* URIs used for the type and these properties can be controlled using
* a TypeMapping object.
*
* ObjectStorer uses Node::fromVariant to convert QObject property
* values to RDF literals: see Node::registerDatatype for the means to
* add new datatypes. Properties with subclass-of-QObject-pointer
* values can be written recursively (see setFollowPolicy); the
* default is to write them only if the "value" QObject already has a
* URI. ObjectStorer can write properties which have set and sequence
* container types (converting sets to multiple RDF properties with
* the same subject URI, and sequences to RDF lists) if those types
* have been registered with ContainerBuilder.
*
* Finally, you can register callbacks (using addStoreCallback) to be
* called after each object is stored, in case you wish to associate
* more information with an object.
*
* ObjectStorer is primarily intended to provide a simple, open and
* extensible storage format for small networks of
* application-specific objects. With TypeMapping there is some
* flexibility to assist with creating object structures from
* arbitrary RDF graphs, and the mechanism has been tested and
* optimised to some degree for some millions of triples, but that way
* could lie madness.
*
* ObjectStorer is re-entrant, but not thread-safe.
*/
class ObjectStorer
{
public:
/**
* ObjectNodeMap contains a record of the RDF node used for each
* object. This can be filled in a call to store() and passed to
* subsequent calls in order to hasten lookup, avoid unnecessary
* repeated stores, and ensure consistency for generated URIs.
*
* Note that, although ObjectStorer places the URI of each object
* in its uri property, certain objects may be written using blank
* nodes -- those nodes can only be retrieved through this map.
*
* The caller is responsible for ensuring that any objects
* subsequently deleted are also removed from this map.
*/
typedef QHash<QObject *, Node> ObjectNodeMap;
/**
* Create an ObjectStorer ready to store objects to the given
* datastore.
*/
ObjectStorer(Store *s);
~ObjectStorer();
/**
* Retrieve the store object that was passed to the constructor.
*/
Store *getStore();
/**
* Provide a TypeMapping object, which controls the URIs chosen by
* ObjectStorer to represent object types and properties.
* Generally if you are using ObjectStorer and ObjectLoader
* together, you will want to use the same TypeMapping object with
* both.
*/
void setTypeMapping(const TypeMapping &);
/**
* Retrieve the current TypeMapping object.
*/
const TypeMapping &getTypeMapping() const;
enum PropertyStorePolicy {
/**
* Store only properties that differ from default object
*/
StoreIfChanged,
/**
* Store all properties (if storable, readable & writable) (default)
*/
StoreAlways
};
/**
* Set the policy used to determine whether to store a property.
*
* If StoreIfChanged, properties will only be written if they
* differ in value from those retrieved from a newly-constructed
* instance of the object. If StoreAlways, all suitable
* properties will be written. The default is StoreAlways.
*
* StoreIfChanged only works for objects that have been registered
* with ObjectBuilder so that a default object can be constructed.
* Any other objects will have all suitable properties written.
*
* In either case, only properties whose QObject property
* definitions have all of READ, WRITE, and STORED set to true
* will be considered suitable and stored.
*/
void setPropertyStorePolicy(PropertyStorePolicy policy);
/**
* Retrieve the current policy used to determine whether to store
* a property.
*/
PropertyStorePolicy getPropertyStorePolicy() const;
/**
* Set the policy used to determine whether to give an object a
* URI or use a blank node for it.
*
* If BlankNodesAsNeeded (the default), objects will be given
* blank nodes if it appears to ObjectStorer that they do not need
* URIs. In practice this means that objects which are referred
* to because they are properties of other objects and which do
* not appear elsewhere in the list of objects being stored, do
* not have an existing uri property, and do not have a URI node
* allocated in an ObjectNodeMap passed to the store method, will
* be assigned blank nodes.
*
* If NoBlankObjectNodes, all objects written will be given URIs.
* These will be drawn from the object's uri property if it exists
* and is of Dataquay::Uri type, or else invented uniquely based
* on the object's class name.
*
* If NeverUseBlankNodes, the ObjectStorer will never generate a
* blank node -- all objects written will be given URIs, and list
* nodes will be given URIs generated from those of their
* contents. With this setting, an object graph written twice
* using the same object-node map will produce identical RDF
* graphs.
*!!! ^^^ write a unit test for this, and ensure that it is true
*
* If you are using BlankNodesAsNeeded but would prefer
* ObjectStorer not to use a blank node for a specific object, you
* can assign a URI in advance by setting a Dataquay::Uri to its
* "uri" property (either a declared property or a user property).
*
* Note that if a blank node is used for an object, there will be
* no way to retrieve that node through the object (no equivalent
* of the "uri" property). If you want to refer to the node
* subsequently you will need to ensure you provide an
* ObjectNodeMap to the store method to retrieve the node that was
* generated.
*/
void setBlankNodePolicy(BlankNodePolicy policy);
/**
* Retrieve the current policy used to determine whether to give
* an object a URI or use a blank node for it.
*/
BlankNodePolicy getBlankNodePolicy() const;
enum FollowOption {
FollowNone = 0, // the default
FollowObjectProperties = 1,
FollowParent = 2,
FollowSiblings = 4,
FollowChildren = 8
// there is no FollowAll; it generally isn't a good idea
//!!! revise this in light of two-step rework
};
typedef int FollowPolicy;
/**
* Set the policy used to determine which objects to store, based
* on their relationship to an object whose storage is being
* explicitly requested.
*
* If the policy is FollowNone, only the objects explicitly
* requested for storage by being passed as arguments to a store()
* method call will be stored.
*
* If the policy has FollowObjectProperties set, then where an
* object has a property that is suitable for storing (see
* setPropertyStorePolicy) and whose type is a pointer-to-object
* class for some subclass of QObject, the object referred to by
* that property will be stored. Otherwise, such properties will
* only be written where their objects have URIs available already
* (either because they exist in the object-node map or because
* they have a QObject property of name uri and Dataquay::Uri
* type).
*
* If the policy has FollowParent set, then where an object has a
* QObject parent, that parent will also be written.
*
* If the policy has FollowSiblings set, then where an object has
* QObject siblings (i.e. the object and those other objects share
* a parent), those siblings will also be written.
*
* If the policy has FollowChildren set, then where an object has
* QObject children, those children will also be written.
*/
void setFollowPolicy(FollowPolicy policy);
FollowPolicy getFollowPolicy() const;
/**
* Store the given object and return its URI in the datastore.
* Other objects may also be stored, depending on the FollowPolicy
* setting.
*
* The object will be stored even if it already exists in the
* store. No other data will be changed; for example, if other
* triples already exist with this object's URI as subject, they
* will be left alone. See setBlankNodePolicy for details of the
* assignment of nodes to objects.
*/
Uri store(QObject *o);
/**
* Store the given object; add the object and its node to the
* ObjectNodeMap, and return its URI in the datastore. Other
* objects may also be stored, depending on the FollowPolicy
* setting, and will be recorded in the ObjectNodeMap as well.
*
* The object will be stored even if it already exists in the
* store. No other data will be changed; for example, if other
* triples already exist with this object's URI as subject, they
* will be left alone. See setBlankNodePolicy for details of the
* assignment of nodes to objects.
*/
Uri store(QObject *o, ObjectNodeMap &map);
/**
* Store the given objects. Other objects may also be stored,
* depending on the FollowPolicy setting.
*/
void store(QObjectList o);
/**
* Store the given objects, and add them and their nodes to the
* ObjectNodeMap. Other objects may also be stored, depending on
* the FollowPolicy setting.
*/
void store(QObjectList o, ObjectNodeMap &map);
/**
* Remove an object from the store, given its node. This removes
* all triples with the node as subject. If any such triple
* references a blank node that is not referred to elsewhere in
* the store, all triples with that node as subject will be
* removed as well. If such a blank node is also the head of an
* RDF list, the rest of the RDF list will also be removed
* provided it fulfils the same criteria.
*/
void removeObject(Node node);
struct StoreCallback {
/**
* An object has been stored by the given ObjectStorer,
* resulting in the given RDF node. The object and node will
* also be found in the ObjectNodeMap, which additionally
* references any other objects that have been stored during
* this storage sequence.
*/
virtual void stored(ObjectStorer *, ObjectNodeMap &, QObject *, Node) = 0;
};
/**
* Register the given callback (a subclass of the abstract
* StoreCallback class) as providing a "stored" callback method
* which will be called after each object is stored.
*/
void addStoreCallback(StoreCallback *callback);
private:
ObjectStorer(const ObjectStorer &);
ObjectStorer &operator=(const ObjectStorer &);
class D;
D *m_d;
};
}
#endif
|