C++: Add managed by search into SearchAgent
[smartapi.git] / Common / C++ / SmartAPI / smartapi / agents / SearchAgent.cpp
1 #include "SearchAgent.h"
2 #include "smartapi/common/Duration.h"
3 #include "smartapi/common/PROPERTY.h"
4 #include "smartapi/common/SERIALIZATION.h"
5 #include "smartapi/common/ACTIVITIES.h"
6 #include "smartapi/factory/RequestFactory.h"
7 #include "smartapi/model/Response.h"
8 #include "smartapi/model/Classification.h"
9
10
11 SearchAgent::SearchAgent(QString myId, QNetworkAccessManager* am) :
12         Agent(am),
13         mGeneratedBy(myId)
14 {
15         mEntity = new Entity();
16         // mEntity->clearTypes();
17         mRegistrationUri = SMARTAPI_REGISTER_SEARCH_URI;
18 }
19
20 SearchAgent::~SearchAgent()
21 {
22         if (mEntity != NULL) mEntity->destroyCascade();
23 }
24
25 void SearchAgent::setEntity(Entity* e)
26 {
27         if (mEntity != NULL) mEntity->destroyCascade();
28         mEntity = e;
29 }
30
31 void SearchAgent::doSearch(int callId, QObject* caller, const char* onSuccess, const char* onFail, QVariant userData)
32 {
33         AsyncData ac(callId, caller, onSuccess, onFail, userData);
34         Request* request = RequestFactory::create(mGeneratedBy);
35         Activity* activity = new Activity(SMARTAPI_SEARCH_ACTIVITY_URI);
36         activity->setMethod(QUrl(RESOURCE__READ));
37         activity->addEntity(mEntity);
38         request->addActivity(activity);
39         QString messageBody = Tools::toString(request, mSerialization);
40         request->destroyCascade();
41         mEntity = NULL;
42
43         runAsyncQuery(callId, this, "onItemsFound", "onItemSearchFailed", mRegistrationUri, toContentType(mSerialization), toContentType(mSerialization), messageBody, qVariantFromValue(ac));
44 }
45
46 QList<Entity*> SearchAgent::searchSync()
47 {
48         // generate search message
49         Request* request = RequestFactory::create(mGeneratedBy);
50         Activity* activity = new Activity(SMARTAPI_SEARCH_ACTIVITY_URI);
51         activity->setMethod(QUrl(RESOURCE__READ));
52         activity->addEntity(mEntity);
53         request->addActivity(activity);
54         QString messageBody = Tools::toString(request, mSerialization);
55         request->destroyCascade();
56         mEntity = NULL;
57
58         QMap<QString, QString> headers;
59         headers["X-SmartAPI-Method"] = "Request";
60         QString responseStr = runSyncQuery(mRegistrationUri,
61                         toContentType(mSerialization),
62                         toContentType(mSerialization),
63                         messageBody,
64                         headers);
65         Response* response = dynamic_cast<Response*>(Tools::fromStringAsObj(responseStr, mSerialization));
66
67         if (response && response->hasActivity()) {
68                 Activity* a = response->firstActivity();
69                 QList<Entity*> el = a->getEntities().toQList();
70                 a->unlinkEntities();
71                 response->destroyCascade();
72                 return el;
73         } else {
74                 return QList<Entity*>();
75         }
76 }
77
78 QList<Entity*> SearchAgent::searchByPointAndTypeSync(int freshnessInDays, double latitude, double longitude, int distanceInKm, QStringList types)
79 {
80         clear();
81
82         anyOfTypes(types);
83         daysOldData(freshnessInDays);
84         pointSearchArea(new Coordinates(latitude, longitude), distanceInKm);
85         return searchSync();
86 }
87
88 QList<Entity*> SearchAgent::searchByPoint(double latitude, double longitude, double distanceInKm)
89 {
90         clear();
91
92         pointSearchArea(new Coordinates(latitude, longitude), distanceInKm);
93         return searchSync();
94 }
95
96 QList<Entity*> SearchAgent::searchByPoint(double latitude, double longitude, double distanceInKm, QString type)
97 {
98         clear();
99
100         ofType(type);
101         pointSearchArea(new Coordinates(latitude, longitude), distanceInKm);
102         return searchSync();
103 }
104
105 QList<Entity*> SearchAgent::searchByNameAndTypeSync(int freshnessInDays, QStringList keywords, QStringList types)
106 {
107         clear();
108
109         anyOfTypes(types);
110         daysOldData(freshnessInDays);
111         anyOfNames(keywords);
112         return searchSync();
113 }
114
115 QList<Entity*> SearchAgent::searchByIdSync(int freshnessInDays, QString idRegex)
116 {
117         clear();
118
119         ofType(RESOURCE__ENTITY);
120         ofId(idRegex);
121         daysOldData(freshnessInDays);
122         return searchSync();
123 }
124
125 QList<Entity*> SearchAgent::searchByDescriptionSync(int freshnessInDays, QString searchString)
126 {
127         clear();
128
129         ofType(RESOURCE__ENTITY);
130         daysOldData(freshnessInDays);
131         ofDescription(searchString);
132         return searchSync();
133 }
134
135 QList<Entity*> SearchAgent::searchById(QString idRegex)
136 {
137         clear();
138
139         ofType(RESOURCE__ENTITY);
140         ofId(idRegex);
141         return searchSync();
142 }
143
144 QList<Entity*> SearchAgent::searchById(QString idRegex, QString type)
145 {
146         clear();
147
148         ofType(type);
149         ofId(idRegex);
150         return searchSync();
151 }
152
153 QList<Entity*> SearchAgent::searchByRegistrant(QString registrantId)
154 {
155         clear();
156
157         ofRegistrantId(registrantId);
158         return searchSync();
159 }
160
161 QList<Entity*> SearchAgent::searchByRegistrant(QString registrantId, QString type)
162 {
163         clear();
164
165         ofRegistrantId(registrantId);
166         ofType(type);
167         return searchSync();
168 }
169
170 QList<Entity*> SearchAgent::searchByType(QString type)
171 {
172         clear();
173
174         ofType(type);
175         return searchSync();
176 }
177
178 void SearchAgent::hasChanged(int callId, QObject* caller, const char* onSuccess, const char* onFail, Entity* entity)
179 {
180         if (entity == NULL || !entity->hasIdentifierUri()) {
181                 if (caller != NULL && onSuccess != NULL) {
182                         QMetaObject::invokeMethod(caller, onSuccess, Qt::DirectConnection, Q_ARG(int, callId), Q_ARG(bool, true));
183                 }
184         }
185         hasChanged(callId, caller, onSuccess, onFail, entity->getIdentifierUri(), entity->generateChecksum());
186 }
187
188 void SearchAgent::hasChanged(int callId, QObject* caller, const char* onSuccess, const char* onFail, QString entityId, QString checksum)
189 {
190         AsyncData ac(callId, caller, onSuccess, onFail, QVariant());
191         Request* request = RequestFactory::create(mGeneratedBy);
192         Activity* activity = new Activity(SMARTAPI_SEARCH_ACTIVITY_URI);
193         Entity* e = new Entity(entityId);
194         e->setChecksum(checksum);
195         activity->setMethod(QUrl(RESOURCE__CHECK));
196         activity->addEntity(e);
197         request->addActivity(activity);
198         QString messageBody = Tools::toString(request, mSerialization);
199         request->destroyCascade();
200         mEntity = NULL;
201
202         runAsyncQuery(callId, this, "onHasChangedResult", "onItemSearchFailed", mRegistrationUri, toContentType(mSerialization), toContentType(mSerialization), messageBody, qVariantFromValue(ac));
203 }
204
205 Entity* SearchAgent::fetchBySmartAPIId(QString idToFetch)
206 {
207         clear(idToFetch);
208         QList<Entity*> res = searchSync();
209         if (res.length() > 0) {
210                 Entity* e = res.takeFirst();
211                 while (res.length() > 0) res.takeFirst()->destroyCascade();
212                 return e;
213         } else {
214                 return NULL;
215         }
216 }
217
218
219 void SearchAgent::clear()
220 {
221         //delete mEntity; // FIXME deleteCascade?
222         mEntity = new Entity();
223         mEntity->clearTypes();
224 }
225
226 void SearchAgent::clear(QString entityUri)
227 {
228         delete mEntity; // FIXME deleteCascade?
229         mEntity = new Entity(entityUri);
230         mEntity->clearTypes();
231 }
232
233 void SearchAgent::ofName(QString searchString, bool exactMatch)
234 {
235         if (exactMatch) {
236                 mEntity->setName(searchString);
237         } else {
238                 Condition* condition = new Condition();
239                 condition->addRegex("(?i)" + searchString);
240                 mEntity->add(PROPERTY__RDFS_LABEL, condition);
241         }
242 }
243
244 void SearchAgent::ofRegistrantId(QString regId)
245 {
246         mEntity->add(PROPERTY__ISREGISTEREDBY, new Obj(regId));
247 }
248
249 void SearchAgent::ofType(QString type)
250 {
251         mEntity->addType(type);
252 }
253
254 void SearchAgent::ofId(QString searchString)
255 {
256         Condition* condition = new Condition();
257         condition->addRegex("(?i)" + searchString);
258         mEntity->add(PROPERTY__ID, condition);
259 }
260
261 void SearchAgent::ofServedById(QString serviceId)
262 {
263         mEntity->add(PROPERTY__ISSERVEDBY, new Obj(serviceId));
264 }
265
266 void SearchAgent::ofManagedById(QString serviceId)
267 {
268         mEntity->add(PROPERTY__ISMANAGEDBY, new Obj(serviceId));
269 }
270
271 void SearchAgent::ofIds(QStringList searchStrings)
272 {
273         for (int i = 0; i < searchStrings.length(); i++) {
274                 if (searchStrings.at(i).length() > 0) {
275                         Condition* condition = new Condition();
276                         condition->addRegex("(?i)" + searchStrings.at(i));
277                         mEntity->add(PROPERTY__ID, condition);
278                 }
279         }
280 }
281
282 void SearchAgent::ofDescription(QString searchString)
283 {
284         Condition* condition = new Condition();
285         condition->addRegex("(?i)" + searchString);
286         mEntity->add(PROPERTY__COMMENT, condition);
287 }
288
289 void SearchAgent::ofOutputCategory(QString category)
290 {
291         Activity* activity = new Activity();
292         mEntity->addCapability(activity);
293         Output* output = new Output();
294         activity->addOutput(output);
295         output->setCategory(category);
296 }
297
298 void SearchAgent::ofInputCategory(QString category)
299 {
300         Activity* activity = new Activity();
301         mEntity->addCapability(activity);
302         Input* input = new Input();
303         activity->addInput(input);
304         input->setCategory(category);
305 }
306
307 void SearchAgent::anyOfNames(QStringList searchStrings)
308 {
309         if (searchStrings.length() == 1) {
310                 ofName(searchStrings.at(0));
311         } else if (searchStrings.length() > 1) {
312                 Condition* condition = new Condition();
313                 QStringListIterator si(searchStrings);
314                 while (si.hasNext()) {
315                         condition->addRegex("(?i)" + si.next());
316                 }
317                 mEntity->add(PROPERTY__RDFS_LABEL, condition);
318         }
319 }
320
321 void SearchAgent::anyOfTypes(QStringList types)
322 {
323         if (types.length() == 1) {
324                 ofType(types.at(0));
325         } else if (types.length() > 1) {
326                 Condition* condition = new Condition();
327                 QStringListIterator si(types);
328                 while (si.hasNext()) {
329                         condition->addOr(new Obj(si.next()));
330                 }
331                 mEntity->addType(RESOURCE__CONDITION);
332         }
333 }
334
335
336 void SearchAgent::ofTopic(QString searchString, bool exactMatch)
337 {
338         if (exactMatch) {
339                 mEntity->add(PROPERTY__TOPIC, searchString);
340         } else {
341                 Condition* condition = new Condition();
342                 condition->addRegex("(?i)" + searchString);
343                 mEntity->add(PROPERTY__TOPIC, condition);
344         }
345 }
346
347 void SearchAgent::ofTheme(QString searchString, bool exactMatch)
348 {
349         Classification* classification = new Classification();
350         classification->addType(NS__SMARTAPI + "Theme");
351         if (exactMatch) {
352                 classification->add(PROPERTY__RDFS_LABEL, searchString);
353         } else {
354                 Condition* condition = new Condition();
355                 condition->addRegex("(?i)" + searchString);
356                 classification->add(PROPERTY__RDFS_LABEL, condition);
357         }
358         mEntity->add(PROPERTY__CLASSIFICATION, classification);
359 }
360
361 void SearchAgent::ofLocality(QString searchString, bool exactMatch)
362 {
363         if (exactMatch) {
364                 mEntity->add(PROPERTY__LOCALITY, searchString);
365         } else {
366                 Condition* condition = new Condition();
367                 condition->addRegex("(?i)" + searchString);
368                 mEntity->add(PROPERTY__LOCALITY, condition);
369         }
370 }
371
372 void SearchAgent::ofCountry(QString searchString, bool exactMatch)
373 {
374         if (exactMatch) {
375                 mEntity->add(PROPERTY__COUNTRY_NAME, searchString);
376         } else {
377                 Condition* condition = new Condition();
378                 condition->addRegex("(?i)" + searchString);
379                 mEntity->add(PROPERTY__COUNTRY_NAME, condition);
380         }
381 }
382
383 void SearchAgent::minutesOldData(int minutes)
384 {
385         mEntity->add(PROPERTY__FRESHNESS, new Variant(new Duration(0, 0, 0, 0, minutes, 0)));
386 }
387
388 void SearchAgent::hoursOldData(int hours)
389 {
390         mEntity->add(PROPERTY__FRESHNESS, new Variant( new Duration(0, 0, 0, hours, 0, 0)));
391 }
392
393 void SearchAgent::daysOldData(int days)
394 {
395         mEntity->add(PROPERTY__FRESHNESS, new Variant(new Duration(0, 0, days, 0, 0, 0)));
396 }
397
398 void SearchAgent::monthsOldData(int months)
399 {
400         mEntity->add(PROPERTY__FRESHNESS, new Variant(new Duration(0, months, 0, 0, 0, 0)));
401 }
402
403 void SearchAgent::yearsOldData(int years)
404 {
405         mEntity->add(PROPERTY__FRESHNESS, new Variant(new Duration(years, 0, 0, 0, 0, 0)));
406 }
407
408 void SearchAgent::polygonSearchArea(QList<Coordinates*> polygon)
409 {
410         QList<Obj*> p;
411         QListIterator<Coordinates*> pi(polygon);
412         while (pi.hasNext()) {
413                 p.append(pi.next());
414         }
415         mEntity->add(PROPERTY__POLYGON, p);
416 }
417
418 void SearchAgent::multipolygonSearchArea(QList<QList<Coordinates*> > polygons)
419 {
420         for (int i = 0; i < polygons.length(); i++) {
421                 polygonSearchArea(polygons.at(i));
422         }
423 }
424
425 void SearchAgent::rectangleSearchArea(Coordinates* minCoordinates, Coordinates* maxCoordinates)
426 {
427         mEntity->add(PROPERTY__MINLOCATION, minCoordinates);
428         mEntity->add(PROPERTY__MAXLOCATION, maxCoordinates);
429 }
430
431 void SearchAgent::pointSearchArea(Coordinates* center, double kilometers)
432 {
433         Ring* ring = new Ring();
434         ring->setCoordinates(center);
435 //      ring->add(PROPERTY__LAT, center->getLatitude());
436 //      ring->add(PROPERTY__LONG, center->getLongitude());
437         ValueObject* maxR = new ValueObject();
438         maxR->setQuantity(RESOURCE__LENGTH);
439         maxR->setUnit(RESOURCE__KILOMETER);
440         maxR->setValue(kilometers);
441         ring->setMaxRadius(maxR);
442         mEntity->add(PROPERTY__RING, ring);
443 }
444
445 void SearchAgent::ringSearchArea(Coordinates* center, double minRadius, double maxRadius)
446 {
447         Ring* ring = new Ring();
448         ring->add(PROPERTY__LAT, center->getLatitude());
449         ring->add(PROPERTY__LONG, center->getLongitude());
450         ValueObject* minR = new ValueObject();
451         minR->setQuantity(RESOURCE__LENGTH);
452         minR->setUnit(RESOURCE__KILOMETER);
453         minR->setValue(minRadius);
454         ring->setMinRadius(minR);
455         ValueObject* maxR = new ValueObject();
456         maxR->setQuantity(RESOURCE__LENGTH);
457         maxR->setUnit(RESOURCE__KILOMETER);
458         maxR->setValue(maxRadius);
459         ring->setMaxRadius(maxR);
460         mEntity->add(PROPERTY__RING, ring);
461 }
462
463 void SearchAgent::onItemsFound(int callId, QVariant replyContentType, QByteArray replyData, QVariant userData)
464 {
465         AsyncData h = qvariant_cast<AsyncData>(userData);
466         if (h.caller != NULL && h.onSuccess != NULL) {
467                 Response* response = dynamic_cast<Response*>(Tools::fromStringAsObj(QString(replyData), replyContentType.toString()));
468                 if (response && response->hasActivity()) {
469                         Activity* a = response->firstActivity();
470                         QList<Entity*> el = a->getEntities().toQList();
471                         a->unlinkEntities();
472                         response->destroyCascade();
473                         QMetaObject::invokeMethod(h.caller, h.onSuccess, Qt::DirectConnection, Q_ARG(int, h.callId), Q_ARG(QList<Entity*>, el), Q_ARG(QVariant, h.callbackData));
474                 } else {
475                         QMetaObject::invokeMethod(h.caller, h.onFail, Qt::DirectConnection, Q_ARG(int, h.callId), Q_ARG(int, 0), Q_ARG(QVariant, h.callbackData));
476                 }
477         }
478 }
479
480 void SearchAgent::onItemSearchFailed(int callId, int errorCode, QVariant userData)
481 {
482         AsyncData h = qvariant_cast<AsyncData>(userData);
483         if (h.caller != NULL && h.onFail != NULL) {
484                 QMetaObject::invokeMethod(h.caller, h.onFail, Qt::DirectConnection, Q_ARG(int, h.callId), Q_ARG(int, errorCode), Q_ARG(QVariant, h.callbackData));
485         }
486 }
487
488 void SearchAgent::onHasChangedResult(int callId, QVariant replyContentType, QByteArray replyData, QVariant userData)
489 {
490         AsyncData h = qvariant_cast<AsyncData>(userData);
491         if (h.caller != NULL && h.onSuccess != NULL) {
492                 Response* response = dynamic_cast<Response*>(Tools::fromStringAsObj(QString(replyData), replyContentType.toString()));
493                 if (response) {
494                         if (response->hasActivity()) {
495                                 Activity* a = response->firstActivity();
496                                 if (a->hasEntity()) {
497                                         QList<Entity*> el = a->getEntities().toQList();
498                                         if (el.length() == 1) {
499                                                 bool result = !el.at(0)->getCheckResult();
500                                                 QMetaObject::invokeMethod(h.caller, h.onSuccess, Qt::DirectConnection, Q_ARG(int, h.callId), Q_ARG(bool, result), Q_ARG(QVariant, h.callbackData));
501                                         } else {
502                                                 qDebug() << "SmartAPI Find returned wrong number of entities for Ask request. One expected.";
503                                                 QMetaObject::invokeMethod(h.caller, h.onFail, Qt::DirectConnection, Q_ARG(int, h.callId), Q_ARG(int, 1), Q_ARG(QVariant, h.callbackData));
504                                         }
505                                 } else {
506                                         qDebug() << "SmartAPI Find returned  null for a list of result entities for Ask request.";
507                                         QMetaObject::invokeMethod(h.caller, h.onFail, Qt::DirectConnection, Q_ARG(int, h.callId), Q_ARG(int, 2), Q_ARG(QVariant, h.callbackData));
508                                 }
509                         } else {
510                                 qDebug() << "SmartAPI Find returned  a result with no Activities.";
511                                 QMetaObject::invokeMethod(h.caller, h.onFail, Qt::DirectConnection, Q_ARG(int, h.callId), Q_ARG(int, 3), Q_ARG(QVariant, h.callbackData));
512                         }
513                         response->destroyCascade();
514                 } else {
515                         QMetaObject::invokeMethod(h.caller, h.onFail, Qt::DirectConnection, Q_ARG(int, h.callId), Q_ARG(int, 0), Q_ARG(QVariant, h.callbackData));
516                 }
517         }
518 }
519