PageRenderTime 55ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/tests/RDFTest.cpp

https://bitbucket.org/metatoaster/cellml-api
C++ | 1365 lines | 1114 code | 151 blank | 100 comment | 223 complexity | fc0401c246a28d7b7d60222c25eb339f MD5 | raw file
Possible License(s): LGPL-2.1, BSD-3-Clause, GPL-2.0
  1. #define __STDC_FORMAT_MACROS
  2. #include "RDFTest.hpp"
  3. #include "DOMBootstrap.hxx"
  4. #include "CellMLBootstrap.hpp"
  5. #include "RDFBootstrap.hpp"
  6. #include "Utilities.hxx"
  7. #include <fstream>
  8. #include <iostream>
  9. #ifdef HAVE_INTTYPES_H
  10. #include <inttypes.h>
  11. #endif
  12. #ifndef PRIxPTR
  13. #define PRIxPTR "x"
  14. #endif
  15. #include "cda_config.h"
  16. #ifndef BASE_DIRECTORY_NTRIP
  17. #define BASE_DIRECTORY_NTRIP TESTDIR8 "/test_rdf/"
  18. #endif
  19. #ifndef BASE_URI
  20. #ifdef WIN32
  21. #define BASE_URI L"file:///" TESTDIR L"/test_rdf/"
  22. #else
  23. #define BASE_URI L"file://" TESTDIR L"/test_rdf/"
  24. #endif
  25. #endif
  26. #ifndef BASE_DIRECTORY_CELLML
  27. #ifdef WIN32
  28. #define BASE_DIRECTORY_CELLML L"file:///" TESTDIR L"/test_xml/"
  29. #else
  30. #define BASE_DIRECTORY_CELLML L"file://" TESTDIR L"/test_xml/"
  31. #endif
  32. #endif
  33. #ifdef _WIN32
  34. #ifndef swprintf
  35. #define swprintf _snwprintf
  36. #endif
  37. #endif
  38. CPPUNIT_TEST_SUITE_REGISTRATION( RDFTest );
  39. void
  40. RDFTest::setUp()
  41. {
  42. }
  43. void
  44. RDFTest::tearDown()
  45. {
  46. }
  47. static char*
  48. CDA_wchar_to_UTF8(const wchar_t *str)
  49. {
  50. uint32_t len = 0;
  51. const wchar_t* p = str;
  52. wchar_t c;
  53. for (; (c = *p); p++)
  54. {
  55. if (c <= 0x7F)
  56. len++;
  57. else if (c <= 0x7FF)
  58. len += 2;
  59. #ifndef WCHAR_T_CONSTANT_WIDTH
  60. else if ((c & 0xFC00) == 0xD800)
  61. len += 4;
  62. #endif
  63. else
  64. #if defined(WCHAR_T_CONSTANT_WIDTH) && defined(WCHAR_T_IS_32BIT)
  65. if (c <= 0xFFFF)
  66. #endif
  67. len += 3;
  68. #if defined(WCHAR_T_CONSTANT_WIDTH) && defined(WCHAR_T_IS_32BIT)
  69. else
  70. len += 4;
  71. #endif
  72. }
  73. char* newData = (char*)malloc(len + 1);
  74. char* np = newData;
  75. p = str;
  76. while ((c = *p++))
  77. {
  78. if (c <= 0x7F)
  79. *np++ = (char)c;
  80. else if (c <= 0x7FF)
  81. {
  82. *np++ = (char)(0xC0 | ((c >> 6) & 0x1F));
  83. *np++ = (char)(0x80 | (c & 0x3F));
  84. }
  85. #ifndef WCHAR_T_CONSTANT_WIDTH
  86. else if ((c & 0xFC00) == 0xD800)
  87. {
  88. uint16_t u = ((c >> 6) & 0xF) + 1;
  89. *np++ = 0xF0 | ((u >> 2) & 0x7);
  90. *np++ = 0x80 | ((u << 4) & 0x30) | ((c >> 2) & 0xF);
  91. wchar_t c2 = *p++;
  92. *np++ = 0x80 | ((c << 4) & 0x30) | ((c2 >> 6) & 0xF);
  93. *np++ = 0x80 | (c2 & 0x3F);
  94. }
  95. #endif
  96. else
  97. #if defined(WCHAR_T_CONSTANT_WIDTH) && defined(WCHAR_T_IS_32BIT)
  98. if (c <= 0xFFFF)
  99. #endif
  100. {
  101. *np++ = (char)(0xE0 | ((c >> 12) & 0xF));
  102. *np++ = (char)(0x80 | ((c >> 6) & 0x3F));
  103. *np++ = (char)(0x80 | (c & 0x3F));
  104. }
  105. #if defined(WCHAR_T_CONSTANT_WIDTH) && defined(WCHAR_T_IS_32BIT)
  106. else
  107. {
  108. *np++ = (char)(0xF0 | ((c >> 18) & 0x7));
  109. *np++ = (char)(0x80 | ((c >> 12) & 0x3F));
  110. *np++ = (char)(0x80 | ((c >> 6) & 0x3F));
  111. *np++ = (char)(0x80 | (c & 0x3F));
  112. }
  113. #endif
  114. }
  115. *np++ = 0;
  116. return newData;
  117. }
  118. std::ostream&
  119. operator<<(std::ostream& aStream, iface::rdf_api::Node* aNode)
  120. {
  121. DECLARE_QUERY_INTERFACE_OBJREF(res, aNode, rdf_api::Resource);
  122. if (res != NULL)
  123. {
  124. DECLARE_QUERY_INTERFACE_OBJREF(ur, aNode, rdf_api::URIReference);
  125. if (ur != NULL)
  126. {
  127. RETURN_INTO_WSTRING(uri, ur->URI());
  128. char* t = CDA_wchar_to_UTF8(uri.c_str());
  129. aStream << "<" << t << ">";
  130. free(t);
  131. }
  132. else
  133. {
  134. aStream << "<blanknode>";
  135. }
  136. }
  137. else
  138. {
  139. DECLARE_QUERY_INTERFACE_OBJREF(pl, aNode, rdf_api::PlainLiteral);
  140. if (pl != NULL)
  141. {
  142. RETURN_INTO_WSTRING(lf, pl->lexicalForm());
  143. RETURN_INTO_WSTRING(lang, pl->language());
  144. char* lft = CDA_wchar_to_UTF8(lf.c_str());
  145. char* langt = CDA_wchar_to_UTF8(lang.c_str());
  146. aStream << "\"" << lft << "\"@" << langt;
  147. free(lft);
  148. free(langt);
  149. }
  150. else
  151. {
  152. DECLARE_QUERY_INTERFACE_OBJREF(tl, aNode, rdf_api::TypedLiteral);
  153. RETURN_INTO_WSTRING(lf, tl->lexicalForm());
  154. RETURN_INTO_WSTRING(dt, tl->datatypeURI());
  155. char* lft = CDA_wchar_to_UTF8(lf.c_str());
  156. char* dtt = CDA_wchar_to_UTF8(dt.c_str());
  157. aStream << "\"" << lft << "\"^^<" << dtt << ">";
  158. free(lft);
  159. free(dtt);
  160. }
  161. }
  162. return aStream;
  163. }
  164. template<class T>
  165. class ContainerReleaser
  166. {
  167. public:
  168. ContainerReleaser(T& aContainer)
  169. : mContainer(aContainer)
  170. {
  171. }
  172. ~ContainerReleaser()
  173. {
  174. for (iterator i = mContainer.begin(); i != mContainer.end(); i++)
  175. (*i)->release_ref();
  176. }
  177. private:
  178. T& mContainer;
  179. typedef typename T::iterator iterator;
  180. };
  181. class NTripleFile
  182. {
  183. public:
  184. NTripleFile(iface::rdf_api::Bootstrap* aBS, const std::string& testId,
  185. uint32_t aTestNo)
  186. : mTestNo(aTestNo)
  187. {
  188. std::string path(BASE_DIRECTORY_NTRIP);
  189. path += testId;
  190. path += ".nt";
  191. std::ifstream f(path.c_str());
  192. mDataSource = already_AddRefd<iface::rdf_api::DataSource>
  193. (aBS->createDataSource());
  194. while (f.good())
  195. {
  196. std::string l;
  197. std::getline(f, l);
  198. if (l[0] == '#')
  199. continue;
  200. std::string ws(" \t\r\n");
  201. std::string::iterator i;
  202. for (i = l.begin(); i != l.end(); i++)
  203. if (ws.find(*i) == std::string::npos)
  204. break;
  205. if (i == l.end())
  206. continue;
  207. ObjRef<iface::rdf_api::Node> subject, predicate, object;
  208. iface::rdf_api::Node* n;
  209. l = parsePart(l, &n);
  210. subject = already_AddRefd<iface::rdf_api::Node>(n);
  211. DECLARE_QUERY_INTERFACE_OBJREF(subjectr, subject, rdf_api::Resource);
  212. if (subjectr == NULL)
  213. {
  214. std::cout << "Invalid subject in ntriples." << std::endl;
  215. continue;
  216. }
  217. l = parsePart(l, &n);
  218. predicate = already_AddRefd<iface::rdf_api::Node>(n);
  219. DECLARE_QUERY_INTERFACE_OBJREF(predicater, predicate, rdf_api::Resource);
  220. if (predicater == NULL)
  221. {
  222. std::cout << "Invalid predicate in ntriples." << std::endl;
  223. continue;
  224. }
  225. parsePart(l, &n);
  226. object = already_AddRefd<iface::rdf_api::Node>(n);
  227. if (object == NULL)
  228. {
  229. std::cout << "Invalid object in ntriples." << std::endl;
  230. continue;
  231. }
  232. subjectr->createTripleOutOf(predicater, object);
  233. }
  234. }
  235. ~NTripleFile()
  236. {
  237. for (std::map<std::string, iface::rdf_api::BlankNode*>::iterator i =
  238. mNTripleBlankNodeByName.begin();
  239. i != mNTripleBlankNodeByName.end();
  240. i++)
  241. (*i).second->release_ref();
  242. }
  243. void
  244. compareTriples(iface::rdf_api::DataSource* aDataSource)
  245. {
  246. // std::cout << "Entering compareTriples" << std::endl;
  247. mErrorCount = 0;
  248. // We go through every triple in aDataSource, and compare it with
  249. // mDataSource. We deleted from mDataSource as we go, so anything left
  250. // over at the end is missing from aDataSource...
  251. {
  252. std::list<iface::rdf_api::Triple*> ambigs;
  253. ContainerReleaser<std::list<iface::rdf_api::Triple*> > ct(ambigs);
  254. RETURN_INTO_OBJREF(ts, iface::rdf_api::TripleSet, aDataSource->getAllTriples());
  255. RETURN_INTO_OBJREF(te, iface::rdf_api::TripleEnumerator, ts->enumerateTriples());
  256. while (true)
  257. {
  258. RETURN_INTO_OBJREF(t, iface::rdf_api::Triple, te->getNextTriple());
  259. if (t == NULL)
  260. break;
  261. if (checkTriple(t, false))
  262. {
  263. t->add_ref();
  264. ambigs.push_back(t);
  265. }
  266. }
  267. for (
  268. std::list<iface::rdf_api::Triple*>::iterator i = ambigs.begin();
  269. i != ambigs.end();
  270. i++
  271. )
  272. {
  273. checkTriple(*i, true);
  274. }
  275. }
  276. // Now, any triples left over in mDataSource are missing from the RDF/XML
  277. // parse...
  278. {
  279. RETURN_INTO_OBJREF(ts, iface::rdf_api::TripleSet, mDataSource->getAllTriples());
  280. RETURN_INTO_OBJREF(te, iface::rdf_api::TripleEnumerator, ts->enumerateTriples());
  281. while (true)
  282. {
  283. RETURN_INTO_OBJREF(t, iface::rdf_api::Triple, te->getNextTriple());
  284. if (t == NULL)
  285. break;
  286. RETURN_INTO_OBJREF(s, iface::rdf_api::Node, t->subject());
  287. RETURN_INTO_OBJREF(p, iface::rdf_api::Node, t->predicate());
  288. RETURN_INTO_OBJREF(o, iface::rdf_api::Node, t->object());
  289. std::cerr << "RDF/XML Test " << mTestNo
  290. << ": Triple missing from RDF/XML parse results: "
  291. << s << " " << p << " " << o << " ." << std::endl;
  292. mErrorCount++;
  293. }
  294. }
  295. for (std::map<std::string, iface::rdf_api::BlankNode*>::iterator i =
  296. mNTripleBlankNodeByXMLBlankNode.begin();
  297. i != mNTripleBlankNodeByXMLBlankNode.end();
  298. i++)
  299. (*i).second->release_ref();
  300. for (std::map<std::string, iface::rdf_api::BlankNode*>::iterator i =
  301. mXMLBlankNodeByNTripleBlankNode.begin();
  302. i != mXMLBlankNodeByNTripleBlankNode.end();
  303. i++)
  304. (*i).second->release_ref();
  305. CPPUNIT_ASSERT_EQUAL(0, mErrorCount);
  306. }
  307. private:
  308. std::string
  309. parsePart(const std::string& aStr, iface::rdf_api::Node** aNode)
  310. {
  311. *aNode = NULL;
  312. if (aStr[0] == '<')
  313. {
  314. uint32_t eos = aStr.find('>');
  315. if (eos == std::string::npos)
  316. {
  317. std::cout << "Unterminated URI reference" << std::endl;
  318. return "";
  319. }
  320. std::wstring URI = unescape(aStr.substr(1, eos - 1));
  321. *aNode = mDataSource->getURIReference(URI.c_str());
  322. eos++;
  323. while (aStr[eos] == ' ' || aStr[eos] == '\t')
  324. eos++;
  325. return aStr.substr(eos);
  326. }
  327. else if (aStr[0] == '_')
  328. {
  329. if (aStr[1] != ':')
  330. {
  331. std::cout << "Malformed blank node specification." << std::endl;
  332. return "";
  333. }
  334. size_t pos = aStr.find_first_of(" \t", 2);
  335. std::string name, rem;
  336. if (pos == std::string::npos)
  337. {
  338. name = aStr.substr(2);
  339. rem = "";
  340. }
  341. else
  342. {
  343. name = aStr.substr(2, pos - 2);
  344. while (aStr[pos] == ' ' || aStr[pos] == '\t')
  345. pos++;
  346. rem = aStr.substr(pos);
  347. }
  348. *aNode = findOrCreateBlankNode(name);
  349. return rem;
  350. }
  351. else if (aStr[0] == '"')
  352. {
  353. size_t pos = 0;
  354. while (true)
  355. {
  356. pos = aStr.find('"', pos + 1);
  357. if (pos == std::string::npos)
  358. {
  359. std::cout << "Unterminated string in " << aStr << std::endl;
  360. return "";
  361. }
  362. // This isn't strictly correct, but it gets us through the tests...
  363. if (aStr[pos - 1] != '\\')
  364. break;
  365. }
  366. std::wstring raw = unescape(aStr.substr(1, pos - 1));
  367. pos++;
  368. if (aStr[pos] == '^')
  369. {
  370. pos++;
  371. if (aStr[pos] != '^')
  372. {
  373. std::cout << "Malformed typed literal." << std::endl;
  374. return "";
  375. }
  376. pos++;
  377. if (aStr[pos] != '<')
  378. {
  379. std::cout << "Expected data type after typed literal marker." << std::endl;
  380. return "";
  381. }
  382. pos++;
  383. uint32_t eos = aStr.find('>', pos);
  384. if (eos == std::string::npos)
  385. {
  386. std::cout << "Unterminated typed literal datatype." << std::endl;
  387. return "";
  388. }
  389. std::wstring URI = unescape(aStr.substr(pos, eos - pos));
  390. *aNode = mDataSource->getTypedLiteral(raw.c_str(), URI.c_str());
  391. eos++;
  392. while (aStr[eos] == ' ' || aStr[eos] == '\t')
  393. eos++;
  394. return aStr.substr(eos);
  395. }
  396. std::wstring language = L"en";
  397. if (aStr[pos] == '@')
  398. {
  399. pos++;
  400. size_t end = aStr.find_first_of(" \t");
  401. if (end == std::string::npos)
  402. {
  403. language = unescape(aStr.substr(pos));
  404. pos = aStr.length();
  405. }
  406. else
  407. {
  408. language = unescape(aStr.substr(pos, end - pos));
  409. pos = end;
  410. }
  411. }
  412. *aNode = mDataSource->getPlainLiteral(raw.c_str(), language.c_str());
  413. while (aStr[pos] == ' ' || aStr[pos] == '\t')
  414. pos++;
  415. return aStr.substr(pos);
  416. }
  417. std::cout << "Unexpected start of string: " << aStr[0] << std::endl;
  418. return "";
  419. }
  420. iface::rdf_api::BlankNode*
  421. findOrCreateBlankNode(const std::string& aName)
  422. {
  423. std::map<std::string, iface::rdf_api::BlankNode*>::iterator i =
  424. mNTripleBlankNodeByName.find(aName);
  425. if (i != mNTripleBlankNodeByName.end())
  426. {
  427. (*i).second->add_ref();
  428. return (*i).second;
  429. }
  430. iface::rdf_api::BlankNode* n = mDataSource->createBlankNode();
  431. mNTripleBlankNodeByName.insert(std::pair<std::string, iface::rdf_api::BlankNode*>
  432. (aName, n));
  433. n->add_ref();
  434. return n;
  435. }
  436. std::wstring
  437. unescape(const std::string& aEscaped)
  438. {
  439. std::wstring output;
  440. for (std::string::const_iterator i = aEscaped.begin();
  441. i != aEscaped.end();
  442. i++)
  443. if (*i != '\\')
  444. output += *i;
  445. else
  446. {
  447. i++;
  448. if (i == aEscaped.end())
  449. break;
  450. if (*i == '\\')
  451. output += L'\\';
  452. else if (*i == 't')
  453. output += L'\t';
  454. else if (*i == 'r')
  455. output += L'\r';
  456. else if (*i == 'n')
  457. output += L'\n';
  458. else if (*i == '"')
  459. output += L'"';
  460. else if (*i == 'u')
  461. {
  462. if ((aEscaped.end() - i) < 4)
  463. break;
  464. char buf[5];
  465. buf[0] = *i++;
  466. buf[1] = *i++;
  467. buf[2] = *i++;
  468. buf[3] = *i++;
  469. buf[4] = 0;
  470. output += (wchar_t)strtoul(buf, NULL, 16);
  471. }
  472. else if (*i == 'U')
  473. {
  474. if ((aEscaped.end() - i) < 8)
  475. break;
  476. char buf[9];
  477. buf[0] = *i++;
  478. buf[1] = *i++;
  479. buf[2] = *i++;
  480. buf[3] = *i++;
  481. buf[4] = *i++;
  482. buf[5] = *i++;
  483. buf[6] = *i++;
  484. buf[7] = *i++;
  485. buf[8] = 0;
  486. output += (wchar_t)strtoul(buf, NULL, 16);
  487. }
  488. }
  489. return output;
  490. }
  491. bool
  492. checkTriple(iface::rdf_api::Triple* aTriple, bool allowAmbiguous)
  493. {
  494. RETURN_INTO_OBJREF(xmlSubj, iface::rdf_api::Resource, aTriple->subject());
  495. RETURN_INTO_OBJREF(xmlPredicate, iface::rdf_api::Resource, aTriple->predicate());
  496. RETURN_INTO_OBJREF(xmlObject, iface::rdf_api::Node, aTriple->object());
  497. ObjRef<iface::rdf_api::Resource> ntSubj, ntPredicate;
  498. ObjRef<iface::rdf_api::Node> ntObject;
  499. DECLARE_QUERY_INTERFACE_OBJREF(xmlSubjURI, xmlSubj, rdf_api::URIReference);
  500. if (xmlSubjURI != NULL)
  501. {
  502. RETURN_INTO_WSTRING(uri, xmlSubjURI->URI());
  503. ntSubj = already_AddRefd<iface::rdf_api::Resource>
  504. (mDataSource->getURIReference(uri.c_str()));
  505. }
  506. else
  507. {
  508. char* objid = xmlSubj->objid();
  509. std::map<std::string, iface::rdf_api::BlankNode*>::iterator i =
  510. mNTripleBlankNodeByXMLBlankNode.find(objid);
  511. free(objid);
  512. if (i != mNTripleBlankNodeByXMLBlankNode.end())
  513. ntSubj = (*i).second;
  514. }
  515. DECLARE_QUERY_INTERFACE_OBJREF(xmlPredURI, xmlPredicate, rdf_api::URIReference);
  516. if (xmlPredURI != NULL)
  517. {
  518. RETURN_INTO_WSTRING(uri, xmlPredURI->URI());
  519. ntPredicate = already_AddRefd<iface::rdf_api::Resource>
  520. (mDataSource->getURIReference(uri.c_str()));
  521. }
  522. else
  523. {
  524. char* objid = xmlPredicate->objid();
  525. std::map<std::string, iface::rdf_api::BlankNode*>::iterator i =
  526. mNTripleBlankNodeByXMLBlankNode.find(objid);
  527. free(objid);
  528. if (i != mNTripleBlankNodeByXMLBlankNode.end())
  529. ntPredicate = (*i).second;
  530. }
  531. DECLARE_QUERY_INTERFACE_OBJREF(xmlObjURI, xmlObject, rdf_api::URIReference);
  532. if (xmlObjURI != NULL)
  533. {
  534. RETURN_INTO_WSTRING(uri, xmlObjURI->URI());
  535. ntObject = already_AddRefd<iface::rdf_api::Resource>
  536. (mDataSource->getURIReference(uri.c_str()));
  537. }
  538. else
  539. {
  540. DECLARE_QUERY_INTERFACE_OBJREF(xmlObjPL, xmlObject, rdf_api::PlainLiteral);
  541. if (xmlObjPL != NULL)
  542. {
  543. RETURN_INTO_WSTRING(form, xmlObjPL->lexicalForm());
  544. RETURN_INTO_WSTRING(lang, xmlObjPL->language());
  545. ntObject = already_AddRefd<iface::rdf_api::Node>
  546. (mDataSource->getPlainLiteral(form.c_str(), lang.c_str()));
  547. }
  548. else
  549. {
  550. DECLARE_QUERY_INTERFACE_OBJREF(xmlObjTL, xmlObject, rdf_api::TypedLiteral);
  551. if (xmlObjTL != NULL)
  552. {
  553. RETURN_INTO_WSTRING(form, xmlObjTL->lexicalForm());
  554. RETURN_INTO_WSTRING(type, xmlObjTL->datatypeURI());
  555. ntObject = already_AddRefd<iface::rdf_api::Node>
  556. (mDataSource->getTypedLiteral(form.c_str(), type.c_str()));
  557. }
  558. else
  559. {
  560. char* objid = xmlObject->objid();
  561. std::map<std::string, iface::rdf_api::BlankNode*>::iterator i =
  562. mNTripleBlankNodeByXMLBlankNode.find(objid);
  563. free(objid);
  564. if (i != mNTripleBlankNodeByXMLBlankNode.end())
  565. ntObject = (*i).second;
  566. }
  567. }
  568. }
  569. return checkAndEraseTriple(ntSubj, ntPredicate, ntObject, xmlSubj,
  570. xmlPredicate, xmlObject, allowAmbiguous);
  571. }
  572. bool
  573. checkAndEraseTriple(
  574. iface::rdf_api::Resource* ntSubj,
  575. iface::rdf_api::Resource* ntPredicate,
  576. iface::rdf_api::Node* ntObject,
  577. iface::rdf_api::Resource* xmlSubj,
  578. iface::rdf_api::Resource* xmlPredicate,
  579. iface::rdf_api::Node* xmlObject,
  580. bool allowAmbiguous
  581. )
  582. {
  583. std::vector<iface::rdf_api::Triple*> matches;
  584. ContainerReleaser<std::vector<iface::rdf_api::Triple*> > ct(matches);
  585. // Enumerate all triples...
  586. RETURN_INTO_OBJREF(ts, iface::rdf_api::TripleSet, mDataSource->getAllTriples());
  587. RETURN_INTO_OBJREF(te, iface::rdf_api::TripleEnumerator, ts->enumerateTriples());
  588. while (true)
  589. {
  590. RETURN_INTO_OBJREF(t, iface::rdf_api::Triple, te->getNextTriple());
  591. if (t == NULL)
  592. break;
  593. // std::cout << "Triple for comparison" << std::endl;
  594. RETURN_INTO_OBJREF(tripleSubj, iface::rdf_api::Resource, t->subject());
  595. if (ntSubj)
  596. {
  597. if (CDA_objcmp(ntSubj, tripleSubj))
  598. {
  599. // std::cout << "Subject mismatch." << std::endl;
  600. continue;
  601. }
  602. }
  603. else
  604. {
  605. DECLARE_QUERY_INTERFACE_OBJREF(blank, tripleSubj, rdf_api::BlankNode);
  606. if (blank == NULL)
  607. continue;
  608. char* objid = blank->objid();
  609. bool known = (mXMLBlankNodeByNTripleBlankNode.find(objid) !=
  610. mXMLBlankNodeByNTripleBlankNode.end());
  611. free(objid);
  612. if (known)
  613. continue;
  614. }
  615. RETURN_INTO_OBJREF(triplePredicate, iface::rdf_api::Resource, t->predicate());
  616. if (ntPredicate)
  617. {
  618. if (CDA_objcmp(ntPredicate, triplePredicate))
  619. {
  620. // std::cout << "Predicate mismatch." << std::endl;
  621. continue;
  622. }
  623. }
  624. else
  625. {
  626. DECLARE_QUERY_INTERFACE_OBJREF(blank, triplePredicate,
  627. rdf_api::BlankNode);
  628. if (blank == NULL)
  629. continue;
  630. char* objid = blank->objid();
  631. bool known = (mXMLBlankNodeByNTripleBlankNode.find(objid) !=
  632. mXMLBlankNodeByNTripleBlankNode.end());
  633. free(objid);
  634. if (known)
  635. continue;
  636. }
  637. RETURN_INTO_OBJREF(tripleObject, iface::rdf_api::Node, t->object());
  638. if (ntObject)
  639. {
  640. if (CDA_objcmp(ntObject, tripleObject))
  641. {
  642. // std::cout << "Objects known and different." << std::endl;
  643. continue;
  644. }
  645. }
  646. else
  647. {
  648. DECLARE_QUERY_INTERFACE_OBJREF(blank, tripleObject,
  649. rdf_api::BlankNode);
  650. if (blank == NULL)
  651. {
  652. // std::cout << "Object QI to blank node failed." << std::endl;
  653. continue;
  654. }
  655. char* objid = blank->objid();
  656. bool known = (mXMLBlankNodeByNTripleBlankNode.find(objid) !=
  657. mXMLBlankNodeByNTripleBlankNode.end());
  658. free(objid);
  659. if (known)
  660. {
  661. // std::cout << "Object blank node already known." << std::endl;
  662. continue;
  663. }
  664. }
  665. // std::cout << "Performing blank equality tests..." << std::endl;
  666. // We have a plausible match so far, but we also need to check that
  667. // previously unseen blank nodes are the same if and only if they are the
  668. // same in the RDF/XML we are comparing with...
  669. if (!ntSubj && !ntPredicate)
  670. {
  671. if ((CDA_objcmp(xmlSubj, xmlPredicate) != 0) !=
  672. (CDA_objcmp(tripleSubj, triplePredicate) != 0))
  673. continue;
  674. }
  675. if (!ntSubj && !ntObject)
  676. {
  677. if ((CDA_objcmp(xmlSubj, xmlObject) != 0) !=
  678. (CDA_objcmp(tripleSubj, tripleObject) != 0))
  679. continue;
  680. }
  681. if (!ntPredicate && !ntObject)
  682. {
  683. if ((CDA_objcmp(xmlPredicate, xmlObject) != 0) !=
  684. (CDA_objcmp(triplePredicate, tripleObject) != 0))
  685. continue;
  686. }
  687. // If we get here, we have a match. But it might not be unique...
  688. t->add_ref();
  689. matches.push_back(t);
  690. }
  691. if (matches.size() == 0)
  692. {
  693. mErrorCount++;
  694. std::cerr << "RDF/XML Test " << mTestNo
  695. << ": Extraneous triple in XML parse results: ";
  696. if (ntSubj)
  697. std::cerr << ntSubj << " ";
  698. else
  699. std::cerr << "<blank> ";
  700. if (ntPredicate)
  701. std::cerr << ntPredicate << " ";
  702. else
  703. std::cerr << "<blank> ";
  704. if (ntObject)
  705. std::cerr << ntObject << " ." << std::endl;
  706. else
  707. std::cerr << "<blank> ." << std::endl;
  708. return false;
  709. }
  710. if (matches.size() > 1 && !allowAmbiguous)
  711. return true;
  712. iface::rdf_api::Triple* t = matches[0];
  713. RETURN_INTO_OBJREF(tripleSubj, iface::rdf_api::Resource, t->subject());
  714. RETURN_INTO_OBJREF(triplePredicate, iface::rdf_api::Resource, t->predicate());
  715. RETURN_INTO_OBJREF(tripleObject, iface::rdf_api::Node, t->object());
  716. // Save any blank node matches...
  717. iface::rdf_api::Node* tripleNodes[] = {tripleSubj, triplePredicate, tripleObject};
  718. iface::rdf_api::Node* xmlNodes[] = {xmlSubj, xmlPredicate, xmlObject};
  719. iface::rdf_api::Node* ntNodes[] = {ntSubj, ntPredicate, ntObject};
  720. for (uint32_t i = 0; i < 3; i++)
  721. {
  722. if (!ntNodes[i])
  723. {
  724. DECLARE_QUERY_INTERFACE_OBJREF(tripleBN, tripleNodes[i], rdf_api::BlankNode);
  725. DECLARE_QUERY_INTERFACE_OBJREF(xmlBN, xmlNodes[i], rdf_api::BlankNode);
  726. char* objid = xmlBN->objid();
  727. bool done = true;
  728. if (
  729. mNTripleBlankNodeByXMLBlankNode.find(objid) ==
  730. mNTripleBlankNodeByXMLBlankNode.end()
  731. )
  732. {
  733. done = false;
  734. mNTripleBlankNodeByXMLBlankNode.insert
  735. (std::pair<std::string, iface::rdf_api::BlankNode*>(objid, tripleBN));
  736. tripleBN->add_ref();
  737. }
  738. free(objid);
  739. if (!done)
  740. {
  741. objid = tripleBN->objid();
  742. mXMLBlankNodeByNTripleBlankNode.insert
  743. (std::pair<std::string, iface::rdf_api::BlankNode*>(objid, xmlBN));
  744. xmlBN->add_ref();
  745. free(objid);
  746. }
  747. }
  748. }
  749. // Now we delete the triple...
  750. t->unassert();
  751. return false;
  752. }
  753. ObjRef<iface::rdf_api::DataSource> mDataSource;
  754. std::map<std::string, iface::rdf_api::BlankNode*> mNTripleBlankNodeByName;
  755. std::map<std::string, iface::rdf_api::BlankNode*> mNTripleBlankNodeByXMLBlankNode;
  756. std::map<std::string, iface::rdf_api::BlankNode*> mXMLBlankNodeByNTripleBlankNode;
  757. uint32_t mTestNo;
  758. int32_t mErrorCount;
  759. };
  760. void
  761. RDFTest::testW3CSuite()
  762. {
  763. RETURN_INTO_OBJREF(bs, iface::rdf_api::Bootstrap, CreateRDFBootstrap());
  764. RETURN_INTO_OBJREF(cdibs, CellML_DOMImplementationBase, CreateDOMImplementation());
  765. std::map<uint32_t, const wchar_t*> baseURIOverrides;
  766. #define BASE_URI_OVERRIDE(n, uri) baseURIOverrides.insert(std::pair<uint32_t, const wchar_t*>(n, uri));
  767. BASE_URI_OVERRIDE(20, L"http://www.w3.org/2000/10/rdf-tests/rdfcore/rdf-containers-syntax-vs-schema/test004.rdf");
  768. BASE_URI_OVERRIDE(21, L"http://www.w3.org/2000/10/rdf-tests/rdfcore/rdf-containers-syntax-vs-schema/test006.rdf");
  769. BASE_URI_OVERRIDE(67, L"http://www.w3.org/2000/10/rdf-tests/rdfcore/rdfms-syntax-incomplete/test004.rdf");
  770. BASE_URI_OVERRIDE(69, L"http://www.w3.org/2000/10/rdf-tests/rdfcore/rdfms-not-id-and-resource-attr/test001.rdf");
  771. BASE_URI_OVERRIDE(71, L"http://www.w3.org/2000/10/rdf-tests/rdfcore/rdfms-not-id-and-resource-attr/test004.rdf");
  772. BASE_URI_OVERRIDE(72, L"http://www.w3.org/2000/10/rdf-tests/rdfcore/rdfms-not-id-and-resource-attr/test005.rdf");
  773. BASE_URI_OVERRIDE(75, L"http://www.w3.org/2000/10/rdf-tests/rdfcore/rdf-ns-prefix-confusion/test0004.rdf");
  774. BASE_URI_OVERRIDE(80, L"http://www.w3.org/2000/10/rdf-tests/rdfcore/rdf-ns-prefix-confusion/test0011.rdf");
  775. BASE_URI_OVERRIDE(81, L"http://www.w3.org/2000/10/rdf-tests/rdfcore/rdf-ns-prefix-confusion/test0012.rdf");
  776. BASE_URI_OVERRIDE(82, L"http://www.w3.org/2000/10/rdf-tests/rdfcore/rdf-ns-prefix-confusion/test0013.rdf");
  777. BASE_URI_OVERRIDE(83, L"http://www.w3.org/2000/10/rdf-tests/rdfcore/rdf-ns-prefix-confusion/test0014.rdf");
  778. BASE_URI_OVERRIDE(85, L"http://www.w3.org/2000/10/rdf-tests/rdfcore/rdfs-no-cycles-in-subPropertyOf/test001");
  779. BASE_URI_OVERRIDE(90, L"http://www.w3.org/2000/10/rdf-tests/rdfcore/rdfms-empty-property-elements/test005.rdf");
  780. BASE_URI_OVERRIDE(91, L"http://www.w3.org/2000/10/rdf-tests/rdfcore/rdfms-empty-property-elements/test006.rdf");
  781. BASE_URI_OVERRIDE(96, L"http://www.w3.org/2000/10/rdf-tests/rdfcore/rdfms-empty-property-elements/test011.rdf");
  782. BASE_URI_OVERRIDE(97, L"http://www.w3.org/2000/10/rdf-tests/rdfcore/rdfms-empty-property-elements/test012.rdf");
  783. BASE_URI_OVERRIDE(108, L"http://www.w3.org/2000/10/rdf-tests/rdfcore/rdfms-difference-between-ID-and-about/test1.rdf");
  784. BASE_URI_OVERRIDE(109, L"http://www.w3.org/2000/10/rdf-tests/rdfcore/rdfms-difference-between-ID-and-about/test2.rdf");
  785. BASE_URI_OVERRIDE(110, L"http://www.w3.org/2000/10/rdf-tests/rdfcore/rdfms-difference-between-ID-and-about/test3.rdf");
  786. BASE_URI_OVERRIDE(112, L"http://www.w3.org/2000/10/rdf-tests/rdfcore/rdfms-xml-literal-namespaces/test001.rdf");
  787. BASE_URI_OVERRIDE(125, L"http://www.w3.org/2000/10/rdf-tests/rdfcore/xmlbase/test014.rdf");
  788. BASE_URI_OVERRIDE(128, L"http://www.w3.org/2000/10/rdf-tests/rdfcore/rdfs-no-cycles-in-subClassOf/test001");
  789. std::set<uint32_t> exclusions;
  790. #define DELIBERATE_EXCLUSION(x, reason) exclusions.insert(x);
  791. DELIBERATE_EXCLUSION(113, "Proper XC14N canonicalisation is not implemented yet because no one wants it.");
  792. DELIBERATE_EXCLUSION(126, "Proper XC14N canonicalisation is not implemented yet because no one wants it.");
  793. for (uint32_t i = 1; i < 131; i++)
  794. {
  795. if (exclusions.count(i) != 0)
  796. continue;
  797. char buf[30];
  798. sprintf(buf, "test%u", i);
  799. // Parse the triple file...
  800. NTripleFile ntf(bs, buf, i);
  801. std::wstring url(BASE_URI);
  802. wchar_t wbuf[30];
  803. swprintf(wbuf, 30, L"test%u.rdf", i);
  804. url += wbuf;
  805. std::wstring msg;
  806. RETURN_INTO_OBJREF(doc, iface::dom::Document, cdibs->loadDocument
  807. (url.c_str(), msg));
  808. RETURN_INTO_OBJREF(de, iface::dom::Element, doc->documentElement());
  809. RETURN_INTO_OBJREF(ds, iface::rdf_api::DataSource, bs->createDataSource());
  810. std::map<uint32_t, const wchar_t*>::iterator uo = baseURIOverrides.find(i);
  811. const wchar_t* uriStr = url.c_str();
  812. if (uo != baseURIOverrides.end())
  813. uriStr = (*uo).second;
  814. bs->parseIntoDataSource(ds, de, uriStr);
  815. // Now, we are going to convert it back to a DOM representation...
  816. RETURN_INTO_OBJREF(doc2, iface::dom::Document, bs->getDOMForDataSource(ds, uriStr));
  817. // And parse it again...
  818. RETURN_INTO_OBJREF(de2, iface::dom::Element, doc2->documentElement());
  819. RETURN_INTO_OBJREF(ds2, iface::rdf_api::DataSource, bs->createDataSource());
  820. bs->parseIntoDataSource(ds2, de2, uriStr);
  821. RETURN_INTO_WSTRING(s, bs->serialiseDataSource(ds, uriStr));
  822. ntf.compareTriples(ds2);
  823. }
  824. }
  825. void
  826. debug_PrintNode(iface::rdf_api::Node* aNode)
  827. {
  828. DECLARE_QUERY_INTERFACE_OBJREF(ur, aNode, rdf_api::URIReference);
  829. if (ur != NULL)
  830. {
  831. RETURN_INTO_WSTRING(s, ur->URI());
  832. printf("<URI: %S> ", s.c_str());
  833. return;
  834. }
  835. DECLARE_QUERY_INTERFACE_OBJREF(bn, aNode, rdf_api::BlankNode);
  836. if (bn != NULL)
  837. {
  838. printf("<BlankNode %08" PRIxPTR ">", reinterpret_cast<uintptr_t>(static_cast<iface::rdf_api::BlankNode*>(bn)));
  839. return;
  840. }
  841. DECLARE_QUERY_INTERFACE_OBJREF(pl, aNode, rdf_api::PlainLiteral);
  842. if (pl != NULL)
  843. {
  844. RETURN_INTO_WSTRING(lf, pl->lexicalForm());
  845. RETURN_INTO_WSTRING(l, pl->language());
  846. printf("<PlainLiteral: %S language %S> ", lf.c_str(), l.c_str());
  847. return;
  848. }
  849. DECLARE_QUERY_INTERFACE_OBJREF(tl, aNode, rdf_api::TypedLiteral);
  850. if (tl != NULL)
  851. {
  852. RETURN_INTO_WSTRING(lf, tl->lexicalForm());
  853. RETURN_INTO_WSTRING(l, tl->datatypeURI());
  854. printf("<TypedLiteral: %S type %S> ", lf.c_str(), l.c_str());
  855. return;
  856. }
  857. }
  858. void
  859. RDFTest::testRDFAPIImplementation()
  860. {
  861. RETURN_INTO_OBJREF(cb, iface::cellml_api::CellMLBootstrap,
  862. CreateCellMLBootstrap());
  863. RETURN_INTO_OBJREF(ml, iface::cellml_api::ModelLoader,
  864. cb->modelLoader());
  865. RETURN_INTO_OBJREF(m, iface::cellml_api::Model,
  866. ml->loadFromURL
  867. (BASE_DIRECTORY_CELLML L"Ach_cascade_1995.xml"));
  868. CPPUNIT_ASSERT(m != NULL);
  869. RETURN_INTO_OBJREF(rr, iface::cellml_api::RDFRepresentation, m->getRDFRepresentation(L"http://www.cellml.org/RDF/API"));
  870. CPPUNIT_ASSERT(rr != NULL);
  871. DECLARE_QUERY_INTERFACE_OBJREF(rar, rr, rdf_api::RDFAPIRepresentation);
  872. CPPUNIT_ASSERT(rar != NULL);
  873. RETURN_INTO_OBJREF(ds, iface::rdf_api::DataSource, rar->source());
  874. CPPUNIT_ASSERT(ds != NULL);
  875. #if 0
  876. {
  877. RETURN_INTO_OBJREF(ts, iface::rdf_api::TripleSet, ds->getAllTriples());
  878. RETURN_INTO_OBJREF(te, iface::rdf_api::TripleEnumerator, ts->enumerateTriples());
  879. while (true)
  880. {
  881. RETURN_INTO_OBJREF(t, iface::rdf_api::Triple, te->getNextTriple());
  882. if (t == NULL) break;
  883. RETURN_INTO_OBJREF(s, iface::rdf_api::Resource, t->subject());
  884. debug_PrintNode(s);
  885. RETURN_INTO_OBJREF(p, iface::rdf_api::Resource, t->predicate());
  886. debug_PrintNode(p);
  887. RETURN_INTO_OBJREF(o, iface::rdf_api::Node, t->object());
  888. debug_PrintNode(o);
  889. printf("\n");
  890. }
  891. }
  892. #endif
  893. RETURN_INTO_OBJREF(modur, iface::rdf_api::URIReference,
  894. ds->getURIReference(L"http://www.example.org/repository/Ach_cascade_1995.xml"));
  895. CPPUNIT_ASSERT(modur != NULL);
  896. RETURN_INTO_OBJREF(dcpublisher, iface::rdf_api::URIReference,
  897. ds->getURIReference(L"http://purl.org/dc/elements/1.1/publisher"));
  898. RETURN_INTO_OBJREF(dcp, iface::rdf_api::Triple, modur->getTripleOutOfByPredicate(dcpublisher));
  899. CPPUNIT_ASSERT(dcp != NULL);
  900. RETURN_INTO_OBJREF(dcpo, iface::rdf_api::Node, dcp->object());
  901. CPPUNIT_ASSERT(dcpo != NULL);
  902. DECLARE_QUERY_INTERFACE_OBJREF(pl, dcpo, rdf_api::PlainLiteral);
  903. RETURN_INTO_WSTRING(lf, pl->lexicalForm());
  904. CPPUNIT_ASSERT(lf == L"\n The University of Auckland, Bioengineering Institute\n ");
  905. }
  906. void
  907. RDFTest::assertContainerContents
  908. (
  909. iface::rdf_api::Container* aCT,
  910. const wchar_t** aExpect
  911. )
  912. {
  913. RETURN_INTO_OBJREF(ni, iface::rdf_api::NodeIterator, aCT->iterateChildren());
  914. while (true)
  915. {
  916. RETURN_INTO_OBJREF(n, iface::rdf_api::Node, ni->getNextNode());
  917. if (*aExpect == NULL)
  918. {
  919. CPPUNIT_ASSERT(n == NULL);
  920. return;
  921. }
  922. else
  923. {
  924. CPPUNIT_ASSERT(n);
  925. }
  926. DECLARE_QUERY_INTERFACE_OBJREF(pl, n, rdf_api::PlainLiteral);
  927. CPPUNIT_ASSERT(pl);
  928. RETURN_INTO_WSTRING(lf, pl->lexicalForm());
  929. // printf("lf: %S, expect: %S\n", lf.c_str(), *aExpect);
  930. CPPUNIT_ASSERT(lf == *aExpect);
  931. aExpect++;
  932. }
  933. }
  934. void
  935. RDFTest::testContainerLibrary()
  936. {
  937. RETURN_INTO_OBJREF(bs, iface::rdf_api::Bootstrap, CreateRDFBootstrap());
  938. RETURN_INTO_OBJREF(cdibs, CellML_DOMImplementationBase, CreateDOMImplementation());
  939. std::wstring url(BASE_URI);
  940. url += L"test131.rdf";
  941. std::wstring msg;
  942. RETURN_INTO_OBJREF(doc, iface::dom::Document, cdibs->loadDocument
  943. (url.c_str(), msg));
  944. RETURN_INTO_OBJREF(de, iface::dom::Element, doc->documentElement());
  945. RETURN_INTO_OBJREF(ds, iface::rdf_api::DataSource, bs->createDataSource());
  946. const wchar_t* uriStr = url.c_str();
  947. bs->parseIntoDataSource(ds, de, uriStr);
  948. // /**
  949. // * Retrieves a 'Container' interface around this Resource.
  950. // */
  951. // readonly attribute Container correspondingContainer;
  952. RETURN_INTO_OBJREF(ur, iface::rdf_api::URIReference,
  953. ds->getURIReference(L"http://example.org/thing"));
  954. RETURN_INTO_OBJREF(cc, iface::rdf_api::Container, ur->correspondingContainer());
  955. CPPUNIT_ASSERT(cc);
  956. // /**
  957. // * Retrieves the resource this container is built on.
  958. // */
  959. // readonly attribute Resource correspondingResource;
  960. RETURN_INTO_OBJREF(cr, iface::rdf_api::Resource, cc->correspondingResource());
  961. CPPUNIT_ASSERT(!CDA_objcmp(cr, ur));
  962. // /**
  963. // * Finds the type of container (or one of the types, if there are multiple
  964. // * types).
  965. // */
  966. // attribute Resource containerType;
  967. RETURN_INTO_OBJREF(ct, iface::rdf_api::Resource, cc->containerType());
  968. CPPUNIT_ASSERT(ct);
  969. RETURN_INTO_OBJREF(bag, iface::rdf_api::URIReference,
  970. ds->getURIReference(L"http://www.w3.org/1999/02/22-rdf-syntax-ns#Bag"));
  971. RETURN_INTO_OBJREF(seq, iface::rdf_api::URIReference,
  972. ds->getURIReference(L"http://www.w3.org/1999/02/22-rdf-syntax-ns#Seq"));
  973. CPPUNIT_ASSERT(!CDA_objcmp(ct, bag));
  974. cc->containerType(seq);
  975. ct = already_AddRefd<iface::rdf_api::Resource>(cc->containerType());
  976. CPPUNIT_ASSERT(ct);
  977. CPPUNIT_ASSERT(!CDA_objcmp(ct, seq));
  978. //
  979. // /**
  980. // * Iterates through all children in this container.
  981. // */
  982. // NodeIterator iterateChildren();
  983. // printf("Initial container iteration.\n");
  984. {
  985. const wchar_t* expect[] =
  986. {
  987. L"Hello", L"World", L"I", L"Hope", L"This",
  988. L"Works!", NULL
  989. };
  990. assertContainerContents(cc, expect);
  991. }
  992. //
  993. // /**
  994. // * Appends a child to this container. The child will have the first free
  995. // * index, even if there is a higher index already in use.
  996. // */
  997. // void appendChild(in Node aChild);
  998. RETURN_INTO_OBJREF(word1, iface::rdf_api::PlainLiteral, ds->getPlainLiteral(L"We", L"en"));
  999. cc->appendChild(word1);
  1000. RETURN_INTO_OBJREF(word2, iface::rdf_api::PlainLiteral, ds->getPlainLiteral(L"think", L"en"));
  1001. cc->appendChild(word2);
  1002. RETURN_INTO_OBJREF(word3, iface::rdf_api::PlainLiteral, ds->getPlainLiteral(L"it", L"en"));
  1003. cc->appendChild(word3);
  1004. RETURN_INTO_OBJREF(word4, iface::rdf_api::PlainLiteral, ds->getPlainLiteral(L"most", L"en"));
  1005. cc->appendChild(word4);
  1006. RETURN_INTO_OBJREF(word5, iface::rdf_api::PlainLiteral, ds->getPlainLiteral(L"certainly", L"en"));
  1007. cc->appendChild(word5);
  1008. RETURN_INTO_OBJREF(word6, iface::rdf_api::PlainLiteral, ds->getPlainLiteral(L"seems", L"en"));
  1009. cc->appendChild(word6);
  1010. RETURN_INTO_OBJREF(word7, iface::rdf_api::PlainLiteral, ds->getPlainLiteral(L"to", L"en"));
  1011. cc->appendChild(word7);
  1012. RETURN_INTO_OBJREF(word8, iface::rdf_api::PlainLiteral, ds->getPlainLiteral(L"work", L"en"));
  1013. cc->appendChild(word8);
  1014. RETURN_INTO_OBJREF(word9, iface::rdf_api::PlainLiteral, ds->getPlainLiteral(L"!", L"en"));
  1015. cc->appendChild(word9);
  1016. {
  1017. const wchar_t* expect[] =
  1018. {
  1019. L"Hello", L"World", L"I", L"Hope", L"This",
  1020. L"Works!", L"We", L"think", L"it", L"most", L"certainly",
  1021. L"seems", L"to", L"work", L"!", NULL
  1022. };
  1023. assertContainerContents(cc, expect);
  1024. }
  1025. //
  1026. // /**
  1027. // * Removes a child. If aDoRenumbering is true, will also reduce the value of
  1028. // * any existing indices above the one of the child being removed by one.
  1029. // * Otherwise, leaves a gap in the numbering.
  1030. // */
  1031. // void removeChild(in Node aChild, in boolean aDoRenumbering);
  1032. cc->removeChild(word1, false);
  1033. cc->removeChild(word2, false);
  1034. cc->removeChild(word3, false);
  1035. cc->removeChild(word4, false);
  1036. cc->removeChild(word5, false);
  1037. // printf("Did removeChild(,false) calls\n");
  1038. {
  1039. const wchar_t* expect[] =
  1040. {
  1041. L"Hello", L"World", L"I", L"Hope", L"This",
  1042. L"Works!",
  1043. L"seems", L"to", L"work", L"!", NULL
  1044. };
  1045. assertContainerContents(cc, expect);
  1046. }
  1047. // Also check it wasn't renumbered.
  1048. RETURN_INTO_OBJREF(twelth, iface::rdf_api::URIReference,
  1049. ds->getURIReference(L"http://www.w3.org/1999/02/22-rdf-syntax-ns#_12"));
  1050. RETURN_INTO_OBJREF(t12, iface::rdf_api::Triple, cr->getTripleOutOfByPredicate(twelth));
  1051. CPPUNIT_ASSERT(t12);
  1052. RETURN_INTO_OBJREF(t12o, iface::rdf_api::Node, t12->object());
  1053. CPPUNIT_ASSERT(!CDA_objcmp(t12o, word6));
  1054. cc->removeChild(word6, true);
  1055. // printf("Did removeChild(,true) call\n");
  1056. {
  1057. const wchar_t* expect[] =
  1058. {
  1059. L"Hello", L"World", L"I", L"Hope", L"This",
  1060. L"Works!",
  1061. L"to", L"work", L"!", NULL
  1062. };
  1063. assertContainerContents(cc, expect);
  1064. }
  1065. t12 = already_AddRefd<iface::rdf_api::Triple>(cr->getTripleOutOfByPredicate(twelth));
  1066. CPPUNIT_ASSERT(t12);
  1067. t12o = already_AddRefd<iface::rdf_api::Node>(t12->object());
  1068. CPPUNIT_ASSERT(!CDA_objcmp(t12o, word7));
  1069. //
  1070. // /**
  1071. // * Renumbers all indices in the container to be consecutive starting from 1.
  1072. // */
  1073. // void renumberContainer();
  1074. cc->renumberContainer();
  1075. // printf("Did renumberContainer() call\n");
  1076. {
  1077. const wchar_t* expect[] =
  1078. {
  1079. L"Hello", L"World", L"I", L"Hope", L"This",
  1080. L"Works!",
  1081. L"to", L"work", L"!", NULL
  1082. };
  1083. assertContainerContents(cc, expect);
  1084. }
  1085. RETURN_INTO_OBJREF(ninth, iface::rdf_api::URIReference,
  1086. ds->getURIReference(L"http://www.w3.org/1999/02/22-rdf-syntax-ns#_9"));
  1087. RETURN_INTO_OBJREF(t9, iface::rdf_api::Triple, cr->getTripleOutOfByPredicate(ninth));
  1088. CPPUNIT_ASSERT(t9);
  1089. RETURN_INTO_OBJREF(t9o, iface::rdf_api::Node, t9->object());
  1090. CPPUNIT_ASSERT(!CDA_objcmp(t9o, word9));
  1091. //
  1092. // /**
  1093. // * Creates a merged container. This does not change the RDF, but merely
  1094. // * creates a merged view.
  1095. // * Merged containers return the same correspondingResource and type as
  1096. // * this (not aContainer). Iterating children will iterate
  1097. // * the children of this, and then the children of aContainer (with
  1098. // * repetition possible). appendChild will have the same effect as performing
  1099. // * appendChild on this. removeChild will have the same effect as performing
  1100. // * removeChild on this and aContainer. renumberContainer will have the same
  1101. // * effect as performing the renumber on each container separately. Merged
  1102. // * containers can in turn be further merged.
  1103. // */
  1104. // Container mergeWith(in Container aContainer);
  1105. RETURN_INTO_OBJREF(ur2, iface::rdf_api::URIReference,
  1106. ds->getURIReference(L"http://example.org/thing2"));
  1107. RETURN_INTO_OBJREF(cc2, iface::rdf_api::Container, ur2->correspondingContainer());
  1108. CPPUNIT_ASSERT(cc2);
  1109. RETURN_INTO_OBJREF(ccm, iface::rdf_api::Container, cc->mergeWith(cc2));
  1110. RETURN_INTO_OBJREF(crm, iface::rdf_api::Resource, ccm->correspondingResource());
  1111. CPPUNIT_ASSERT(!CDA_objcmp(crm, ur));
  1112. RETURN_INTO_OBJREF(ctm, iface::rdf_api::Resource, ccm->containerType());
  1113. CPPUNIT_ASSERT(ctm);
  1114. CPPUNIT_ASSERT(!CDA_objcmp(ctm, seq));
  1115. ccm->containerType(bag);
  1116. ctm = already_AddRefd<iface::rdf_api::Resource>(ccm->containerType());
  1117. CPPUNIT_ASSERT(ctm);
  1118. CPPUNIT_ASSERT(!CDA_objcmp(ctm, bag));
  1119. {
  1120. const wchar_t* expect[] =
  1121. {
  1122. L"Hello", L"World", L"I", L"Hope", L"This",
  1123. L"Works!",
  1124. L"to", L"work", L"!",
  1125. L"Testing", L"Things:", L"It's", L"Good", L"When It", L"Succeeds!",
  1126. NULL
  1127. };
  1128. // printf("Merge container test 1\n");
  1129. assertContainerContents(ccm, expect);
  1130. }
  1131. ccm->appendChild(word1);
  1132. {
  1133. const wchar_t* expect[] =
  1134. {
  1135. L"Hello", L"World", L"I", L"Hope", L"This",
  1136. L"Works!",
  1137. L"to", L"work", L"!", L"We",
  1138. L"Testing", L"Things:", L"It's", L"Good", L"When It", L"Succeeds!",
  1139. NULL
  1140. };
  1141. // printf("Merge container test 2\n");
  1142. assertContainerContents(ccm, expect);
  1143. }
  1144. ccm->removeChild(word1, false);
  1145. RETURN_INTO_OBJREF(succeeds, iface::rdf_api::PlainLiteral, ds->getPlainLiteral(L"Succeeds!", L"en"));
  1146. ccm->removeChild(succeeds, true);
  1147. {
  1148. const wchar_t* expect[] =
  1149. {
  1150. L"Hello", L"World", L"I", L"Hope", L"This",
  1151. L"Works!",
  1152. L"to", L"work", L"!",
  1153. L"Testing", L"Things:", L"It's", L"Good", L"When It",
  1154. NULL
  1155. };
  1156. // printf("Merge container test 3\n");
  1157. assertContainerContents(ccm, expect);
  1158. }
  1159. ccm->renumberContainer();
  1160. {
  1161. const wchar_t* expect[] =
  1162. {
  1163. L"Hello", L"World", L"I", L"Hope", L"This",
  1164. L"Works!",
  1165. L"to", L"work", L"!",
  1166. L"Testing", L"Things:", L"It's", L"Good", L"When It",
  1167. NULL
  1168. };
  1169. // printf("Merge container test 4\n");
  1170. assertContainerContents(ccm, expect);
  1171. }
  1172. // /**
  1173. // * Finds or makes a particular container out of 'this', with the
  1174. // * specified predicate, and the specified type. If there are multiple
  1175. // * existing containers, the returned container is a merged view of all
  1176. // * containers. The underlying RDF is only changed if the container doesn't
  1177. // * already exist, in which case:
  1178. // * A new triple (subject=this) (predicate=aPredicate) (object=new blank node 'A')
  1179. // * is made.
  1180. // * A new triple (subject=the new blank node 'A') (predicate=RDF type) (object=aContainerType)
  1181. // * is made.
  1182. // * The returned Container is the correspondingContainer around the new blank node 'A'.
  1183. // */
  1184. // Container findOrMakeContainer(in Resource aPredicate,
  1185. // in Resource aContainerType);
  1186. RETURN_INTO_OBJREF(ur3, iface::rdf_api::URIReference,
  1187. ds->getURIReference(L"http://example.org/myitem"));
  1188. RETURN_INTO_OBJREF(cont, iface::rdf_api::Container, ur3->findOrMakeContainer(ur, bag));
  1189. {
  1190. const wchar_t* expect[] =
  1191. {
  1192. L"Hello", L"World", L"I", L"Hope", L"This",
  1193. L"Works!",
  1194. L"to", L"work", L"!", NULL
  1195. };
  1196. // printf("findOrMakeContainer test 1\n");
  1197. assertContainerContents(cont, expect);
  1198. }
  1199. RETURN_INTO_OBJREF(ur4, iface::rdf_api::URIReference,
  1200. ds->getURIReference(L"http://example.org/myitem2"));
  1201. RETURN_INTO_OBJREF(cont2, iface::rdf_api::Container, ur4->findOrMakeContainer(ur, bag));
  1202. cont2->appendChild(word1);
  1203. {
  1204. // printf("findOrMakeContainer test 2\n");
  1205. const wchar_t* expect[] =
  1206. {
  1207. L"We",
  1208. NULL
  1209. };
  1210. assertContainerContents(cont2, expect);
  1211. }
  1212. RETURN_INTO_OBJREF(ct3, iface::rdf_api::Resource, cc->containerType());
  1213. CPPUNIT_ASSERT(!CDA_objcmp(ct3, bag));
  1214. }