public function testSerializerWithMultipleSubjects()
 {
     $g = new MongoGraph();
     $docs = json_decode(file_get_contents(dirname(__FILE__) . '/data/resources.json'), true);
     foreach ($docs as $d) {
         $g->add_tripod_array($d);
     }
     $expected = "<http://life.ac.uk/resources/BFBC6A06-A8B0-DED8-53AA-8E80DB44CC53> <http://purl.org/dc/terms/title> \"Title of resource 2\" <http://talisaspire.com/> .\n<http://life.ac.uk/resources/836E7CAD-63D2-63A0-B1CB-AA6A7E54A5C9> <http://purl.org/dc/terms/title> \"Title of resource 1\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA> <http://purl.org/dc/terms/isVersionOf> <http://talisaspire.com/works/4d101f63c10a6> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA> <http://purl.org/dc/terms/source> <http://life.ac.uk/resources/BFBC6A06-A8B0-DED8-53AA-8E80DB44CC53> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA> <http://purl.org/dc/terms/source> <http://life.ac.uk/resources/836E7CAD-63D2-63A0-B1CB-AA6A7E54A5C9> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA> <http://purl.org/dc/terms/subject> <http://talisaspire.com/disciplines/physics> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA> <http://purl.org/ontology/bibo/isbn13> \"9780393929690\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA> <http://talisaspire.com/schema#bookmarkReferences> <http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA/bookmarks> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA> <http://talisaspire.com/schema#foo> \"wibble\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA> <http://talisaspire.com/schema#jacsUri> <http://jacs3.dataincubator.org/f300> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA> <http://talisaspire.com/schema#jacsUri> <http://jacs3.dataincubator.org/f340> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA> <http://talisaspire.com/schema#listReferences> <http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA/lists> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA> <http://talisaspire.com/schema#openLibraryUri> <http://openlibrary.org/books/OL10157958M> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA> <http://talisaspire.com/schema#preferredMetadata> <http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA/metadata> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA> <http://talisaspire.com/searchTerms/schema#author> \"Ohanian\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA> <http://talisaspire.com/searchTerms/schema#discipline> \"physics\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA> <http://talisaspire.com/searchTerms/schema#isbn> \"9780393929690\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA> <http://talisaspire.com/searchTerms/schema#openLibrarySubject> \"Engineering: general\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA> <http://talisaspire.com/searchTerms/schema#openLibrarySubject> \"PHYSICS\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA> <http://talisaspire.com/searchTerms/schema#openLibrarySubject> \"Science\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA> <http://talisaspire.com/searchTerms/schema#title> \"Physics 3rd Edition\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA> <http://talisaspire.com/searchTerms/schema#title> \"Physics for Engineers and Scientists\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA> <http://talisaspire.com/searchTerms/schema#topic> \"engineering: general\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA> <http://talisaspire.com/searchTerms/schema#topic> \"physics\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA> <http://talisaspire.com/searchTerms/schema#topic> \"science\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA> <http://talisaspire.com/searchTerms/schema#usedAt> \"0071\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://purl.org/ontology/bibo/Book> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://talisaspire.com/schema#Resource> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA> <http://www.w3.org/2002/07/owl#sameAs> <http://talisaspire.com/isbn/9780393929690> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA-2> <http://purl.org/dc/terms/isVersionOf> <http://talisaspire.com/works/4d101f63c10a6> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA-2> <http://purl.org/dc/terms/source> <http://life.ac.uk/resources/836E7CAD-63D2-63A0-B1CB-AA6A7E54A5C9> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA-2> <http://purl.org/dc/terms/source> <http://life.ac.uk/resources/BFBC6A06-A8B0-DED8-53AA-8E80DB44CC53> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA-2> <http://purl.org/dc/terms/subject> <http://talisaspire.com/disciplines/physics> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA-2> <http://purl.org/ontology/bibo/isbn13> \"9780393929691\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA-2> <http://talisaspire.com/schema#bookmarkReferences> <http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA/bookmarks> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA-2> <http://talisaspire.com/schema#foo> \"wibble\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA-2> <http://talisaspire.com/schema#jacsUri> <http://jacs3.dataincubator.org/f300> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA-2> <http://talisaspire.com/schema#jacsUri> <http://jacs3.dataincubator.org/f340> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA-2> <http://talisaspire.com/schema#listReferences> <http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA/lists> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA-2> <http://talisaspire.com/schema#openLibraryUri> <http://openlibrary.org/books/OL10157958M> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA-2> <http://talisaspire.com/schema#preferredMetadata> <http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA/metadata> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA-2> <http://talisaspire.com/searchTerms/schema#author> \"Ohanian\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA-2> <http://talisaspire.com/searchTerms/schema#discipline> \"physics\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA-2> <http://talisaspire.com/searchTerms/schema#isbn> \"9780393929690\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA-2> <http://talisaspire.com/searchTerms/schema#openLibrarySubject> \"Engineering: general\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA-2> <http://talisaspire.com/searchTerms/schema#openLibrarySubject> \"PHYSICS\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA-2> <http://talisaspire.com/searchTerms/schema#openLibrarySubject> \"Science\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA-2> <http://talisaspire.com/searchTerms/schema#title> \"Physics 3rd Edition\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA-2> <http://talisaspire.com/searchTerms/schema#title> \"Physics for Engineers and Scientists\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA-2> <http://talisaspire.com/searchTerms/schema#topic> \"engineering: general\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA-2> <http://talisaspire.com/searchTerms/schema#topic> \"physics\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA-2> <http://talisaspire.com/searchTerms/schema#topic> \"science\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA-2> <http://talisaspire.com/searchTerms/schema#usedAt> \"0071\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA-2> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://purl.org/ontology/bibo/Book> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA-2> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://talisaspire.com/schema#Resource> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA-2> <http://www.w3.org/2002/07/owl#sameAs> <http://talisaspire.com/isbn/9780393929690> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/indexKeyTooLarge> <http://purl.org/dc/terms/isVersionOf> <http://talisaspire.com/works/4d101f63c10a6> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/indexKeyTooLarge> <http://purl.org/dc/terms/source> <http://life.ac.uk/resources/836E7CAD-63D2-63A0-B1CB-AA6A7E54A5C9> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/indexKeyTooLarge> <http://purl.org/dc/terms/source> <http://life.ac.uk/resources/BFBC6A06-A8B0-DED8-53AA-8E80DB44CC53> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/indexKeyTooLarge> <http://purl.org/dc/terms/subject> <http://talisaspire.com/disciplines/physics> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/indexKeyTooLarge> <http://purl.org/ontology/bibo/isbn13> \"1234567890123\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/indexKeyTooLarge> <http://talisaspire.com/schema#bookmarkReferences> <http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA/bookmarks> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/indexKeyTooLarge> <http://talisaspire.com/schema#foo> \"wibble\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/indexKeyTooLarge> <http://talisaspire.com/schema#jacsUri> <http://jacs3.dataincubator.org/f300> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/indexKeyTooLarge> <http://talisaspire.com/schema#jacsUri> <http://jacs3.dataincubator.org/f340> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/indexKeyTooLarge> <http://talisaspire.com/schema#listReferences> <http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA/lists> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/indexKeyTooLarge> <http://talisaspire.com/schema#openLibraryUri> <http://openlibrary.org/books/OL10157958M> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/indexKeyTooLarge> <http://talisaspire.com/schema#preferredMetadata> <http://talisaspire.com/resources/3SplCtWGPqEyXcDiyhHQpA/metadata> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/indexKeyTooLarge> <http://talisaspire.com/searchTerms/schema#author> \"Ohanian\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/indexKeyTooLarge> <http://talisaspire.com/searchTerms/schema#discipline> \"physics\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/indexKeyTooLarge> <http://talisaspire.com/searchTerms/schema#isbn> \"1234567890\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/indexKeyTooLarge> <http://talisaspire.com/searchTerms/schema#openLibrarySubject> \"Engineering: general\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/indexKeyTooLarge> <http://talisaspire.com/searchTerms/schema#openLibrarySubject> \"PHYSICS\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/indexKeyTooLarge> <http://talisaspire.com/searchTerms/schema#openLibrarySubject> \"Science\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/indexKeyTooLarge> <http://talisaspire.com/searchTerms/schema#title> \"Mahommah Gardo Baquaqua. Biography of Mahommah G. Baquaqua, a Native of Zoogoo, in the Interior of Africa. (A Convert to Christianity,) With a Description of That Part of the World; Including the Manners and Customs of the Inhabitants, Their Religious Notions, Form of Government, Laws, Appearance of the Country, Buildings, Agriculture, Manufactures, Shepherds and Herdsmen, Domestic Animals, Marriage Ceremonials, Funeral Services, Styles of Dress, Trade and Commerce, Modes of Warfare, System of Slavery, &amp;c., &amp;c. Mahommah&#039;s Early Life, His Education, His Capture and Slavery in Western Africa and Brazil, His Escape to the United States, from Thence to Hayti, (the City of Port Au Prince,) His Reception by the Baptist Missionary There, The Rev. W. L. Judd; His Conversion to Christianity, Baptism, and Return to This Country, His Views, Objects and Aim. Written and Revised from His Own Words, by Samuel Moore, Esq., Late Publisher of the &quot;North of England Shipping Gazette,&quot; Author of Several Popular Works, and Editor of Sundry Reform Papers.\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/indexKeyTooLarge> <http://talisaspire.com/searchTerms/schema#topic> \"engineering: general\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/indexKeyTooLarge> <http://talisaspire.com/searchTerms/schema#topic> \"physics\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/indexKeyTooLarge> <http://talisaspire.com/searchTerms/schema#topic> \"science\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/indexKeyTooLarge> <http://talisaspire.com/searchTerms/schema#usedAt> \"0071\" <http://talisaspire.com/> .\n<http://talisaspire.com/resources/indexKeyTooLarge> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://purl.org/ontology/bibo/Book> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/indexKeyTooLarge> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://talisaspire.com/schema#ResourceForTruncating> <http://talisaspire.com/> .\n<http://talisaspire.com/resources/indexKeyTooLarge> <http://www.w3.org/2002/07/owl#sameAs> <http://talisaspire.com/isbn/9780393929690> <http://talisaspire.com/> .\n<http://jacs3.dataincubator.org/f300> <http://purl.org/dc/terms/title> \"First title\" <http://talisaspire.com/> .\n<http://jacs3.dataincubator.org/f300> <http://purl.org/dc/terms/title> \"Second title\" <http://talisaspire.com/> .\n<http://jacs3.dataincubator.org/f340> <http://purl.org/dc/terms/title> \"First title\" <http://talisaspire.com/> .\n<http://talisaspire.com/works/4d101f63c10a6> <http://purl.org/dc/terms/subject> <http://talisaspire.com/disciplines/physics> <http://talisaspire.com/> .\n<http://talisaspire.com/works/4d101f63c10a6> <http://purl.org/ontology/bibo/isbn13> \"9780393929691\" <http://talisaspire.com/> .\n<http://talisaspire.com/works/4d101f63c10a6> <http://purl.org/ontology/bibo/isbn13> \"9780393929691-2\" <http://talisaspire.com/> .\n<http://talisaspire.com/works/4d101f63c10a6> <http://talisaspire.com/searchTerms/schema#discipline> \"physics\" <http://talisaspire.com/> .\n<http://talisaspire.com/works/4d101f63c10a6> <http://talisaspire.com/schema#seeAlso> <http://talisaspire.com/works/4d101f63c10a6-2> <http://talisaspire.com/> .\n<http://talisaspire.com/works/4d101f63c10a6> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://purl.org/ontology/bibo/Book> <http://talisaspire.com/> .\n<http://talisaspire.com/works/4d101f63c10a6> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://talisaspire.com/schema#Work> <http://talisaspire.com/> .\n<http://talisaspire.com/works/4d101f63c10a6-2> <http://purl.org/dc/terms/subject> <http://talisaspire.com/disciplines/physics> <http://talisaspire.com/> .\n<http://talisaspire.com/works/4d101f63c10a6-2> <http://purl.org/ontology/bibo/isbn13> \"9780393929691\" <http://talisaspire.com/> .\n<http://talisaspire.com/works/4d101f63c10a6-2> <http://talisaspire.com/searchTerms/schema#discipline> \"physics\" <http://talisaspire.com/> .\n<http://talisaspire.com/works/4d101f63c10a6-2> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://purl.org/ontology/bibo/Book> <http://talisaspire.com/> .\n<http://talisaspire.com/works/4d101f63c10a6-2> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://talisaspire.com/schema#Work> <http://talisaspire.com/> .\n<http://talisaspire.com/works/lockedDoc> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://purl.org/ontology/bibo/Book> <http://talisaspire.com/> .\n<http://talisaspire.com/works/lockedDoc> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://talisaspire.com/schema#Work> <http://talisaspire.com/> .\n<http://basedata.com/b/1> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://talisaspire.com/schema#Work> <http://talisaspire.com/> .\n<http://basedata.com/b/1> <http://talisaspire.com/schema#seeAlso> <http://talisaspire.com/works/4d101f63c10a6-2> <http://talisaspire.com/> .\n<http://basedata.com/b/2> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://talisaspire.com/schema#Work> <http://talisaspire.com/> .\n<http://basedata.com/b/2> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://talisaspire.com/schema#Work2> <http://talisaspire.com/> .\n<http://basedata.com/b/2> <http://talisaspire.com/schema#seeAlso> <http://basedata.com/b/1> <http://talisaspire.com/> .\n<tenantUsers:s2123> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://rdfs.org/sioc/spec/User> <http://talisaspire.com/> .\n<tenantUsers:s2123> <http://xmlns.com/foaf/0.1/firstName> \"Harry\" <http://talisaspire.com/> .\n<tenantUsers:s2123> <http://xmlns.com/foaf/0.1/surname> \"Potter\" <http://talisaspire.com/> .\n<tenantUsers:s2123> <http://lists.talis.com/schema/temp#last_login> \"2014-03-25T15:07:12+00:00\" <http://talisaspire.com/> .\n<tenantUsers:s2123> <http://lists.talis.com/schema/temp#last_login_invalid> \"invalid\" <http://talisaspire.com/> .\n<http://basedata.com/b/foo1234> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://purl.org/ontology/bibo/Document> <http://talisaspire.com/> .\n<http://basedata.com/b/foo1234> <http://purl.org/dc/terms/creator> <http://schemas.talis.com/2005/user/schema#10101> <http://talisaspire.com/> .\n<http://basedata.com/b/foo1234> <http://purl.org/dc/terms/title> \"A document title\" <http://talisaspire.com/> .\n<http://basedata.com/b/foo1234> <http://purl.org/dc/terms/isVersionOf> <http://talisaspire.com/works/4d101f63c10a6> <http://talisaspire.com/> .\n<http://schemas.talis.com/2005/user/schema#10101> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://xmlns.com/foaf/0.1/Person> <http://talisaspire.com/> .\n<http://schemas.talis.com/2005/user/schema#10101> <http://xmlns.com/foaf/0.1/name> \"A. Person\" <http://talisaspire.com/> .\n<http://schemas.talis.com/2005/user/schema#10101> <http://xmlns.com/foaf/0.1/knows> <http://schemas.talis.com/2005/user/schema#10102> <http://talisaspire.com/> .\n<http://schemas.talis.com/2005/user/schema#10102> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://xmlns.com/foaf/0.1/Person> <http://talisaspire.com/> .\n<http://schemas.talis.com/2005/user/schema#10102> <http://xmlns.com/foaf/0.1/name> \"Anne O'ther\" <http://talisaspire.com/> .\n<http://basedata.com/b/bar1234> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://purl.org/ontology/bibo/Document> <http://talisaspire.com/> .\n<http://basedata.com/b/bar1234> <http://purl.org/dc/terms/creator> <http://schemas.talis.com/2005/user/schema#10103> <http://talisaspire.com/> .\n<http://basedata.com/b/bar1234> <http://purl.org/dc/terms/contributor> <http://schemas.talis.com/2005/user/schema#10101> <http://talisaspire.com/> .\n<http://basedata.com/b/bar1234> <http://purl.org/dc/terms/contributor> <http://schemas.talis.com/2005/user/schema#10102> <http://talisaspire.com/> .\n<http://basedata.com/b/bar1234> <http://purl.org/dc/terms/title> \"Another document title\" <http://talisaspire.com/> .\n<http://basedata.com/b/docWithEmptySeq123> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://basedata.com/b/DocWithSequence> <http://talisaspire.com/> .\n<http://basedata.com/b/docWithEmptySeq123> <http://basedata.com/b/hasSequence> <http://basedata.com/b/sequence123> <http://talisaspire.com/> .\n<http://basedata.com/b/docWithEmptySeq123> <http://purl.org/dc/terms/creator> <http://schemas.talis.com/2005/user/schema#xyz> <http://talisaspire.com/> .\n<http://basedata.com/b/docWithEmptySeq123> <http://purl.org/dc/terms/title> \"Doc with sequence\" <http://talisaspire.com/> .";
     $serializer = new NQuadSerializer();
     $actual = $serializer->getSerializedIndex($g->_index, \Tripod\Mongo\Config::getInstance()->getDefaultContextAlias());
     // This test initially asserted that $expected was equal to $actual
     //   $this->assertEquals($expected, $actual);
     // However, each time test data was added - it would also need to be added to expected above.
     // Rather than increasing the size of $expected further when adding new test data
     // this test now asserts that each line in $expected has been serialised correctly, without failing
     // due to new test data.
     foreach (preg_split("/((\r?\n)|(\r\n?))/", $expected) as $expectedLine) {
         $this->assertTrue(strpos($actual, rtrim($expectedLine)) !== false, "Failed checking for line: " . rtrim($expectedLine));
     }
 }
