server/src/tests/Models/DocumentTest.php
author ymh <ymh.work@gmail.com>
Thu, 02 Jun 2016 18:24:19 +0200
changeset 168 17f10b56c079
parent 143 023b6d467566
child 169 8fddc113095e
permissions -rw-r--r--
improve document model and propagate changes. This include the change of document fixtures to better reflect what the api is effectively returning

<?php

use CorpusParole\Models\Document;
use CorpusParole\Libraries\CocoonUtils;

/**
 *
 */
class DocumentTest extends TestCase {

    const TEST_DOC = <<<EOT
    @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
    @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
    @prefix sesame: <http://www.openrdf.org/schema/sesame#> .
    @prefix owl: <http://www.w3.org/2002/07/owl#> .
    @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
    @prefix fn: <http://www.w3.org/2005/xpath-functions#> .

    <%1\$scrdo-CFPP2000_35_SOUND> a <http://www.openarchives.org/ore/terms/Aggregation> ;
        <http://www.europeana.eu/schemas/edm/aggregatedCHO> <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-CFPP2000_35_SOUND> ;
        <http://www.europeana.eu/schemas/edm/dataProvider> "Langage et langues : description, théorisation, transmission" ;
        <http://www.europeana.eu/schemas/edm/hasView> <http://cocoon.huma-num.fr/exist/crdo/cfpp2000/fra/Ozgur_Kilic_H_32_alii_3e-2.xml> , <http://cocoon.huma-num.fr/data/cfpp2000/Ozgur_Kilic_H_32_alii_3e-2.mp3> , <http://cocoon.huma-num.fr/data/cfpp2000/Ozgur_Kilic_H_32_alii_3e-2.wav> ;
        <http://www.europeana.eu/schemas/edm/isShownAt> <http://corpusdelaparole.huma-num.fr/corpus-app#/detail/crdo-CFPP2000_35_SOUND> ;
        <http://www.europeana.eu/schemas/edm/isShownBy> <http://cocoon.huma-num.fr/data/archi/masters/372593.wav> ;
        <http://www.europeana.eu/schemas/edm/provider> "Corpus de la Parole"@fr ;
        <http://www.europeana.eu/schemas/edm/rights> <http://creativecommons.org/licenses/by-nc-sa/4.0/> .

