C++: Compile fixes on OSX
[smartapi.git] / Common / C++ / SmartAPI / smartapi / model / Obj.cpp
1 #include "Obj.h"
2 #include <QtDebug>
3 #include <unistd.h>
4
5 #include "smartapi/agents/TransactionAgent.h"
6 #include "smartapi/common/HttpMessage.h"
7 #include "smartapi/common/NS.h"
8 #include "smartapi/common/URLs.h"
9 #include "smartapi/common/OntologyCache.h"
10 #include "smartapi/common/PROPERTY.h"
11 #include "smartapi/common/SmartAPICrypto.h"
12 #include "smartapi/common/ObjectPrinter.h"
13 #include "smartapi/common/SERIALIZATION.h"
14 #include "smartapi/common/Tools.h"
15 #include "smartapi/exceptions/VerifyException.h"
16 #include "smartapi/model/AbstractEntity.h"
17 #include "smartapi/model/Activity.h"
18 #include "smartapi/model/Device.h"
19 #include "smartapi/model/Entity.h"
20 #include "smartapi/model/Evaluation.h"
21 #include "smartapi/model/Input.h"
22 #include "smartapi/model/Map.h"
23 #include "smartapi/model/Offering.h"
24 #include "smartapi/model/Output.h"
25 #include "smartapi/model/Error.h"
26 #include "smartapi/model/Status.h"
27 #include "smartapi/model/Parameter.h"
28 #include "smartapi/model/PhysicalEntity.h"
29 #include "smartapi/model/Provenance.h"
30 #include "smartapi/model/Restriction.h"
31 #include "smartapi/model/Service.h"
32 #include "smartapi/model/ServiceProvider.h"
33 #include "smartapi/model/TimeSeries.h"
34 #include "smartapi/model/Transaction.h"
35         
36         
37 Obj::Obj(QString identifierUri)
38         : GraphItem(),
39         mIdentifierUri(),
40         mName(),
41         mDescription(),
42         mGeneratedAt(),
43         mTransaction(NULL),
44         mSameAs(NULL),
45         mStatus(NULL),
46         mGeneratedBy(),
47         mTypes(QList<QString>()),
48         mSign(false),
49         mSignKey(NULL),
50         mEncrypt(false),
51         mEncryptPKey(NULL),
52         mEncryptSecretKey(),
53         mIsDecrypted(false),
54         mHashCode(),
55         mSignature(),
56         mSessionKey(),
57         mEncryptionKeyType(),
58         mSerializeAsReference(false),
59         mReferenceUriPrefix(REFERENCE_URI_PREFIX)
60 {
61         // Unlike all subclass constructors, Obj constructor doesn't call setType(RESOURCE__OBJ).
62         // The reason for this is that the type is represented as Obj too, so calling setType()
63         // in Obj constructor would lead to a loop. It would be redundant information anyway.
64
65         if (identifierUri.length() > 0) {
66                 mIdentifierUri = QUrl(identifierUri);
67         } else mIdentifierUri = QUrl();
68         mProvenances.setParent(this);
69         mRestrictions.setParent(this);
70         INIT_PROPERTYLIST(mErrors,PROPERTY__ERROR)
71         INIT_PROPERTYLIST(mOfferings,PROPERTY__OFFERS)
72 }
73
74 Obj::Obj(QUrl identifierUri)
75         : Obj()
76 {
77         mIdentifierUri = identifierUri;
78 }
79
80 Obj::Obj(Obj* o)
81         : Obj()
82 {
83         mIdentifierUri = QUrl();
84         if (o != NULL) {
85                 mName = o->getName();
86                 mDescription = o->getDescription();
87                 mGeneratedBy = o->getGeneratedBy();
88                 mGeneratedAt = o->getGeneratedAt();
89                 mSignKey = o->getSignKey();
90                 mEncryptPKey = o->getEncryptKey();
91                 mEncryptSecretKey = o->getSecretKey();
92                 mHashCode = o->getHashCode();
93                 mSignature = o->getSignature();
94                 mSessionKey = o->getSessionKey();
95                 mStringRepresentation = o->getStringRepresentation();
96                 mReferenceUriPrefix = o->getReferenceUriPrefix();
97                 mEncryptionKeyType = o->getEncryptionKeyType();
98                 if (o->hasNotary())                                                     setNotary(o->getNotary());
99
100                 mSign = o->isToBeSigned();
101                 mEncrypt = o->isToBeEncrypted();
102                 mIsDecrypted = o->isDecrypted();
103                 mSerializeAsReference = o->isToBeSerializedAsReference();
104
105                 if (o->hasIdentifierUri())                                      mIdentifierUri = o->getIdentifierUri();
106                 if (o->hasTransaction())                                        mTransaction = new Transaction(o->getTransaction());
107                 if (o->hasSameAs())                                                     mSameAs = new Obj(o->getSameAs());
108                 if (o->hasStatus())                                                     mStatus = new Status(o->getStatus());
109
110                 QListIterator<QString> t(o->getTypes());
111                 while (t.hasNext()) mTypes.append(t.next());
112
113                 mErrors                 = o->getErrors();
114                 mProvenances    = o->getProvenances();
115                 mRestrictions   = o->getRestrictions();
116                 mOfferings              = o->getOfferings();
117
118                 // Copy all items in the property list. Note that because of this operation,
119                 // any child of Obj does not need to copy any properties or property lists
120                 // in its own copy constructor
121                 // Children only copy references from this map into their local variables
122                 QMap<QString, PropertyList<GraphItem*>* > mp = o->getAllProperties();
123                 QList<QString> keys = mp.keys();
124                 for (int j = 0; j < keys.length(); j++) {
125                         PropertyList<GraphItem*>* vars = mp.value(keys.at(j));
126                         for (PropertyListItem<GraphItem*>* i = vars->firstItem(); i != NULL; i = i->next()) {
127 //                              add(keys.at(j), (Variant*)i->getItem());
128                                 GraphItem* val = (Variant*)i->getItem();
129                                 if (val != NULL) {
130                                         add(keys.at(j), Tools::copy(val));
131                                 }
132                         }
133                         // copy list type
134                         PropertyList<GraphItem*>* localVars = getAll(keys.at(j));
135                         if (localVars != NULL && localVars->length() > 0) {
136                                 localVars->setListType(vars->getListType());
137                         }
138                 }
139         }
140         mProvenances.setParent(this);
141         mRestrictions.setParent(this);
142         mOfferings.setParent(this);
143         mErrors.setParent(this);
144 }
145
146 Obj::~Obj()
147 {
148         // Note that because encryption keys are set as pointers, the
149         // destructor should not touch them
150 }
151
152 void Obj::clearReferences(QSet<GraphItem*>* trash)
153 {
154         if (mSameAs != NULL)                            mSameAs->destroyCascade(trash);
155         if (mStatus != NULL)                            mStatus->destroyCascade(trash);
156         if (mTransaction != NULL)                       mTransaction->destroyCascade(trash);
157
158         while (mProvenances.length() > 0)       mProvenances.destroyFirstCascade(trash);
159         while (mRestrictions.length() > 0)      mRestrictions.destroyFirstCascade(trash);
160         while (mErrors.length() > 0)            mErrors.destroyFirstCascade(trash);
161         while (!mVariantMap.isEmpty()) {
162                 QString k = mVariantMap.firstKey();
163                 PropertyList<GraphItem*>* vars = mVariantMap.take(k);
164                 while (vars->length() > 0 && vars->destroyFirstCascade(trash));
165
166                 // If a property list is in stack (not heap), it should not be deleted as items
167                 // in stack are deleted automatically
168                 if (!vars->isInStack()) delete vars;
169         }
170 }
171
172 /*
173 bool Obj::hasSpecialSerialization(Model *model)
174 {
175         // if the object has already been serialized, do not serialize again
176         if (hasIdentifierUri() && model->isCached(getIdentifierUri())) {
177                 //mSpecialSerialization = model->createResource(getIdentifierUri());
178                 return true;
179         }
180
181         // if the object is a reference, then serialize it as one
182         // and add object as a separate part to the HttpMessage
183         if (isToBeSerializedAsReference()) {
184                 mSpecialSerialization = serializeToReference(model);
185                 return true;
186         }
187
188         return false;
189 }
190 */
191
192 void Obj::addType(QString type)
193 {
194         QString typeStr = Tools::toAbsoluteUri(type);
195         if (!mTypes.contains(typeStr))
196                 mTypes.append(typeStr);
197 }
198
199 void Obj::setTypes(QList<QString> types)
200 {
201         clearTypes();
202         while (types.length() > 0) {
203                 QString typeStr = Tools::toAbsoluteUri(types.takeFirst());
204                 mTypes.append(typeStr);
205         }
206 }
207
208 bool Obj::hasType(QString type)
209 {
210         QString typeStr = Tools::toAbsoluteUri(type);
211         return mTypes.contains(typeStr);
212 }
213
214 bool Obj::removeType(QString type)
215 {
216         QString typeStr = Tools::toAbsoluteUri(type);
217         return mTypes.removeAll(typeStr);
218 }
219
220 bool Obj::hasSpecialSerialization(Model *model)
221 {
222         // is already serialized
223         if (model->isInSerializedObjsCache(this)) {
224                 //mSpecialSerialization = model->createResource(getIdentifierUri());
225                 return true;
226         }
227         // needs to be serialized as reference
228         if (isToBeSerializedAsReference()) {
229                 return true;
230         }
231         return false;
232 }
233
234 Resource* Obj::getSpecialSerialization(Model *model)
235 {
236         // if the object has already been serialized, use that serialized resource
237         if (model->isInSerializedObjsCache(this)) {
238                 return model->getFromSerializedObjsCache(this);
239         }
240
241         // if the object is a reference, then serialize it as one
242         // and add object as a separate part to the HttpMessage
243         if (isToBeSerializedAsReference()) {
244                 return serializeToReference(model);
245         }
246
247         return NULL;
248 }
249
250 QString Obj::generateChecksum()
251 {
252         QString csum = Tools::generateChecksum(this);
253         return csum;
254 }
255
256 QString Obj::generateTemporaryIdentifier()
257 {
258         return "http://smart-api.io/temporary/" + SmartAPICrypto::generate16ByteCryptoRandomString();
259 }
260
261 bool Obj::getCheckResult()
262 {
263         GraphItem* r = get(PROPERTY__CHECKRESULT);
264         if (r != NULL && r->isVariant())
265                 return ((Variant*)r)->asBoolean();
266         return false;
267 }
268
269 QVariantMap Obj::toNude()
270 {
271         return QVariantMap();
272 }
273
274 void Obj::fromNude(QVariantMap n)
275 {
276         Q_UNUSED(n);
277 }
278
279 void Obj::setIdentifierUri(QString uri)
280
281         mIdentifierUri = QUrl(uri);
282 }
283
284 void Obj::setIdentifierUri(QUrl uri)
285
286         mIdentifierUri = uri; 
287 }
288
289 void Obj::setSameAs(QString uri)
290
291         Obj* e = new Obj(uri);
292         setSameAs(e);
293 }
294
295 bool Obj::fetchKeyFromNotary(QString identity, QString notaryServer, EVP_PKEY* privKey)
296 {
297         QByteArray key = Tools::fetchKeyFromNotary(identity, getIdentifierUri(), getHashCode(), getSignature(), notaryServer, privKey);
298
299         if (key.size() > 0) {
300                 mEncryptSecretKey = key;
301                 return true;
302         } else {
303                 return false;
304         }
305 }
306
307 bool Obj::sign(EVP_PKEY* key)
308 {
309         mSign = true;
310         mSignKey = key;
311         mSerializeAsReference = true;
312         return true;
313 }
314
315 bool Obj::verifySignature(EVP_PKEY* key)
316 {
317         bool verified = false;
318         if (!hasHashCode()) {
319                 throw new VerifyException("No hashcode found.");
320         } else if (!hasSignature()) {
321                 throw new VerifyException("No signature found.");
322         } else if (!hasStringRepresentation()) {
323                 throw new VerifyException("No string representation found.");
324         } else if (!verifyHash()) {
325                 throw new VerifyException("Hash code mismatch.");
326         } else {
327                 verified = SmartAPICrypto::verifySignature(getSignature(), key, getStringRepresentation());
328                 // Note that the object from string representation will always be used, even when signature fails
329                 // This way the recipient may choose to process it despite the mismatch.
330                 replaceThisObjectWith(getStringRepresentation());
331         }
332         return verified;
333 }
334
335 bool Obj::verifyHash()
336 {
337         if (!hasHashCode()) {
338                 throw new VerifyException("No hashcode found.");
339         } else if (!hasStringRepresentation()) {
340                 throw new VerifyException("No string representation found.");
341         } else {
342                 return SmartAPICrypto::verifyEncodedMessageDigest(getHashCode(), getStringRepresentation());
343         }
344 }
345
346 bool Obj::encrypt(QByteArray secretKey)
347 {
348         mEncrypt = true;
349         mSerializeAsReference = true;
350         mEncryptSecretKey = secretKey;
351         delete mEncryptPKey;
352         mEncryptPKey = NULL;
353         setEncryptionKeyType(RESOURCE__SESSIONKEY);
354         return true;
355 }
356
357 QByteArray Obj::encrypt(EVP_PKEY *publicKey)
358 {
359         QByteArray secretKey = SmartAPICrypto::generateSymmetricKey();
360         encrypt(publicKey, secretKey);
361         return secretKey;
362 }
363
364 bool Obj::encrypt(EVP_PKEY* publicKey, QByteArray secretKey)
365 {
366         mEncrypt = true;
367         mSerializeAsReference = true;
368         delete mEncryptPKey;
369         mEncryptPKey = publicKey;
370         mEncryptSecretKey = secretKey;
371         setEncryptionKeyType(RESOURCE__PUBLICKEY);
372         //addType(RESOURCE__REFERENCE);
373         addType(RESOURCE__ENCRYPTEDREFERENCE);
374         return true;
375 }
376
377 bool Obj::decrypt(QByteArray secretKey)
378 {
379         if (mStringRepresentation.length() > 0) {
380                 unsigned char* key;
381                 key = (unsigned char*)malloc(AES_KEYLEN/8);
382                 memcpy(key, secretKey.data(), 16);
383                 QString decrypted = SmartAPICrypto::symmetricDecrypt(key, mStringRepresentation);
384                 free(key);
385                 if (replaceThisObjectWith(decrypted)) {
386                         removeType(RESOURCE__ENCRYPTEDREFERENCE);
387                         mIsDecrypted = true;
388                         return true;
389                 } else {
390                         return false;
391                 }
392                 return true;
393         }
394         return false;
395 }
396
397 bool Obj::decrypt(EVP_PKEY* privateKey)
398 {
399         if (hasEncryptionKeyType() && getEncryptionKeyType() == RESOURCE__PUBLICKEY) {
400                 QString decrypted = SmartAPICrypto::asymmetricDecrypt(privateKey, getStringRepresentation(), NULL);
401                 if (replaceThisObjectWith(decrypted)) {
402                         //removeType(RESOURCE__ENCRYPTEDREFERENCE);
403                         mIsDecrypted = true;
404                         return true;
405                 } else {
406                         qDebug() << "WARNING: object decryption failed.";
407                         return false;
408                 }
409         }
410         else if (hasEncryptionKeyType() && getEncryptionKeyType() == RESOURCE__NOTARIZEDSESSIONKEY) {
411                 QByteArray sessionKey = SmartAPICrypto::decryptAndDecodeKey(privateKey, getSessionKey());
412                 return decrypt(sessionKey);
413         }
414         return false;
415 }
416
417 void Obj::encryptAndNotarize(QString notaryAddress, EVP_PKEY* publicKey, EVP_PKEY* privateKey)
418 {
419         mEncrypt = true;
420         delete mEncryptPKey;
421         mEncryptPKey = publicKey;
422         mEncryptSecretKey.clear();
423         addType(RESOURCE__REFERENCE);
424         addType(RESOURCE__ENCRYPTEDREFERENCE);
425         setNotary(notaryAddress);
426         setEncryptionKeyType(RESOURCE__NOTARIZEDSESSIONKEY);
427         if (privateKey) {
428                 mSign = true;
429                 mSignKey = privateKey;
430         }
431         mSerializeAsReference = true;
432 }
433
434 bool Obj::confirmContentValidityAndFetchKey(QString identity, QString notaryAddress, EVP_PKEY* privateKey)
435 {
436         if (verifyHash()) {
437                 return fetchKeyFromNotary(identity, notaryAddress, privateKey);
438         } else {
439                 return false;
440         }
441 }
442
443 // used to replace a Reference with the actual object
444 bool Obj::replaceThisObjectWith(QString str)
445 {
446         // here we could remove some Reference related properties
447
448         // Don't parse a zero length string. The model does not like that.
449         if (str.length() == 0)
450                 return false;
451
452         // parse str to model
453         Model* model = Tools::fromString(str);
454         if (!model) {
455                 return false;
456         }
457
458         // find root resource in model
459         QMap<QString, Resource*> types = Tools::getTopNodes(model);
460         QStringList keys = types.keys();
461         bool ok = true;
462         for (int i = 0; i < keys.length(); i++) {
463                 QString nodeType = keys.at(i);
464                 Resource* res = types.value(nodeType);
465                 if (res) {
466                         QList<Statement*> sl = res->findProperties();
467                         while (sl.length() > 0) {
468                                 parse(sl.at(0));
469                                 delete sl.takeFirst();
470                         }
471                         delete res;
472                 } else {
473                         ok = false;
474                 }
475         }
476         delete model;
477         return ok;
478 }
479
480 Resource* Obj::serialize(Model* model)
481 {
482         // check if this obj is serialized in a special way
483         if ( hasSpecialSerialization(model) ) {
484                 return getSpecialSerialization(model);
485         }
486
487         Resource* resource;
488
489         if (model->isInSerializedObjsCache(this)) {
490                 resource = model->getFromSerializedObjsCache(this);
491         } else {
492                 // create resource
493                 if (hasIdentifierUri()) {
494                         resource = model->createResource(getIdentifierUrl()); // note that it says "url" not "uri" here
495                 } else {
496                         resource = model->createResource();
497                 }
498
499                 // add this object to map of serialized objects
500                 model->addToSerializedObjsCache(this, resource);
501         }
502
503         // transaction
504         if (hasTransaction()) {
505                 resource->addProperty(model->createProperty(PROPERTY__TRANSACTION), getTransaction()->serialize(model));
506         }
507
508         // sameas
509         if (hasSameAs()) {
510                 resource->addProperty(model->createProperty(PROPERTY__SAMEAS), getSameAs()->serialize(model));
511         }
512
513         // types
514         QListIterator<QString> ti(getTypes());
515         while (ti.hasNext()) {
516                 // This needs to be a URI
517                 resource->addProperty(model->createProperty(PROPERTY__RDF_TYPE), QUrl(ti.next()));
518         }
519
520         // generatedby
521         if (hasGeneratedBy()) {
522                 resource->addProperty(model->createProperty(PROPERTY__GENERATEDBY), getGeneratedBy());
523         }
524
525         // generatedat
526         if (hasGeneratedAt()) {
527                 resource->addProperty(model->createProperty(PROPERTY__GENERATEDAT),
528                                 model->createTypedLiteral(Tools::dateToString(getGeneratedAt()), Tools::getXsdString() + "dateTime"));
529         }
530
531         // name
532         if (hasName()) {
533                 resource->addProperty(model->createProperty(PROPERTY__RDFS_LABEL), getName());
534         }
535
536         // comment
537         if (hasDescription()) {
538                 resource->addProperty(model->createProperty(PROPERTY__COMMENT), getDescription());
539         }
540
541         SERIALIZE_PROPERTYLIST(Provenance,mProvenances,PROPERTY__PROVENANCE)    // provenances
542         SERIALIZE_PROPERTYLIST(Restriction,mRestrictions,PROPERTY__RESTRICTION) // restrictions
543         SERIALIZE_PROPERTYLIST(Offering,mOfferings,PROPERTY__OFFERS)                    // offerings
544         SERIALIZE_PROPERTYLIST(Error,mErrors,PROPERTY__ERROR)                                   // errors
545
546         // add additional variant properties
547         QMapIterator<QString, PropertyList<GraphItem*>* > mi(mVariantMap);
548         while (mi.hasNext()) {
549                 mi.next();
550                 PropertyList<GraphItem*>* gi = mi.value();
551                 QString prop = mi.key();
552                 // Properties that properly start with http should be serialized as links ...
553                 if (prop.startsWith("http")) {
554                         if (PropertyList<GraphItem*>* pl = dynamic_cast<PropertyList<GraphItem*>*>(gi)) {
555                                 pl->serialize(resource, prop);
556                         }
557
558                 // ... and properties without a http prefix are parameters
559                 } else {
560                         for (PropertyListItem<GraphItem*>* i = gi->firstItem(); i != NULL; i = i->next()) {
561                                 GraphItem* pi = i->getItem();
562                                 Parameter* p = NULL;
563                                 Variant* v = NULL;
564                                 if (Obj* o = dynamic_cast<Obj*>(pi)) {
565                                         v = new Variant(o);
566                                         p = new Parameter(prop, v);
567                                 } else
568                                         p = new Parameter(prop, ((Variant*)pi));
569                                 resource->addProperty(model->createProperty(PROPERTY__PARAMETER), p->serialize(model));
570                                 model->removeFromSerializedObjsCache(p); // this one is important
571                                 delete p; // no cascade here
572                                 if (v != NULL) delete v; // no cascade here
573                         }
574                 }
575         }
576
577         // hashCode
578         if (hasHashCode()) {
579                 resource->addProperty(model->createProperty(PROPERTY__HASHCODE),
580                                 model->createLiteral(getHashCode()));
581         }
582
583         // signature
584         if (hasSignature()) {
585                 resource->addProperty(model->createProperty(PROPERTY__SIGNATURE),
586                                 model->createLiteral(getSignature()));
587         }
588
589         // sessionKey
590         if (hasSessionKey()) {
591                 resource->addProperty(model->createProperty(PROPERTY__SESSIONKEY),
592                                 model->createLiteral(getSessionKey()));
593         }
594
595         // encryptionKeyType
596         if (hasEncryptionKeyType()) {
597                 resource->addProperty(model->createProperty(PROPERTY__ENCRYPTIONKEYTYPE),
598                                 model->createResource(getEncryptionKeyType()));
599         }
600
601         // notary
602         if (hasNotary()) {
603                 resource->addProperty(model->createProperty(PROPERTY__NOTARY),
604                                 model->createResource(getNotary()));
605         }
606
607         return resource;
608 }
609
610 Obj* Obj::fromStringRepresentation(Model* model)
611 {
612         // Parse an object that contains data from the string representation of the object and return it.
613         Obj* replacement = Tools::fromIdentifiedStringAsObj(getStringRepresentation(), getIdentifierUri(), model, false);
614         if (replacement != NULL) {
615                 replacement->setStringRepresentation(getStringRepresentation());
616                 replacement->setHashCode(getHashCode());
617                 replacement->setSignature(getSignature());
618                 replacement->setIdentifierUri(getIdentifierUri());
619         }
620         return replacement;
621 }
622
623 Resource* Obj::serializeToReference(Model* model)
624 {
625         Resource* resource;
626
627         // No longer need to make reference serialization. Set flag to false to prevent loop.
628         mSerializeAsReference = false;
629
630         // add id to this obj if it does not have one yet
631         if (!hasIdentifierUri()) {
632                 if (mReferenceUriPrefix.length() == 0)
633                         setIdentifierUri("http://" + SmartAPICrypto::generate16ByteCryptoRandomString());
634                 else
635                         setIdentifierUri(mReferenceUriPrefix + SmartAPICrypto::generate16ByteCryptoRandomString());
636         }
637         // Start by creating a standard string representation of this resource.
638         // Note: DO NOT recycle the model here by giving it as an argument to tools.
639         // Redland does not like serializing the same model twice and as toString will
640         // cause one round of  serialization, it must be done with an "independent" model.
641         // What we do want to retain however is the HttpMessage that should be carried out
642         // throughout the serialization process. So feed that in (this will disable the automated
643         // deletion of the message, it will be deleted by the model we are taking the message from)
644         QString partString = Tools::toString(this, SERIALIZATION__DEFAULT, model->getMessage());
645
646         // This is needed to unify the message with encoding put in place during transit as MIME multipart
647         partString.replace("\n", "\r\n");
648         
649         addType(RESOURCE__REFERENCE);
650
651         // encrypt if needed
652         if (mEncrypt && mEncryptPKey != NULL) {
653                 // symmetric with notary
654                 if (getEncryptionKeyType() == RESOURCE__NOTARIZEDSESSIONKEY) {
655                         // encrypt data
656                         QByteArray sessionKey = SmartAPICrypto::generateSymmetricKey();
657                         partString = SmartAPICrypto::symmetricEncrypt((unsigned char*)sessionKey.data(), partString);
658
659                         // encrypt session key with recipient's public key
660                         QString encryptedKey = SmartAPICrypto::encryptAndEncodeKey(mEncryptPKey, sessionKey);
661                         setHashCode(SmartAPICrypto::createEncodedMessageDigest(partString));
662                         if (mSign && mSignKey != NULL) {
663                                 setSignature(SmartAPICrypto::sign(mSignKey, getHashCode()));
664                         }
665
666                         // send encrypted key to notary for storing
667                         TransactionAgent a;
668                         if (!a.sendKeyToNotarySync(getGeneratedBy().toString(), getIdentifierUri(), getHashCode(), encryptedKey, getSignature(), getNotary(), mSignKey)) {
669                                 qCritical() << "Sending notarized session key to notary failed.";
670                         }
671                 }
672
673                 // with public key
674                 else if (getEncryptionKeyType() == RESOURCE__PUBLICKEY) {
675                         // encrypt data
676                         partString = SmartAPICrypto::asymmetricEncrypt(mEncryptPKey, partString, mEncryptSecretKey, NULL);
677                 }
678
679                 // with only session key
680                 else if (getEncryptionKeyType() == RESOURCE__SESSIONKEY) {
681                         // encrypt data
682                         partString = SmartAPICrypto::symmetricEncrypt((unsigned char*)mEncryptSecretKey.data(), partString);
683                         QString key = mEncryptSecretKey.toBase64();
684                         //setSessionKey(key); // do not add sessionkey because key would then be transferred in the message
685                 }
686         }
687
688         // create hash if not yet created
689         if (!hasHashCode()) {
690                 setHashCode(SmartAPICrypto::createEncodedMessageDigest(partString));
691         }
692
693         // sign if needed
694         if (mSign && !hasSignature() && mSignKey != NULL) {
695                 setSignature(SmartAPICrypto::sign(mSignKey, partString));
696         }
697
698         // create and add message part
699         if (model->hasMessage()) {
700                 model->getMessage()->add(getIdentifierUri(), partString.toLocal8Bit());
701                 model->getMessage()->addHeader(getIdentifierUri(), "Content-ID", getIdentifierUri().toLocal8Bit());
702                 model->getMessage()->addHeader(getIdentifierUri(), "Content-Type", "text/turtle");
703         }
704
705         addType(RESOURCE__MULTIPARTREFERENCE);
706
707         // serialize as reference into this model
708         // create resource
709         if (hasIdentifierUri()) {
710                 resource = model->createResource(mIdentifierUri);
711         } else {
712                 resource = model->createResource();
713         }
714         model->addToSerializedObjsCache(this, resource);
715
716         // types
717         QListIterator<QString> typeIter(mTypes);
718         while (typeIter.hasNext()) {
719                 resource->addProperty(model->createProperty(PROPERTY__RDF_TYPE), QUrl(typeIter.next()));
720         }
721
722         // hashCode
723         if (hasHashCode()) {
724                 resource->addProperty(model->createProperty(PROPERTY__HASHCODE), getHashCode());
725         }
726
727         // signature
728         if (hasSignature()) {
729                 resource->addProperty(model->createProperty(PROPERTY__SIGNATURE), getSignature());
730         }
731
732         // session key
733         if (hasSessionKey()) {
734                 resource->addProperty(model->createProperty(PROPERTY__SESSIONKEY), getSessionKey());
735         }
736
737         // encryption key type
738         if (hasEncryptionKeyType()) {
739                 resource->addProperty(model->createProperty(PROPERTY__ENCRYPTIONKEYTYPE), model->createResource(getEncryptionKeyType()));
740         }
741
742         // notary
743         if (hasNotary()) {
744                 resource->addProperty(model->createProperty(PROPERTY__NOTARY), model->createResource(getNotary()));
745         }
746
747         return resource;
748 }
749
750 void Obj::addProperty(Model* model, Resource* resource, QString property, QVariant propObj)
751 {
752         if (property.startsWith("http")) {
753                 if (propObj.canConvert<QString>())
754                         resource->addProperty(model->createProperty(property), propObj.toString());
755                 else if (propObj.canConvert<int>())
756                         resource->addProperty(model->createProperty(property), model->createTypedLiteral(propObj, Tools::getXsdString() + "int"));
757                 else if (propObj.canConvert<double>())
758                         resource->addProperty(model->createProperty(property), model->createTypedLiteral(propObj, Tools::getXsdString() + "double"));
759                 else if (propObj.canConvert<bool>())
760                         resource->addProperty(model->createProperty(property), model->createTypedLiteral(propObj, Tools::getXsdString() + "boolean"));
761                 else {
762                         Variant* propObjVariant = (Variant*)propObj.value<void*>();
763                         if (propObjVariant != NULL)
764                                 resource->addProperty(model->createProperty(property), propObjVariant->serialize(model));
765                 }
766         } else {
767                 Resource* param = model->createResource();
768                 Variant* propVariant = new Variant(property);
769                 Variant* valueVariant = NULL;
770                 param->addProperty(model->createProperty(PROPERTY__RDF_TYPE), model->createResource(PROPERTY__PARAMETER));
771                 param->addProperty(model->createProperty(PROPERTY__KEY), propVariant->serialize(model));
772                 
773                 if (propObj.type() == QMetaType::QVariantList) {
774                         valueVariant = new Variant(propObj);
775                         param->addProperty(model->createProperty(PROPERTY__RDF_VALUE), valueVariant->serialize(model));
776                         delete valueVariant;
777                 } else if (propObj.type() == QMetaType::VoidStar) {
778                         Variant* orig = (Variant*)propObj.value<void*>();
779                         //param->addProperty(model->createProperty(PROPERTY__RDF_VALUE), model->createTypedLiteral(QVariant(1), Tools::getXsdString() + "int"));
780                         
781                         if (orig->isObj()) {
782                                 Obj* origValue = (Obj*)orig->getValue().value<void *>();
783                                 param->addProperty(model->createProperty(PROPERTY__RDF_VALUE), origValue->serialize(model));
784                         } else {
785                                 param->addProperty(model->createProperty(PROPERTY__RDF_VALUE), orig->serialize(model));
786                         }
787                 } else {
788                         valueVariant = new Variant(propObj);
789                         param->addProperty(model->createProperty(PROPERTY__RDF_VALUE), valueVariant->serialize(model));
790                         delete valueVariant;
791                 }
792                 resource->addProperty(model->createProperty(PROPERTY__PARAMETER), param);
793                 delete propVariant;
794         }
795 }
796
797 void Obj::parse(QList<Statement*> statements)
798 {
799         for (int i = 0; i < statements.length(); i++)  parse(statements.at(i));
800 }
801
802 void Obj::parse(Statement* statement)
803 {
804         // get predicate
805         QString predicate = statement->getPredicateUriString();
806
807         // get object
808         raptor_term* objectNode = statement->getObject();
809
810         // transaction
811         if (predicate == PROPERTY__TRANSACTION) {
812                 setTransaction(Obj::parse<Transaction>(statement->getResource()));
813                 return;
814         }
815
816         // type
817         if (predicate == PROPERTY__RDF_TYPE) {
818                 // Set types as strings. Don't change this implementation unless
819                 // you know what you are doing (and test for memleaks)
820                 addType(statement->getResource()->toString());
821                 return;
822         }
823
824         if (predicate == PROPERTY__GENERATEDBY) {
825                 setGeneratedBy(statement->getResource()->toString());
826                 return;
827         }
828
829         // generatedat
830         if (predicate == PROPERTY__GENERATEDAT) {
831                 setGeneratedAt(Tools::stringToDate(statement->getString()));
832                 return;
833         }
834
835         // sameas
836         if (predicate == PROPERTY__SAMEAS) {
837                 setSameAs(Obj::parse<Entity>(statement->getResource()));
838                 return;
839         }
840
841         // label
842         if (predicate == PROPERTY__RDFS_LABEL) {
843                 setName(statement->getString());
844                 // TODO what if it is a Variant? see Java implementation
845                 return;
846         }
847         
848         // comment
849         if (predicate == PROPERTY__COMMENT) {
850                 setDescription(statement->getString());
851                 // TODO what if it is a Variant? see Java implementation
852                 return;
853         }
854         
855         // provenance
856         if (predicate == PROPERTY__PROVENANCE) {
857                 addProvenance(Obj::parse<Provenance>(statement->getResource()));
858                 return;
859         }
860
861         // restriction
862         if (predicate == PROPERTY__RESTRICTION) {
863                 addRestriction(Obj::parse<Restriction>(statement->getResource()));
864                 return;
865         }
866
867         // offerings
868         if (predicate == PROPERTY__OFFERS) {
869                 addOffering(Obj::parse<Offering>(statement->getResource()));
870                 return;
871         }
872
873         // errors
874         if (predicate == PROPERTY__ERROR) {
875                 addError(Obj::parse<Error>(statement->getResource()));
876                 return;
877         }
878
879         // hashCode
880         if (predicate == PROPERTY__HASHCODE) {
881                 setHashCode(statement->getString());
882                 return;
883         }
884
885         // signature
886         if (predicate == PROPERTY__SIGNATURE) {
887                 setSignature(statement->getString());
888                 return;
889         }
890
891         // sessionKey
892         if (predicate == PROPERTY__SESSIONKEY) {
893                 setSessionKey(statement->getString());
894                 return;
895         }
896
897         // encryptionKeyType
898         if (predicate == PROPERTY__ENCRYPTIONKEYTYPE) {
899                 // TODO is this correct? Java impl uses getURI() instead of toString()
900                 setEncryptionKeyType(statement->getResource()->toString());
901                 return;
902         }
903
904         // notary
905         if (predicate == PROPERTY__NOTARY) {
906                 // TODO is this correct? Java impl uses getURI() instead of toString()
907                 setNotary(statement->getResource()->toString());
908                 return;
909         }
910
911         // parameter
912         if (predicate == PROPERTY__PARAMETER) {
913                 Parameter* p = Obj::parse<Parameter>(statement->getResource());
914                 if (p) {
915                         add(p->getKey(), p->getValues());
916                         delete p;
917                 }
918                 return;
919         }
920         
921         // if literal object
922         if (objectNode->type == RAPTOR_TERM_TYPE_LITERAL) {
923                 this->add(predicate, Tools::raptorLiteralToQVariant(objectNode->value.literal));
924                 return;
925         }
926
927         // if resource
928         if (statement->getResource() != NULL) {
929                 Resource* resource = statement->getResource();
930                 Obj* instanceClass = Tools::fromResourceAsObj(resource);
931                 this->add(predicate, instanceClass);
932                 return;
933         }
934 }
935
936 bool Obj::isReadable()
937 {
938         return hasType(RESOURCE__READABLE);
939 }
940
941 bool Obj::isWritable()
942 {
943         return hasType(RESOURCE__WRITABLE);
944 }
945
946 void Obj::setProvenances(QList<Provenance*> provenances)
947 {
948         mProvenances.append(provenances);
949 }
950
951 void Obj::setRestrictions(QList<Restriction*> restrictions)
952 {
953         mRestrictions.append(restrictions);
954 }
955
956 void Obj::setOfferings(QList<Offering *> offerings)
957 {
958         mOfferings.append(offerings);
959 }
960
961 void Obj::addOffering(Offering* offering, float amount, QString unitOfmeasurement, QString name, QString description)
962 {
963         addOffering(offering);
964         offering->addItem(this, amount, unitOfmeasurement, name, description);
965 }
966
967 Offering* Obj::firstOffering()
968 {
969         if (mOfferings.length() > 0) return mOfferings.at(0);
970         return NULL;
971 }
972
973 void Obj::addOptionalPropertyDescription(QStringList dataRanges, QString property)
974 {
975         addRestriction(new Restriction(NULL, NULL, NULL, true, dataRanges, property));
976 }
977
978 void Obj::addOptionalPropertyDescription(QStringList dataRanges, QStringList properties)
979 {
980         addRestriction(new Restriction(NULL, NULL, NULL, true, dataRanges, properties));
981 }
982
983 void Obj::addOptionalPropertyDescription(QString dataRange, QString property)
984 {
985         addRestriction(new Restriction(NULL, NULL, NULL, true, dataRange, property));
986 }
987
988 void Obj::addOptionalPropertyDescription(QString dataRange, QStringList properties)
989 {
990         addRestriction(new Restriction(NULL, NULL, NULL, true, dataRange, properties));
991 }
992
993 void Obj::addOptionalPropertyDescription(int numOfValues, QStringList dataRanges, QString property)
994 {
995         addRestriction(new Restriction(new Variant(numOfValues), NULL, NULL, true, dataRanges, property));
996 }
997
998 void Obj::addOptionalPropertyDescription(int numOfValues, QStringList dataRanges, QStringList properties)
999 {
1000         addRestriction(new Restriction(new Variant(numOfValues), NULL, NULL, true, dataRanges, properties));
1001 }
1002
1003 void Obj::addOptionalPropertyDescription(int numOfValues, QString dataRange, QString property)
1004 {
1005         addRestriction(new Restriction(new Variant(numOfValues), NULL, NULL, true, dataRange, property));
1006 }
1007
1008 void Obj::addOptionalPropertyDescription(int numOfValues, QString dataRange, QStringList properties)
1009 {
1010         addRestriction(new Restriction(new Variant(numOfValues), NULL, NULL, true, dataRange, properties));
1011 }
1012
1013 void Obj::addOptionalPropertyDescription(Variant* minNumOfValues, Variant* maxNumOfValues, QStringList dataRanges, QString property)
1014 {
1015         addRestriction(new Restriction(NULL, minNumOfValues, maxNumOfValues, true, dataRanges, property));
1016 }
1017
1018 void Obj::addOptionalPropertyDescription(Variant* minNumOfValues, Variant* maxNumOfValues, QStringList dataRanges, QStringList properties)
1019 {
1020         addRestriction(new Restriction(NULL, minNumOfValues, maxNumOfValues, true, dataRanges, properties));
1021 }
1022
1023 void Obj::addOptionalPropertyDescription(Variant* minNumOfValues, Variant* maxNumOfValues, QString dataRange, QString property)
1024 {
1025         addRestriction(new Restriction(NULL, minNumOfValues, maxNumOfValues, true, dataRange, property));
1026 }
1027
1028 void Obj::addOptionalPropertyDescription(Variant* minNumOfValues, Variant* maxNumOfValues, QString dataRange, QStringList properties)
1029 {
1030         addRestriction(new Restriction(NULL, minNumOfValues, maxNumOfValues, true, dataRange, properties));
1031 }
1032
1033 void Obj::addRequiredPropertyDescription(QStringList dataRanges, QString property)
1034 {
1035         addRestriction(new Restriction(NULL, NULL, NULL, false, dataRanges, property));
1036 }
1037
1038 void Obj::addRequiredPropertyDescription(QStringList dataRanges, QStringList properties)
1039 {
1040         addRestriction(new Restriction(NULL, NULL, NULL, false, dataRanges, properties));
1041 }
1042
1043 void Obj::addRequiredPropertyDescription(QString dataRange, QString property)
1044 {
1045         addRestriction(new Restriction(NULL, NULL, NULL, false, dataRange, property));
1046 }
1047
1048 void Obj::addRequiredPropertyDescription(QString dataRange, QStringList properties)
1049 {
1050         addRestriction(new Restriction(NULL, NULL, NULL, false, dataRange, properties));
1051 }
1052
1053 void Obj::addRequiredPropertyDescription(int numOfValues, QStringList dataRanges, QString property)
1054 {
1055         addRestriction(new Restriction(new Variant(numOfValues), NULL, NULL, false, dataRanges, property));
1056 }
1057
1058 void Obj::addRequiredPropertyDescription(int numOfValues, QStringList dataRanges, QStringList properties)
1059 {
1060         addRestriction(new Restriction(new Variant(numOfValues), NULL, NULL, false, dataRanges, properties));
1061 }
1062
1063 void Obj::addRequiredPropertyDescription(int numOfValues, QString dataRange, QString property)
1064 {
1065         addRestriction(new Restriction(new Variant(numOfValues), NULL, NULL, false, dataRange, property));
1066 }
1067
1068 void Obj::addRequiredPropertyDescription(int numOfValues, QString dataRange, QStringList properties)
1069 {
1070         addRestriction(new Restriction(new Variant(numOfValues), NULL, NULL, false, dataRange, properties));
1071 }
1072
1073 void Obj::addRequiredPropertyDescription(Variant* minNumOfValues, Variant* maxNumOfValues, QStringList dataRanges, QString property)
1074 {
1075         addRestriction(new Restriction(NULL, minNumOfValues, maxNumOfValues, false, dataRanges, property));
1076 }
1077
1078 void Obj::addRequiredPropertyDescription(Variant* minNumOfValues, Variant* maxNumOfValues, QStringList dataRanges, QStringList properties)
1079 {
1080         addRestriction(new Restriction(NULL, minNumOfValues, maxNumOfValues, false, dataRanges, properties));
1081 }
1082
1083 void Obj::addRequiredPropertyDescription(Variant* minNumOfValues, Variant* maxNumOfValues, QString dataRange, QString property)
1084 {
1085         addRestriction(new Restriction(NULL, minNumOfValues, maxNumOfValues, false, dataRange, property));
1086 }
1087
1088 void Obj::addRequiredPropertyDescription(Variant* minNumOfValues, Variant* maxNumOfValues, QString dataRange, QStringList properties)
1089 {
1090         addRestriction(new Restriction(NULL, minNumOfValues, maxNumOfValues, false, dataRange, properties));
1091 }
1092
1093 QMap<QString, PropertyList<GraphItem*>* > Obj::getAllProperties()
1094 {
1095         return mVariantMap;
1096 }
1097
1098
1099 PropertyList<GraphItem*>* Obj::getAll(QString property)
1100 {
1101         if (mVariantMap.contains(property)) {
1102                 return mVariantMap.value(property);
1103         }
1104         return NULL;
1105 }
1106
1107 void Obj::setProperties(QMap<QString, PropertyList<GraphItem*>* > properties)
1108 {
1109         mVariantMap = properties;
1110 }
1111
1112 bool Obj::has(QString property)
1113 {
1114         return mVariantMap.contains(property);
1115 }
1116
1117 void Obj::add(QString property, QList<Obj*> obj)
1118 {
1119         Variant* v = new Variant(obj);
1120         add(property, v);
1121 }
1122
1123 void Obj::add(QString property, QList<Map*> obj)
1124 {
1125         Variant* v = new Variant(obj);
1126         add(property, v);
1127 }
1128
1129 void Obj::add(QString property, PropertyList<Variant*> obj)
1130 {
1131         PropertyList<GraphItem*>* l;
1132         if (mVariantMap.contains(property)) {
1133                 l = mVariantMap.value(property);
1134         } else {
1135                 l = new PropertyList<GraphItem*>();
1136                 l->setParent(this);
1137         }
1138
1139         for (PropertyListItem<Variant*>* i = obj.firstItem(); i != NULL; i = i->next()) {
1140                 l->append(i->getItem());
1141         }
1142         mVariantMap.insert(property, l);
1143 }
1144
1145 void Obj::add(QString property, QVariant v)
1146 {
1147         add(property, new Variant(v));
1148 }
1149
1150 void Obj::add(QString property, GraphItem* v)
1151 {
1152         if (v != NULL) {
1153                 if (v->isPropertyList()) {
1154                         mVariantMap.insert(property,(PropertyList<GraphItem*>*)v);
1155                 } else {
1156                         PropertyList<GraphItem*>* l;
1157                         if (mVariantMap.contains(property)) {
1158                                 l = mVariantMap.value(property);
1159                         } else {
1160                                 l = new PropertyList<GraphItem*>();
1161                                 l->setParent(this);
1162                         }
1163                         l->append(v);
1164                         mVariantMap.insert(property, l);
1165                 }
1166         }
1167 }
1168
1169 void Obj::add(QUrl property, GraphItem* obj)
1170 {
1171         add(property.toString(), obj);
1172 }
1173
1174 void Obj::add(QString property, PropertyList<GraphItem*> obj)
1175 {
1176         PropertyList<GraphItem*>* l;
1177         if (mVariantMap.contains(property)) {
1178                 l = mVariantMap.value(property);
1179         } else {
1180                 l = new PropertyList<GraphItem*>();
1181                 l->setParent(this);
1182         }
1183
1184         for (PropertyListItem<GraphItem*>* i = obj.firstItem(); i != NULL; i = i->next())
1185                 l->append(i->getItem());
1186         mVariantMap.insert(property, l);
1187 }
1188
1189 void Obj::set(QString property, GraphItem* v)
1190 {
1191         PropertyList<GraphItem*>* l;
1192         if (mVariantMap.contains(property)) {
1193                 l = mVariantMap.value(property);
1194                 l->destroyCascade();
1195         } else {
1196                 l = new PropertyList<GraphItem*>();
1197                 l->setParent(this);
1198         }
1199         l->append(v);
1200         mVariantMap.insert(property, l);
1201 }
1202
1203 void Obj::remove(QString property, GraphItem* obj)
1204 {
1205         if (mVariantMap.contains(property)) {
1206                 PropertyList<GraphItem*>* l = mVariantMap.value(property);
1207                 cleanList(l, obj);
1208                 mVariantMap.insert(property, l);
1209         }
1210 }
1211
1212 GraphItem* Obj::get(QString property)
1213 {
1214         PropertyList<GraphItem*>* f = getAll(property);
1215         if (f) {
1216                 return f->at(0);
1217         }
1218         return NULL;
1219 }
1220
1221 QVariant Obj::getValue(QString property)
1222 {
1223         GraphItem* g =  get(property);
1224         if (g != NULL && g->isVariant())
1225                 return ((Variant*)g)->getValue();
1226         return QVariant();
1227 }
1228
1229 QString Obj::getAsQString(QString property)
1230 {
1231         GraphItem* g =  get(property);
1232         if (g != NULL && g->isVariant())
1233                 return ((Variant*)g)->getAsString();
1234         return QString();
1235 }
1236
1237 QList<QString> Obj::activePropertyNames()
1238 {
1239         QList<QString> ap;
1240         for (int i = 0; i < mVariantMap.keys().length(); i++) {
1241                 if (mVariantMap.value(mVariantMap.keys().at(i))->length() > 0) {
1242                         ap << mVariantMap.keys().at(i);
1243                 }
1244         }
1245         return ap;
1246 }
1247
1248 QList<QString> Obj::propertyNames()
1249 {
1250         return mVariantMap.keys();
1251 }
1252
1253 void Obj::clearProperties()
1254 {
1255         QSet<GraphItem*> trash;
1256         while (!mVariantMap.isEmpty()) {
1257                 PropertyList<GraphItem*>* vars = mVariantMap.take(mVariantMap.firstKey());
1258                 while (vars->length() > 0) vars->destroyFirstCascade(&trash);
1259                 delete vars;
1260         }
1261         QSet<GraphItem *>::const_iterator i = trash.constBegin();
1262         while (i != trash.constEnd()) { delete (*i); ++i; }
1263 }
1264
1265 /* FIXME
1266 QVariantList Obj::copyList(QList<Variant*> l)
1267 {
1268         QVariantList lc;
1269         for (int i = 0; i < l.length(); i++) {
1270                 QVariant v = l.at(i);
1271                 if (v.type() == QMetaType::VoidStar) {
1272                         Variant* o = new Variant((Variant*)v.value<void*>());
1273                         lc.append(qVariantFromValue((void*)o));
1274                 } else {
1275                         lc.append(v);
1276                 }
1277         }
1278
1279         return lc;
1280 }
1281 */
1282
1283
1284 void Obj::cleanList(PropertyList<GraphItem*>* l)
1285 {
1286         QSet<GraphItem*> trash;
1287         while (l->length() > 0) l->destroyFirstCascade(&trash);
1288         
1289         QSet<GraphItem *>::const_iterator i = trash.constBegin();
1290         while (i != trash.constEnd()) {
1291                 delete (*i);
1292                 ++i;
1293         }
1294 }
1295
1296 void Obj::cleanList(PropertyList<GraphItem*>* l, GraphItem* obj)
1297 {
1298         QSet<GraphItem*> trash;
1299         for (PropertyListItem<GraphItem*>* i = l->firstItem(); i != NULL; i = i->next()) {
1300                 if (i->getItem() == obj) i->getItem()->destroyCascade(&trash);
1301         }
1302         
1303         QSet<GraphItem *>::const_iterator i = trash.constBegin();
1304         while (i != trash.constEnd()) {
1305                 delete (*i);
1306                 ++i;
1307         }
1308 }
1309
1310 QString Obj::getIdentifierUriPart(int index)
1311 {
1312         if (hasIdentifierUri()) {
1313                 QStringList parts = getIdentifierUri().split("://");
1314                 if (parts.length() > 1) {
1315                         QStringList idParts = parts.at(1).split('/');
1316                         if (idParts.length() > index) {
1317                                 return QUrl::fromPercentEncoding(idParts.at(index).toLocal8Bit());
1318                         }
1319                 }
1320         }
1321
1322         return QString();
1323 }
1324
1325 QString Obj::asTurtle()
1326 {
1327         return Tools::toString(this, SERIALIZATION__TURTLE);
1328 }
1329
1330 void Obj::turtlePrint()
1331 {
1332         ObjectPrinter* op = new ObjectPrinter();  // note, the ObjectPrinter deletes itself automatically once printing is done
1333         op->printAsTurtle(this);
1334 }
1335
1336 void Obj::printOut(bool destroyAfterPrinting)
1337 {
1338         ObjectPrinter* op = new ObjectPrinter();  // note, the ObjectPrinter deletes itself automatically once printing is done
1339         op->printAsFlat(this, destroyAfterPrinting);
1340 }
1341
1342 void Obj::explain(bool destroyAfterPrinting)
1343 {
1344         ObjectPrinter* op = new ObjectPrinter();  // note, the ObjectPrinter deletes itself automatically once printing is done
1345         op->printWithExplanations(this, destroyAfterPrinting);
1346 }
1347