Example #2
0
 /**
  * @param array $query
  * @param string $type
  * @param Collection|null $collection
  * @param array $includeProperties
  * @param int $cursorSize
  * @return MongoGraph
  */
 protected function fetchGraph($query, $type, $collection = null, $includeProperties = array(), $cursorSize = 101)
 {
     $graph = new MongoGraph();
     $t = new \Tripod\Timer();
     $t->start();
     if ($collection == null) {
         $collection = $this->collection;
         $collectionName = $collection->getCollectionName();
     } else {
         $collectionName = $collection->getCollectionName();
     }
     if (empty($includeProperties)) {
         $cursor = $collection->find($query);
     } else {
         $fields = array();
         foreach ($includeProperties as $property) {
             $fields[$this->labeller->uri_to_alias($property)] = true;
         }
         $cursor = $collection->find($query, array('projection' => $fields, 'batchSize' => $cursorSize));
     }
     $ttlExpiredResources = false;
     $retries = 1;
     $exception = null;
     $cursorSuccess = false;
     do {
         try {
             foreach ($cursor as $result) {
                 // handle MONGO_VIEWS that have expired due to ttl. These are expired
                 // on read (lazily) rather than on write
                 if ($type == MONGO_VIEW && array_key_exists(_EXPIRES, $result['value'])) {
                     // if expires < current date, regenerate view..
                     $currentDate = \Tripod\Mongo\DateUtil::getMongoDate();
                     if ($result['value'][_EXPIRES]->__toString() < $currentDate) {
                         // regenerate!
                         $this->generateView($result['_id']['type'], $result['_id']['r']);
                     }
                 }
                 $graph->add_tripod_array($result);
             }
             $cursorSuccess = true;
         } catch (\Exception $e) {
             self::getLogger()->error("CursorException attempt " . $retries . ". Retrying...:" . $e->getMessage());
             sleep(1);
             $retries++;
             $exception = $e;
         }
     } while ($retries <= Config::CONNECTION_RETRIES && $cursorSuccess === false);
     if ($cursorSuccess === false) {
         self::getLogger()->error("CursorException failed after " . $retries . " attempts (MAX:" . Config::CONNECTION_RETRIES . "): " . $e->getMessage());
         throw new \Exception($exception);
     }
     if ($ttlExpiredResources) {
         // generate views and retry...
         $this->debugLog("One or more view had exceeded TTL was regenerated - request again...");
         $graph = $this->fetchGraph($query, $type, $collection);
     }
     $t->stop();
     $this->timingLog($type, array('duration' => $t->result(), 'query' => $query, 'collection' => $collectionName));
     if ($type == MONGO_VIEW) {
         if (array_key_exists("_id.type", $query)) {
             $this->getStat()->timer("{$type}.{$query["_id.type"]}", $t->result());
         } else {
             if (array_key_exists("_id", $query) && array_key_exists("type", $query["_id"])) {
                 $this->getStat()->timer("{$type}.{$query["_id"]["type"]}", $t->result());
             }
         }
     } else {
         $this->getStat()->timer("{$type}.{$collectionName}", $t->result());
     }
     return $graph;
 }