    <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-CFPP2000_35_SOUND> a <http://www.europeana.eu/schemas/edm/ProvidedCHO> ;
        <http://purl.org/dc/terms/accessRights> "Freely available for non-commercial use" ;
        <http://purl.org/dc/terms/created> "2010-11-17"^^<http://purl.org/dc/terms/W3CDTF> ;
        <http://purl.org/dc/terms/extent> "PT48M26S" ;
        <http://purl.org/dc/terms/issued> "2013-10-12T14:35:57+02:00"^^<http://purl.org/dc/terms/W3CDTF> ;
        <http://purl.org/dc/terms/license> <http://creativecommons.org/licenses/by-nc-sa/3.0/> ;
        <http://purl.org/dc/elements/1.1/contributor> <http://viaf.org/viaf/93752300> , "Tanguy, Noalig" , "Chevrier, Michel" , "Kiliç, Ozgur" , "Salvegas, Etienne" , "du-Breuil-de-Pont-en-Auge, Augustin" , "du-Breuil-de-Pont-en-Auge, Benoît" ;
        <http://purl.org/dc/elements/1.1/description> "Enregistrement issu du Corpus de Français Parlé Parisien des années 2000 (CFPP2000)"@fr , "Quartier(s) concerné(s) : Paris 3e, et 20e (pour l'âge adulte); Anonymisation : Noalig TANGUY;"@fr ;
        <http://purl.org/dc/elements/1.1/identifier> "ark:/87895/1.17-375004" , "%2\$scrdo-CFPP2000_35_SOUNDid" , "oai:crdo.vjf.cnrs.fr:crdo-CFPP2000_35" , "Cote producteur: [03-01] Ozgur_Kilic_H_32_alii_3e"@fr , "ark:/87895/1.17-372593" , "oai:crdo.vjf.cnrs.fr:crdo-CFPP2000_35_SOUND" ;
        <http://purl.org/dc/elements/1.1/language> <http://lexvo.org/id/iso639-3/fra> ;
        <http://purl.org/dc/elements/1.1/publisher> <http://viaf.org/viaf/142432638>;
        <http://purl.org/dc/elements/1.1/subject> <http://ark.bnf.fr/ark:/12148/cb13318415c> , "anthropological_linguistics"^^<http://www.language-archives.org/OLAC/1.1/linguistic-field> , "lexicography"^^<http://www.language-archives.org/OLAC/1.1/linguistic-field> , "phonetics"^^<http://www.language-archives.org/OLAC/1.1/linguistic-field> , <http://lexvo.org/id/iso639-3/fra> , <http://ark.bnf.fr/ark:/12148/cb133188907> , <http://ark.bnf.fr/ark:/12148/cb11932762f> , "general_linguistics"^^<http://www.language-archives.org/OLAC/1.1/linguistic-field> , <http://ark.bnf.fr/ark:/12148/cb133183660> , "text_and_corpus_linguistics"^^<http://www.language-archives.org/OLAC/1.1/linguistic-field> , "Français"@fr , <http://ark.bnf.fr/ark:/12148/cb122368540> , "phonology"^^<http://www.language-archives.org/OLAC/1.1/linguistic-field> , "semantics"^^<http://www.language-archives.org/OLAC/1.1/linguistic-field> , "sociolinguistics"^^<http://www.language-archives.org/OLAC/1.1/linguistic-field> , "syntax"^^<http://www.language-archives.org/OLAC/1.1/linguistic-field> , "typology"^^<http://www.language-archives.org/OLAC/1.1/linguistic-field> , <http://ark.bnf.fr/ark:/12148/cb119418302> , <http://ark.bnf.fr/ark:/12148/cb135540729> , "discourse_analysis"^^<http://www.language-archives.org/OLAC/1.1/linguistic-field> , "historical_linguistics"^^<http://www.language-archives.org/OLAC/1.1/linguistic-field> , "language_documentation"^^<http://www.language-archives.org/OLAC/1.1/linguistic-field> , <http://ark.bnf.fr/ark:/12148/cb133192210> , <http://ark.bnf.fr/ark:/12148/cb119377452> , <http://ark.bnf.fr/ark:/12148/cb13320451h> , <http://ark.bnf.fr/ark:/12148/cb13318422n> , <http://ark.bnf.fr/ark:/12148/cb11975823c> , "mathematical_linguistics"^^<http://www.language-archives.org/OLAC/1.1/linguistic-field> ;
        <http://purl.org/dc/elements/1.1/title> "Entretien de Ozgur Kiliç 2"@fr ;
        <http://purl.org/dc/elements/1.1/type> <http://ark.bnf.fr/ark:/12148/cb11932135w> , <http://ark.bnf.fr/ark:/12148/cb12481481z> , <http://purl.org/dc/dcmitype/Sound> , "primary_text"^^<http://www.language-archives.org/OLAC/1.1/linguistic-type> , <http://purl.org/dc/dcmitype/Text> , "narrative"^^<http://www.language-archives.org/OLAC/1.1/discourse-type> , "report"^^<http://www.language-archives.org/OLAC/1.1/discourse-type> , "unintelligible_speech"^^<http://www.language-archives.org/OLAC/1.1/discourse-type> ;
        <http://purl.org/dc/terms/available> "2013-10-12"^^<http://purl.org/dc/terms/W3CDTF> ;
        <http://purl.org/dc/terms/spatial> [
            a <http://www.europeana.eu/schemas/edm/Place> ;
            owl:sameAs <http://sws.geonames.org/6618626/> ;
            <http://www.w3.org/2004/02/skos/core#note> "FR"^^<http://purl.org/dc/terms/ISO3166> , "France, Île-de-France, Paris, Université Sorbonne Nouvelle Paris 3, site Censier"@fr , "Domicile de Ozgur Kiliç"@fr , "France, Île-de-France, Paris 20"@fr
        ];
        <http://www.europeana.eu/schemas/edm/isGatheredInto> <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_LANGUESDEFRANCE> , <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_CFPP2000> ;
        <http://www.language-archives.org/OLAC/1.1/depositor> <http://viaf.org/viaf/93752300> ;
        <http://www.language-archives.org/OLAC/1.1/interviewer> <http://viaf.org/viaf/93752300> ;
        <http://www.language-archives.org/OLAC/1.1/transcriber> "Tanguy, Noalig" ;
        <http://purl.org/dc/elements/1.1/coverage> "Quartier concerné : 3e"@fr ;
        <http://www.language-archives.org/OLAC/1.1/responder> "Chevrier, Michel" , "Kiliç, Ozgur" , "Salvegas, Etienne" , "du-Breuil-de-Pont-en-Auge, Augustin" , "du-Breuil-de-Pont-en-Auge, Benoît" ;
        <http://purl.org/dc/elements/1.1/relation> <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-CFPP2000_31_SOUND> .


    <http://cocoon.huma-num.fr/exist/crdo/cfpp2000/fra/Ozgur_Kilic_H_32_alii_3e-2.xml> a <http://www.europeana.eu/schemas/edm/WebResource> ;
        <http://purl.org/dc/elements/1.1/format> "application/xml"^^<http://purl.org/dc/terms/IMT> ;
        <http://purl.org/dc/terms/accessRights> "Freely available for non-commercial use" ;
        <http://purl.org/dc/terms/created> "2010-11-17"^^<http://purl.org/dc/terms/W3CDTF> ;
        <http://purl.org/dc/terms/issued> "2013-11-04T22:20:07+01:00"^^<http://purl.org/dc/terms/W3CDTF> ;
        <http://purl.org/dc/terms/license> <http://creativecommons.org/licenses/by-nc-sa/3.0/> ;
        <http://purl.org/dc/terms/conformsTo> <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-dtd_transcriber> .

    <http://cocoon.huma-num.fr/data/archi/masters/372593.wav> a <http://www.europeana.eu/schemas/edm/WebResource> ;
        <http://purl.org/dc/elements/1.1/format> "audio/x-wav"^^<http://purl.org/dc/terms/IMT> ;
        <http://purl.org/dc/terms/accessRights> "Freely available for non-commercial use" ;
        <http://purl.org/dc/terms/created> "2010-11-17"^^<http://purl.org/dc/terms/W3CDTF> ;
        <http://purl.org/dc/terms/extent> "PT48M26S" ;
        <http://purl.org/dc/terms/issued> "2013-10-12T14:35:57+02:00"^^<http://purl.org/dc/terms/W3CDTF> ;
        <http://purl.org/dc/terms/license> <http://creativecommons.org/licenses/by-nc-sa/3.0/> .

    <http://cocoon.huma-num.fr/data/cfpp2000/Ozgur_Kilic_H_32_alii_3e-2.mp3> a <http://www.europeana.eu/schemas/edm/WebResource> ;
        <http://purl.org/dc/elements/1.1/format> "audio/mpeg"^^<http://purl.org/dc/terms/IMT> ;
        <http://purl.org/dc/terms/accessRights> "Freely available for non-commercial use" ;
        <http://purl.org/dc/terms/created> "2010-11-17"^^<http://purl.org/dc/terms/W3CDTF> ;
        <http://purl.org/dc/terms/extent> "PT48M26S" ;
        <http://purl.org/dc/terms/issued> "2013-10-12T14:35:57+02:00"^^<http://purl.org/dc/terms/W3CDTF> ;
        <http://purl.org/dc/terms/license> <http://creativecommons.org/licenses/by-nc-sa/3.0/> ;
        <http://www.europeana.eu/schemas/edm/isDerivativeOf> <http://cocoon.huma-num.fr/data/archi/masters/372593.wav> .

    <http://cocoon.huma-num.fr/data/cfpp2000/Ozgur_Kilic_H_32_alii_3e-2.wav> a <http://www.europeana.eu/schemas/edm/WebResource> ;
        <http://purl.org/dc/elements/1.1/format> "audio/x-wav"^^<http://purl.org/dc/terms/IMT> ;
        <http://purl.org/dc/terms/accessRights> "Freely available for non-commercial use" ;
        <http://purl.org/dc/terms/created> "2010-11-17"^^<http://purl.org/dc/terms/W3CDTF> ;
        <http://purl.org/dc/terms/extent> "PT48M26S" ;
        <http://purl.org/dc/terms/issued> "2013-10-12T14:35:57+02:00"^^<http://purl.org/dc/terms/W3CDTF> ;
        <http://purl.org/dc/terms/license> <http://creativecommons.org/licenses/by-nc-sa/3.0/> ;
        <http://www.europeana.eu/schemas/edm/isDerivativeOf> <http://cocoon.huma-num.fr/data/archi/masters/372593.wav> .