Example #3
0
 /**
  * @param \Tripod\ChangeSet $cs Change-set to apply
  * @param string $contextAlias
  * @throws \Tripod\Exceptions\Exception
  * @return array An array of subjects and predicates that have been changed
  */
 protected function storeChanges(\Tripod\ChangeSet $cs, $contextAlias)
 {
     $t = new \Tripod\Timer();
     $t->start();
     $subjectsOfChange = $cs->get_subjects_of_change();
     $transaction_id = $this->generateTransactionId();
     // store the details of the transaction in the transaction log
     $mongoGraph = new MongoGraph();
     $mongoGraph->_index = $cs->_index;
     $csDoc = $mongoGraph->to_tripod_view_array("changes", $contextAlias);
     // todo - this changed to tripod view array, why is "changes" the docId?
     $originalCBDs = array();
     // apply the changes
     try {
         // 1. lock all documents
         // 2. create new transaction
         // 3. apply changes
         // 4. unlock all documents
         // 5. complete transaction
         $originalCBDs = $this->lockAllDocuments($subjectsOfChange, $transaction_id, $contextAlias);
         $this->getTransactionLog()->createNewTransaction($transaction_id, $csDoc['value'][_GRAPHS], $originalCBDs, $this->getStoreName(), $this->getPodName());
         if (empty($originalCBDs)) {
             $this->getTransactionLog()->failTransaction($transaction_id, new \Exception('Did not obtain locks on documents'));
             throw new \Exception('Did not obtain locks on documents');
         }
         $changes = $this->applyChangeSet($cs, $originalCBDs, $contextAlias, $transaction_id);
         $this->debugLog(MONGO_LOCK, array('description' => 'Driver::storeChanges - Unlocking documents, apply change-set completed', 'transaction_id' => $transaction_id));
         $this->unlockAllDocuments($transaction_id);
         $this->getTransactionLog()->completeTransaction($transaction_id, $changes['newCBDs']);
         $t->stop();
         $this->timingLog(MONGO_WRITE, array('duration' => $t->result(), 'subjectsOfChange' => implode(", ", $subjectsOfChange)));
         $this->getStat()->timer(MONGO_WRITE . ".{$this->getPodName()}", $t->result());
         return $changes;
     } catch (\Exception $e) {
         $this->getStat()->increment(MONGO_ROLLBACK);
         $this->errorLog(MONGO_ROLLBACK, array('description' => 'Save Failed Rolling back transaction:' . $e->getMessage(), 'transaction_id' => $transaction_id, 'subjectsOfChange' => implode(",", $subjectsOfChange), 'mongoDriverError' => $this->getLastDBError($this->getDatabase()), 'exceptionMessage' => $e->getMessage()));
         $this->rollbackTransaction($transaction_id, $originalCBDs, $e);
         throw new \Tripod\Exceptions\Exception('Error storing changes: ' . $e->getMessage() . " >>>" . $e->getTraceAsString());
     }
 }
Example #4
-1
 /**
  * @param string $cbdSubject
  * @param MongoGraph $cbdGraph
  * @param Collection $collection
  * @param string $context
  * @throws \Exception
  */
 protected function saveCBD($cbdSubject, MongoGraph $cbdGraph, Collection $collection, $context)
 {
     $cbdSubject = $this->labeller->uri_to_alias($cbdSubject);
     if ($cbdGraph == null || $cbdGraph->is_empty()) {
         throw new \Exception("graph for {$cbdSubject} was null");
     }
     try {
         $collection->insertOne($cbdGraph->to_tripod_array($cbdSubject, $context), array("w" => 1));
         print ".";
     } catch (\Exception $e) {
         if (preg_match('/E11000/', $e->getMessage())) {
             print "M";
             // key already exists, merge it
             $criteria = array("_id" => array("r" => $cbdSubject, "c" => $context));
             $existingGraph = new MongoGraph();
             $existingGraph->add_tripod_array($collection->findOne($criteria));
             $existingGraph->add_graph($cbdGraph);
             try {
                 $collection->updateOne($criteria, ['$set' => $existingGraph->to_tripod_array($cbdSubject, $context)], array("w" => 1));
             } catch (\Exception $e2) {
                 throw new \Exception($e2->getMessage());
                 // todo: would be good to have typed exception
             }
         } else {
             // retry
             print "CursorException on update: " . $e->getMessage() . ", retrying\n";
             try {
                 $collection->insertOne($cbdGraph->to_tripod_array($cbdSubject, $context), array("w" => 1));
             } catch (\Exception $e2) {
                 throw new \Exception($e2->getMessage());
                 // todo: would be good to have typed exception
             }
         }
     }
 }