EOT;


    public function setUp() {

        parent::setup();
        $this->graph = new EasyRdf\Graph(config('corpusparole.corpus_doc_id_base_uri')."crdo-CFPP2000_35_SOUND", sprintf(DocumentTest::TEST_DOC, config('corpusparole.corpus_doc_id_base_uri'), config('corpusparole.corpus_id_scheme')));

    }

    public function testConstructor() {
        $this->assertNotNull($this->graph, 'Graph shoud not be null');

        $doc = new Document(config('corpusparole.corpus_doc_id_base_uri')."crdo-CFPP2000_35_SOUND", $this->graph);

        $this->assertEquals(config('corpusparole.corpus_id_scheme').'crdo-CFPP2000_35_SOUNDid',$doc->getId(),'Must have the correct id');
    }

    public function testTitle() {
        $this->assertNotNull($this->graph, 'Graph shoud not be null');

        $doc = new Document(config('corpusparole.corpus_doc_id_base_uri')."crdo-CFPP2000_35_SOUND", $this->graph);

        $this->assertEquals("Entretien de Ozgur Kiliç 2",$doc->getTitle(),'Must have correct title');
        $this->assertInstanceOf(EasyRdf\Literal::class, $doc->getTitle(), "Title must be a literal");
        $this->assertEquals('fr', $doc->getTitle()->getLang(), "Language title must be fr");
    }

    public function testModified() {
        $this->assertNotNull($this->graph, 'Graph shoud not be null');

        $doc = new Document(config('corpusparole.corpus_doc_id_base_uri')."crdo-CFPP2000_35_SOUND", $this->graph);
        $this->assertInstanceOf(EasyRdf\Literal::class, $doc->getModified(), "Modified must be a literal");
        $this->assertEquals("http://purl.org/dc/terms/W3CDTF", $doc->getModified()->getDatatypeURI(), "type must be http://purl.org/dc/terms/W3CDTF");
        $this->assertEquals("2013-10-12T14:35:57+02:00", $doc->getModified(), "modified must be 2013-10-12T14:35:57+02:00");

    }

    public function testSetModified() {
        $currentTime = gmdate(DateTime::ATOM);
        $doc = new Document(config('corpusparole.corpus_doc_id_base_uri')."crdo-CFPP2000_35_SOUND", $this->graph);
        $doc->setModified($currentTime);
        $this->assertInstanceOf(EasyRdf\Literal::class, $doc->getModified(), "Modified must be a literal");
        $this->assertEquals("http://purl.org/dc/terms/W3CDTF", $doc->getModified()->getDatatypeURI(), "type must be http://purl.org/dc/terms/W3CDTF");
        $this->assertEquals(preg_replace('/[\+\-]00(\:?)00$/', 'Z', $currentTime), $doc->getModified()->getValue(), "modified must be $currentTime");
    }

    public function testSetModifiedNull() {
        $doc = new Document(config('corpusparole.corpus_doc_id_base_uri')."crdo-CFPP2000_35_SOUND", $this->graph);
        $doc->setModified();
        $this->assertInstanceOf(EasyRdf\Literal::class, $doc->getModified(), "Modified must be a literal");
        $this->assertEquals("http://purl.org/dc/terms/W3CDTF", $doc->getModified()->getDatatypeURI(), "type must be http://purl.org/dc/terms/W3CDTF");
        $foundDateTime = \DateTime::createFromFormat(\DateTime::ATOM, $doc->getModified()->getValue());
        $nowUTC = new \DateTime('now', new \DateTimeZone("UTC"));
        $this->assertTrue($nowUTC->getTimestamp() -  $foundDateTime->getTimestamp() < 2, "must have less than 2 seconds diff");
    }

    public function testPublisher() {

        $doc = new Document(config('corpusparole.corpus_doc_id_base_uri')."crdo-CFPP2000_35_SOUND", $this->graph);

        $this->assertCount(1, $doc->getPublishers(), 'Publisher is an array of size 1');
        $this->assertInstanceOf('EasyRdf\Resource', $doc->getPublishers()[0], 'publisher is a resource');
        $this->assertEquals("http://viaf.org/viaf/142432638", $doc->getPublishers()[0]->getUri(),"");
    }

    public function testMediaArray() {
        $doc = new Document(config('corpusparole.corpus_doc_id_base_uri')."crdo-CFPP2000_35_SOUND", $this->graph);

        $this->assertCount(3, $doc->getMediaArray(), "Media array must be of size 3");
        //print_r($doc->getMediaArray());
        foreach($doc->getMediaArray() as $media) {
            $this->assertInstanceOf('CorpusParole\Models\MediaResource', $media, "media msute of type MediaResource");
            // $this->assertArrayHasKey('format', $media, "media has 'format key'");
            // $this->assertArrayHasKey('url', $media, "media has url");
            // $this->assertCount(5, $media, "media is a 4 element array");
            // $this->assertArrayHasKey('extent', $media, "media has extent");
            // $this->assertArrayHasKey('extent_ms', $media, "media has extent_ms");
            // $this->assertArrayHasKey('master', $media, "media has master");

            //$this->assertEquals($media['url'], $url);

            $this->assertContains(
                $media->getUrl(),
                [ "http://cocoon.huma-num.fr/data/cfpp2000/Ozgur_Kilic_H_32_alii_3e-2.wav",
                  "http://cocoon.huma-num.fr/data/cfpp2000/Ozgur_Kilic_H_32_alii_3e-2.mp3",
                  "http://cocoon.huma-num.fr/data/archi/masters/372593.wav"
                ]
            );
            if($media->getUrl() === "http://cocoon.huma-num.fr/data/archi/masters/372593.wav") {
                $this->assertEquals('audio/x-wav', $media->getFormat());
                $this->assertTrue($media->isMaster() === true, "should be master");
            }
            else {
                $this->assertTrue($media->isMaster() === false, "should not be master");
            }

            $this->assertEquals("PT48M26S", $media->getExtent(), "extent is PT48M26S");
            $this->assertGreaterThan(0, $media->getExtentMs(), "extent_ms must be > 0");
            $this->assertStringStartsWith('audio/', $media->getFormat());
        }
    }

    public function testGetTypes() {
        $doc = new Document(config('corpusparole.corpus_doc_id_base_uri')."crdo-CFPP2000_35_SOUND", $this->graph);

        $this->assertCount(8, $doc->getTypes(), "types array must be of size 5");

        foreach($doc->getTypes() as $type) {
            $this->assertThat(
                $type,
                $this->logicalXor(
                    $this->isInstanceOf(EasyRdf\Literal::class),
                    $this->isInstanceOf(EasyRdf\Resource::class)
                )
            );
        }
    }

    public function testGetOtherTypes() {
        $doc = new Document(config('corpusparole.corpus_doc_id_base_uri')."crdo-CFPP2000_35_SOUND", $this->graph);

        $this->assertCount(5, $doc->getOtherTypes(), "types array must be of size 5");

        foreach($doc->getTypes() as $type) {
            $this->assertThat(
                $type,
                $this->logicalXor(
                    $this->isInstanceOf(EasyRdf\Literal::class),
                    $this->isInstanceOf(EasyRdf\Resource::class)
                )
            );
        }
    }

    public function testGetDiscourseTypes() {
        $doc = new Document(config('corpusparole.corpus_doc_id_base_uri')."crdo-CFPP2000_35_SOUND", $this->graph);

        $this->assertCount(3, $doc->getDiscourseTypes(), "types array must be of size 3");

        $this->assertContainsOnlyInstancesOf("EasyRdf\Literal", $doc->getDiscourseTypes(), "Result contains only literals");
        $type = $doc->getDiscourseTypes()[0];
        $this->assertEquals("narrative", $type->getValue(), "discourse type is narrative");
        $this->assertEquals("http://www.language-archives.org/OLAC/1.1/discourse-type", $type->getDatatypeUri(), "discourse type url");
    }

    public function testCloneDocument() {
        $doc = new Document(config('corpusparole.corpus_doc_id_base_uri')."crdo-CFPP2000_35_SOUND", $this->graph);

        $doc2 = clone $doc;

        $this->assertNotSame($doc, $doc2, "documents must not be the same");
        $this->assertNotSame($doc->getGraph(), $doc2->getGraph(), "documents must not be the same");

        $this->assertTrue(EasyRdf\Isomorphic::isomorphic($doc->getGraph(), $doc2->getGraph()),"graph must be isomorphic");
    }

    public function testIsIsomorphic() {
        $doc1 = new Document(config('corpusparole.corpus_doc_id_base_uri')."crdo-CFPP2000_35_SOUND", $this->graph);
        $doc2 = new Document(config('corpusparole.corpus_doc_id_base_uri')."crdo-CFPP2000_35_SOUND", new EasyRdf\Graph(config('corpusparole.corpus_doc_id_base_uri')."crdo-CFPP2000_35_SOUND", sprintf(DocumentTest::TEST_DOC, config('corpusparole.corpus_doc_id_base_uri'), config('corpusparole.corpus_id_scheme'))));

        $this->assertTrue($doc1->isIsomorphic($doc2),"document must be isomorphic");

        $doc2->addLiteral('dc11:type', new EasyRdf\Literal("oratory", null, Config::get('OLAC_DISCOURSE_TYPE')['uri']));

        $this->assertFalse($doc1->isIsomorphic($doc2),"document must not be isomorphic");
    }

    public function testUpdateDiscourseTypes() {

        $newDiscourseTypes = ['oratory','dialogue','narrative', 'formulaic', 'ludic'];

        $doc = new Document(config('corpusparole.corpus_doc_id_base_uri')."crdo-CFPP2000_35_SOUND", $this->graph);
        $this->assertCount(3, $doc->getDiscourseTypes(), "types array must be of size 3");

        $doc->updateDiscourseTypes($newDiscourseTypes);

        $this->assertCount(5, $doc->getDiscourseTypes(), "types array must be of size 5");

        $discourseTypes = $doc->getDiscourseTypes();
        foreach($newDiscourseTypes as $dt) {
            $this->assertContains($dt, $discourseTypes, "all discourse types must be in result list");
        }

    }

    public function testUpdateDiscourseTypesDelta() {

        $newDiscourseTypes = ['oratory','dialogue','narrative', 'formulaic', 'ludic'];

        $doc = new Document(config('corpusparole.corpus_doc_id_base_uri')."crdo-CFPP2000_35_SOUND", $this->graph);

        $doc->updateDiscourseTypes($newDiscourseTypes);

        $this->assertTrue($doc->isDirty());

        $this->assertEquals(1, $doc->deltaCount(), "There is one delta");

        $delta = $doc->getDeltaList()[0];

        $this->assertEquals(config('corpusparole.corpus_doc_id_base_uri')."crdo-CFPP2000_35_SOUND", $delta->getDeletedGraph()->getUri(), "uri of deleted graph must be ok");
        $this->assertEquals(config('corpusparole.corpus_doc_id_base_uri')."crdo-CFPP2000_35_SOUND", $delta->getAddedGraph()->getUri(), "uri of added graph must be ok");

        $this->assertEquals(3, $delta->getDeletedGraph()->countTriples(), "deleted graph must have only 3 triples");
        $this->assertEquals(5, $delta->getAddedGraph()->countTriples(), "deleted graph must have only 5 triples");

        $resQueryDiscourseType = $delta->getAddedGraph()->allLiterals($doc->getProvidedCHO(), 'dc11:type');
        foreach($resQueryDiscourseType as $dt) {
            $this->assertInstanceOf(EasyRdf\Literal::class, $dt, "This must be a litteral");
            $this->assertEquals('http://www.language-archives.org/OLAC/1.1/discourse-type', $dt->getDatatypeUri(), "The type of the Litteral must be correct");
        }
        foreach($newDiscourseTypes as $dt) {
            $this->assertContains($dt, $resQueryDiscourseType, "all discourse types must be in result list");
        }

    }

    public function testUpdateTitle() {
        $doc = new Document(config('corpusparole.corpus_doc_id_base_uri')."crdo-CFPP2000_35_SOUND", $this->graph);

        $oldTitle = $doc->getTitle();

        $doc->setTitle("new title", "en");

        $this->assertEquals("new title", $doc->getTitleValue());
        $this->assertEquals("new title", $doc->getTitle()->getValue());
        $this->assertEquals("en", $doc->getTitle()->getLang());

        $this->assertTrue($doc->isDirty());
        $this->assertEquals(1, $doc->deltaCount(), "There is one delta");

        $delta = $doc->getDeltaList()[0];

        $addedTitles = $delta->getAddedGraph()->allLiterals($doc->getProvidedCHO(), '<http://purl.org/dc/elements/1.1/title>');
        $this->assertCount(1, $addedTitles);

        $removedTitles = $delta->getDeletedGraph()->allLiterals($doc->getProvidedCHO(), '<http://purl.org/dc/elements/1.1/title>');
        $this->assertCount(1, $removedTitles);


    }

    public function testUpdateDiscourseTypesIsomorphic() {

        $newDiscourseTypes = ['oratory','dialogue','narrative'];

        $doc = new Document(config('corpusparole.corpus_doc_id_base_uri')."crdo-CFPP2000_35_SOUND", $this->graph);
        $doc->updateDiscourseTypes($newDiscourseTypes);

        $doc2 = new Document(config('corpusparole.corpus_doc_id_base_uri')."crdo-CFPP2000_35_SOUND", new EasyRdf\Graph(config('corpusparole.corpus_doc_id_base_uri')."crdo-CFPP2000_35_SOUND", sprintf(DocumentTest::TEST_DOC, config('corpusparole.corpus_doc_id_base_uri'), config('corpusparole.corpus_id_scheme'))));

        $this->assertFalse($doc->isIsomorphic($doc2),"document must not be isomorphic after adding discourse type");
    }

    public function testGetContributors() {
        $doc = new Document(config('corpusparole.corpus_doc_id_base_uri')."crdo-CFPP2000_35_SOUND", $this->graph);

        $contributors = $doc->getContributors();

        $this->assertNotEmpty($contributors, "The contributors array should not be empty");
        $this->assertCount(8, $contributors, "The contributors array should have 8 elements");

        foreach ($contributors as $contribDef) {
            $this->assertArrayHasKey('name', $contribDef, "ContribDef must have name key");
            $this->assertArrayHasKey('url', $contribDef, "ContribDef must have url key");
            $this->assertArrayHasKey('role', $contribDef, "ContribDef must have role key");
            $this->assertContains($contribDef['role'], CocoonUtils::OLAC_ROLES, "Role should be in OLAC_ROLES");
        }
    }

    public function testSetContributors() {
        $doc = new Document(config('corpusparole.corpus_doc_id_base_uri')."crdo-CFPP2000_35_SOUND", $this->graph);

        $contributors = $doc->getContributors();

        $contribList = [[
            "name"=> "Guylaine Brun-Trigaud",
            "url"=> "http://viaf.org/viaf/56666014",
            "role"=> "http://www.language-archives.org/OLAC/1.1/data_inputter"
        ], [
            "name"=> "LDOR",
            "url"=> null,
            "role"=> "http://www.language-archives.org/OLAC/1.1/depositor"
        ], [
            "name"=> "Thésaurus Occitan",
            "url"=> null,
            "role"=> "http://www.language-archives.org/OLAC/1.1/depositor"
        ], [
            "name"=> "Équipe de Recherche en Syntaxe et Sémantique",
            "url"=> null,
            "role"=> "http://www.language-archives.org/OLAC/1.1/editor"
        ], [
            "name"=> "Bases, corpus, langage",
            "url"=> null,
            "role"=> "http://www.language-archives.org/OLAC/1.1/editor"
        ], [
            "name"=> "Patrick Sauzet",
            "url"=> "http://viaf.org/viaf/51700729",
            "role"=> "http://www.language-archives.org/OLAC/1.1/researcher"
        ], [
            "name"=> "Alazet, Pierre",
            "url"=> null,
            "role"=> "http://www.language-archives.org/OLAC/1.1/speaker"
        ], [
            "name"=> "Del Duca, Jeanne",
            "url"=> null,
            "role"=> "http://www.language-archives.org/OLAC/1.1/transcriber"
        ], [
            "name"=> "Jane Austen, 1775-1817",
            "url"=> "http://viaf.org/viaf/102333412",
            "role"=> "http://www.language-archives.org/OLAC/1.1/compiler"
        ]];

        $doc->setContributors($contribList);

        $newContribs = $doc->getContributors();

        $this->assertCount(9, $newContribs);

        $this->assertTrue($doc->isDirty());
        $this->assertEquals(1, $doc->deltaCount(), "There is one delta");

        $delta = $doc->getDeltaList()[0];

        $addedGraph = $delta->getAddedGraph();
        $this->assertEquals(9, $addedGraph->countTriples());

        $removedGraph = $delta->getDeletedGraph();
        $this->assertEquals(count($contributors), $removedGraph->countTriples());

        $foundJaneAusten = false;
        foreach ($newContribs as $contribDef) {
            if(!is_null($contribDef['nameLiteral'])) {
                $lit = $contribDef['nameLiteral'];
                $this->assertNull($lit->getDatatype(), "Data type must be null $lit");
                $this->assertNotNull($lit->getLang(), "lang must not be null $lit");
            }
            if($contribDef['url'] == 'http://viaf.org/viaf/102333412') {
                $this->assertNull($contribDef['name'], 'Name must be null');
                $this->assertNull($contribDef['nameLiteral'], 'Name literal must be null');
                $foundJaneAusten = true;
            }
        }
        $this->assertTrue($foundJaneAusten, "Jane austenn not foud");

    }

    public function testGetSubjects() {
        $doc = new Document(config('corpusparole.corpus_doc_id_base_uri')."crdo-CFPP2000_35_SOUND", $this->graph);

        $subjects = $doc->getSubjects();

        $this->assertCount(28, $subjects, "Must have 28 subjects");

        foreach ($doc->getSubjects() as $s) {
            $this->assertThat(
                $s,
                $this->logicalXor(
                    $this->isInstanceOf('EasyRdf\Literal'),
                    $this->isInstanceOf('EasyRdf\Resource')
                )
            );
        }
    }

    public function testSetSubjects() {
        $doc = new Document(config('corpusparole.corpus_doc_id_base_uri')."crdo-CFPP2000_35_SOUND", $this->graph);

        $newSubjects = [
            "http://ark.bnf.fr/ark:/12148/cb13318415c",
            "http://ark.bnf.fr/ark:/12148/cb133188907",
            "http://ark.bnf.fr/ark:/12148/cb11932762f",
            "http://ark.bnf.fr/ark:/12148/cb133183660",
            "http://ark.bnf.fr/ark:/12148/cb122368540",
            "http://ark.bnf.fr/ark:/12148/cb119418302",
            "http://ark.bnf.fr/ark:/12148/cb135540729",
            "http://ark.bnf.fr/ark:/12148/cb133192210",
            "http://ark.bnf.fr/ark:/12148/cb119377452",
            "http://ark.bnf.fr/ark:/12148/cb13320451h",
            "http://ark.bnf.fr/ark:/12148/cb13318422n",
            "http://ark.bnf.fr/ark:/12148/cb11975823c"
        ];

        $doc->setSubjects($newSubjects);

        $this->assertTrue($doc->isDirty(), "The document must have changed");

        $subjects = $doc->getSubjects();

        $this->assertCount(12, $subjects, "Must have 12 subjects");

        foreach ($doc->getSubjects() as $s) {
            $this->assertInstanceOf('EasyRdf\Resource', $s, "Mustbe a Resource");
            $this->assertTrue(strrpos($s->getUri(), "http://ark.bnf.fr/ark:/12148/cb") === 0, "Must start with http://ark.bnf.fr/ark:/12148/cb");
            $this->assertContains($s->getUri(), $newSubjects, "$s must be in new subjects list");
            if(($key = array_search($s->getUri(), $newSubjects)) !== false) {
                unset($newSubjects[$key]);
            }
        }
        $this->assertEmpty($newSubjects, "all subjects must have been removed");
    }

    //TODO: test null transcript + null media array
    public function testJsonSerialize() {
        $doc = new Document(config('corpusparole.corpus_doc_id_base_uri')."crdo-CFPP2000_35_SOUND", $this->graph);

        $json = $doc->jsonSerialize();

        $this->assertTrue(is_array($json), 'Returned json must be an array');
        $this->assertEquals(
            ["id", "uri", "title", "language", "modified", "issued", "publishers", "contributors", "subjects", "transcript", "mediaArray"],
            array_keys($json)
        );
        $this->assertEquals(sprintf('%1$s/crdo-CFPP2000_35_SOUNDid', config('corpusparole.handle_prefix')), $json['id']);
        $this->assertTrue(is_array($json['transcript']));
        $this->assertTrue(is_array($json['mediaArray']));

    }


}