add rdf mapper + merger + basic database model
authorymh <ymh.work@gmail.com>
Tue, 17 Nov 2015 13:11:55 +0100
changeset 18 f2a40bbc27f6
parent 17 ac3dc090e987
child 19 eadaf0b8f02e
add rdf mapper + merger + basic database model
.hgignore
dev/Vagrantfile
dev/provisioning/playbook.yml
server/bo_client/bower.json
server/src/app/Console/Commands/ImportCocoonRDF.php
server/src/app/Libraries/CocoonUtils.php
server/src/app/Libraries/Mappers/CocoonAbstractRdfMapper.php
server/src/app/Libraries/Mappers/CocoonCollectionRdfMapper.php
server/src/app/Libraries/Mappers/CocoonContentRdfMapper.php
server/src/app/Libraries/Mappers/CocoonSoundRdfMapper.php
server/src/app/Libraries/Mappers/CocoonTextRdfMapper.php
server/src/app/Libraries/Mappers/RdfMapper.php
server/src/app/Libraries/Mergers/CocoonAbstractRdfMerger.php
server/src/app/Libraries/Mergers/CocoonCollectionRdfMerger.php
server/src/app/Libraries/Mergers/CocoonSoundRdfMerger.php
server/src/app/Libraries/Mergers/RdfMerger.php
server/src/app/Libraries/Utils.php
server/src/app/Models/CocoonDocument.php
server/src/app/Models/CocoonRevision.php
server/src/app/Models/Document.php
server/src/composer.json
server/src/composer.lock
server/src/config/corpusparole.php
server/src/database/migrations/2015_11_16_182634_create_cocoon_documents_table.php
server/src/database/migrations/2015_11_16_183307_create_cocoon_revisions_table.php
server/src/tests/libraries/Mappers/CocoonCollectionRdfMapperTest.php
server/src/tests/libraries/Mappers/CocoonSoundRdfMapperTest.php
server/src/tests/libraries/Mappers/CocoonTextRdfMapperTest.php
server/src/tests/libraries/Mergers/CocoonCollectionRdfMergerTest.php
server/src/tests/libraries/Mergers/CocoonSoundRdfMergerTest.php
--- a/.hgignore	Fri Nov 13 16:45:27 2015 +0100
+++ b/.hgignore	Tue Nov 17 13:11:55 2015 +0100
@@ -1,5 +1,6 @@
 syntax: regexp
 ^dev/\.vagrant
+^dev/corpus-dev.box$
 ^server/data
 ^server/src/\.git.*
 ^server/src/\.env
@@ -8,6 +9,7 @@
 ^server/src/node_modules
 ^server/src/bootstrap/cache/
 ^server/src/database/.*\.sqlite$
+^server/src/storage/.*\.sqlite$
 ^server/src/storage/laravel.log$
 ^server/src/storage/app/
 ^server/src/storage/logs/
--- a/dev/Vagrantfile	Fri Nov 13 16:45:27 2015 +0100
+++ b/dev/Vagrantfile	Tue Nov 17 13:11:55 2015 +0100
@@ -77,7 +77,7 @@
   # end
   #
   config.vm.provider "virtualbox" do |v|
-    v.memory = 512
+    v.memory = 1024
     v.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
   end
 
--- a/dev/provisioning/playbook.yml	Fri Nov 13 16:45:27 2015 +0100
+++ b/dev/provisioning/playbook.yml	Tue Nov 17 13:11:55 2015 +0100
@@ -237,19 +237,20 @@
       register: sesame_jar
 
     - name: download sesame
-      get_url: url=http://sourceforge.net/projects/sesame/files/Sesame%202/2.8.3/openrdf-sesame-2.8.3-sdk.tar.gz/download dest=/tmp/openrdf-sesame-2.8.3-sdk.tar.gz
+#http://sourceforge.net/projects/sesame/files/Sesame%204/4.0.0/openrdf-sesame-4.0.0-sdk.tar.gz/download
+      get_url: url=http://sourceforge.net/projects/sesame/files/Sesame%202/2.8.6/openrdf-sesame-2.8.6-sdk.tar.gz/download dest=/tmp/openrdf-sesame-2.8.6-sdk.tar.gz
       when: sesame_jar.stat.exists == False
 
     - name: create sesame untar dest
-      file: path=/tmp/openrdf-sesame-2.8.3-sdk state=directory
+      file: path=/tmp/openrdf-sesame-2.8.6-sdk state=directory
       when: sesame_jar.stat.exists == False
 
     - name: unarchive sesame
-      unarchive: src=/tmp/openrdf-sesame-2.8.3-sdk.tar.gz dest=/tmp/openrdf-sesame-2.8.3-sdk copy=false
+      unarchive: src=/tmp/openrdf-sesame-2.8.6-sdk.tar.gz dest=/tmp/openrdf-sesame-2.8.6-sdk copy=false
       when: sesame_jar.stat.exists == False
 
     - name: deploy sesame jar
-      shell: cp /tmp/openrdf-sesame-2.8.3-sdk/openrdf-sesame-2.8.3/war/*.war /var/lib/tomcat/webapps/
+      shell: cp /tmp/openrdf-sesame-2.8.6-sdk/openrdf-sesame-2.8.6/war/*.war /var/lib/tomcat/webapps/
       when: sesame_jar.stat.exists == False
 
     - name: create sesame data folder
@@ -259,7 +260,7 @@
     - name: update tomcat config
       lineinfile:
         dest: /etc/tomcat/tomcat.conf
-        line: 'JAVA_OPTS=\"${JAVA_OPTS} -Dinfo.aduna.platform.appdata.basedir=/var/lib/sesame/data\"'
+        line: 'JAVA_OPTS=\"${JAVA_OPTS} -Dinfo.aduna.platform.appdata.basedir=/var/lib/sesame/data -Xms512m -Xmx512m\"'
         state: present
       when: sesame_jar.stat.exists == False
 
@@ -268,10 +269,10 @@
       when: sesame_jar.stat.exists == False
 
     - name : delete sesame archive
-      file: path=/tmp/openrdf-sesame-2.8.3-sdk.tar.gz state=absent
+      file: path=/tmp/openrdf-sesame-2.8.6-sdk.tar.gz state=absent
 
     - name : delete sesame untar
-      file: path=/tmp/openrdf-sesame-2.8.3-sdk state=absent
+      file: path=/tmp/openrdf-sesame-2.8.6-sdk state=absent
 
 
 #set postgresql local access to trust
--- a/server/bo_client/bower.json	Fri Nov 13 16:45:27 2015 +0100
+++ b/server/bo_client/bower.json	Tue Nov 17 13:11:55 2015 +0100
@@ -1,10 +1,10 @@
 {
   "name": "bo-client",
   "dependencies": {
-    "ember": ">=2.0.0",
+    "ember": "2.1.0",
     "ember-cli-shims": "ember-cli/ember-cli-shims#0.0.3",
     "ember-cli-test-loader": "ember-cli-test-loader#0.1.3",
-    "ember-data": ">=2.0.0",
+    "ember-data": ">=2.1.0",
     "ember-load-initializers": "ember-cli/ember-load-initializers#0.1.5",
     "ember-qunit": "0.4.9",
     "ember-qunit-notifications": "0.0.7",
--- a/server/src/app/Console/Commands/ImportCocoonRDF.php	Fri Nov 13 16:45:27 2015 +0100
+++ b/server/src/app/Console/Commands/ImportCocoonRDF.php	Tue Nov 17 13:11:55 2015 +0100
@@ -12,6 +12,8 @@
 
 class ImportCocoonRDF extends Command {
 
+    const INSERT_TIMEOUT_RETRY = 5;
+
     /**
      * The console command description.
      *
@@ -58,6 +60,8 @@
         $progressBar = $this->output->createProgressBar($recs->getTotalRecordsInCollection());
         $progressBar->setFormat(' %current%/%max% [%bar%] %percent:3s%% - %message%');
 
+        $insertTimeouts = 0;
+
         foreach ($recs as $item) {
 
             $identifier = (string) $item->xpath('/record/header/identifier')[0];
@@ -72,6 +76,7 @@
             $progressBar->advance();
 
             $docUri = config('corpusparole.cocoon_doc_id_base_uri').substr($identifier, strlen(Config::get('corpusparole.cocoon_doc_id_base')));
+
             $resDocs = $gs->query("ASK WHERE { GRAPH <$docUri> { ?s ?p ?o }}");
             if(!$resDocs->getBoolean()) {
                 $docLoaded = false;
@@ -108,8 +113,23 @@
                 //TODO: treat errors
                 $subjects = $doc->resources();
                 $subject = reset($subjects)->getUri();
-                //TODO: exceptions ? but if pb on insert probably we have to fail anyway
-                $gs->insert($doc, $subject);
+                try {
+                    $gs->insert($doc, $subject);
+                }
+                catch(\Exception $e) {
+                    // just log not much we can do here...
+                    $this->error("\nError on insert $identifier ($docRdfUrl) : $e");
+                    Log::error("Error on insert $identifier ($docRdfUrl) : $e");
+                    $code = $e->getCode();
+                    $message = $e->getMessage();
+                    if($e instanceof EasyRdf\Exception && stripos($message, 'timed out')>=0 && $insertTimeout<= ImportCocoonRDF::INSERT_TIMEOUT_RETRY) {
+                        $this->info("\nThis is a timeout, we continue.");
+                        Log::info("This is a timeout, we continue.");
+                        $insertTimeouts++;
+                        continue;
+                    }
+                    throw $e;
+                }
             }
         }
         $progressBar->setMessage("finished");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/app/Libraries/CocoonUtils.php	Tue Nov 17 13:11:55 2015 +0100
@@ -0,0 +1,28 @@
+<?php
+namespace CorpusParole\Libraries;
+
+class CocoonUtils {
+
+    /**
+     * Extract id form cocoon url.
+     *
+     * @return string
+     */
+    public static function getIdFromUri($uri) {
+        return substr($uri, strlen(config('corpusparole.cocoon_doc_id_base_uri')));
+    }
+
+    /**
+     * Create a Corpus resource id (purl url)
+     *
+     * @return string
+     */
+    public static function getCorpusUriFromId($id) {
+        return rtrim(config('corpusparole.corpus_doc_id_base_uri'),'/')."/$id";
+    }
+
+    public static function getCocoonPubUrl($id) {
+        return rtrim(config('corpusparole.cocoon_doc_pub_base_uri'), '/')."/$id";
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/app/Libraries/Mappers/CocoonAbstractRdfMapper.php	Tue Nov 17 13:11:55 2015 +0100
@@ -0,0 +1,143 @@
+<?php
+namespace CorpusParole\Libraries\Mappers;
+
+use Config;
+
+use CorpusParole\Libraries\Utils;
+use CorpusParole\Libraries\CocoonUtils;
+
+use EasyRdf\RdfNamespace;
+use EasyRdf\Graph;
+use EasyRdf\Literal;
+use EasyRdf\Resource;
+
+
+RdfNamespace::set('edm', 'http://www.europeana.eu/schemas/edm/');
+RdfNamespace::set('ore', 'http://www.openarchives.org/ore/terms/');
+RdfNamespace::set('crdo', 'http://crdo.risc.cnrs.fr/schemas/');
+RdfNamespace::set('olac', 'http://www.language-archives.org/OLAC/1.1/');
+RdfNamespace::set('skos', 'http://www.w3.org/2004/02/skos/core#');
+
+
+/**
+ *
+ */
+abstract class CocoonAbstractRdfMapper implements RdfMapper {
+
+    public function __construct(Graph $inputGraph) {
+        $this->inputGraph = $inputGraph;
+        $this->uri = $inputGraph->getUri();
+        $this->outputGraphes = [];
+    }
+
+    abstract protected function mapResource($res, $outputGraph);
+    abstract protected function getResourceBaseId($res=null);
+
+    public function getOutputGraphes() {
+        return $this->outputGraphes;
+    }
+
+    /**
+     * Map a Cocoon Rdf Graph to a CP graph
+     * @return the new mapped graph
+     */
+    public function mapGraph() {
+
+        $outputGraph = $this->buildOutputGraph();
+
+        $resources = $this->inputGraph->allOfType('crdo:Resource');
+        foreach ($resources as $res) {
+            $this->mapResource($res, $outputGraph);
+        }
+    }
+
+    /**
+     * Build the main outputgraph
+     * @return the new empty graph
+     */
+     protected function buildOutputGraph() {
+
+         //$soundRes = $this->inputGraph->resource($this->uri)->get('http://purl.org/dc/terms/requires');
+         $id = CocoonUtils::getIdFromUri($this->getResourceBaseId());
+
+         $outputGraph = new Graph(CocoonUtils::getCorpusUriFromId($id));
+         $this->outputGraphes[$this->getResourceBaseId()] = $outputGraph;
+
+         return $outputGraph;
+     }
+
+
+    protected function propertyOlacRoleMap($targetRes, $prop, $value) {
+        $targetRes->add($prop, $value);
+        $targetRes->add('http://purl.org/dc/elements/1.1/contributor', $value);
+    }
+
+    protected function propertyIdentityMap($targetRes, $prop, $value) {
+        $targetRes->add($prop, $value);
+    }
+
+    protected function propertyTrimMap($providedCHOResource, $prop, $value) {
+        $providedCHOResource->add($prop, trim($value));
+    }
+
+    protected function addSpatialProperties($destRes, $res, $outputGraph) {
+        $spatials = $res->all($this->inputGraph->resource('http://purl.org/dc/terms/spatial'));
+        $lats = $res->all($this->inputGraph->resource('http://www.w3.org/2003/01/geo/wgs84_pos#lat'));
+        $longs = $res->all($this->inputGraph->resource('http://www.w3.org/2003/01/geo/wgs84_pos#long'));
+        $alts = $res->all($this->inputGraph->resource('http://www.w3.org/2003/01/geo/wgs84_pos#alt'));
+
+        if( count($spatials) > 0 || count($lats) > 0 || count($longs) > 0 || count($alts)) {
+            $placeNode = $outputGraph->newBNode(['edm:Place']);
+            foreach($lats as $latitude) {
+                $placeNode->addLiteral('http://www.w3.org/2003/01/geo/wgs84_pos#lat', $latitude);
+            }
+            foreach($longs as $longitude) {
+                $placeNode->addLiteral('http://www.w3.org/2003/01/geo/wgs84_pos#long', $longitude);
+            }
+            foreach($spatials as $s) {
+                if($s instanceof Literal) {
+                    $placeNode->addLiteral('skos:note', $s);
+                }
+                elseif ($s instanceof Resource) {
+                    $placeNode->addResource('owl:sameAs', $s);
+                }
+            }
+            $destRes->add($outputGraph->resource('http://purl.org/dc/terms/spatial'), $placeNode);
+        }
+    }
+
+    protected function applyPropertiesToRes($sourceRes, $targetRes, $properties) {
+
+        foreach( $properties as list($prop, $mappingMethod)) {
+            if( is_null($mappingMethod) ) {
+                $mappingMethod = 'propertyIdentityMap';
+            }
+
+            foreach($sourceRes->all($this->inputGraph->resource($prop)) as $value) {
+                call_user_func(array($this, $mappingMethod), $targetRes, $prop, $value);
+            }
+        }
+    }
+
+    protected function addDateProperties($targetRes, $res, $outputGraph) {
+        $this->applyPropertiesToRes($res, $targetRes, [
+            ['http://purl.org/dc/terms/available', null],
+            ['http://purl.org/dc/terms/created', null],
+            ['http://purl.org/dc/terms/issued', null],
+            ['http://purl.org/dc/terms/modified', null],
+        ]);
+    }
+
+    protected function mapCollections($res) {
+        $collections = $res->all('dc:isPartOf');
+        foreach($collections as $coll) {
+            if($coll instanceof Resource) {
+                $collectionGraph = new Graph($coll->getUri());
+                $this->outputGraphes[$coll->getUri()] = $collectionGraph;
+                $collectionGraph->resource($coll->getUri(), 'edm:Collection');
+            }
+        }
+    }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/app/Libraries/Mappers/CocoonCollectionRdfMapper.php	Tue Nov 17 13:11:55 2015 +0100
@@ -0,0 +1,138 @@
+<?php
+namespace CorpusParole\Libraries\Mappers;
+
+use EasyRdf\Graph;
+
+//<http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_ALA_CL> a <http://crdo.risc.cnrs.fr/schemas/Resource> ;
+//	<http://purl.org/dc/elements/1.1/description> """Cette série d'entretiens semi-dirigés avait comme objectif de susciter un discours
+//            sur les pratiques linguistiques des locuteurs. Les locuteurs se sont exprimés dans la langue de leur choix.
+//            Le questionnaire servant de trame à l'entretien comportait les volets suivants :
+//            # la biographie sociolinguistique
+//            # la délimitation de l'espace de vie et de l'espace linguistique d'appartenance
+//            # l'auto-évaluation des compétences linguistiques en alsacien, en français et en allemand
+//            # les normes linguistiques des trois variétés
+//            # les variations (alsacien, français, allemand)
+//            # les pratiques linguistiques et langagières
+//            # l'idéologie linguistique (rapport langue / identité, dialecte / école …)."""@fr ;
+//    <http://purl.org/dc/elements/1.1/type> "primary_text"^^<http://www.language-archives.org/OLAC/1.1/linguistic-type> , "dialogue"^^<http://www.language-archives.org/OLAC/1.1/discourse-type> , <http://purl.org/dc/dcmitype/Collection> , "lexicon"^^<http://www.language-archives.org/OLAC/1.1/linguistic-type> ;
+//    <http://purl.org/dc/elements/1.1/subject> <http://lexvo.org/id/iso639-3/gsw> ;
+//    <http://purl.org/dc/elements/1.1/language> <http://lexvo.org/id/iso639-3/gsw> ;
+//    <http://www.language-archives.org/OLAC/1.1/depositor> <http://viaf.org/viaf/9122216> ;
+//    <http://purl.org/dc/elements/1.1/publisher> "Atlas linguistiques, cultures et parlers régionaux de France" ;
+//    <http://purl.org/dc/elements/1.1/rights> "Copyright (c) Département de dialectologie alsacienne et mosellane de l'Université de Strasbourg" ;
+//    <http://purl.org/dc/elements/1.1/title> "Atlas Linguistique et ethnographique de l'Alsace: Enquêtes sur la conscience linguistique"@fr ;
+//    <http://purl.org/dc/terms/accessRights> "Freely available for non-commercial use" ;
+//    <http://purl.org/dc/terms/license> <http://creativecommons.org/licenses/by-nc-nd/2.5/> ;
+//    <http://purl.org/dc/terms/isPartOf> <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_ALA> ;
+//    <http://purl.org/dc/terms/created> "start=1988; end=1989"^^<http://purl.org/dc/terms/Period> ;
+//    <http://purl.org/dc/terms/spatial> "France, Alsace"@fr , "FR"^^<http://purl.org/dc/terms/ISO3166> ;
+//    <http://purl.org/dc/terms/available> "2014-04-18"^^<http://purl.org/dc/terms/W3CDTF> ;
+//    <http://purl.org/dc/terms/issued> "2015-07-09T09:40:21 02:00"^^<http://purl.org/dc/terms/W3CDTF> ;
+//    <http://www.language-archives.org/OLAC/1.1/transcriber> "Huck, Dominique" ;
+//    <http://www.language-archives.org/OLAC/1.1/researcher> "Bothorel-Witz, Arlette" .
+
+// http://purl.org/dc/elements/1.1/description
+// http://purl.org/dc/elements/1.1/language
+// http://purl.org/dc/elements/1.1/publisher
+// http://purl.org/dc/elements/1.1/rights
+// http://purl.org/dc/elements/1.1/subject
+// http://purl.org/dc/elements/1.1/title
+// http://purl.org/dc/elements/1.1/type
+// http://purl.org/dc/terms/accessRights
+// http://purl.org/dc/terms/available
+// http://purl.org/dc/terms/created
+// http://purl.org/dc/terms/issued
+// http://purl.org/dc/terms/license
+// http://purl.org/dc/terms/spatial
+// http://www.language-archives.org/OLAC/1.1/depositor
+// http://www.language-archives.org/OLAC/1.1/researcher
+// http://www.language-archives.org/OLAC/1.1/transcriber
+// http://purl.org/dc/terms/isPartOf
+// http://www.language-archives.org/OLAC/1.1/compiler
+// http://www.language-archives.org/OLAC/1.1/data_inputter
+// http://www.language-archives.org/OLAC/1.1/developer
+// http://www.language-archives.org/OLAC/1.1/interviewer
+// http://www.language-archives.org/OLAC/1.1/sponsor
+// http://www.w3.org/2003/01/geo/wgs84_pos#lat
+// http://www.w3.org/2003/01/geo/wgs84_pos#long
+
+class CocoonCollectionRdfMapper extends CocoonAbstractRdfMapper {
+
+    protected function getResourceBaseId($res=null) {
+
+        if(is_null($res)) {
+            $res = $this->inputGraph->resource($this->uri);
+        }
+        return $res->getUri();
+    }
+
+    /**
+     * Build the main outputgraph
+     * @return the new empty graph
+     */
+     protected function buildOutputGraph() {
+
+         $outputGraph = new Graph($this->uri);
+         $this->outputGraphes[$this->getResourceBaseId()] = $outputGraph;
+
+         return $outputGraph;
+     }
+
+
+    protected function mapResource($res, $outputGraph) {
+        $resUri = $res->getUri();
+
+        $collNode = $outputGraph->resource($resUri, 'edm:Collection');
+
+        $this->addSimpleProperties($collNode, $res);
+        $this->addDateProperties($collNode, $res, $outputGraph);
+        $this->addSpatialProperties($collNode, $res, $outputGraph);
+
+        $this->mapCollections($res);
+    }
+
+
+    protected function addSimpleProperties($targetRes, $sourceRes) {
+        $this->applyPropertiesToRes($sourceRes, $targetRes, [
+            ['http://purl.org/dc/elements/1.1/description', null],
+            ['http://purl.org/dc/elements/1.1/language', null],
+            ['http://purl.org/dc/elements/1.1/publisher', null],
+            ['http://purl.org/dc/elements/1.1/rights', null],
+            ['http://purl.org/dc/elements/1.1/type', null],
+            ['http://purl.org/dc/terms/license', null],
+            ['http://purl.org/dc/elements/1.1/subject', null],
+            ['http://purl.org/dc/elements/1.1/title', null],
+            ['http://purl.org/dc/elements/1.1/language', null],
+            ['http://purl.org/dc/terms/accessRights', 'propertyTrimMap'],
+            ['http://purl.org/dc/terms/extent', null],
+            ['http://purl.org/dc/terms/isPartOf', null],
+            ['http://www.language-archives.org/OLAC/1.1/annotator', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/author', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/compiler', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/consultant', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/data_inputter', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/depositor', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/developer', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/editor', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/illustrator', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/interpreter', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/interviewer', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/participant', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/performer', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/photographer', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/recorder', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/researcher', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/research_participant', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/responder', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/signer', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/singer', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/speaker', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/sponsor', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/transcriber', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/translator', 'propertyOlacRoleMap'],
+        ]);
+    }
+
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/app/Libraries/Mappers/CocoonContentRdfMapper.php	Tue Nov 17 13:11:55 2015 +0100
@@ -0,0 +1,159 @@
+<?php
+namespace CorpusParole\Libraries\Mappers;
+
+use CorpusParole\Libraries\CocoonUtils;
+
+use EasyRdf\Graph;
+use EasyRdf\Literal;
+use EasyRdf\Resource;
+
+
+abstract class CocoonContentRdfMapper extends CocoonAbstractRdfMapper {
+
+
+    protected function mapResource($res, $outputGraph) {
+        $this->mapMainGraph($res, $outputGraph);
+        //map collection
+        $this->mapCollections($res);
+    }
+
+    abstract protected function mapWebResources($res, $outputGraph);
+
+    protected function mapMainGraph($res, $outputGraph) {
+        $this->mapAggregationNode($res, $outputGraph);
+        $this->mapProvidedCHO($res, $outputGraph);
+        $this->mapWebResources($res, $outputGraph);
+    }
+
+    /**
+     * Build the aggregation node
+     */
+    protected function mapAggregationNode($res, $outputGraph) {
+        $resId = CocoonUtils::getIdFromUri($this->getResourceBaseId($res));
+        $resUri = CocoonUtils::getCorpusUriFromId($resId);
+
+        $aggregationNode = $outputGraph->resource($resUri, 'ore:Aggregation');
+
+        $aggregationResource = $aggregationNode->addResource('edm:aggregatedCHO', $this->getResourceBaseId($res));
+
+        $aggregationNode->addLiteral('edm:provider', config('corpusparole.edm_provider'), 'fr');
+
+        $publishersInputs = $res->all($this->inputGraph->resource('http://purl.org/dc/elements/1.1/publisher'));
+        if(count($publishersInputs) == 0) {
+            $provider = Literal::create(config('corpusparole.edm_provider'), 'fr');
+        }
+        else {
+            $provider = $publishersInputs[0];
+            //TODO: if this is a resource, get id from it (viaf)
+        }
+        $aggregationNode->add('edm:dataProvider', $provider);
+
+        $aggregationNode->addResource('edm:isShownAt', CocoonUtils::getCocoonPubUrl($resId));
+
+        $master = null;
+        $masterList = $res->all($this->inputGraph->resource('http://crdo.risc.cnrs.fr/schemas/master'));
+        if(count($masterList)==0) {
+            $masterList = $res->all($this->inputGraph->resource('http://purl.org/dc/terms/isFormatOf'));
+        }
+        if(count($masterList)>0) {
+            $aggregationNode->add('edm:isShownBy', $masterList[0]);
+        }
+
+        $license = $res->get('dc:license');
+        $matches = [];
+
+        if( ($license instanceof Resource) &&
+            (preg_match('/http\:\/\/creativecommons\.org\/licenses\/([a-z-]+)\/[\d\.]+\//', $license->getUri(), $matches) > 0) ) {
+            $license = "http://creativecommons.org/licenses/$matches[1]/4.0/";
+        }
+        else {
+            $license = config('corpusparole.corpus_doc_default_cc_rights');
+        }
+
+        $aggregationNode->addResource('edm:rights', $license);
+    }
+
+    protected function propertyTypeMap($providedCHOResource, $prop, $value) {
+        $providedCHOResource->add($prop, $value);
+    }
+
+    protected function propertyReferenceCorrectMap($providedCHOResource, $prop, $value) {
+        $providedCHOResource->add('http://purl.org/dc/terms/references', $value);
+    }
+
+    /**
+     * Build the provided CHO.
+     */
+    private function mapProvidedCHO($res, $outputGraph) {
+
+        $providedCHOResource = $outputGraph->resource($this->getResourceBaseId($res), 'edm:ProvidedCHO');
+
+        $this->addCHOResourceProperties($providedCHOResource, $res, $outputGraph);
+
+        $this->addDateProperties($providedCHOResource, $res, $outputGraph);
+        $this->addSpatialProperties($providedCHOResource, $res, $outputGraph);
+
+    }
+
+    protected function addCHOResourceProperties($providedCHOResource, $res, $outputGraph) {
+        $this->applyPropertiesToRes($res, $providedCHOResource, [
+            ['http://purl.org/dc/terms/tableOfContents', null],
+            ['http://purl.org/dc/elements/1.1/description', null],
+            ['http://purl.org/dc/elements/1.1/language', null],
+            ['http://purl.org/dc/elements/1.1/publisher', null],
+            ['http://purl.org/dc/elements/1.1/rights', null],
+            ['http://purl.org/dc/elements/1.1/type', 'propertyTypeMap'],
+            ['http://purl.org/dc/terms/license', null],
+            ['http://purl.org/dc/elements/1.1/subject', null],
+            ['http://purl.org/dc/elements/1.1/title', null],
+            ['http://purl.org/dc/elements/1.1/language', null],
+            ['http://purl.org/dc/terms/accessRights', 'propertyTrimMap'],
+            ['http://purl.org/dc/terms/extent', null],
+            ['http://purl.org/dc/terms/isPartOf', null],
+            ['http://purl.org/dc/elements/1.1/source', null],
+            ['http://purl.org/dc/terms/medium', null],
+            ['http://purl.org/dc/terms/alternative', null],
+            ['http://purl.org/dc/terms/bibliographicCitation', null],
+            ['http://purl.org/dc/elements/1.1/identifier', null],
+            ['http://purl.org/dc/terms/references', null],
+            ['http://purl.org/dc/elements/1.1/reference', 'propertyReferenceCorrectMap'],
+            ['http://purl.org/dc/elements/1.1/coverage', null],
+            ['http://purl.org/dc/elements/1.1/relation', null],
+            ['http://purl.org/dc/elements/1.1/creator', null],
+            ['http://www.language-archives.org/OLAC/1.1/annotator', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/author', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/compiler', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/consultant', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/data_inputter', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/depositor', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/developer', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/editor', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/illustrator', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/interpreter', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/interviewer', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/participant', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/performer', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/photographer', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/recorder', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/researcher', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/research_participant', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/responder', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/signer', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/singer', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/speaker', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/sponsor', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/transcriber', 'propertyOlacRoleMap'],
+            ['http://www.language-archives.org/OLAC/1.1/translator', 'propertyOlacRoleMap'],
+        ]);
+
+    }
+
+    protected function addDateToWebResource($sourceRes, $targetRes) {
+
+        $this->applyPropertiesToRes($sourceRes, $targetRes, [
+            ['http://purl.org/dc/terms/created', null],
+            ['http://purl.org/dc/terms/issued', null],
+        ]);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/app/Libraries/Mappers/CocoonSoundRdfMapper.php	Tue Nov 17 13:11:55 2015 +0100
@@ -0,0 +1,142 @@
+<?php
+namespace CorpusParole\Libraries\Mappers;
+
+use Config;
+
+use CorpusParole\Libraries\Utils;
+use CorpusParole\Libraries\CocoonUtils;
+
+use EasyRdf\Graph;
+use EasyRdf\Literal;
+use EasyRdf\Resource;
+
+
+/**
+ *
+ * rdf:type
+ * sesame:directType
+ ** <http://purl.org/dc/elements/1.1/description> -> providedCHO
+ * <http://purl.org/dc/elements/1.1/format> -> webRepresentation
+ * <http://purl.org/dc/elements/1.1/language> -> providedCHO
+ * <http://purl.org/dc/elements/1.1/publisher> -> providedCHO
+ * <http://purl.org/dc/elements/1.1/rights> -> providedCHO
+ * <http://purl.org/dc/elements/1.1/subject> -> providedCHO
+ * <http://purl.org/dc/elements/1.1/title> -> providedCHO
+ * <http://purl.org/dc/elements/1.1/type> -> providedCHO
+ * <http://purl.org/dc/terms/accessRights> -> providedCHO
+ * <http://purl.org/dc/terms/available> -> providedCHO
+ * <http://purl.org/dc/terms/conformsTo> -> for text -> webRepresentation (2 val : http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-dtd_transcriber : transcript, http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-dtd_archive)
+ * <http://purl.org/dc/terms/created> -> providedCHO
+ * <http://purl.org/dc/terms/isFormatOf> -> webResource
+ *** <http://purl.org/dc/terms/isPartOf> ->collections
+ * <http://purl.org/dc/terms/issued> -> providedCHO
+ * <http://purl.org/dc/terms/license> -> providedCHO
+ *** <http://purl.org/dc/terms/requires> -> transcriptions
+ * <http://www.language-archives.org/OLAC/1.1/data_inputter> -> providedCHO
+ * <http://www.language-archives.org/OLAC/1.1/depositor> -> providedCHO
+ * <http://www.language-archives.org/OLAC/1.1/editor> -> providedCHO
+ * <http://www.language-archives.org/OLAC/1.1/interviewer> -> providedCHO
+ * <http://www.language-archives.org/OLAC/1.1/researcher> -> providedCHO
+ * <http://www.language-archives.org/OLAC/1.1/speaker> -> providedCHO
+ * <http://www.language-archives.org/OLAC/1.1/transcriber> -> providedCHO
+ * <http://www.language-archives.org/OLAC/1.1/participant> -> providedCHO
+ * <http://www.language-archives.org/OLAC/1.1/compiler> -> providedCHO
+ * <http://www.language-archives.org/OLAC/1.1/interpreter> -> providedCHO
+ * <http://www.language-archives.org/OLAC/1.1/author> -> providedCHO
+ * <http://www.language-archives.org/OLAC/1.1/translator> -> providedCHO
+ * <http://www.language-archives.org/OLAC/1.1/signer> -> providedCHO
+ * <http://www.language-archives.org/OLAC/1.1/recorder> -> providedCHO
+ * <http://www.language-archives.org/OLAC/1.1/responder> -> providedCHO
+ * <http://www.language-archives.org/OLAC/1.1/developer> -> providedCHO
+ * <http://www.language-archives.org/OLAC/1.1/sponsor> -> providedCHO
+ * <http://www.language-archives.org/OLAC/1.1/annotator> -> providedCHO
+ * <http://www.language-archives.org/OLAC/1.1/singer> -> providedCHO
+ * <http://www.language-archives.org/OLAC/1.1/consultant> -> providedCHO
+ * <http://www.language-archives.org/OLAC/1.1/research_participant> -> providedCHO
+ * <http://crdo.risc.cnrs.fr/schemas/master> -> webRepresentation
+ * <http://purl.org/dc/terms/extent> -> webRepresentation
+ * <http://purl.org/dc/terms/isRequiredBy> -> transcriptions
+ * <http://purl.org/dc/terms/spatial> -> edm:Place
+ * <http://www.w3.org/2003/01/geo/wgs84_pos#lat> -> edm:Place
+ * <http://www.w3.org/2003/01/geo/wgs84_pos#long> -> edm:Place
+ * <http://purl.org/dc/elements/1.1/source> -> providedCHO
+ * <http://purl.org/dc/terms/tableOfContents> -> providedCHO
+ * <http://purl.org/dc/terms/alternative> -> providedCHO
+ * <http://purl.org/dc/terms/modified> -> providedCHO
+ * <http://purl.org/dc/terms/abstract> -> providedCHO
+ * <http://purl.org/dc/elements/1.1/identifier> -> providedCHO but question...
+ * <http://purl.org/dc/terms/medium> -> providedCHO
+ * <http://purl.org/dc/elements/1.1/coverage> -> providedCHO
+ * <http://purl.org/dc/elements/1.1/relation> - providedCHO
+ * <http://purl.org/dc/terms/description> -> ProvidedCHO
+ * <http://purl.org/dc/terms/bibliographicCitation> -> providedCHO
+ * <http://purl.org/dc/elements/1.1/creator> -> providedCHO
+ * <http://purl.org/dc/terms/references> -> providedCHO
+ * <http://purl.org/dc/elements/1.1/reference> -> providedCHO
+ *
+ * pour olac : http://quijote.fdi.ucm.es:8084/LLOD-LSASummerWorkshop2015/Presentations/Simons--OLAC%20Metadata.pdf
+ * DATA consolidation
+ * -> edm:place : get label + altLabel
+ */
+class CocoonSoundRdfMapper extends CocoonContentRdfMapper {
+
+    protected function getResourceBaseId($res=null) {
+
+        if(is_null($res)) {
+            $res = $this->inputGraph->resource($this->uri);
+        }
+        return $res->getUri();
+    }
+
+    /**
+     * Build teh webresources
+     */
+    protected function mapWebResources($res, $outputGraph) {
+
+        $resId = CocoonUtils::getIdFromUri($res->getUri());
+        $resUri = CocoonUtils::getCorpusUriFromId($resId);
+
+
+        $aggregationNode = $outputGraph->resource($resUri, 'ore:Aggregation');
+
+        // get extent
+        $extent = $res->get($this->inputGraph->resource('http://purl.org/dc/terms/extent'));
+
+        // build master webresources
+        $masterReprUrl = $res->get($this->inputGraph->resource('http://crdo.risc.cnrs.fr/schemas/master'));
+        if(! is_null($masterReprUrl)) {
+            $masterWebResource = $outputGraph->resource($masterReprUrl, 'edm:WebResources');
+            if(!is_null($extent)) {
+                $masterWebResource->addLiteral($outputGraph->resource('http://purl.org/dc/terms/extent'),$extent);
+            }
+            $formatAdded = false;
+            foreach($res->all($this->inputGraph->resource('http://purl.org/dc/elements/1.1/format')) as $wrformat) {
+                $masterWebResource->addLiteral('http://purl.org/dc/elements/1.1/format', $wrformat);
+                $formatAdded = true;
+            }
+            if(!$formatAdded) {
+                $mimetype = Utils::getMimetype($masterReprUrl);
+                $masterWebResource->addLiteral('http://purl.org/dc/elements/1.1/format', Literal::create($mimetype, null, $outputGraph->resource('http://purl.org/dc/terms/IMT')));
+            }
+
+            $this->addDateToWebResource($res, $masterWebResource);
+
+        }
+
+        // build others
+        foreach($res->all($this->inputGraph->resource('http://purl.org/dc/terms/isFormatOf')) as $reprUrl) {
+            $webResource = $outputGraph->resource($reprUrl, 'edm:WebResources');
+            if(!is_null($extent)) {
+                $webResource->addLiteral($outputGraph->resource('http://purl.org/dc/terms/extent'),$extent);
+            }
+            $mimetype = Utils::getMimetype($reprUrl);
+            $webResource->addLiteral('http://purl.org/dc/elements/1.1/format', Literal::create($mimetype, null, $outputGraph->resource('http://purl.org/dc/terms/IMT')));
+
+            if(!is_null($masterReprUrl)) {
+                $webResource->addResource('edm:isDerivativeOf', $masterReprUrl);
+            }
+            $this->addDateToWebResource($res, $webResource);
+            $aggregationNode->addResource('edm:hasView', $reprUrl);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/app/Libraries/Mappers/CocoonTextRdfMapper.php	Tue Nov 17 13:11:55 2015 +0100
@@ -0,0 +1,165 @@
+<?php
+namespace CorpusParole\Libraries\Mappers;
+
+use Config;
+
+use CorpusParole\Libraries\Utils;
+use CorpusParole\Libraries\CocoonUtils;
+
+use EasyRdf\RdfNamespace;
+use EasyRdf\Graph;
+use EasyRdf\Literal;
+use EasyRdf\Resource;
+
+/**
+ * <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-UVE_MOCIKA> a <http://crdo.risc.cnrs.fr/schemas/Resource> ;
+ * 	<http://purl.org/dc/elements/1.1/description> "Voilà pourquoi le bernard-l'hermite, aujourd'hui, se cache dans les coquilles vides qu'il trouve, alors que le crabe de cocotier n'a pas honte de se promener tout nu."@fr ;
+ * 	<http://purl.org/dc/elements/1.1/format> "text/xml"^^<http://purl.org/dc/terms/IMT> ;
+ * 	<http://purl.org/dc/elements/1.1/type> "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> ;
+ * 	<http://purl.org/dc/elements/1.1/subject> <http://lexvo.org/id/iso639-3/uve> ;
+ * 	<http://purl.org/dc/elements/1.1/language> <http://lexvo.org/id/iso639-3/uve> ;
+ * 	<http://www.language-archives.org/OLAC/1.1/depositor> <http://viaf.org/viaf/56614135> ;
+ * 	<http://purl.org/dc/elements/1.1/publisher> <http://viaf.org/viaf/154919513> ;
+ * 	<http://purl.org/dc/elements/1.1/rights> "Copyright (c) Moyse-Faurie, Claire" ;
+ * 	<http://purl.org/dc/elements/1.1/title> "The two hermit crabs and the coconut crab"@en ;
+ * 	<http://purl.org/dc/terms/isFormatOf> <http://cocoon.huma-num.fr/exist/crdo/moyse-faurie/uve/crdo-UVE_MOCIKA.xml> , <http://cocoon.huma-num.fr/exist/crdo/moyse-faurie/uve/crdo-UVE_MOCIKA.xhtml> ;
+ * 	<http://purl.org/dc/terms/accessRights> "Freely available for non-commercial use" ;
+ * 	<http://purl.org/dc/terms/license> <http://creativecommons.org/licenses/by-nc-sa/2.5/> ;
+ * 	<http://purl.org/dc/terms/isPartOf> <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_LANGUESDEFRANCE> , <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_LACITO> ;
+ * 	<http://purl.org/dc/terms/spatial> "NC"^^<http://purl.org/dc/terms/ISO3166> , "New Caledonia, Ohnyat (Ouvéa)" ;
+ * 	<http://purl.org/dc/terms/available> "2011-02-05"^^<http://purl.org/dc/terms/W3CDTF> ;
+ * 	<http://purl.org/dc/terms/issued> "2011-02-05T23:22:23+01:00"^^<http://purl.org/dc/terms/W3CDTF> ;
+ * 	<http://www.language-archives.org/OLAC/1.1/speaker> "Idakote, Félicien" ;
+ * 	<http://purl.org/dc/terms/requires> <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-UVE_MOCIKA_SOUND> ;
+ * 	<http://purl.org/dc/terms/alternative> "Les deux bernard-l'hermite et le crabe de cocotier"@fr ;
+ * 	<http://www.language-archives.org/OLAC/1.1/researcher> "Moyse-Faurie, Claire" ;
+ * 	<http://purl.org/dc/terms/modified> "2002-02-20"^^<http://purl.org/dc/terms/W3CDTF> ;
+ * 	<http://purl.org/dc/terms/conformsTo> <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-dtd_archive> .
+ *
+ * <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-UVE_MOCIKA_SOUND> a <http://crdo.risc.cnrs.fr/schemas/Resource> ;
+ * 	<http://purl.org/dc/elements/1.1/format> "audio/x-wav"^^<http://purl.org/dc/terms/IMT> ;
+ * 	<http://purl.org/dc/elements/1.1/type> <http://purl.org/dc/dcmitype/Sound> , "primary_text"^^<http://www.language-archives.org/OLAC/1.1/linguistic-type> , "narrative"^^<http://www.language-archives.org/OLAC/1.1/discourse-type> ;
+ * 	<http://purl.org/dc/elements/1.1/subject> <http://lexvo.org/id/iso639-3/uve> ;
+ * 	<http://purl.org/dc/elements/1.1/language> <http://lexvo.org/id/iso639-3/uve> ;
+ * 	<http://www.language-archives.org/OLAC/1.1/depositor> <http://viaf.org/viaf/56614135> ;
+ * 	<http://purl.org/dc/elements/1.1/publisher> <http://viaf.org/viaf/154919513> ;
+ * 	<http://purl.org/dc/elements/1.1/rights> "Copyright (c) Moyse-Faurie, Claire" ;
+ * 	<http://purl.org/dc/elements/1.1/title> "The two hermit crabs and the coconut crab"@en ;
+ * 	<http://purl.org/dc/terms/isFormatOf> <http://cocoon.huma-num.fr/data/archi/144187_MOCIKA_22km.wav> , <http://cocoon.huma-num.fr/data/archi/mp3/144187_MOCIKA_44k.mp3> ;
+ * 	<http://purl.org/dc/terms/accessRights> "Freely available for non-commercial use" ;
+ * 	<http://purl.org/dc/terms/license> <http://creativecommons.org/licenses/by-nc-nd/2.5/> ;
+ * 	<http://purl.org/dc/terms/isPartOf> <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_LANGUESDEFRANCE> , <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_LACITO> ;
+ * 	<http://purl.org/dc/terms/extent> "PT2M35S" ;
+ * 	<http://purl.org/dc/terms/created> "1997-08-29"^^<http://purl.org/dc/terms/W3CDTF> ;
+ * 	<http://purl.org/dc/terms/spatial> "NC"^^<http://purl.org/dc/terms/ISO3166> , "New Caledonia, Ohnyat (Ouvéa)" ;
+ * 	<http://crdo.risc.cnrs.fr/schemas/master> <http://cocoon.huma-num.fr/data/archi/masters/144187.wav> ;
+ * 	<http://purl.org/dc/terms/available> "2010-10-23"^^<http://purl.org/dc/terms/W3CDTF> ;
+ * 	<http://purl.org/dc/terms/issued> "2010-10-23T00:08:27+02:00"^^<http://purl.org/dc/terms/W3CDTF> ;
+ * 	<http://www.language-archives.org/OLAC/1.1/speaker> "Idakote, Félicien" ;
+ * 	<http://www.w3.org/2003/01/geo/wgs84_pos#long> "166.6526"^^xsd:float ;
+ * 	<http://www.w3.org/2003/01/geo/wgs84_pos#lat> "-20.4765"^^xsd:float ;
+ * 	<http://purl.org/dc/terms/isRequiredBy> <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-UVE_MOCIKA> ;
+ * 	<http://www.language-archives.org/OLAC/1.1/researcher> "Moyse-Faurie, Claire" .
+ *
+ *  http://purl.org/dc/elements/1.1/description
+ *  http://purl.org/dc/elements/1.1/format
+ *  http://purl.org/dc/elements/1.1/language
+ *  http://purl.org/dc/elements/1.1/publisher
+ *  http://purl.org/dc/elements/1.1/rights
+ *  http://purl.org/dc/elements/1.1/subject
+ *  http://purl.org/dc/elements/1.1/title
+ *  http://purl.org/dc/elements/1.1/type
+ *  http://purl.org/dc/terms/accessRights
+ *  http://purl.org/dc/terms/available
+ *  http://purl.org/dc/terms/conformsTo
+ *  http://purl.org/dc/terms/created
+ *  http://purl.org/dc/terms/isFormatOf
+ *  http://purl.org/dc/terms/isPartOf
+ *  http://purl.org/dc/terms/issued
+ *  http://purl.org/dc/terms/license
+ *  http://purl.org/dc/terms/requires
+ *  http://www.language-archives.org/OLAC/1.1/data_inputter
+ *  http://www.language-archives.org/OLAC/1.1/depositor
+ *  http://www.language-archives.org/OLAC/1.1/editor
+ *  http://www.language-archives.org/OLAC/1.1/interviewer
+ *  http://www.language-archives.org/OLAC/1.1/researcher
+ *  http://www.language-archives.org/OLAC/1.1/speaker
+ *  http://www.language-archives.org/OLAC/1.1/transcriber
+ *  http://www.language-archives.org/OLAC/1.1/author
+ *  http://www.language-archives.org/OLAC/1.1/recorder
+ *  http://www.language-archives.org/OLAC/1.1/translator
+ *  http://www.language-archives.org/OLAC/1.1/responder
+ *  http://www.language-archives.org/OLAC/1.1/sponsor
+ *  http://www.language-archives.org/OLAC/1.1/annotator
+ *  http://www.language-archives.org/OLAC/1.1/participant
+ *  http://www.language-archives.org/OLAC/1.1/compiler
+ *  http://www.language-archives.org/OLAC/1.1/developer
+ *  http://www.language-archives.org/OLAC/1.1/consultant
+ *  http://www.language-archives.org/OLAC/1.1/research_participant
+ *  http://purl.org/dc/terms/spatial
+ *  http://purl.org/dc/terms/tableOfContents
+ *  http://www.w3.org/2003/01/geo/wgs84_pos#lat
+ *  http://www.w3.org/2003/01/geo/wgs84_pos#long
+ *  http://purl.org/dc/terms/alternative
+ *  http://purl.org/dc/terms/modified
+ *  http://purl.org/dc/elements/1.1/identifier
+ *  http://purl.org/dc/terms/extent
+ *  http://purl.org/dc/terms/medium
+ *  http://purl.org/dc/elements/1.1/source
+ *  http://purl.org/dc/elements/1.1/coverage
+ *  http://crdo.risc.cnrs.fr/schemas/master
+ *  http://purl.org/dc/elements/1.1/creator
+ *  http://purl.org/dc/elements/1.1/reference
+ *  http://purl.org/dc/terms/references
+ *  http://purl.org/dc/terms/abstract
+ *  http://purl.org/dc/elements/1.1/relation
+ */
+class CocoonTextRdfMapper extends CocoonContentRdfMapper {
+
+
+    protected function getResourceBaseId($res=null) {
+
+        if(is_null($res)) {
+            $res = $this->inputGraph->resource($this->uri);
+        }
+        $soundRes = $res->get('dc:requires');
+
+        if(! $soundRes instanceof Resource) {
+            throw new \Exception("Input graph for text not correct, can not find sound resource", 1);
+        }
+
+        return $soundRes->getUri();
+    }
+
+    protected function addCHOResourceDateProperties($providedCHOResource, $res, $outputGraph) {
+        // We do not add date to the providedCHO for Text resource
+    }
+
+    protected function propertyTypeMap($providedCHOResource, $prop, $value) {
+        if((!$value instanceof Resource) || $value->getUri() !== "http://purl.org/dc/dcmitype/Text") {
+            $providedCHOResource->add($prop, $value);
+        }
+    }
+
+    protected function mapWebResources($res, $outputGraph) {
+        $resId = CocoonUtils::getIdFromUri($this->getResourceBaseId($res));
+        $resUri = CocoonUtils::getCorpusUriFromId($resId);
+
+
+        $aggregationNode = $outputGraph->resource($resUri, 'ore:Aggregation');
+
+        // build others
+        foreach($res->all($this->inputGraph->resource('http://purl.org/dc/terms/isFormatOf')) as $reprUrl) {
+            $webResource = $outputGraph->resource($reprUrl, 'edm:WebResources');
+            $mimetype = Utils::getMimetype($reprUrl);
+
+            $webResource->addLiteral('http://purl.org/dc/elements/1.1/format', Literal::create($mimetype, null, $outputGraph->resource('http://purl.org/dc/terms/IMT')));
+
+            $this->addDateToWebResource($res, $webResource);
+            $aggregationNode->addResource('edm:hasView', $reprUrl);
+
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/app/Libraries/Mappers/RdfMapper.php	Tue Nov 17 13:11:55 2015 +0100
@@ -0,0 +1,20 @@
+<?php
+namespace CorpusParole\Libraries\Mappers;
+
+/**
+ * Map a rdf graph to one more graph(es).
+ */
+interface RdfMapper {
+
+    /**
+     * Map an Rdf Graph from one model to another
+     * @return the new mapped graph
+     */
+    function mapGraph();
+
+    /**
+     * Get output graphes
+     * @return array
+     */
+    function getOutputGraphes();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/app/Libraries/Mergers/CocoonAbstractRdfMerger.php	Tue Nov 17 13:11:55 2015 +0100
@@ -0,0 +1,200 @@
+<?php
+namespace CorpusParole\Libraries\Mergers;
+
+
+use EasyRdf\RdfNamespace;
+use EasyRdf\Graph;
+
+RdfNamespace::set('edm', 'http://www.europeana.eu/schemas/edm/');
+RdfNamespace::set('ore', 'http://www.openarchives.org/ore/terms/');
+RdfNamespace::set('crdo', 'http://crdo.risc.cnrs.fr/schemas/');
+RdfNamespace::set('olac', 'http://www.language-archives.org/OLAC/1.1/');
+RdfNamespace::set('skos', 'http://www.w3.org/2004/02/skos/core#');
+
+abstract class CocoonAbstractRdfMerger implements RdfMerger {
+
+    const ORIGIN_BASE = 0;
+    const ORIGIN_SRC = 1;
+
+    abstract protected function getTypeMergeMethodMap();
+
+    /**
+     * Merge an Rdf Graph from one model to another
+     *
+     * @param EasyRdf\Graph $baseGraph The graph used as base for the merge
+     * @param EasyRdf\Graph $srcGraph The source graph with the new triples to add
+     *
+     * @return EasyRdf\Graph The new merged graph
+     */
+    function mergeGraph($baseGraph, $srcGraph) {
+
+        $this->mergedArray = [];
+        $this->resGraph = new Graph($baseGraph->getUri());
+        $this->bnodeMerge = [];
+        $this->baseGraph = $baseGraph;
+        $this->srcGraph = $srcGraph;
+
+
+        $typeMergeMethodMap = $this->getTypeMergeMethodMap();
+
+        foreach ( $typeMergeMethodMap as $nodeType => $mergeMethod) {
+
+            foreach($baseGraph->allOfType($nodeType) as $baseResource) {
+                if($baseResource->isBNode()) {
+                    continue;
+                }
+                $this->mergedArray[$baseResource->getUri()] = $baseGraph->toRdfPhp()[$baseResource->getUri()];
+            }
+            foreach($srcGraph->allOfType($nodeType) as $srcResource) {
+                if($baseResource->isBNode()) {
+                    continue;
+                }
+                if(empty($baseGraph->propertyUris($srcResource->getUri()))) {
+                    $this->mergedArray[$srcResource->getUri()] = $srcGraph->toRdfPhp()[$srcResource->getUri()];
+                }
+                else {
+                    $baseResource = $baseGraph->resource($srcResource->getUri());
+                    $this->mergedArray[$srcResource->getUri()] = $baseGraph->toRdfPhp()[$baseResource->getUri()];
+                    call_user_func(array($this, $mergeMethod), $baseResource, $srcResource);
+                }
+            }
+        }
+
+        // merge blank node
+        reset($this->bnodeMerge);
+        while(list($bnodeId, $bnodeDef) = each($this->bnodeMerge)) {
+
+            $srcUrl = isset($bnodeDef['src_url'])?$bnodeDef['src_url']:null;
+            $baseUrl = isset($bnodeDef['base_url'])?$bnodeDef['base_url']:null;
+
+            if(is_null($srcUrl) && !is_null($baseUrl)) {
+                $this->mergedArray[$bnodeId] = $this->copyResource($baseGraph->toRdfPhp()[$baseUrl],CocoonAbstractRdfMerger::ORIGIN_BASE);
+            }
+            elseif (is_null($baseUrl) && !is_null($srcUrl)) {
+                $this->mergedArray[$bnodeId] = $this->copyResource($srcGraph->toRdfPhp()[$srcUrl],CocoonAbstractRdfMerger::ORIGIN_SRC);
+            }
+            elseif (!is_null($baseUrl) && !is_null($srcUrl)) {
+
+                $baseResource = $baseGraph->resource($baseUrl);
+                $srcResource = $srcGraph->resource($srcUrl);
+
+                $mergeMethod = $typeMergeMethodMap[$baseResource->typeAsResource()->getUri()];
+                $this->mergedArray[$bnodeId] = [];
+
+                call_user_func(array($this, $mergeMethod), $baseResource, $srcResource, $bnodeId);
+
+            }
+
+        }
+
+        //echo "MERGED ARRAY:\n";
+        $this->resGraph->parse($this->mergedArray);
+        return $this->resGraph;
+    }
+
+    /**
+     * Copy a full resource node
+     *
+     */
+    protected function copyResource($origArray, $origin) {
+        $resArray = [];
+        foreach($origArray as $prop => $propValues) {
+            $resArray[$prop] = $this->buildValueList($propValues, $origin);
+        }
+        return $resArray;
+    }
+
+    /**
+     * Build a value list. replace the blank node reference.
+     * @param $srcValues array The original values
+     * @param $origin int values are 'ORIGIN_BASE' if bnode from base graph or 'ORIGIN_SRC' from source graph
+     */
+    protected function buildValueList($srcValues, $origin) {
+        $srcArrayProps = [];
+        foreach ($srcValues as $propValue) {
+            if(is_array($propValue) && array_key_exists('type', $propValue) && $propValue['type'] == 'bnode') {
+                $newBNodeId = $this->resGraph->newBNodeId();
+                if($origin == CocoonAbstractRdfMerger::ORIGIN_SRC) {
+                    $this->bnodeMerge[$newBNodeId] = ['src_url' => $propValue['value'], 'base_url' => null];
+                }
+                else {
+                    $this->bnodeMerge[$newBNodeId] = ['base_url' => $propValue['value'], 'src_url' => null];
+                }
+
+                $propValue['value'] = $newBNodeId;
+            }
+            $srcArrayProps[] = $propValue;
+        }
+        return $srcArrayProps;
+    }
+
+    protected function mergePropertySingleValue($prop, &$targetArray, $baseArray, $srcArray) {
+
+        if(isset($baseArray[$prop])) {
+            $targetArray[$prop] = $this->buildValueList($baseArray[$prop], CocoonAbstractRdfMerger::ORIGIN_BASE);
+        }
+        elseif(isset($srcArray[$prop])) {
+            $targetArray[$prop] = $this->buildValueList($srcArray[$prop], CocoonAbstractRdfMerger::ORIGIN_SRC);
+        }
+    }
+
+    protected function mergePropertyMultiplevalue($prop, &$targetArray, $baseArray, $srcArray) {
+        $propArray = $this->buildValueList(isset($baseArray[$prop])?$baseArray[$prop]:[], CocoonAbstractRdfMerger::ORIGIN_BASE);
+        if(isset($srcArray[$prop])) {
+            $mergedArray = array_merge($propArray, $this->buildValueList($srcArray[$prop], CocoonAbstractRdfMerger::ORIGIN_BASE));
+            //yes, this is real. Array_unique does not work on multidimentional arrays. Most work-around suggest the use of serialize to compare sub arrays...
+            $propArray = array_values(array_intersect_key($mergedArray, array_unique(array_map('md5',array_map('serialize', $mergedArray)))));
+        }
+
+        if(!empty($propArray)) {
+            $targetArray[$prop] = $propArray;
+        }
+    }
+
+    protected function mergePropertySingleBNode($prop, &$targetArray, $baseArray, $srcArray) {
+
+        $newBNodeId = $this->resGraph->newBNodeId();
+
+        $srcUrl = null;
+        $baseUrl = null;
+
+        // in src but not in base
+        if(array_key_exists($prop, $baseArray) &&
+            !empty($baseArray[$prop]) &&
+            array_key_exists('type',$baseArray[$prop][0]) &&
+            array_key_exists('value',$baseArray[$prop][0]) &&
+            $baseArray[$prop][0]['type'] === 'bnode') {
+            $baseUrl = $baseArray[$prop][0]['value'];
+        }
+
+        if(array_key_exists($prop, $srcArray) &&
+            !empty($srcArray[$prop]) &&
+            array_key_exists('type',$srcArray[$prop][0]) &&
+            array_key_exists('value',$srcArray[$prop][0]) &&
+            $srcArray[$prop][0]['type'] === 'bnode') {
+            $srcUrl = $srcArray[$prop][0]['value'];
+        }
+
+        $this->bnodeMerge[$newBNodeId] = ['src_url' => $srcUrl, 'base_url' => $baseUrl];
+
+        $targetArray[$prop] = [ [ 'type' => 'bnode', 'value' => $newBNodeId], ];
+
+    }
+
+
+    protected function mergeProperties($singleBNodeProperties, $singleProperties, &$targetArray, $baseRes, $srcRes) {
+        $srcArray = $this->srcGraph->toRdfPhp()[$srcRes->getUri()];
+        $baseArray = $this->baseGraph->toRdfPhp()[$baseRes->getUri()];
+        foreach($srcRes->propertyUris() as $prop) {
+            if(in_array($prop, $singleBNodeProperties)) {
+                $this->mergePropertySingleBNode($prop, $targetArray, $baseArray, $srcArray);
+            }
+            elseif(in_array($prop, $singleProperties)) {
+                $this->mergePropertySingleValue($prop, $targetArray, $baseArray, $srcArray);
+            }
+            else {
+                $this->mergePropertyMultiplevalue($prop, $targetArray, $baseArray, $srcArray);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/app/Libraries/Mergers/CocoonCollectionRdfMerger.php	Tue Nov 17 13:11:55 2015 +0100
@@ -0,0 +1,47 @@
+<?php
+namespace CorpusParole\Libraries\Mergers;
+
+
+class CocoonCollectionRdfMerger extends CocoonAbstractRdfMerger {
+
+    protected function getTypeMergeMethodMap() {
+        return [
+            'http://www.europeana.eu/schemas/edm/Collection' => 'mergeEdmCollection',
+            'http://www.europeana.eu/schemas/edm/Place' => 'mergeDcSpatialBlankNode'
+        ];
+    }
+
+    protected function mergeEdmCollection($baseRes, $srcRes, $uri = null) {
+
+        if(is_null($uri)) {
+            $uri = $baseRes->getUri();
+        }
+        $targetArray =& $this->mergedArray[$uri];
+
+        $this->mergeProperties([
+            "http://purl.org/dc/terms/spatial"
+        ], [
+            "http://purl.org/dc/elements/1.1/title",
+            "http://purl.org/dc/terms/available",
+            "http://purl.org/dc/terms/created",
+            "http://purl.org/dc/terms/issued",
+            "http://purl.org/dc/terms/modified"
+        ], $targetArray, $baseRes, $srcRes);
+
+    }
+
+    protected function mergeDcSpatialBlankNode($baseRes, $srcRes, $uri=null) {
+        if(is_null($uri)) {
+            $uri = $baseRes->getUri();
+        }
+        $targetArray =& $this->mergedArray[$uri];
+
+        $this->mergeProperties([],[
+            "http://www.w3.org/2003/01/geo/wgs84_pos#lat",
+            "http://www.w3.org/2003/01/geo/wgs84_pos#long",
+            "http://www.w3.org/2003/01/geo/wgs84_pos#alt",
+            "http://www.w3.org/2002/07/owl#sameAs"
+        ], $targetArray, $baseRes, $srcRes);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/app/Libraries/Mergers/CocoonSoundRdfMerger.php	Tue Nov 17 13:11:55 2015 +0100
@@ -0,0 +1,163 @@
+<?php
+namespace CorpusParole\Libraries\Mergers;
+
+
+// @prefix ore: <http://www.openarchives.org/ore/terms/> .
+// @prefix edm: <http://www.europeana.eu/schemas/edm/> .
+// @prefix dc: <http://purl.org/dc/terms/> .
+// @prefix dc11: <http://purl.org/dc/elements/1.1/> .
+// @prefix olac: <http://www.language-archives.org/OLAC/1.1/> .
+// @prefix geo: <http://www.w3.org/2003/01/geo/wgs84_pos#> .
+// @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+// @prefix skos: <http://www.w3.org/2004/02/skos/core#> .
+// @prefix owl: <http://www.w3.org/2002/07/owl#> .
+//
+// <http://purl.org/poi/corpusdelaparole.huma-num.fr/crdo-ESLO1_ENT_019>
+//   a ore:Aggregation ;
+//   edm:aggregatedCHO <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-ESLO1_ENT_019> ;
+//   edm:provider "Corpus de la Parole"@fr ;
+//   edm:dataProvider <http://viaf.org/viaf/181558906> ;
+//   edm:isShownAt <http://cocoon.huma-num.fr/exist/crdo/meta/crdo-ESLO1_ENT_019> ;
+//   edm:isShownBy <http://cocoon.huma-num.fr/data/eslo/masters/ESLO1_ENT_019.wav> ;
+//   edm:rights <http://creativecommons.org/licenses/by-nc-sa/4.0/> ;
+//   edm:hasView <http://cocoon.huma-num.fr/data/eslo/ESLO1_ENT_019_22km.wav>, <http://cocoon.huma-num.fr/data/eslo/ESLO1_ENT_019.mp3> .
+//
+// <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-ESLO1_ENT_019>
+//   a edm:ProvidedCHO ;
+//   dc:tableOfContents "01 née; famille a toujours habité Orléans03 oui, on y a des amis, relations04 oui, certainementT1 centralisait comptabilité dans une industrieT2 RR passer des écritures, caisse; horaires avant et après loi de 1936T3 aimait travail, rien ne lui déplaisaitT4 n'a jamais pensé à çaT5 actuellement on est forcée quelquefois - assurance sociale - retraite appréciable; autre chose avec enfantL1 concerts, théâtre, réunions, etc...:préfère s'occuperL2 messe, puis a passé la journée avec une amieL3 (quand elle travaillait) au bord de la mer ou voyages organisésE1 n'en sait rienE2 lui semble que ça aide le françaisE3 peut-être chimie, physiqueE4 intelligence, travail, familleE5 dépend de leurs capacitésE6 non : dépend de la vie de l'enfant plus tardP1 oui, à part loyers chersP4 ne comprend pas motifs des étudiants; très calme à OrléansP9 moins qu'avant 1940P10 RR bourgeois = gros rentiers, femmes d'officierss, gros industriels; chaque groupe se recevait mutuellement, formait un clanQ. Orléans une ville renfermée? oui : orléanais assez distant, peut-être moins maintenantP6 il faut avoir la moitié des votesP7 des candidats se retirentP8 droite gaulliste, réservée; gauche avancéeP5 pas grand-chose - attachés à leurs partisP11 oui, maintenant, par l'éducation; famille moins importanteP12 à diminuer : les gens travaillent beaucoup plus et l'argent a changé de mainsOmelette (je casse mes oeufs...)Questionnaire sociolinguistique"@fr ;
+//   dc11:description "Extrait du corpus d'Orléans, réalisé dans le cadre de l'Enquête SocioLinguistique à Orléans à la fin des années 1960."@fr ;
+//   dc11:language <http://lexvo.org/id/iso639-3/fra> ;
+//   dc11:publisher <http://viaf.org/viaf/181558906> ;
+//   dc11:rights "Copyright (c) 2012 Université d'Orléans/LLL" ;
+//   dc11:type <http://purl.org/dc/dcmitype/Sound>, "primary_text"^^olac:linguistic-type, "dialogue"^^olac:discourse-type ;
+//   dc:license <http://creativecommons.org/licenses/by-nc-sa/3.0/> ;
+//   dc11:subject <http://lexvo.org/id/iso639-3/fra>, "text_and_corpus_linguistics"^^olac:linguistic-field, <http://ark.bnf.fr/ark:/12148/cb135052099>, <http://ark.bnf.fr/ark:/12148/cb11943508j>, <http://ark.bnf.fr/ark:/12148/cb11934124q>, <http://ark.bnf.fr/ark:/12148/cb11931498c>, <http://ark.bnf.fr/ark:/12148/cb11935508t>, <http://ark.bnf.fr/ark:/12148/cb11934132b>, <http://ark.bnf.fr/ark:/12148/cb11939893p>, <http://ark.bnf.fr/ark:/12148/cb11933091b> ;
+//   dc11:title "ESLO1: entretien 019"@fr ;
+//   dc:accessRights "Freely available for non-commercial use" ;
+//   dc:extent "PT0H47M16S" ;
+//   dc:isPartOf <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_LANGUESDEFRANCE>, <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_ESLO1> ;
+//   dc11:source <http://archivesetmanuscrits.bnf.fr/ead.html?id=FRBNFEAD000095934&c=FRBNFEAD000095934_a19844296> ;
+//   dc:medium "1 bande magnétique audio"@fr ;
+//   dc:alternative "ESLO1: entretien 019 alt"@fr ;
+//   dc:bibliographicCitation "A.-M. VURPAS (1988), Autrefois dans les monts du Beaujolais, Action graphique." ;
+//   dc11:identifier "Cote producteur: 001_3"@fr ;
+//   dc:references <http://panini.u-paris10.fr> ;
+//   dc11:coverage "Quartier concerné : Montreuil"@fr ;
+//   dc11:relation <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-ESLO1_ENTCONT_233> ;
+//   dc11:creator "Blanc, Michel", "Biggs, Patricia" ;
+//   olac:depositor <http://viaf.org/viaf/181558906> ;
+//   dc11:contributor <http://viaf.org/viaf/181558906>, <http://viaf.org/viaf/39685504>, <http://viaf.org/viaf/200058210>, "Kay, Jack", "JK", "UG393" ;
+//   olac:editor <http://viaf.org/viaf/39685504>, <http://viaf.org/viaf/200058210> ;
+//   olac:researcher "Kay, Jack" ;
+//   olac:speaker "JK", "UG393" ;
+//   dc:available "2014-11-06"^^dc:W3CDTF ;
+//   dc:created "1969-04-11"^^dc:W3CDTF ;
+//   dc:issued "2014-12-05T15:00:19+01:00"^^dc:W3CDTF ;
+//   dc:modified "2014-12-05T15:00:19+01:00"^^dc:W3CDTF ;
+//   dc:spatial [
+//     a edm:Place ;
+//     geo:lat "47.90"^^xsd:float ;
+//     geo:long "1.90"^^xsd:float ;
+//     skos:note "FR"^^dc:ISO3166, "France, Centre, Loiret, Orléans"@fr ;
+//     owl:sameAs <http://vocab.getty.edu/tgn/7008337>
+//   ] .
+//
+// <http://cocoon.huma-num.fr/data/eslo/masters/ESLO1_ENT_019.wav>
+//   a edm:WebResources ;
+//   dc:extent "PT0H47M16S" ;
+//   dc11:format "audio/x-wav"^^dc:IMT ;
+//   dc:created "1969-04-11"^^dc:W3CDTF ;
+//   dc:issued "2014-12-05T15:00:19+01:00"^^dc:W3CDTF .
+//
+// <http://cocoon.huma-num.fr/data/eslo/ESLO1_ENT_019_22km.wav>
+//   a edm:WebResources ;
+//   dc:extent "PT0H47M16S" ;
+//   dc11:format "audio/x-wav"^^dc:IMT ;
+//   edm:isDerivativeOf <http://cocoon.huma-num.fr/data/eslo/masters/ESLO1_ENT_019.wav> ;
+//   dc:created "1969-04-11"^^dc:W3CDTF ;
+//   dc:issued "2014-12-05T15:00:19+01:00"^^dc:W3CDTF .
+//
+// <http://cocoon.huma-num.fr/data/eslo/ESLO1_ENT_019.mp3>
+//   a edm:WebResources ;
+//   dc:extent "PT0H47M16S" ;
+//   dc11:format "audio/mpeg"^^dc:IMT ;
+//   edm:isDerivativeOf <http://cocoon.huma-num.fr/data/eslo/masters/ESLO1_ENT_019.wav> ;
+//   dc:created "1969-04-11"^^dc:W3CDTF ;
+//   dc:issued "2014-12-05T15:00:19+01:00"^^dc:W3CDTF .
+
+class CocoonSoundRdfMerger extends CocoonAbstractRdfMerger {
+
+    protected function getTypeMergeMethodMap() {
+        return [
+            'http://www.openarchives.org/ore/terms/Aggregation' => 'mergeOreAggregation',
+            'http://www.europeana.eu/schemas/edm/ProvidedCHO' => 'mergeEdmProvidedCHO',
+            'http://www.europeana.eu/schemas/edm/WebResources' => 'mergeEdmWebResources',
+            'http://www.europeana.eu/schemas/edm/Place' => 'mergeDcSpatialBlankNode'
+        ];
+    }
+
+    protected function mergeOreAggregation($baseRes, $srcRes, $uri = null) {
+
+        if(is_null($uri)) {
+            $uri = $baseRes->getUri();
+        }
+        $targetArray =& $this->mergedArray[$uri];
+
+        $this->mergeProperties([], [
+            "http://www.europeana.eu/schemas/edm/aggregatedCHO",
+            "http://www.europeana.eu/schemas/edm/provider",
+            "http://www.europeana.eu/schemas/edm/dataProvider",
+            "http://www.europeana.eu/schemas/edm/isShownAt",
+            "http://www.europeana.eu/schemas/edm/isShownBy"
+        ], $targetArray, $baseRes, $srcRes);
+
+    }
+
+    protected function mergeEdmProvidedCHO($baseRes, $srcRes, $uri=null) {
+        if(is_null($uri)) {
+            $uri = $baseRes->getUri();
+        }
+        $targetArray =& $this->mergedArray[$uri];
+
+        $this->mergeProperties([
+            "http://purl.org/dc/terms/spatial"
+        ], [
+            "http://purl.org/dc/elements/1.1/title",
+            "http://purl.org/dc/terms/extent",
+            "http://purl.org/dc/terms/available",
+            "http://purl.org/dc/terms/created",
+            "http://purl.org/dc/terms/issued",
+            "http://purl.org/dc/terms/modified"
+        ], $targetArray, $baseRes, $srcRes);
+
+    }
+
+    protected function mergeEdmWebResources($baseRes, $srcRes, $uri=null) {
+        if(is_null($uri)) {
+            $uri = $baseRes->getUri();
+        }
+        $targetArray =& $this->mergedArray[$uri];
+        $this->mergeProperties([],[
+            "http://purl.org/dc/terms/extent",
+            "http://purl.org/dc/elements/1.1/format",
+            "http://www.europeana.eu/schemas/edm/isDerivativeOf",
+            "http://purl.org/dc/terms/created",
+            "http://purl.org/dc/terms/issued"
+        ], $targetArray, $baseRes, $srcRes);
+    }
+
+    protected function mergeDcSpatialBlankNode($baseRes, $srcRes, $uri=null) {
+        if(is_null($uri)) {
+            $uri = $baseRes->getUri();
+        }
+        $targetArray =& $this->mergedArray[$uri];
+
+        $this->mergeProperties([],[
+            "http://www.w3.org/2003/01/geo/wgs84_pos#lat",
+            "http://www.w3.org/2003/01/geo/wgs84_pos#long",
+            "http://www.w3.org/2003/01/geo/wgs84_pos#alt",
+            "http://www.w3.org/2002/07/owl#sameAs"
+        ], $targetArray, $baseRes, $srcRes);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/app/Libraries/Mergers/RdfMerger.php	Tue Nov 17 13:11:55 2015 +0100
@@ -0,0 +1,20 @@
+<?php
+namespace CorpusParole\Libraries\Mergers;
+
+/**
+ * merge graphes after mapping them.
+ */
+interface RdfMerger {
+
+
+    /**
+     * Merge an Rdf Graph from one model to another
+     *
+     * @param EasyRdf\Graph $baseGraph The graph used as base for the merge
+     * @param EasyRdf\Graph $srcGraph The source graph with the new triples to add
+     *
+     * @return EasyRdf\Graph The new merged graph
+     */
+    function mergeGraph($baseGraph, $srcGraph);
+
+}
--- a/server/src/app/Libraries/Utils.php	Fri Nov 13 16:45:27 2015 +0100
+++ b/server/src/app/Libraries/Utils.php	Tue Nov 17 13:11:55 2015 +0100
@@ -1,5 +1,4 @@
 <?php
-
 namespace CorpusParole\Libraries;
 
 /**
@@ -10,7 +9,7 @@
     /*
      * From http://www.thecave.info/php-get-mime-type-from-file-extension/
      */
-    public static function get_mimetype($file) {
+    public static function getMimetype($file) {
 
         // our list of mime types
         $mime_types = array(
@@ -51,7 +50,7 @@
         return $mime_types[$extension];
     }
 
-    public static function process_literal_or_string($val) {
+    public static function processLiteralOrString($val) {
         if(is_null($val)) {
             return $val;
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/app/Models/CocoonDocument.php	Tue Nov 17 13:11:55 2015 +0100
@@ -0,0 +1,12 @@
+<?php
+
+namespace CorpusParole\Models;
+
+use Illuminate\Database\Eloquent\Model;
+
+class CocoonDocument extends Model
+{
+    public function revisions() {
+        return $this->hasMany('CorpusParole\Models\CocoonDocument', 'document_id');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/app/Models/CocoonRevision.php	Tue Nov 17 13:11:55 2015 +0100
@@ -0,0 +1,12 @@
+<?php
+
+namespace CorpusParole\Models;
+
+use Illuminate\Database\Eloquent\Model;
+
+class CocoonRevision extends Model
+{
+    public function document() {
+        return $this->belongsTo('CorpusParole\Models\CocoonDocument');
+    }
+}
--- a/server/src/app/Models/Document.php	Fri Nov 13 16:45:27 2015 +0100
+++ b/server/src/app/Models/Document.php	Tue Nov 17 13:11:55 2015 +0100
@@ -3,6 +3,7 @@
 
 use Config;
 use CorpusParole\Libraries\Utils;
+use CorpusParole\Libraries\CocoonUtils;
 use CorpusParole\Libraries\RdfModel\RdfModelResource;
 use JsonSerializable;
 use Log;
@@ -26,7 +27,7 @@
 
     public function getId() {
         if(is_null($this->id)) {
-            $this->id = substr($this->uri, strlen(Config::get('corpusparole.cocoon_doc_id_base_uri')));
+            $this->id = CocoonUtils::getIdFromUri($this->uri);
         }
         return $this->id;
     }
@@ -59,7 +60,7 @@
         }
         foreach ($formats as $f) {
             $uri = $f->getUri();
-            $mimetype = Utils::get_mimetype($uri);
+            $mimetype = Utils::getMimetype($uri);
             array_push($res, ["url" => $uri, "format" => $mimetype]);
         }
 
@@ -127,13 +128,13 @@
         } else {
             $mediaArray = array_map(
                 function($m) {
-                    $f = Utils::process_literal_or_string($m['format']);
+                    $f = Utils::processLiteralOrString($m['format']);
                     return ['url' => $m['url'], 'format' => $f];},
                 $this->getMediaArray()
             );
 
             $publishers = array_map(
-                function($v) { return Utils::process_literal_or_string($v); },
+                function($v) { return Utils::processLiteralOrString($v); },
                 $this->getPublishers()
             );
 
--- a/server/src/composer.json	Fri Nov 13 16:45:27 2015 +0100
+++ b/server/src/composer.json	Tue Nov 17 13:11:55 2015 +0100
@@ -13,7 +13,7 @@
 		"laravelcollective/html": "5.1.*"
 	},
 	"require-dev": {
-		"phpunit/phpunit": "~4.0",
+		"phpunit/phpunit": "~5.0",
 		"phpspec/phpspec": "~2.1",
 		"fabpot/php-cs-fixer": "^1.9",
 		"mockery/mockery": "dev-master"
--- a/server/src/composer.lock	Fri Nov 13 16:45:27 2015 +0100
+++ b/server/src/composer.lock	Tue Nov 17 13:11:55 2015 +0100
@@ -4,7 +4,8 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
         "This file is @generated automatically"
     ],
-    "hash": "43b757168dd323060f8ecedc259686a8",
+    "hash": "814fed9487bfb758c37b3f322650ade6",
+    "content-hash": "80322b0e38b8cc26e4ef4caa3a13894f",
     "packages": [
         {
             "name": "caseyamcl/phpoaipmh",
@@ -281,12 +282,12 @@
             "source": {
                 "type": "git",
                 "url": "https://github.com/njh/easyrdf.git",
-                "reference": "4f7f1e5e726e4abaf1428888cf45796abbc7d70b"
+                "reference": "02864f8996311ff7c6619be70fc1ecf6f3165c48"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/njh/easyrdf/zipball/4f7f1e5e726e4abaf1428888cf45796abbc7d70b",
-                "reference": "4f7f1e5e726e4abaf1428888cf45796abbc7d70b",
+                "url": "https://api.github.com/repos/njh/easyrdf/zipball/02864f8996311ff7c6619be70fc1ecf6f3165c48",
+                "reference": "02864f8996311ff7c6619be70fc1ecf6f3165c48",
                 "shasum": ""
             },
             "require": {
@@ -340,20 +341,20 @@
                 "rdfa",
                 "sparql"
             ],
-            "time": "2015-04-02 06:12:11"
+            "time": "2015-10-07 11:58:54"
         },
         {
             "name": "guzzlehttp/guzzle",
-            "version": "6.0.2",
+            "version": "6.1.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/guzzle/guzzle.git",
-                "reference": "a8dfeff00eb84616a17fea7a4d72af35e750410f"
+                "reference": "66fd14b4d0b8f2389eaf37c5458608c7cb793a81"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/guzzle/guzzle/zipball/a8dfeff00eb84616a17fea7a4d72af35e750410f",
-                "reference": "a8dfeff00eb84616a17fea7a4d72af35e750410f",
+                "url": "https://api.github.com/repos/guzzle/guzzle/zipball/66fd14b4d0b8f2389eaf37c5458608c7cb793a81",
+                "reference": "66fd14b4d0b8f2389eaf37c5458608c7cb793a81",
                 "shasum": ""
             },
             "require": {
@@ -369,7 +370,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "6.0-dev"
+                    "dev-master": "6.1-dev"
                 }
             },
             "autoload": {
@@ -402,7 +403,7 @@
                 "rest",
                 "web service"
             ],
-            "time": "2015-07-04 20:09:24"
+            "time": "2015-09-08 17:36:26"
         },
         {
             "name": "guzzlehttp/promises",
@@ -660,16 +661,16 @@
         },
         {
             "name": "laravel/framework",
-            "version": "v5.1.12",
+            "version": "v5.1.19",
             "source": {
                 "type": "git",
                 "url": "https://github.com/laravel/framework.git",
-                "reference": "76a9816f37a58383f6ba093ccf08f253e5488555"
+                "reference": "45e181369991579dc3ad015665eabbb72c0fadba"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/laravel/framework/zipball/76a9816f37a58383f6ba093ccf08f253e5488555",
-                "reference": "76a9816f37a58383f6ba093ccf08f253e5488555",
+                "url": "https://api.github.com/repos/laravel/framework/zipball/45e181369991579dc3ad015665eabbb72c0fadba",
+                "reference": "45e181369991579dc3ad015665eabbb72c0fadba",
                 "shasum": ""
             },
             "require": {
@@ -784,20 +785,20 @@
                 "framework",
                 "laravel"
             ],
-            "time": "2015-08-30 23:25:48"
+            "time": "2015-10-01 18:32:48"
         },
         {
             "name": "laravelcollective/html",
-            "version": "v5.1.5",
+            "version": "v5.1.6",
             "source": {
                 "type": "git",
                 "url": "https://github.com/LaravelCollective/html.git",
-                "reference": "59f124084c9135a6a8d87323e5c5562ab823deb4"
+                "reference": "8b7c357e78b8fb6a2e48377cf2441441aac6dd1e"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/LaravelCollective/html/zipball/59f124084c9135a6a8d87323e5c5562ab823deb4",
-                "reference": "59f124084c9135a6a8d87323e5c5562ab823deb4",
+                "url": "https://api.github.com/repos/LaravelCollective/html/zipball/8b7c357e78b8fb6a2e48377cf2441441aac6dd1e",
+                "reference": "8b7c357e78b8fb6a2e48377cf2441441aac6dd1e",
                 "shasum": ""
             },
             "require": {
@@ -834,25 +835,28 @@
                     "email": "adam@laravelcollective.com"
                 }
             ],
-            "time": "2015-07-28 03:18:41"
+            "time": "2015-09-03 17:16:48"
         },
         {
             "name": "league/flysystem",
-            "version": "1.0.11",
+            "version": "1.0.15",
             "source": {
                 "type": "git",
                 "url": "https://github.com/thephpleague/flysystem.git",
-                "reference": "c16222fdc02467eaa12cb6d6d0e65527741f6040"
+                "reference": "31525caf9e8772683672fefd8a1ca0c0736020f4"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/c16222fdc02467eaa12cb6d6d0e65527741f6040",
-                "reference": "c16222fdc02467eaa12cb6d6d0e65527741f6040",
+                "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/31525caf9e8772683672fefd8a1ca0c0736020f4",
+                "reference": "31525caf9e8772683672fefd8a1ca0c0736020f4",
                 "shasum": ""
             },
             "require": {
                 "php": ">=5.4.0"
             },
+            "conflict": {
+                "league/flysystem-sftp": "<1.0.6"
+            },
             "require-dev": {
                 "ext-fileinfo": "*",
                 "mockery/mockery": "~0.9",
@@ -915,7 +919,7 @@
                 "sftp",
                 "storage"
             ],
-            "time": "2015-07-28 20:41:58"
+            "time": "2015-09-30 22:26:59"
         },
         {
             "name": "ml/iri",
@@ -1182,16 +1186,16 @@
         },
         {
             "name": "nikic/php-parser",
-            "version": "v1.4.0",
+            "version": "v1.4.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/nikic/PHP-Parser.git",
-                "reference": "196f177cfefa0f1f7166c0a05d8255889be12418"
+                "reference": "f78af2c9c86107aa1a34cd1dbb5bbe9eeb0d9f51"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/196f177cfefa0f1f7166c0a05d8255889be12418",
-                "reference": "196f177cfefa0f1f7166c0a05d8255889be12418",
+                "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f78af2c9c86107aa1a34cd1dbb5bbe9eeb0d9f51",
+                "reference": "f78af2c9c86107aa1a34cd1dbb5bbe9eeb0d9f51",
                 "shasum": ""
             },
             "require": {
@@ -1223,7 +1227,7 @@
                 "parser",
                 "php"
             ],
-            "time": "2015-07-14 17:31:05"
+            "time": "2015-09-19 14:15:08"
         },
         {
             "name": "psr/http-message",
@@ -1439,16 +1443,16 @@
         },
         {
             "name": "symfony/console",
-            "version": "v2.7.3",
+            "version": "v2.7.5",
             "source": {
                 "type": "git",
-                "url": "https://github.com/symfony/Console.git",
-                "reference": "d6cf02fe73634c96677e428f840704bfbcaec29e"
+                "url": "https://github.com/symfony/console.git",
+                "reference": "06cb17c013a82f94a3d840682b49425cd00a2161"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/Console/zipball/d6cf02fe73634c96677e428f840704bfbcaec29e",
-                "reference": "d6cf02fe73634c96677e428f840704bfbcaec29e",
+                "url": "https://api.github.com/repos/symfony/console/zipball/06cb17c013a82f94a3d840682b49425cd00a2161",
+                "reference": "06cb17c013a82f94a3d840682b49425cd00a2161",
                 "shasum": ""
             },
             "require": {
@@ -1492,20 +1496,20 @@
             ],
             "description": "Symfony Console Component",
             "homepage": "https://symfony.com",
-            "time": "2015-07-28 15:18:12"
+            "time": "2015-09-25 08:32:23"
         },
         {
             "name": "symfony/css-selector",
-            "version": "v2.7.3",
+            "version": "v2.7.5",
             "source": {
                 "type": "git",
-                "url": "https://github.com/symfony/CssSelector.git",
-                "reference": "0b5c07b516226b7dd32afbbc82fe547a469c5092"
+                "url": "https://github.com/symfony/css-selector.git",
+                "reference": "abe19cc0429a06be0c133056d1f9859854860970"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/CssSelector/zipball/0b5c07b516226b7dd32afbbc82fe547a469c5092",
-                "reference": "0b5c07b516226b7dd32afbbc82fe547a469c5092",
+                "url": "https://api.github.com/repos/symfony/css-selector/zipball/abe19cc0429a06be0c133056d1f9859854860970",
+                "reference": "abe19cc0429a06be0c133056d1f9859854860970",
                 "shasum": ""
             },
             "require": {
@@ -1545,20 +1549,20 @@
             ],
             "description": "Symfony CssSelector Component",
             "homepage": "https://symfony.com",
-            "time": "2015-05-15 13:33:16"
+            "time": "2015-09-22 13:49:29"
         },
         {
             "name": "symfony/debug",
-            "version": "v2.7.3",
+            "version": "v2.7.5",
             "source": {
                 "type": "git",
-                "url": "https://github.com/symfony/Debug.git",
-                "reference": "9daa1bf9f7e615fa2fba30357e479a90141222e3"
+                "url": "https://github.com/symfony/debug.git",
+                "reference": "c79c361bca8e5ada6a47603875a3c964d03b67b1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/Debug/zipball/9daa1bf9f7e615fa2fba30357e479a90141222e3",
-                "reference": "9daa1bf9f7e615fa2fba30357e479a90141222e3",
+                "url": "https://api.github.com/repos/symfony/debug/zipball/c79c361bca8e5ada6a47603875a3c964d03b67b1",
+                "reference": "c79c361bca8e5ada6a47603875a3c964d03b67b1",
                 "shasum": ""
             },
             "require": {
@@ -1570,14 +1574,9 @@
             },
             "require-dev": {
                 "symfony/class-loader": "~2.2",
-                "symfony/http-foundation": "~2.1",
                 "symfony/http-kernel": "~2.3.24|~2.5.9|~2.6,>=2.6.2",
                 "symfony/phpunit-bridge": "~2.7"
             },
-            "suggest": {
-                "symfony/http-foundation": "",
-                "symfony/http-kernel": ""
-            },
             "type": "library",
             "extra": {
                 "branch-alias": {
@@ -1605,20 +1604,20 @@
             ],
             "description": "Symfony Debug Component",
             "homepage": "https://symfony.com",
-            "time": "2015-07-09 16:07:40"
+            "time": "2015-09-14 08:41:38"
         },
         {
             "name": "symfony/dom-crawler",
-            "version": "v2.7.3",
+            "version": "v2.7.5",
             "source": {
                 "type": "git",
-                "url": "https://github.com/symfony/DomCrawler.git",
-                "reference": "9dabece63182e95c42b06967a0d929a5df78bc35"
+                "url": "https://github.com/symfony/dom-crawler.git",
+                "reference": "2e185ca136399f902b948694987e62c80099c052"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/DomCrawler/zipball/9dabece63182e95c42b06967a0d929a5df78bc35",
-                "reference": "9dabece63182e95c42b06967a0d929a5df78bc35",
+                "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/2e185ca136399f902b948694987e62c80099c052",
+                "reference": "2e185ca136399f902b948694987e62c80099c052",
                 "shasum": ""
             },
             "require": {
@@ -1658,20 +1657,20 @@
             ],
             "description": "Symfony DomCrawler Component",
             "homepage": "https://symfony.com",
-            "time": "2015-07-09 16:07:40"
+            "time": "2015-09-20 21:13:58"
         },
         {
             "name": "symfony/event-dispatcher",
-            "version": "v2.7.3",
+            "version": "v2.7.5",
             "source": {
                 "type": "git",
-                "url": "https://github.com/symfony/EventDispatcher.git",
-                "reference": "9310b5f9a87ec2ea75d20fec0b0017c77c66dac3"
+                "url": "https://github.com/symfony/event-dispatcher.git",
+                "reference": "ae4dcc2a8d3de98bd794167a3ccda1311597c5d9"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/9310b5f9a87ec2ea75d20fec0b0017c77c66dac3",
-                "reference": "9310b5f9a87ec2ea75d20fec0b0017c77c66dac3",
+                "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/ae4dcc2a8d3de98bd794167a3ccda1311597c5d9",
+                "reference": "ae4dcc2a8d3de98bd794167a3ccda1311597c5d9",
                 "shasum": ""
             },
             "require": {
@@ -1716,20 +1715,20 @@
             ],
             "description": "Symfony EventDispatcher Component",
             "homepage": "https://symfony.com",
-            "time": "2015-06-18 19:21:56"
+            "time": "2015-09-22 13:49:29"
         },
         {
             "name": "symfony/finder",
-            "version": "v2.7.3",
+            "version": "v2.7.5",
             "source": {
                 "type": "git",
-                "url": "https://github.com/symfony/Finder.git",
-                "reference": "ae0f363277485094edc04c9f3cbe595b183b78e4"
+                "url": "https://github.com/symfony/finder.git",
+                "reference": "8262ab605973afbb3ef74b945daabf086f58366f"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/Finder/zipball/ae0f363277485094edc04c9f3cbe595b183b78e4",
-                "reference": "ae0f363277485094edc04c9f3cbe595b183b78e4",
+                "url": "https://api.github.com/repos/symfony/finder/zipball/8262ab605973afbb3ef74b945daabf086f58366f",
+                "reference": "8262ab605973afbb3ef74b945daabf086f58366f",
                 "shasum": ""
             },
             "require": {
@@ -1765,20 +1764,20 @@
             ],
             "description": "Symfony Finder Component",
             "homepage": "https://symfony.com",
-            "time": "2015-07-09 16:07:40"
+            "time": "2015-09-19 19:59:23"
         },
         {
             "name": "symfony/http-foundation",
-            "version": "v2.7.3",
+            "version": "v2.7.5",
             "source": {
                 "type": "git",
-                "url": "https://github.com/symfony/HttpFoundation.git",
-                "reference": "863af6898081b34c65d42100c370b9f3c51b70ca"
+                "url": "https://github.com/symfony/http-foundation.git",
+                "reference": "e1509119f164a0d0a940d7d924d693a7a28a5470"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/863af6898081b34c65d42100c370b9f3c51b70ca",
-                "reference": "863af6898081b34c65d42100c370b9f3c51b70ca",
+                "url": "https://api.github.com/repos/symfony/http-foundation/zipball/e1509119f164a0d0a940d7d924d693a7a28a5470",
+                "reference": "e1509119f164a0d0a940d7d924d693a7a28a5470",
                 "shasum": ""
             },
             "require": {
@@ -1818,20 +1817,20 @@
             ],
             "description": "Symfony HttpFoundation Component",
             "homepage": "https://symfony.com",
-            "time": "2015-07-22 10:11:00"
+            "time": "2015-09-22 13:49:29"
         },
         {
             "name": "symfony/http-kernel",
-            "version": "v2.7.3",
+            "version": "v2.7.5",
             "source": {
                 "type": "git",
-                "url": "https://github.com/symfony/HttpKernel.git",
-                "reference": "405d3e7a59ff7a28ec469441326a0ac79065ea98"
+                "url": "https://github.com/symfony/http-kernel.git",
+                "reference": "353aa457424262d7d4e4289ea483145921cffcb5"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/HttpKernel/zipball/405d3e7a59ff7a28ec469441326a0ac79065ea98",
-                "reference": "405d3e7a59ff7a28ec469441326a0ac79065ea98",
+                "url": "https://api.github.com/repos/symfony/http-kernel/zipball/353aa457424262d7d4e4289ea483145921cffcb5",
+                "reference": "353aa457424262d7d4e4289ea483145921cffcb5",
                 "shasum": ""
             },
             "require": {
@@ -1898,20 +1897,20 @@
             ],
             "description": "Symfony HttpKernel Component",
             "homepage": "https://symfony.com",
-            "time": "2015-07-31 13:24:45"
+            "time": "2015-09-25 11:16:52"
         },
         {
             "name": "symfony/process",
-            "version": "v2.7.3",
+            "version": "v2.7.5",
             "source": {
                 "type": "git",
-                "url": "https://github.com/symfony/Process.git",
-                "reference": "48aeb0e48600321c272955132d7606ab0a49adb3"
+                "url": "https://github.com/symfony/process.git",
+                "reference": "b27c8e317922cd3cdd3600850273cf6b82b2e8e9"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/Process/zipball/48aeb0e48600321c272955132d7606ab0a49adb3",
-                "reference": "48aeb0e48600321c272955132d7606ab0a49adb3",
+                "url": "https://api.github.com/repos/symfony/process/zipball/b27c8e317922cd3cdd3600850273cf6b82b2e8e9",
+                "reference": "b27c8e317922cd3cdd3600850273cf6b82b2e8e9",
                 "shasum": ""
             },
             "require": {
@@ -1947,20 +1946,20 @@
             ],
             "description": "Symfony Process Component",
             "homepage": "https://symfony.com",
-            "time": "2015-07-01 11:25:50"
+            "time": "2015-09-19 19:59:23"
         },
         {
             "name": "symfony/routing",
-            "version": "v2.7.3",
+            "version": "v2.7.5",
             "source": {
                 "type": "git",
-                "url": "https://github.com/symfony/Routing.git",
-                "reference": "ea9134f277162b02e5f80ac058b75a77637b0d26"
+                "url": "https://github.com/symfony/routing.git",
+                "reference": "6c5fae83efa20baf166fcf4582f57094e9f60f16"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/Routing/zipball/ea9134f277162b02e5f80ac058b75a77637b0d26",
-                "reference": "ea9134f277162b02e5f80ac058b75a77637b0d26",
+                "url": "https://api.github.com/repos/symfony/routing/zipball/6c5fae83efa20baf166fcf4582f57094e9f60f16",
+                "reference": "6c5fae83efa20baf166fcf4582f57094e9f60f16",
                 "shasum": ""
             },
             "require": {
@@ -2018,20 +2017,20 @@
                 "uri",
                 "url"
             ],
-            "time": "2015-07-09 16:07:40"
+            "time": "2015-09-14 14:14:09"
         },
         {
             "name": "symfony/translation",
-            "version": "v2.7.3",
+            "version": "v2.7.5",
             "source": {
                 "type": "git",
-                "url": "https://github.com/symfony/Translation.git",
-                "reference": "c8dc34cc936152c609cdd722af317e4239d10dd6"
+                "url": "https://github.com/symfony/translation.git",
+                "reference": "485877661835e188cd78345c6d4eef1290d17571"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/Translation/zipball/c8dc34cc936152c609cdd722af317e4239d10dd6",
-                "reference": "c8dc34cc936152c609cdd722af317e4239d10dd6",
+                "url": "https://api.github.com/repos/symfony/translation/zipball/485877661835e188cd78345c6d4eef1290d17571",
+                "reference": "485877661835e188cd78345c6d4eef1290d17571",
                 "shasum": ""
             },
             "require": {
@@ -2043,7 +2042,7 @@
             "require-dev": {
                 "psr/log": "~1.0",
                 "symfony/config": "~2.7",
-                "symfony/intl": "~2.3",
+                "symfony/intl": "~2.4",
                 "symfony/phpunit-bridge": "~2.7",
                 "symfony/yaml": "~2.2"
             },
@@ -2079,20 +2078,20 @@
             ],
             "description": "Symfony Translation Component",
             "homepage": "https://symfony.com",
-            "time": "2015-07-09 16:07:40"
+            "time": "2015-09-06 08:36:38"
         },
         {
             "name": "symfony/var-dumper",
-            "version": "v2.7.3",
+            "version": "v2.7.5",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/var-dumper.git",
-                "reference": "e8903ebba5eb019f5886ffce739ea9e3b7519579"
+                "reference": "ba8c9a0edf18f70a7efcb8d3eb35323a10263338"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/var-dumper/zipball/e8903ebba5eb019f5886ffce739ea9e3b7519579",
-                "reference": "e8903ebba5eb019f5886ffce739ea9e3b7519579",
+                "url": "https://api.github.com/repos/symfony/var-dumper/zipball/ba8c9a0edf18f70a7efcb8d3eb35323a10263338",
+                "reference": "ba8c9a0edf18f70a7efcb8d3eb35323a10263338",
                 "shasum": ""
             },
             "require": {
@@ -2138,7 +2137,7 @@
                 "debug",
                 "dump"
             ],
-            "time": "2015-07-28 15:18:12"
+            "time": "2015-09-22 14:41:01"
         },
         {
             "name": "vlucas/phpdotenv",
@@ -2347,12 +2346,12 @@
             "source": {
                 "type": "git",
                 "url": "https://github.com/padraic/mockery.git",
-                "reference": "e585573c91b0c821e511afd14666b4503ef7255b"
+                "reference": "bb19cd92e91aee51c344d8bd1a453dc85de47c21"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/padraic/mockery/zipball/e585573c91b0c821e511afd14666b4503ef7255b",
-                "reference": "e585573c91b0c821e511afd14666b4503ef7255b",
+                "url": "https://api.github.com/repos/padraic/mockery/zipball/bb19cd92e91aee51c344d8bd1a453dc85de47c21",
+                "reference": "bb19cd92e91aee51c344d8bd1a453dc85de47c21",
                 "shasum": ""
             },
             "require": {
@@ -2404,7 +2403,49 @@
                 "test double",
                 "testing"
             ],
-            "time": "2015-07-31 13:51:58"
+            "time": "2015-10-02 20:03:43"
+        },
+        {
+            "name": "myclabs/deep-copy",
+            "version": "1.4.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/myclabs/DeepCopy.git",
+                "reference": "d8093b631a31628342d0703764935f8bac2c56b1"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/d8093b631a31628342d0703764935f8bac2c56b1",
+                "reference": "d8093b631a31628342d0703764935f8bac2c56b1",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.4.0"
+            },
+            "require-dev": {
+                "doctrine/collections": "1.*",
+                "phpunit/phpunit": "~4.1"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "DeepCopy\\": "src/DeepCopy/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "description": "Create deep copies (clones) of your objects",
+            "homepage": "https://github.com/myclabs/DeepCopy",
+            "keywords": [
+                "clone",
+                "copy",
+                "duplicate",
+                "object",
+                "object graph"
+            ],
+            "time": "2015-10-05 15:07:09"
         },
         {
             "name": "phpdocumentor/reflection-docblock",
@@ -2491,16 +2532,16 @@
         },
         {
             "name": "phpspec/phpspec",
-            "version": "2.2.1",
+            "version": "2.3.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/phpspec/phpspec.git",
-                "reference": "e9a40577323e67f1de2e214abf32976a0352d8f8"
+                "reference": "36635a903bdeb54899d7407bc95610501fd98559"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/phpspec/phpspec/zipball/e9a40577323e67f1de2e214abf32976a0352d8f8",
-                "reference": "e9a40577323e67f1de2e214abf32976a0352d8f8",
+                "url": "https://api.github.com/repos/phpspec/phpspec/zipball/36635a903bdeb54899d7407bc95610501fd98559",
+                "reference": "36635a903bdeb54899d7407bc95610501fd98559",
                 "shasum": ""
             },
             "require": {
@@ -2512,15 +2553,14 @@
                 "symfony/console": "~2.3",
                 "symfony/event-dispatcher": "~2.1",
                 "symfony/finder": "~2.1",
-                "symfony/process": "~2.1",
+                "symfony/process": "^2.6",
                 "symfony/yaml": "~2.1"
             },
             "require-dev": {
                 "behat/behat": "^3.0.11",
                 "bossa/phpspec2-expect": "~1.0",
                 "phpunit/phpunit": "~4.4",
-                "symfony/filesystem": "~2.1",
-                "symfony/process": "~2.1"
+                "symfony/filesystem": "~2.1"
             },
             "suggest": {
                 "phpspec/nyan-formatters": "~1.0 – Adds Nyan formatters"
@@ -2565,7 +2605,7 @@
                 "testing",
                 "tests"
             ],
-            "time": "2015-05-30 15:21:40"
+            "time": "2015-09-07 07:07:37"
         },
         {
             "name": "phpspec/prophecy",
@@ -2629,20 +2669,20 @@
         },
         {
             "name": "phpunit/php-code-coverage",
-            "version": "2.2.2",
+            "version": "3.0.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
-                "reference": "2d7c03c0e4e080901b8f33b2897b0577be18a13c"
+                "reference": "c84f05be256cd7c9d2340b26f7995b4afbf8787b"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2d7c03c0e4e080901b8f33b2897b0577be18a13c",
-                "reference": "2d7c03c0e4e080901b8f33b2897b0577be18a13c",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/c84f05be256cd7c9d2340b26f7995b4afbf8787b",
+                "reference": "c84f05be256cd7c9d2340b26f7995b4afbf8787b",
                 "shasum": ""
             },
             "require": {
-                "php": ">=5.3.3",
+                "php": ">=5.6",
                 "phpunit/php-file-iterator": "~1.3",
                 "phpunit/php-text-template": "~1.2",
                 "phpunit/php-token-stream": "~1.3",
@@ -2651,7 +2691,7 @@
             },
             "require-dev": {
                 "ext-xdebug": ">=2.1.4",
-                "phpunit/phpunit": "~4"
+                "phpunit/phpunit": "~5"
             },
             "suggest": {
                 "ext-dom": "*",
@@ -2661,7 +2701,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "2.2.x-dev"
+                    "dev-master": "3.0.x-dev"
                 }
             },
             "autoload": {
@@ -2687,7 +2727,7 @@
                 "testing",
                 "xunit"
             ],
-            "time": "2015-08-04 03:42:39"
+            "time": "2015-10-06 15:51:05"
         },
         {
             "name": "phpunit/php-file-iterator",
@@ -2820,16 +2860,16 @@
         },
         {
             "name": "phpunit/php-token-stream",
-            "version": "1.4.6",
+            "version": "1.4.8",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/php-token-stream.git",
-                "reference": "3ab72c62e550370a6cd5dc873e1a04ab57562f5b"
+                "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3ab72c62e550370a6cd5dc873e1a04ab57562f5b",
-                "reference": "3ab72c62e550370a6cd5dc873e1a04ab57562f5b",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da",
+                "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da",
                 "shasum": ""
             },
             "require": {
@@ -2865,20 +2905,20 @@
             "keywords": [
                 "tokenizer"
             ],
-            "time": "2015-08-16 08:51:00"
+            "time": "2015-09-15 10:49:45"
         },
         {
             "name": "phpunit/phpunit",
-            "version": "4.8.6",
+            "version": "5.0.4",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/phpunit.git",
-                "reference": "2246830f4a1a551c67933e4171bf2126dc29d357"
+                "reference": "6b3a71e90026801f6bcfd1d72cce4a06685c2637"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2246830f4a1a551c67933e4171bf2126dc29d357",
-                "reference": "2246830f4a1a551c67933e4171bf2126dc29d357",
+                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/6b3a71e90026801f6bcfd1d72cce4a06685c2637",
+                "reference": "6b3a71e90026801f6bcfd1d72cce4a06685c2637",
                 "shasum": ""
             },
             "require": {
@@ -2887,18 +2927,20 @@
                 "ext-pcre": "*",
                 "ext-reflection": "*",
                 "ext-spl": "*",
-                "php": ">=5.3.3",
+                "myclabs/deep-copy": "~1.3",
+                "php": ">=5.6",
                 "phpspec/prophecy": "^1.3.1",
-                "phpunit/php-code-coverage": "~2.1",
+                "phpunit/php-code-coverage": "~3.0",
                 "phpunit/php-file-iterator": "~1.4",
                 "phpunit/php-text-template": "~1.2",
                 "phpunit/php-timer": ">=1.0.6",
-                "phpunit/phpunit-mock-objects": "~2.3",
+                "phpunit/phpunit-mock-objects": ">=3.0",
                 "sebastian/comparator": "~1.1",
                 "sebastian/diff": "~1.2",
                 "sebastian/environment": "~1.3",
                 "sebastian/exporter": "~1.2",
                 "sebastian/global-state": "~1.0",
+                "sebastian/resource-operations": "~1.0",
                 "sebastian/version": "~1.0",
                 "symfony/yaml": "~2.1|~3.0"
             },
@@ -2911,7 +2953,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "4.8.x-dev"
+                    "dev-master": "5.0.x-dev"
                 }
             },
             "autoload": {
@@ -2937,30 +2979,30 @@
                 "testing",
                 "xunit"
             ],
-            "time": "2015-08-24 04:09:38"
+            "time": "2015-10-07 10:45:35"
         },
         {
             "name": "phpunit/phpunit-mock-objects",
-            "version": "2.3.7",
+            "version": "3.0.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
-                "reference": "5e2645ad49d196e020b85598d7c97e482725786a"
+                "reference": "b66bfd55201aa33e8096d8c9bcb762361521c301"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/5e2645ad49d196e020b85598d7c97e482725786a",
-                "reference": "5e2645ad49d196e020b85598d7c97e482725786a",
+                "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/b66bfd55201aa33e8096d8c9bcb762361521c301",
+                "reference": "b66bfd55201aa33e8096d8c9bcb762361521c301",
                 "shasum": ""
             },
             "require": {
                 "doctrine/instantiator": "^1.0.2",
-                "php": ">=5.3.3",
+                "php": ">=5.6",
                 "phpunit/php-text-template": "~1.2",
                 "sebastian/exporter": "~1.2"
             },
             "require-dev": {
-                "phpunit/phpunit": "~4.4"
+                "phpunit/phpunit": "~5"
             },
             "suggest": {
                 "ext-soap": "*"
@@ -2968,7 +3010,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "2.3.x-dev"
+                    "dev-master": "3.0.x-dev"
                 }
             },
             "autoload": {
@@ -2993,7 +3035,7 @@
                 "mock",
                 "xunit"
             ],
-            "time": "2015-08-19 09:14:08"
+            "time": "2015-10-01 06:43:55"
         },
         {
             "name": "sebastian/comparator",
@@ -3332,6 +3374,48 @@
             "time": "2015-06-21 08:04:50"
         },
         {
+            "name": "sebastian/resource-operations",
+            "version": "1.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/resource-operations.git",
+                "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52",
+                "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.6.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de"
+                }
+            ],
+            "description": "Provides a list of PHP built-in functions that operate on resources",
+            "homepage": "https://www.github.com/sebastianbergmann/resource-operations",
+            "time": "2015-07-28 20:34:47"
+        },
+        {
             "name": "sebastian/version",
             "version": "1.0.6",
             "source": {
@@ -3368,16 +3452,16 @@
         },
         {
             "name": "symfony/filesystem",
-            "version": "v2.7.3",
+            "version": "v2.7.5",
             "source": {
                 "type": "git",
-                "url": "https://github.com/symfony/Filesystem.git",
-                "reference": "2d7b2ddaf3f548f4292df49a99d19c853d43f0b8"
+                "url": "https://github.com/symfony/filesystem.git",
+                "reference": "a17f8a17c20e8614c15b8e116e2f4bcde102cfab"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/Filesystem/zipball/2d7b2ddaf3f548f4292df49a99d19c853d43f0b8",
-                "reference": "2d7b2ddaf3f548f4292df49a99d19c853d43f0b8",
+                "url": "https://api.github.com/repos/symfony/filesystem/zipball/a17f8a17c20e8614c15b8e116e2f4bcde102cfab",
+                "reference": "a17f8a17c20e8614c15b8e116e2f4bcde102cfab",
                 "shasum": ""
             },
             "require": {
@@ -3413,20 +3497,20 @@
             ],
             "description": "Symfony Filesystem Component",
             "homepage": "https://symfony.com",
-            "time": "2015-07-09 16:07:40"
+            "time": "2015-09-09 17:42:36"
         },
         {
             "name": "symfony/stopwatch",
-            "version": "v2.7.3",
+            "version": "v2.7.5",
             "source": {
                 "type": "git",
-                "url": "https://github.com/symfony/Stopwatch.git",
-                "reference": "b07a866719bbac5294c67773340f97b871733310"
+                "url": "https://github.com/symfony/stopwatch.git",
+                "reference": "08dd97b3f22ab9ee658cd16e6758f8c3c404336e"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/Stopwatch/zipball/b07a866719bbac5294c67773340f97b871733310",
-                "reference": "b07a866719bbac5294c67773340f97b871733310",
+                "url": "https://api.github.com/repos/symfony/stopwatch/zipball/08dd97b3f22ab9ee658cd16e6758f8c3c404336e",
+                "reference": "08dd97b3f22ab9ee658cd16e6758f8c3c404336e",
                 "shasum": ""
             },
             "require": {
@@ -3462,20 +3546,20 @@
             ],
             "description": "Symfony Stopwatch Component",
             "homepage": "https://symfony.com",
-            "time": "2015-07-01 18:23:16"
+            "time": "2015-09-22 13:49:29"
         },
         {
             "name": "symfony/yaml",
-            "version": "v2.7.3",
+            "version": "v2.7.5",
             "source": {
                 "type": "git",
-                "url": "https://github.com/symfony/Yaml.git",
-                "reference": "71340e996171474a53f3d29111d046be4ad8a0ff"
+                "url": "https://github.com/symfony/yaml.git",
+                "reference": "31cb2ad0155c95b88ee55fe12bc7ff92232c1770"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/Yaml/zipball/71340e996171474a53f3d29111d046be4ad8a0ff",
-                "reference": "71340e996171474a53f3d29111d046be4ad8a0ff",
+                "url": "https://api.github.com/repos/symfony/yaml/zipball/31cb2ad0155c95b88ee55fe12bc7ff92232c1770",
+                "reference": "31cb2ad0155c95b88ee55fe12bc7ff92232c1770",
                 "shasum": ""
             },
             "require": {
@@ -3511,7 +3595,7 @@
             ],
             "description": "Symfony Yaml Component",
             "homepage": "https://symfony.com",
-            "time": "2015-07-28 14:07:07"
+            "time": "2015-09-14 14:14:09"
         }
     ],
     "aliases": [],
--- a/server/src/config/corpusparole.php	Fri Nov 13 16:45:27 2015 +0100
+++ b/server/src/config/corpusparole.php	Tue Nov 17 13:11:55 2015 +0100
@@ -11,8 +11,14 @@
 
     'cocoon_rdf_base_uri' => env('CORPUSPAROLE_COCOON_RDF_BASE_URI'),
     'cocoon_oaipmh_url' => env('CORPUSPAROLE_COCOON_OAIPMH_URL'),
-    'cocoon_doc_id_base_uri' => env('CORPUSPAROLE_COCOON_DOC_ID_BASE_URI'),
+    'cocoon_doc_id_base_uri' => 'http://purl.org/poi/crdo.vjf.cnrs.fr/',
+    'cocoon_doc_pub_base_uri' => 'http://cocoon.huma-num.fr/exist/crdo/meta/',
     'cocoon_doc_id_base' => 'oai:crdo.vjf.cnrs.fr:',
 
-    'easyrdf_http_client_timeout' => env('EASYRDF_HTTP_CLIENT_TIMEOUT', 10),
+    'corpus_doc_id_base_uri' => 'http://purl.org/poi/corpusdelaparole.huma-num.fr/',
+    'corpus_doc_default_cc_rights' => 'http://creativecommons.org/licenses/by-nc/4.0/',
+
+    'edm_provider' => 'Corpus de la Parole',
+
+    'easyrdf_http_client_timeout' => env('EASYRDF_HTTP_CLIENT_TIMEOUT', 1000),
 ];
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/database/migrations/2015_11_16_182634_create_cocoon_documents_table.php	Tue Nov 17 13:11:55 2015 +0100
@@ -0,0 +1,32 @@
+<?php
+
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Migrations\Migration;
+
+class CreateCocoonDocumentsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('cocoon_documents', function (Blueprint $table) {
+            $table->increments('id');
+            $table->string('uri')->unique();
+            $table->string('title', 2048);
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::drop('cocoon_documents');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/database/migrations/2015_11_16_183307_create_cocoon_revisions_table.php	Tue Nov 17 13:11:55 2015 +0100
@@ -0,0 +1,31 @@
+<?php
+
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Migrations\Migration;
+
+class CreateCocoonRevisionsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('cocoon_revisions', function (Blueprint $table) {
+            $table->increments('id');
+            $table->timestamps();
+            $table->integer('document_id');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::drop('cocoon_revisions');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/tests/libraries/Mappers/CocoonCollectionRdfMapperTest.php	Tue Nov 17 13:11:55 2015 +0100
@@ -0,0 +1,203 @@
+<?php
+
+use CorpusParole\Libraries\Mappers\CocoonCollectionRdfMapper;
+use CorpusParole\Libraries\CocoonUtils;
+
+use EasyRdf\Graph;
+use EasyRdf\Resource;
+use EasyRdf\Literal;
+
+use Illuminate\Foundation\Testing\WithoutMiddleware;
+use Illuminate\Foundation\Testing\DatabaseMigrations;
+use Illuminate\Foundation\Testing\DatabaseTransactions;
+
+class CocoonCollectionRdfMapperTest extends TestCase
+{
+
+    const TEST_INPUT_DOCS = [
+        'BASE' => <<<EOT
+        @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+        @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#> .
+        @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+        @prefix sesame: <http://www.openrdf.org/schema/sesame#> .
+        @prefix v: <http://rdf.data-vocabulary.org/#> .
+        <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_CFPP2000> a <http://crdo.risc.cnrs.fr/schemas/Resource> ;
+            <http://purl.org/dc/elements/1.1/description> "Corpus de Français Parlé Parisien des années 2000."@fr , "Le Corpus de Français Parlé Parisien (CFPP2000) est composé d'un ensemble d'interviews non directives sur les quartiers de Paris et de la proche banlieue. Les entretiens, transcrits en orthographe et alignés au tour de parole, sont disponibles sur le net ; ils sont librement employables en échange de la mention dans la bibliographie des travaux qui en seraient tirés d'une part de l'adresse du site: http://cfpp2000.univ-paris3.fr/ et d'autre part du document de présentation suivant : Branca-Rosoff S., Fleury S., Lefeuvre F., Pires M., 2012, \"Discours sur la ville. Présentation du Corpus de Français Parlé Parisien des années 2000 (CFPP2000)\". En février 2013, ce corpus comprenait environ 550 000 mots. Un certain nombre d'outils en ligne, notamment un concordancier et  des outils textométriques permettent de mener des requêtes lexicales et grammaticales. CFPP2000 est particulièrement destiné à des analyses sur le français oral. Le projet sous-jacent au corpus est par ailleurs l'étude des modifications et des variations qui interviennent dans ce qu'on peut considérer comme un parisien véhiculaire en tension entre le pôle du standard et le pôle du vernaculaire. Par ailleurs, il comporte des activités linguistiques diversifiées (description de quartier, anecdotes, argumentation…) et on peut par conséquent travailler sur la syntaxe propre à ces différentes utilisations du langage. Il permet enfin d'opposer dialogues (entre enquêteur et enquêtés) et multilogues (où la présence de plusieurs enquêtés favorise le passage à un registre familier).  CFPP2000 est constitué d'interviews longues (d'une heure en moyenne) intégralement transcrites. Il est donc utilisable pour examiner les singularités qui reviennent à l'idiolecte propre à une personne donnée, par opposition aux variantes diffusées dans des groupes plus larges (quartiers, groupes socio-culturels, classe d'âge, etc.). Le corpus constitue enfin un ensemble de témoignages intéressants sur les représentations de Paris et de sa proche banlieue qui est susceptible d'intéresser des analystes du discours, des sociologues, ou tout simplement des curieux de la ville."@fr ;
+            <http://purl.org/dc/elements/1.1/type> <http://purl.org/dc/dcmitype/Collection> ;
+            <http://purl.org/dc/elements/1.1/subject> <http://lexvo.org/id/iso639-3/fra> ;
+            <http://purl.org/dc/elements/1.1/language> <http://lexvo.org/id/iso639-3/gsw> ;
+            <http://purl.org/dc/terms/created> "start=1988; end=1989"^^<http://purl.org/dc/terms/Period> ;
+            <http://purl.org/dc/elements/1.1/rights> "Copyright (c) Département de dialectologie alsacienne et mosellane de l'Université de Strasbourg" ;
+            <http://www.language-archives.org/OLAC/1.1/depositor> <http://viaf.org/viaf/93752300> ;
+            <http://purl.org/dc/elements/1.1/publisher> <http://viaf.org/viaf/142432638> , "Fédération CLESTHIA" , <http://viaf.org/viaf/154862993> ;
+            <http://purl.org/dc/elements/1.1/title> "Corpus de Français Parlé Parisien des années 2000 (CFPP)"@fr ;
+            <http://www.language-archives.org/OLAC/1.1/interviewer> "Branca-Rosoff, Sonia" , "Lefeuvre, Florence" , "Pires, Mat" ;
+            <http://purl.org/dc/terms/accessRights> "Freely available for non-commercial use" ;
+            <http://purl.org/dc/terms/license> <http://creativecommons.org/licenses/by-nc-sa/3.0/> ;
+            <http://purl.org/dc/terms/spatial> "FR"^^<http://purl.org/dc/terms/ISO3166> , "France, Paris, Université Sorbonne Nouvelle Paris 3, site Censier"@fr , <http://vocab.getty.edu/tgn/7008038> ;
+            <http://purl.org/dc/terms/available> "2013-04-12"^^<http://purl.org/dc/terms/W3CDTF> ;
+            <http://purl.org/dc/terms/issued> "2013-04-12T22:20:23+02:00"^^<http://purl.org/dc/terms/W3CDTF> ;
+            <http://purl.org/dc/terms/modified> "2014-05-10T20:16:27+02:00"^^<http://purl.org/dc/terms/W3CDTF> ;
+            <http://www.language-archives.org/OLAC/1.1/transcriber> "Branca-Rosoff, Sonia" , "Lefeuvre, Florence" , "Pires, Mat" ;
+            <http://www.w3.org/2003/01/geo/wgs84_pos#long> "2.3333"^^xsd:float ;
+            <http://www.w3.org/2003/01/geo/wgs84_pos#lat> "48.8667"^^xsd:float ;
+            <http://www.language-archives.org/OLAC/1.1/compiler> "Branca-Rosoff, Sonia" , "Fleury, Serge" , "Lefeuvre, Florence" , "Pires, Mat" ;
+            <http://www.language-archives.org/OLAC/1.1/data_inputter> "Branca-Rosoff, Sonia" , "Lefeuvre, Florence" , "Pires, Mat" ;
+            <http://www.language-archives.org/OLAC/1.1/researcher> "Branca-Rosoff, Sonia" , "Fleury, Serge" , "Lefeuvre, Florence" , "Pires, Mat" ;
+            <http://www.language-archives.org/OLAC/1.1/sponsor> "Ville de Paris " , "Délégation générale à la langue française et aux langues de France " ;
+            <http://www.language-archives.org/OLAC/1.1/developer> "Fleury, Serge" ;
+            <http://purl.org/dc/terms/isPartOf> <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_ALA> .
+EOT
+    ];
+
+    const TEST_INPUT_ID = "crdo-COLLECTION_CFPP2000";
+    const TEST_GRAPH_URI = "http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_CFPP2000";
+
+    private $inputGraphes = [];
+    private $resGraphes = [];
+    private $mappers = [];
+
+    function __construct(string $name = null) {
+        parent::__construct($name);
+    }
+
+    public function setUp() {
+        parent::setUp();
+
+        foreach(CocoonCollectionRdfMapperTest::TEST_INPUT_DOCS as $key => $inputDoc) {
+            $this->inputGraphes[$key] = new Graph("http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_CFPP2000", $inputDoc);
+            $this->mappers[$key] = new CocoonCollectionRdfMapper($this->inputGraphes[$key]);
+            $this->mappers[$key]->mapGraph();
+            $this->resGraphes[$key] = $this->mappers[$key]->getOutputGraphes()[$this->inputGraphes[$key]->getUri()];
+        }
+    }
+
+    public function tearDown() {
+        parent::tearDown();
+    }
+
+    /**
+     * Just test that the construct and setup are ok
+     *
+     * @return void
+     */
+    public function testInit()
+    {
+        $this->assertTrue(true);
+    }
+
+    /**
+     * Test that the returned graph has the same uri that the original.
+     *
+     * @return void
+     */
+    public function testUri() {
+
+        echo $this->resGraphes['BASE']->serialise('turtle');
+        //echo var_export($this->resGraphes['BASE']->toRdfPhp());
+
+        $this->assertNotNull($this->resGraphes['BASE']);
+        $this->assertEquals(CocoonCollectionRdfMapperTest::TEST_GRAPH_URI, $this->resGraphes['BASE']->getUri(), "URIS must be translated");
+     }
+
+    /**
+      * Test that the return graph has one edm:Collection resource
+      *
+      * @return void
+      */
+    public function testAggregationResource() {
+
+        $resources = $this->resGraphes['BASE']->allOfType('edm:Collection');
+
+        $this->assertCount(1, $resources, "Must found only one resources of type edm:Collection");
+        $this->assertEquals(CocoonCollectionRdfMapperTest::TEST_GRAPH_URI,$resources[0]);
+    }
+
+    /**
+    * Test one to one mapping spatial info
+    *
+    * @return void
+    */
+    public function testSpatial() {
+
+        $coll = $this->resGraphes['BASE']->get('edm:Collection', '^rdf:type');
+        $sourceNode = $this->inputGraphes['BASE']->get('http://crdo.risc.cnrs.fr/schemas/Resource', '^rdf:type');
+
+        $this->assertNotNull($coll);
+        $this->assertNotNull($sourceNode);
+
+        $spatials = $coll->all($this->resGraphes['BASE']->resource('http://purl.org/dc/terms/spatial'));
+
+        $this->assertCount(1, $spatials, "Must have only one spatial node");
+        $spatial = $spatials[0];
+        $this->assertTrue($spatial->isBNode(),"spatial node must be blank");
+        $this->assertEquals("edm:Place", $spatial->type(), "spatial node type must be edm:Place");
+
+        $lats = $spatial->all('geo:lat');
+        $this->assertCount(1, $lats, "One latitude");
+        $this->assertInstanceOf("EasyRdf\Literal", $lats[0], "Latitude must be a litteral");
+        $this->assertEquals(Literal::create("48.8667", null, 'xsd:float'), $lats[0], "lat must be '48.8667'^^xsd:float");
+
+        $longs = $spatial->all('geo:long');
+        $this->assertCount(1, $longs, "One longitude");
+        $this->assertInstanceOf("EasyRdf\Literal", $longs[0], "Longitude must be a litteral");
+        $this->assertEquals(Literal::create("2.3333", null, 'xsd:float'), $longs[0], "long must be '1.90'^^xsd:float");
+
+        $notes = $spatial->all('skos:note');
+        $this->assertCount(2, $notes, "2 notes");
+        $this->assertContainsOnlyInstancesOf("EasyRdf\Literal", $notes, "Notes mus be only literals");
+        $this->assertEquals(Literal::create("FR", null, "dc:ISO3166"), $notes[0], "notes contains 'FR'^^dc:ISO3166");
+        $this->assertEquals(Literal::create("France, Paris, Université Sorbonne Nouvelle Paris 3, site Censier", "fr", null), $notes[1], "notes contains 'France, Paris, Université Sorbonne Nouvelle Paris 3, site Censier'@fr");
+
+        $sameas = $spatial->all('owl:sameAs');
+        $this->assertCount(1, $sameas, "1 same as");
+        $this->assertContainsOnlyInstancesOf("EasyRdf\Resource", $sameas, "Notes mus be only resources");
+        $this->assertEquals('http://vocab.getty.edu/tgn/7008038', $sameas[0]->getUri(), "uri must be http://vocab.getty.edu/tgn/7008038");
+    }
+
+    /**
+     * Test one to one mapping
+     *
+     * @return void
+     */
+    public function testOneToOnePropsIdentity() {
+
+        $properties = [
+            'http://purl.org/dc/elements/1.1/description',
+            'http://purl.org/dc/elements/1.1/language',
+            'http://purl.org/dc/elements/1.1/publisher',
+            'http://purl.org/dc/elements/1.1/rights',
+            'http://purl.org/dc/terms/license',
+            'http://purl.org/dc/elements/1.1/subject',
+            'http://purl.org/dc/elements/1.1/title',
+            'http://purl.org/dc/terms/available',
+            'http://purl.org/dc/terms/created',
+            'http://purl.org/dc/terms/issued',
+            'http://purl.org/dc/elements/1.1/type',
+            'http://purl.org/dc/elements/1.1/language',
+            'http://purl.org/dc/terms/isPartOf',
+            'http://purl.org/dc/terms/modified',
+        ];
+
+        $coll = $this->resGraphes['BASE']->get('edm:Collection', '^rdf:type');
+        $sourceNode = $this->inputGraphes['BASE']->get('http://crdo.risc.cnrs.fr/schemas/Resource', '^rdf:type');
+
+        $this->assertNotNull($coll);
+        $this->assertNotNull($sourceNode);
+
+        foreach ($properties as $prop) {
+            $outputValuesStr = [];
+            foreach($coll->all($this->resGraphes['BASE']->resource($prop)) as $outputValue) {
+                array_push($outputValuesStr, strval($outputValue));
+            }
+            $this->assertNotEmpty($outputValuesStr, "we must found some values to test $prop");
+            foreach ($sourceNode->all($this->inputGraphes['BASE']->resource($prop)) as $value) {
+                $this->assertContains(strval($value), $outputValuesStr, "$prop not found in output graph");
+            }
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/tests/libraries/Mappers/CocoonSoundRdfMapperTest.php	Tue Nov 17 13:11:55 2015 +0100
@@ -0,0 +1,487 @@
+<?php
+
+use CorpusParole\Libraries\Mappers\CocoonSoundRdfMapper;
+use CorpusParole\Libraries\CocoonUtils;
+
+use EasyRdf\Graph;
+use EasyRdf\Resource;
+use EasyRdf\Literal;
+
+use Illuminate\Foundation\Testing\WithoutMiddleware;
+use Illuminate\Foundation\Testing\DatabaseMigrations;
+use Illuminate\Foundation\Testing\DatabaseTransactions;
+
+class CocoonSoundRdfMapperTest extends TestCase
+{
+
+    const TEST_INPUT_DOCS = [
+        'BASE' => <<<EOT
+        @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+        @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#> .
+        @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+        @prefix sesame: <http://www.openrdf.org/schema/sesame#> .
+        @prefix v: <http://rdf.data-vocabulary.org/#> .
+            <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-ESLO1_ENT_019> a <http://crdo.risc.cnrs.fr/schemas/Resource> ;
+            <http://purl.org/dc/elements/1.1/description> "Extrait du corpus d'Orléans, réalisé dans le cadre de l'Enquête SocioLinguistique à Orléans à la fin des années 1960."@fr ;
+            <http://purl.org/dc/elements/1.1/type> <http://purl.org/dc/dcmitype/Sound> , "primary_text"^^<http://www.language-archives.org/OLAC/1.1/linguistic-type> , "dialogue"^^<http://www.language-archives.org/OLAC/1.1/discourse-type> ;
+            <http://purl.org/dc/elements/1.1/subject> <http://lexvo.org/id/iso639-3/fra> , "text_and_corpus_linguistics"^^<http://www.language-archives.org/OLAC/1.1/linguistic-field> , <http://ark.bnf.fr/ark:/12148/cb135052099> , <http://ark.bnf.fr/ark:/12148/cb11943508j> , <http://ark.bnf.fr/ark:/12148/cb11934124q> , <http://ark.bnf.fr/ark:/12148/cb11931498c> , <http://ark.bnf.fr/ark:/12148/cb11935508t> , <http://ark.bnf.fr/ark:/12148/cb11934132b> , <http://ark.bnf.fr/ark:/12148/cb11939893p> , <http://ark.bnf.fr/ark:/12148/cb11933091b> ;
+            <http://purl.org/dc/elements/1.1/language> <http://lexvo.org/id/iso639-3/fra> ;
+            <http://www.language-archives.org/OLAC/1.1/depositor> <http://viaf.org/viaf/181558906> ;
+            <http://purl.org/dc/elements/1.1/publisher> <http://viaf.org/viaf/181558906> ;
+            <http://purl.org/dc/elements/1.1/rights> "Copyright (c) 2012 Université d'Orléans/LLL" ;
+            <http://purl.org/dc/elements/1.1/title> "ESLO1: entretien 019"@fr ;
+            <http://purl.org/dc/terms/alternative> "ESLO1: entretien 019 alt"@fr ;
+            <http://purl.org/dc/terms/isFormatOf> <http://cocoon.huma-num.fr/data/eslo/ESLO1_ENT_019_22km.wav> , <http://cocoon.huma-num.fr/data/eslo/ESLO1_ENT_019.mp3> ;
+            <http://purl.org/dc/terms/accessRights> " Freely available for non-commercial use" ;
+            <http://purl.org/dc/terms/license> <http://creativecommons.org/licenses/by-nc-sa/3.0/> ;
+            <http://purl.org/dc/terms/isPartOf> <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_LANGUESDEFRANCE> , <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_ESLO1> ;
+            <http://purl.org/dc/terms/extent> "PT0H47M16S" ;
+            <http://purl.org/dc/terms/created> "1969-04-11"^^<http://purl.org/dc/terms/W3CDTF> ;
+            <http://purl.org/dc/terms/spatial> "FR"^^<http://purl.org/dc/terms/ISO3166> , <http://vocab.getty.edu/tgn/7008337> , "France, Centre, Loiret, Orléans"@fr ;
+            <http://crdo.risc.cnrs.fr/schemas/master> <http://cocoon.huma-num.fr/data/eslo/masters/ESLO1_ENT_019.wav> ;
+            <http://purl.org/dc/terms/available> "2014-11-06"^^<http://purl.org/dc/terms/W3CDTF> ;
+            <http://purl.org/dc/terms/issued> "2014-12-05T15:00:19+01:00"^^<http://purl.org/dc/terms/W3CDTF> ;
+            <http://purl.org/dc/terms/modified> "2014-12-05T15:00:19+01:00"^^<http://purl.org/dc/terms/W3CDTF> ;
+            <http://www.language-archives.org/OLAC/1.1/speaker> "JK" , "UG393" ;
+            <http://purl.org/dc/elements/1.1/source> <http://archivesetmanuscrits.bnf.fr/ead.html?id=FRBNFEAD000095934&c=FRBNFEAD000095934_a19844296> ;
+            <http://www.w3.org/2003/01/geo/wgs84_pos#long> "1.90"^^xsd:float ;
+            <http://www.w3.org/2003/01/geo/wgs84_pos#lat> "47.90"^^xsd:float ;
+            <http://purl.org/dc/terms/tableOfContents> "01 née; famille a toujours habité Orléans03 oui, on y a des amis, relations04 oui, certainementT1 centralisait comptabilité dans une industrieT2 RR passer des écritures, caisse; horaires avant et après loi de 1936T3 aimait travail, rien ne lui déplaisaitT4 n'a jamais pensé à çaT5 actuellement on est forcée quelquefois - assurance sociale - retraite appréciable; autre chose avec enfantL1 concerts, théâtre, réunions, etc...:préfère s'occuperL2 messe, puis a passé la journée avec une amieL3 (quand elle travaillait) au bord de la mer ou voyages organisésE1 n'en sait rienE2 lui semble que ça aide le françaisE3 peut-être chimie, physiqueE4 intelligence, travail, familleE5 dépend de leurs capacitésE6 non : dépend de la vie de l'enfant plus tardP1 oui, à part loyers chersP4 ne comprend pas motifs des étudiants; très calme à OrléansP9 moins qu'avant 1940P10 RR bourgeois = gros rentiers, femmes d'officierss, gros industriels; chaque groupe se recevait mutuellement, formait un clanQ. Orléans une ville renfermée? oui : orléanais assez distant, peut-être moins maintenantP6 il faut avoir la moitié des votesP7 des candidats se retirentP8 droite gaulliste, réservée; gauche avancéeP5 pas grand-chose - attachés à leurs partisP11 oui, maintenant, par l'éducation; famille moins importanteP12 à diminuer : les gens travaillent beaucoup plus et l'argent a changé de mainsOmelette (je casse mes oeufs...)Questionnaire sociolinguistique"@fr ;
+            <http://purl.org/dc/terms/isRequiredBy> <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-ESLO1_ENT_019_C> , <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-ESLO1_ENT_019_A> ;
+            <http://www.language-archives.org/OLAC/1.1/editor> <http://viaf.org/viaf/39685504> , <http://viaf.org/viaf/200058210> ;
+            <http://purl.org/dc/terms/abstract> " Identifiant du témoin : UG 393 Femme, 72 ans (né en 1897, à Orléans ) ; comptable en retraite Enregistré par Jack Kay, le 11 avril 1969, au domicile du témoin. Questionnaires enregistrés : questionnaire sociolinguistique; questionnaire ouvert(questions 01 ; 03-04 ; T1-T5 ; L1-L3 ; E1-E6 ; P1 ; P4 ; P9-P10 ; P6-P8 ; P5 ; P11-P12 ; omelette). Classe politique du témoin : Centre Remarques sur le témoignage : réponses concises. Intérêt pédagogique : conditions de travail avant la guerre de 1940 ; classes sociales. Acoustique : bonne qualité d'enregistrement."@fr ;
+            <http://www.language-archives.org/OLAC/1.1/researcher> "Kay, Jack" ;
+            <http://purl.org/dc/elements/1.1/relation> <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-ESLO1_ENTCONT_233> ;
+            <http://purl.org/dc/terms/medium> "1 bande magnétique audio"@fr ;
+            <http://purl.org/dc/terms/bibliographicCitation> "A.-M. VURPAS (1988), Autrefois dans les monts du Beaujolais, Action graphique.";
+            <http://purl.org/dc/elements/1.1/identifier> "Cote producteur: 001_3"@fr ;
+            <http://purl.org/dc/elements/1.1/reference> <http://panini.u-paris10.fr> ;
+            <http://purl.org/dc/elements/1.1/coverage> "Quartier concerné : 3e"@fr ;
+            <http://purl.org/dc/elements/1.1/creator> "Blanc, Michel" , "Biggs, Patricia" .
+EOT
+        ,
+        'NO-FORMAT' => <<<EOT
+        @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+        @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#> .
+        @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+        @prefix sesame: <http://www.openrdf.org/schema/sesame#> .
+        @prefix v: <http://rdf.data-vocabulary.org/#> .
+            <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-ESLO1_ENT_019> a <http://crdo.risc.cnrs.fr/schemas/Resource> ;
+            <http://purl.org/dc/elements/1.1/description> "Extrait du corpus d'Orléans, réalisé dans le cadre de l'Enquête SocioLinguistique à Orléans à la fin des années 1960."@fr ;
+            <http://purl.org/dc/elements/1.1/type> <http://purl.org/dc/dcmitype/Sound> , "primary_text"^^<http://www.language-archives.org/OLAC/1.1/linguistic-type> , "dialogue"^^<http://www.language-archives.org/OLAC/1.1/discourse-type> ;
+            <http://purl.org/dc/elements/1.1/subject> <http://lexvo.org/id/iso639-3/fra> , "text_and_corpus_linguistics"^^<http://www.language-archives.org/OLAC/1.1/linguistic-field> , <http://ark.bnf.fr/ark:/12148/cb135052099> , <http://ark.bnf.fr/ark:/12148/cb11943508j> , <http://ark.bnf.fr/ark:/12148/cb11934124q> , <http://ark.bnf.fr/ark:/12148/cb11931498c> , <http://ark.bnf.fr/ark:/12148/cb11935508t> , <http://ark.bnf.fr/ark:/12148/cb11934132b> , <http://ark.bnf.fr/ark:/12148/cb11939893p> , <http://ark.bnf.fr/ark:/12148/cb11933091b> ;
+            <http://purl.org/dc/elements/1.1/language> <http://lexvo.org/id/iso639-3/fra> ;
+            <http://www.language-archives.org/OLAC/1.1/depositor> <http://viaf.org/viaf/181558906> ;
+            <http://purl.org/dc/elements/1.1/publisher> <http://viaf.org/viaf/181558906> ;
+            <http://purl.org/dc/elements/1.1/rights> "Copyright (c) 2012 Université d'Orléans/LLL" ;
+            <http://purl.org/dc/elements/1.1/title> "ESLO1: entretien 019"@fr ;
+            <http://purl.org/dc/terms/alternative> "ESLO1: entretien 019 alt"@fr ;
+            <http://purl.org/dc/terms/isFormatOf> <http://cocoon.huma-num.fr/data/eslo/ESLO1_ENT_019_22km.wav> , <http://cocoon.huma-num.fr/data/eslo/ESLO1_ENT_019.mp3> ;
+            <http://purl.org/dc/terms/accessRights> " Freely available for non-commercial use" ;
+            <http://purl.org/dc/terms/license> <http://creativecommons.org/licenses/by-nc-sa/3.0/> ;
+            <http://purl.org/dc/terms/isPartOf> <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_LANGUESDEFRANCE> , <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_ESLO1> ;
+            <http://purl.org/dc/terms/extent> "PT0H47M16S" ;
+            <http://purl.org/dc/terms/created> "1969-04-11"^^<http://purl.org/dc/terms/W3CDTF> ;
+            <http://purl.org/dc/terms/spatial> "FR"^^<http://purl.org/dc/terms/ISO3166> , <http://vocab.getty.edu/tgn/7008337> , "France, Centre, Loiret, Orléans"@fr ;
+            <http://crdo.risc.cnrs.fr/schemas/master> <http://cocoon.huma-num.fr/data/eslo/masters/ESLO1_ENT_019.wav> ;
+            <http://purl.org/dc/terms/available> "2014-11-06"^^<http://purl.org/dc/terms/W3CDTF> ;
+            <http://purl.org/dc/terms/issued> "2014-12-05T15:00:19+01:00"^^<http://purl.org/dc/terms/W3CDTF> ;
+            <http://purl.org/dc/terms/modified> "2014-12-05T15:00:19+01:00"^^<http://purl.org/dc/terms/W3CDTF> ;
+            <http://www.language-archives.org/OLAC/1.1/speaker> "JK" , "UG393" ;
+            <http://purl.org/dc/elements/1.1/source> <http://archivesetmanuscrits.bnf.fr/ead.html?id=FRBNFEAD000095934&c=FRBNFEAD000095934_a19844296> ;
+            <http://www.w3.org/2003/01/geo/wgs84_pos#long> "1.90"^^xsd:float ;
+            <http://www.w3.org/2003/01/geo/wgs84_pos#lat> "47.90"^^xsd:float ;
+            <http://purl.org/dc/terms/tableOfContents> "01 née; famille a toujours habité Orléans03 oui, on y a des amis, relations04 oui, certainementT1 centralisait comptabilité dans une industrieT2 RR passer des écritures, caisse; horaires avant et après loi de 1936T3 aimait travail, rien ne lui déplaisaitT4 n'a jamais pensé à çaT5 actuellement on est forcée quelquefois - assurance sociale - retraite appréciable; autre chose avec enfantL1 concerts, théâtre, réunions, etc...:préfère s'occuperL2 messe, puis a passé la journée avec une amieL3 (quand elle travaillait) au bord de la mer ou voyages organisésE1 n'en sait rienE2 lui semble que ça aide le françaisE3 peut-être chimie, physiqueE4 intelligence, travail, familleE5 dépend de leurs capacitésE6 non : dépend de la vie de l'enfant plus tardP1 oui, à part loyers chersP4 ne comprend pas motifs des étudiants; très calme à OrléansP9 moins qu'avant 1940P10 RR bourgeois = gros rentiers, femmes d'officierss, gros industriels; chaque groupe se recevait mutuellement, formait un clanQ. Orléans une ville renfermée? oui : orléanais assez distant, peut-être moins maintenantP6 il faut avoir la moitié des votesP7 des candidats se retirentP8 droite gaulliste, réservée; gauche avancéeP5 pas grand-chose - attachés à leurs partisP11 oui, maintenant, par l'éducation; famille moins importanteP12 à diminuer : les gens travaillent beaucoup plus et l'argent a changé de mainsOmelette (je casse mes oeufs...)Questionnaire sociolinguistique"@fr ;
+            <http://purl.org/dc/terms/isRequiredBy> <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-ESLO1_ENT_019_C> , <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-ESLO1_ENT_019_A> ;
+            <http://www.language-archives.org/OLAC/1.1/editor> <http://viaf.org/viaf/39685504> , <http://viaf.org/viaf/200058210> ;
+            <http://purl.org/dc/terms/abstract> " Identifiant du témoin : UG 393 Femme, 72 ans (né en 1897, à Orléans ) ; comptable en retraite Enregistré par Jack Kay, le 11 avril 1969, au domicile du témoin. Questionnaires enregistrés : questionnaire sociolinguistique; questionnaire ouvert(questions 01 ; 03-04 ; T1-T5 ; L1-L3 ; E1-E6 ; P1 ; P4 ; P9-P10 ; P6-P8 ; P5 ; P11-P12 ; omelette). Classe politique du témoin : Centre Remarques sur le témoignage : réponses concises. Intérêt pédagogique : conditions de travail avant la guerre de 1940 ; classes sociales. Acoustique : bonne qualité d'enregistrement."@fr ;
+            <http://www.language-archives.org/OLAC/1.1/researcher> "Kay, Jack" ;
+            <http://purl.org/dc/elements/1.1/relation> <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-ESLO1_ENTCONT_233> ;
+            <http://purl.org/dc/terms/medium> "1 bande magnétique audio"@fr ;
+            <http://purl.org/dc/terms/bibliographicCitation> "A.-M. VURPAS (1988), Autrefois dans les monts du Beaujolais, Action graphique.";
+            <http://purl.org/dc/elements/1.1/identifier> "Cote producteur: 001_3"@fr ;
+            <http://purl.org/dc/elements/1.1/reference> <http://panini.u-paris10.fr> ;
+            <http://purl.org/dc/elements/1.1/creator> "Blanc, Michel" , "Biggs, Patricia" .
+
+EOT
+    ];
+
+    const TEST_INPUT_ID = "crdo-ESLO1_ENT_019";
+    const TEST_GRAPH_URI = "http://purl.org/poi/corpusdelaparole.huma-num.fr/crdo-ESLO1_ENT_019";
+    const TEST_CHO_URI = "http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-ESLO1_ENT_019";
+
+
+    private $inputGraphes = [];
+    private $resGraphes = [];
+    private $mappers = [];
+
+    function __construct(string $name = null) {
+        parent::__construct($name);
+    }
+
+    public function setUp() {
+        parent::setUp();
+
+        foreach(CocoonSoundRdfMapperTest::TEST_INPUT_DOCS as $key => $inputDoc) {
+            $this->inputGraphes[$key] = new Graph("http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-ESLO1_ENT_019", $inputDoc);
+            $this->mappers[$key] = new CocoonSoundRdfMapper($this->inputGraphes[$key]);
+            $this->mappers[$key]->mapGraph();
+            $this->resGraphes[$key] = $this->mappers[$key]->getOutputGraphes()[$this->inputGraphes[$key]->getUri()];
+        }
+    }
+
+    public function tearDown() {
+        parent::tearDown();
+    }
+
+    /**
+     * Just test that the construct and setup are ok
+     *
+     * @return void
+     */
+    public function testInit()
+    {
+        $this->assertTrue(true);
+    }
+
+    /**
+     * Test that the returned graph has the same uri that the original.
+     *
+     * @return void
+     */
+    public function testUri() {
+
+         echo $this->resGraphes['BASE']->serialise('turtle');
+         //echo var_export($this->resGraphes['BASE']->toRdfPhp());
+
+         $this->assertNotNull($this->resGraphes['BASE']);
+         $this->assertEquals(CocoonSoundRdfMapperTest::TEST_GRAPH_URI, $this->resGraphes['BASE']->getUri(), "URIS must be translated");
+     }
+
+    /**
+      * Test that the return graph has one ore:Aggregation resource
+      *
+      * @return void
+      */
+    public function testAggregationResource() {
+
+         $resources = $this->resGraphes['BASE']->allOfType('ore:Aggregation');
+
+         $this->assertCount(1, $resources, "Must found only one resources of type ore:Aggregation");
+         $this->assertEquals(CocoonSoundRdfMapperTest::TEST_GRAPH_URI,$resources[0]);
+     }
+
+    /**
+      * test that there one (and only one) edm:dateProvider and edm:provider property
+      *
+      * @return void
+      */
+    public function testProviders() {
+
+         $providers = $this->resGraphes['BASE']->all(CocoonSoundRdfMapperTest::TEST_GRAPH_URI,'edm:provider');
+
+         $this->assertCount(1,$providers, "one and only one edm provider");
+         $this->assertTrue($providers[0] instanceof Literal);
+         $this->assertEquals('Corpus de la Parole', $providers[0]->getValue(), 'provider must be Corpus de la Parole');
+         $this->assertEquals('fr', $providers[0]->getLang(), 'provider must be in french');
+
+         $dataProviders = $this->resGraphes['BASE']->all(CocoonSoundRdfMapperTest::TEST_GRAPH_URI,'edm:dataProvider');
+
+         $this->assertCount(1,$dataProviders, "one and only one edm data provider");
+         //TODO: to change after viaf resolution
+         $this->assertTrue($dataProviders[0] instanceof Resource);
+         $this->assertEquals('http://viaf.org/viaf/181558906', $dataProviders[0]->getUri(), 'dataProvider uri must be http://viaf.org/viaf/181558906');
+    }
+
+
+    /**
+     * test isShownAt and isShownBy
+     *
+     * @return void
+     */
+    public function testIsShown() {
+
+        $isShownAts = $this->resGraphes['BASE']->all(CocoonSoundRdfMapperTest::TEST_GRAPH_URI, 'edm:isShownAt');
+
+        $this->assertCount(1, $isShownAts, "One edm:isShownAt");
+        $this->assertInstanceOf("EasyRdf\Resource", $isShownAts[0]);
+        $this->assertEquals("http://cocoon.huma-num.fr/exist/crdo/meta/crdo-ESLO1_ENT_019", $isShownAts[0]);
+
+        $isShownBys = $this->resGraphes['BASE']->all(CocoonSoundRdfMapperTest::TEST_GRAPH_URI, 'edm:isShownBy');
+
+        $this->assertCount(1, $isShownBys, "One edm:isShownBy");
+        $this->assertInstanceOf("EasyRdf\Resource", $isShownBys[0]);
+        $this->assertEquals("http://cocoon.huma-num.fr/data/eslo/masters/ESLO1_ENT_019.wav", $isShownBys[0]);
+
+    }
+
+    /**
+     * test rights
+     *
+     * @return void
+     */
+    public function testRights() {
+        $rightsNodes = $this->resGraphes['BASE']->all(CocoonSoundRdfMapperTest::TEST_GRAPH_URI, 'edm:rights');
+
+        $this->assertCount(1, $rightsNodes, "One edm:right");
+
+        $rights = $rightsNodes[0];
+
+        $this->assertTrue($rights instanceof Resource);
+
+        $this->assertEquals("http://creativecommons.org/licenses/by-nc-sa/4.0/", $rights->getUri(), "right must be CC-BY-NC");
+    }
+
+    /**
+     * Test that the return graph has one ore:Aggregation resource
+     *
+     * @return void
+     */
+    public function testProvidedCHO() {
+
+         $resources = $this->resGraphes['BASE']->allOfType('edm:ProvidedCHO');
+
+         $this->assertCount(1, $resources, "Must found only one resources of type edm:aggregatedCHO");
+         $this->assertEquals(CocoonSoundRdfMapperTest::TEST_CHO_URI,$resources[0]);
+     }
+
+    /**
+     * Test one to one mapping
+     *
+     * @return void
+     */
+    public function testOneToOneProvidedCHOIdentity() {
+
+        $properties = [
+            'http://purl.org/dc/terms/tableOfContents',
+            'http://purl.org/dc/elements/1.1/description',
+            'http://purl.org/dc/elements/1.1/language',
+            'http://purl.org/dc/elements/1.1/publisher',
+            'http://purl.org/dc/elements/1.1/rights',
+            'http://purl.org/dc/terms/license',
+            'http://purl.org/dc/elements/1.1/subject',
+            'http://purl.org/dc/elements/1.1/title',
+            'http://purl.org/dc/terms/available',
+            'http://purl.org/dc/terms/created',
+            'http://purl.org/dc/terms/issued',
+            'http://purl.org/dc/terms/extent',
+            'http://purl.org/dc/elements/1.1/type',
+            'http://purl.org/dc/elements/1.1/language',
+            'http://purl.org/dc/terms/medium',
+            'http://purl.org/dc/terms/isPartOf',
+            'http://purl.org/dc/elements/1.1/source',
+            'http://purl.org/dc/terms/alternative',
+            'http://purl.org/dc/terms/modified',
+            'http://purl.org/dc/terms/bibliographicCitation',
+            'http://purl.org/dc/elements/1.1/identifier',
+            'http://purl.org/dc/terms/references',
+            'http://purl.org/dc/elements/1.1/coverage',
+            'http://purl.org/dc/elements/1.1/relation',
+            'http://purl.org/dc/elements/1.1/creator',
+        ];
+
+        $providedCHO = $this->resGraphes['BASE']->get('edm:ProvidedCHO', '^rdf:type');
+        $sourceNode = $this->inputGraphes['BASE']->get('http://crdo.risc.cnrs.fr/schemas/Resource', '^rdf:type');
+
+        $this->assertNotNull($providedCHO);
+        $this->assertNotNull($sourceNode);
+
+        foreach ($properties as $prop) {
+            $outputValuesStr = [];
+            foreach($providedCHO->all($this->resGraphes['BASE']->resource($prop)) as $outputValue) {
+                array_push($outputValuesStr, strval($outputValue));
+            }
+            $this->assertNotEmpty($outputValuesStr, "we must found some values to test $prop");
+            foreach ($sourceNode->all($this->inputGraphes['BASE']->resource($prop)) as $value) {
+                $this->assertContains(strval($value), $outputValuesStr, "$prop not found in output graph");
+            }
+        }
+
+    }
+
+    /**
+    * Test one to one mapping spatial info
+    *
+    * @return void
+    */
+    public function testOneToOneProvidedCHOSpatial() {
+        $providedCHO = $this->resGraphes['BASE']->get('edm:ProvidedCHO', '^rdf:type');
+        $sourceNode = $this->inputGraphes['BASE']->get('http://crdo.risc.cnrs.fr/schemas/Resource', '^rdf:type');
+
+        $this->assertNotNull($providedCHO);
+        $this->assertNotNull($sourceNode);
+
+        $spatials = $providedCHO->all($this->resGraphes['BASE']->resource('http://purl.org/dc/terms/spatial'));
+
+        $this->assertCount(1, $spatials, "Must have only one spatial node");
+        $spatial = $spatials[0];
+        $this->assertTrue($spatial->isBNode(),"spatial node must be blank");
+        $this->assertEquals("edm:Place", $spatial->type(), "spatial node type must be edm:Place");
+
+        $lats = $spatial->all('geo:lat');
+        $this->assertCount(1, $lats, "One latitude");
+        $this->assertInstanceOf("EasyRdf\Literal", $lats[0], "Latitude must be a litteral");
+        $this->assertEquals(Literal::create("47.90", null, 'xsd:float'), $lats[0], "lat must be '47.90'^^xsd:float");
+
+        $longs = $spatial->all('geo:long');
+        $this->assertCount(1, $longs, "One longitude");
+        $this->assertInstanceOf("EasyRdf\Literal", $longs[0], "Longitude must be a litteral");
+        $this->assertEquals(Literal::create("1.90", null, 'xsd:float'), $longs[0], "long must be '1.90'^^xsd:float");
+
+        $notes = $spatial->all('skos:note');
+        $this->assertCount(2, $notes, "2 notes");
+        $this->assertContainsOnlyInstancesOf("EasyRdf\Literal", $notes, "Notes mus be only literals");
+        $this->assertEquals(Literal::create("FR", null, "dc:ISO3166"), $notes[0], "notes contains 'FR'^^dc:ISO3166");
+        $this->assertEquals(Literal::create("France, Centre, Loiret, Orléans", "fr", null), $notes[1], "notes contains 'France, Centre, Loiret, Orléans'@fr");
+
+        $sameas = $spatial->all('owl:sameAs');
+        $this->assertCount(1, $sameas, "1 same as");
+        $this->assertContainsOnlyInstancesOf("EasyRdf\Resource", $sameas, "Notes mus be only resources");
+        $this->assertEquals('http://vocab.getty.edu/tgn/7008337', $sameas[0]->getUri(), "uri must be http://vocab.getty.edu/tgn/7008337");
+    }
+
+    /**
+     * Test one to one mapping trim values
+     *
+     * @return void
+     */
+    public function testOneToOneProvidedCHOTrim() {
+
+        $properties = [
+            'http://purl.org/dc/terms/accessRights',
+        ];
+
+        $providedCHO = $this->resGraphes['BASE']->get('edm:ProvidedCHO', '^rdf:type');
+        $sourceNode = $this->inputGraphes['BASE']->get('http://crdo.risc.cnrs.fr/schemas/Resource', '^rdf:type');
+
+        $this->assertNotNull($providedCHO);
+        $this->assertNotNull($sourceNode);
+
+        foreach ($properties as $prop) {
+            $outputValuesStr = [];
+            foreach($providedCHO->all($this->resGraphes['BASE']->resource($prop)) as $outputValue) {
+                array_push($outputValuesStr, strval($outputValue));
+            }
+            $this->assertNotEmpty($outputValuesStr, 'we must found some values to test');
+            foreach ($sourceNode->all($this->inputGraphes['BASE']->resource($prop)) as $value) {
+                $this->assertContains(trim(strval($value)), $outputValuesStr, "$prop not found in output graph");
+            }
+        }
+    }
+
+    /**
+     * Test one to one mapping trim values
+     *
+     * @return void
+     */
+    public function testOneToOneProvidedCHOReference() {
+
+        $providedCHO = $this->resGraphes['NO-FORMAT']->get('edm:ProvidedCHO', '^rdf:type');
+        $sourceNode = $this->inputGraphes['NO-FORMAT']->get('http://crdo.risc.cnrs.fr/schemas/Resource', '^rdf:type');
+
+        $this->assertNotNull($providedCHO);
+        $this->assertNotNull($sourceNode);
+
+        $outputValuesStr = [];
+        foreach($providedCHO->all($this->resGraphes['NO-FORMAT']->resource('http://purl.org/dc/terms/references')) as $outputValue) {
+            array_push($outputValuesStr, strval($outputValue));
+        }
+        $this->assertNotEmpty($outputValuesStr, 'we must found some values to test for http://purl.org/dc/elements/1.1/reference');
+        foreach ($sourceNode->all($this->inputGraphes['NO-FORMAT']->resource('http://purl.org/dc/elements/1.1/reference')) as $value) {
+            $this->assertContains(strval($value), $outputValuesStr, "http://purl.org/dc/terms/references not found in output graph");
+        }
+    }
+
+
+    /**
+     * Test that the web resources
+     *
+     * @return void
+     */
+    public function testWebResources() {
+
+        $resources = $this->resGraphes['BASE']->allOfType('edm:WebResources');
+
+        $this->assertCount(3, $resources, "Must found three webresources");
+
+        $aggregation = $this->resGraphes['BASE']->resource(CocoonSoundRdfMapperTest::TEST_GRAPH_URI);
+
+        foreach ($resources as $wres) {
+            $mimetypes = $wres->all($this->resGraphes['BASE']->resource('http://purl.org/dc/elements/1.1/format'));
+            $this->assertCount(1, $mimetypes, "Must find one mimetype.");
+            $mimetype = $mimetypes[0];
+            $this->assertInstanceOf("EasyRdf\Literal", $mimetype, "mimetype must be literal");
+            $this->assertEquals("dc:IMT",$mimetype->getDatatype());
+
+            $extends = $wres->all($this->resGraphes['BASE']->resource('http://purl.org/dc/terms/extent'));
+            $this->assertCount(1, $extends, "Must find one extent.");
+            $extent = $extends[0];
+            $this->assertInstanceOf("EasyRdf\Literal", $extent, "extent must be literal");
+            $this->assertStringStartsWith("PT", $extent->getValue(), "value mus start with PT");
+
+            if($wres->hasProperty('edm:isDerivativeOf')) {
+                $derivative = $wres->get('edm:isDerivativeOf');
+                $this->assertInstanceOf("EasyRdf\Resource", $derivative, "Derivative must be a resource");
+                $this->assertEquals("http://cocoon.huma-num.fr/data/eslo/masters/ESLO1_ENT_019.wav", $derivative->getUri(), "derivative uri must be http://cocoon.huma-num.fr/data/eslo/masters/ESLO1_ENT_019.wav");
+                $this->assertTrue($aggregation->hasProperty('edm:hasView', $wres));
+            }
+            else {
+                $this->assertTrue($aggregation->hasProperty('edm:isShownBy', $wres));
+            }
+
+        }
+    }
+
+    /**
+     * Test that the web resources
+     *
+     * @return void
+     */
+    public function testWebResourcesDate() {
+
+        $resources = $this->resGraphes['BASE']->allOfType('edm:WebResources');
+
+        foreach ($resources as $wres) {
+            $this->assertFalse($wres->hasProperty("http://purl.org/dc/terms/available"),"web resource must not have http://purl.org/dc/terms/available");
+            $this->assertFalse($wres->hasProperty("http://purl.org/dc/terms/modified"),"web resource must not have http://purl.org/dc/terms/modified");
+            $this->assertTrue($wres->hasProperty("http://purl.org/dc/terms/issued"), "Must have http://purl.org/dc/terms/issued");
+            $this->assertTrue($wres->hasProperty("http://purl.org/dc/terms/created"), "Must have http://purl.org/dc/terms/created");
+
+            $issued = $wres->getLiteral('dc:issued');
+            //<http://purl.org/dc/terms/issued> "2014-12-05T15:00:19+01:00"^^<http://purl.org/dc/terms/W3CDTF> ;
+            $this->assertInstanceOf('EasyRdf\Literal', $issued, "issued value must be a literal");
+            $this->assertEquals('http://purl.org/dc/terms/W3CDTF', $issued->getDatatypeUri(), "issued datatype uri must be a http://purl.org/dc/terms/W3CDTF");
+            $this->assertEquals('2014-12-05T15:00:19+01:00', $issued->getValue(), "Value must be 2014-12-05T15:00:19+01:00");
+
+            $created = $wres->getLiteral('dc:created');
+            //<http://purl.org/dc/terms/created> "1969-04-11"^^<http://purl.org/dc/terms/W3CDTF> ;
+            $this->assertInstanceOf('EasyRdf\Literal', $created, "created value must be a literal");
+            $this->assertEquals('http://purl.org/dc/terms/W3CDTF', $created->getDatatypeUri(), "created datatype uri must be a http://purl.org/dc/terms/W3CDTF");
+            $this->assertEquals('1969-04-11', $created->getValue(), "Value must be 1969-04-11");
+
+        }
+
+    }
+
+
+    /**
+     * Test collection graph creation
+     * @return void
+     */
+    public function testCollectionGraph() {
+        $outputs = $this->mappers['BASE']->getOutputGraphes();
+        $this->assertCount(3, $outputs, "Must have 3 graphes as output");
+        foreach($outputs as $url => $outputGraph) {
+            if($outputGraph->getUri() == 'http://purl.org/poi/corpusdelaparole.huma-num.fr/crdo-ESLO1_ENT_019') {
+                continue;
+            }
+            $this->assertContains($outputGraph->getUri(), ['http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_LANGUESDEFRANCE', 'http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_ESLO1']);
+            $this->assertEquals($outputGraph->resource($outputGraph->getUri())->type(), 'edm:Collection');
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/tests/libraries/Mappers/CocoonTextRdfMapperTest.php	Tue Nov 17 13:11:55 2015 +0100
@@ -0,0 +1,203 @@
+<?php
+
+use CorpusParole\Libraries\Mappers\CocoonTextRdfMapper;
+use CorpusParole\Libraries\CocoonUtils;
+
+use EasyRdf\Graph;
+use EasyRdf\Resource;
+use EasyRdf\Literal;
+
+use Illuminate\Foundation\Testing\WithoutMiddleware;
+use Illuminate\Foundation\Testing\DatabaseMigrations;
+use Illuminate\Foundation\Testing\DatabaseTransactions;
+
+class CocoonTextRdfMapperTest extends TestCase
+{
+
+    const TEST_INPUT_DOCS = [
+        'BASE' => <<<EOT
+        @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+        @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#> .
+        @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+        @prefix sesame: <http://www.openrdf.org/schema/sesame#> .
+        @prefix v: <http://rdf.data-vocabulary.org/#> .
+        <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-UVE_MOCIKA> a <http://crdo.risc.cnrs.fr/schemas/Resource> ;
+            <http://purl.org/dc/elements/1.1/description> "Voilà pourquoi le bernard-l'hermite, aujourd'hui, se cache dans les coquilles vides qu'il trouve, alors que le crabe de cocotier n'a pas honte de se promener tout nu."@fr ;
+            <http://purl.org/dc/elements/1.1/format> "text/xml"^^<http://purl.org/dc/terms/IMT> ;
+            <http://purl.org/dc/elements/1.1/type> "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> ;
+            <http://purl.org/dc/elements/1.1/subject> <http://lexvo.org/id/iso639-3/uve> ;
+            <http://purl.org/dc/elements/1.1/language> <http://lexvo.org/id/iso639-3/uve> ;
+            <http://www.language-archives.org/OLAC/1.1/depositor> <http://viaf.org/viaf/56614135> ;
+            <http://purl.org/dc/elements/1.1/publisher> <http://viaf.org/viaf/154919513> ;
+            <http://purl.org/dc/elements/1.1/rights> "Copyright (c) Moyse-Faurie, Claire" ;
+            <http://purl.org/dc/elements/1.1/title> "The two hermit crabs and the coconut crab"@en ;
+            <http://purl.org/dc/terms/isFormatOf> <http://cocoon.huma-num.fr/exist/crdo/moyse-faurie/uve/crdo-UVE_MOCIKA.xml> , <http://cocoon.huma-num.fr/exist/crdo/moyse-faurie/uve/crdo-UVE_MOCIKA.xhtml> ;
+            <http://purl.org/dc/terms/accessRights> "Freely available for non-commercial use" ;
+            <http://purl.org/dc/terms/license> <http://creativecommons.org/licenses/by-nc-sa/2.5/> ;
+            <http://purl.org/dc/terms/isPartOf> <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_LANGUESDEFRANCE> , <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_LACITO> ;
+            <http://purl.org/dc/terms/spatial> "NC"^^<http://purl.org/dc/terms/ISO3166> , "New Caledonia, Ohnyat (Ouvéa)" ;
+            <http://purl.org/dc/terms/available> "2011-02-05"^^<http://purl.org/dc/terms/W3CDTF> ;
+            <http://purl.org/dc/terms/issued> "2011-02-05T23:22:23+01:00"^^<http://purl.org/dc/terms/W3CDTF> ;
+            <http://www.language-archives.org/OLAC/1.1/speaker> "Idakote, Félicien" ;
+            <http://purl.org/dc/terms/requires> <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-UVE_MOCIKA_SOUND> ;
+            <http://purl.org/dc/terms/alternative> "Les deux bernard-l'hermite et le crabe de cocotier"@fr ;
+            <http://www.language-archives.org/OLAC/1.1/researcher> "Moyse-Faurie, Claire" ;
+            <http://purl.org/dc/terms/modified> "2002-02-20"^^<http://purl.org/dc/terms/W3CDTF> ;
+            <http://purl.org/dc/terms/conformsTo> <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-dtd_archive> .
+EOT
+    ];
+
+    const TEST_INPUT_ID = "crdo-UVE_MOCIKA_SOUND";
+    const TEST_GRAPH_URI = "http://purl.org/poi/corpusdelaparole.huma-num.fr/crdo-UVE_MOCIKA_SOUND";
+    const TEST_CHO_URI = "http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-UVE_MOCIKA_SOUND";
+
+
+    private $inputGraphes = [];
+    private $resGraphes = [];
+    private $mappers = [];
+
+    function __construct(string $name = null) {
+        parent::__construct($name);
+    }
+
+    public function setUp() {
+        parent::setUp();
+
+        foreach(CocoonTextRdfMapperTest::TEST_INPUT_DOCS as $key => $inputDoc) {
+            $this->inputGraphes[$key] = new Graph("http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-UVE_MOCIKA", $inputDoc);
+            $this->mappers[$key] = new CocoonTextRdfMapper($this->inputGraphes[$key]);
+            $this->mappers[$key]->mapGraph();
+            $this->resGraphes[$key] = $this->mappers[$key]->getOutputGraphes()["http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-UVE_MOCIKA_SOUND"];
+        }
+    }
+
+    public function tearDown() {
+        parent::tearDown();
+    }
+
+    /**
+     * Just test that the construct and setup are ok
+     *
+     * @return void
+     */
+    public function testInit()
+    {
+        $this->assertTrue(true);
+    }
+
+    /**
+     * Test that the returned graph has the same uri that the original.
+     *
+     * @return void
+     */
+    public function testUri() {
+
+        echo $this->resGraphes['BASE']->serialise('turtle');
+        //echo var_export($this->resGraphes['BASE']->toRdfPhp());
+
+        $this->assertNotNull($this->resGraphes['BASE']);
+        $this->assertEquals(CocoonTextRdfMapperTest::TEST_GRAPH_URI, $this->resGraphes['BASE']->getUri(), "URIS must be translated");
+    }
+
+    /**
+     * Test that the return graph has one ore:Aggregation resource
+     *
+     * @return void
+     */
+    public function testAggregationResource() {
+
+        $resources = $this->resGraphes['BASE']->allOfType('ore:Aggregation');
+
+        $this->assertCount(1, $resources, "Must found only one resources of type ore:Aggregation");
+        $this->assertEquals(CocoonTextRdfMapperTest::TEST_GRAPH_URI,$resources[0]->getUri());
+    }
+
+    /**
+     * Test providedCHO uri.
+     *
+     * @return void
+     */
+    public function testProvidedChoURI() {
+        $resources = $this->resGraphes['BASE']->allOfType('edm:ProvidedCHO');
+
+        $this->assertCount(1, $resources, "Must found only one resources of type edm:ProvidedCHO");
+        $this->assertEquals(CocoonTextRdfMapperTest::TEST_CHO_URI,$resources[0]->getUri());
+    }
+
+    /**
+     * Test taht the returned graph does not have a http://purl.org/dc/dcmitype/Sound type
+     *
+     * @return void
+     */
+    public function testType() {
+        //"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> ;
+        $providedCHO = $this->resGraphes['BASE']->get('edm:ProvidedCHO', '^rdf:type');
+
+        $this->assertNotNull($providedCHO);
+
+        $this->assertEmpty($providedCHO->all($this->resGraphes['BASE']->resource('http://purl.org/dc/elements/1.1/type'), 'resource'), 'Should not find dc element:type value as resource');
+        $this->assertcount(2, $providedCHO->all($this->resGraphes['BASE']->resource('http://purl.org/dc/elements/1.1/type')), 'but should find 2 literals');
+
+        $expResMap = [
+            'primary_text' => 'http://www.language-archives.org/OLAC/1.1/linguistic-type',
+            'narrative' => 'http://www.language-archives.org/OLAC/1.1/discourse-type'
+        ];
+
+        $dcTypeList = $providedCHO->all($this->resGraphes['BASE']->resource('http://purl.org/dc/elements/1.1/type'));
+        foreach ($dcTypeList as $dcType) {
+            $this->assertInstanceOf('EasyRdf\Literal', $dcType, "dc type must be a literal");
+            $this->assertArrayHasKey($dcType->getValue(),$expResMap, 'Value must be in expected result Map');
+            $this->assertEquals($expResMap[$dcType->getValue()], $dcType->getDatatypeUri());
+        }
+    }
+
+     /**
+      * Test that the web resources
+      *
+      * @return void
+      */
+    public function testWebResources() {
+
+        $resources = $this->resGraphes['BASE']->allOfType('edm:WebResources');
+
+        $this->assertCount(2, $resources, "Must found three webresources");
+
+        $aggregation = $this->resGraphes['BASE']->resource(CocoonTextRdfMapperTest::TEST_GRAPH_URI);
+
+        foreach ($resources as $wres) {
+            $mimetypes = $wres->all($this->resGraphes['BASE']->resource('http://purl.org/dc/elements/1.1/format'));
+            $this->assertCount(1, $mimetypes, "Must find one mimetype.");
+            $mimetype = $mimetypes[0];
+            $this->assertInstanceOf("EasyRdf\Literal", $mimetype, "mimetype must be literal");
+            $this->assertEquals("dc:IMT",$mimetype->getDatatype());
+        }
+    }
+
+     /**
+      * Test that the web resources
+      *
+      * @return void
+      */
+    public function testWebResourcesDate() {
+
+        $resources = $this->resGraphes['BASE']->allOfType('edm:WebResources');
+
+        foreach ($resources as $wres) {
+            $this->assertFalse($wres->hasProperty("http://purl.org/dc/terms/available"),"web resource must not have http://purl.org/dc/terms/available");
+            $this->assertFalse($wres->hasProperty("http://purl.org/dc/terms/modified"),"web resource must not have http://purl.org/dc/terms/modified");
+            $this->assertTrue($wres->hasProperty("http://purl.org/dc/terms/issued"), "Must have http://purl.org/dc/terms/issued");
+
+            $issued = $wres->getLiteral('dc:issued');
+            //<http://purl.org/dc/terms/issued> "2014-12-05T15:00:19+01:00"^^<http://purl.org/dc/terms/W3CDTF> ;
+            $this->assertInstanceOf('EasyRdf\Literal', $issued, "issued value must be a literal");
+            $this->assertEquals('http://purl.org/dc/terms/W3CDTF', $issued->getDatatypeUri(), "issued datatype uri must be a http://purl.org/dc/terms/W3CDTF");
+            $this->assertEquals('2011-02-05T23:22:23+01:00', $issued->getValue(), "Value must be 2014-12-05T15:00:19+01:00");
+
+        }
+
+    }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/tests/libraries/Mergers/CocoonCollectionRdfMergerTest.php	Tue Nov 17 13:11:55 2015 +0100
@@ -0,0 +1,216 @@
+<?php
+
+use CorpusParole\Libraries\Mergers\CocoonCollectionRdfMerger;
+use CorpusParole\Libraries\CocoonUtils;
+
+use EasyRdf\Graph;
+use EasyRdf\Resource;
+use EasyRdf\Literal;
+
+use Illuminate\Foundation\Testing\WithoutMiddleware;
+use Illuminate\Foundation\Testing\DatabaseMigrations;
+use Illuminate\Foundation\Testing\DatabaseTransactions;
+
+class CocoonCollectionRdfMergerTest extends TestCase
+{
+
+    const TEST_INPUT_DOCS = [
+        'BASE' => <<<EOT
+        @prefix edm: <http://www.europeana.eu/schemas/edm/> .
+        @prefix dc11: <http://purl.org/dc/elements/1.1/> .
+        @prefix dc: <http://purl.org/dc/terms/> .
+        @prefix olac: <http://www.language-archives.org/OLAC/1.1/> .
+        @prefix geo: <http://www.w3.org/2003/01/geo/wgs84_pos#> .
+        @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+        @prefix skos: <http://www.w3.org/2004/02/skos/core#> .
+        @prefix owl: <http://www.w3.org/2002/07/owl#> .
+
+        <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_CFPP2000>
+          a edm:Collection ;
+          dc11:description "Corpus de Français Parlé Parisien des années 2000."@fr, "Le Corpus de Français Parlé Parisien (CFPP2000) est composé d'un ensemble d'interviews non directives sur les quartiers de Paris et de la proche banlieue. Les entretiens, transcrits en orthographe et alignés au tour de parole, sont disponibles sur le net ; ils sont librement employables en échange de la mention dans la bibliographie des travaux qui en seraient tirés d'une part de l'adresse du site: http://cfpp2000.univ-paris3.fr/ et d'autre part du document de présentation suivant : Branca-Rosoff S., Fleury S., Lefeuvre F., Pires M., 2012, \"Discours sur la ville. Présentation du Corpus de Français Parlé Parisien des années 2000 (CFPP2000)\". En février 2013, ce corpus comprenait environ 550 000 mots. Un certain nombre d'outils en ligne, notamment un concordancier et  des outils textométriques permettent de mener des requêtes lexicales et grammaticales. CFPP2000 est particulièrement destiné à des analyses sur le français oral. Le projet sous-jacent au corpus est par ailleurs l'étude des modifications et des variations qui interviennent dans ce qu'on peut considérer comme un parisien véhiculaire en tension entre le pôle du standard et le pôle du vernaculaire. Par ailleurs, il comporte des activités linguistiques diversifiées (description de quartier, anecdotes, argumentation…) et on peut par conséquent travailler sur la syntaxe propre à ces différentes utilisations du langage. Il permet enfin d'opposer dialogues (entre enquêteur et enquêtés) et multilogues (où la présence de plusieurs enquêtés favorise le passage à un registre familier).  CFPP2000 est constitué d'interviews longues (d'une heure en moyenne) intégralement transcrites. Il est donc utilisable pour examiner les singularités qui reviennent à l'idiolecte propre à une personne donnée, par opposition aux variantes diffusées dans des groupes plus larges (quartiers, groupes socio-culturels, classe d'âge, etc.). Le corpus constitue enfin un ensemble de témoignages intéressants sur les représentations de Paris et de sa proche banlieue qui est susceptible d'intéresser des analystes du discours, des sociologues, ou tout simplement des curieux de la ville."@fr ;
+          dc11:language <http://lexvo.org/id/iso639-3/gsw> ;
+          dc11:publisher <http://viaf.org/viaf/142432638>, "Fédération CLESTHIA", <http://viaf.org/viaf/154862993> ;
+          dc11:rights "Copyright (c) Département de dialectologie alsacienne et mosellane de l'Université de Strasbourg" ;
+          dc11:type <http://purl.org/dc/dcmitype/Collection> ;
+          dc:license <http://creativecommons.org/licenses/by-nc-sa/3.0/> ;
+          dc11:subject <http://lexvo.org/id/iso639-3/fra> ;
+          dc11:title "Corpus de Français Parlé Parisien des années 2000 (CFPP)"@fr ;
+          dc:accessRights "Freely available for non-commercial use" ;
+          dc:isPartOf <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_ALA> ;
+          olac:compiler "Branca-Rosoff, Sonia", "Fleury, Serge", "Lefeuvre, Florence", "Pires, Mat" ;
+          dc11:contributor "Branca-Rosoff, Sonia", "Fleury, Serge", "Lefeuvre, Florence", "Pires, Mat", <http://viaf.org/viaf/93752300>, "Ville de Paris ", "Délégation générale à la langue française et aux langues de France " ;
+          olac:data_inputter "Branca-Rosoff, Sonia", "Lefeuvre, Florence", "Pires, Mat" ;
+          olac:depositor <http://viaf.org/viaf/93752300> ;
+          olac:developer "Fleury, Serge" ;
+          olac:interviewer "Branca-Rosoff, Sonia", "Lefeuvre, Florence", "Pires, Mat" ;
+          olac:researcher "Branca-Rosoff, Sonia", "Fleury, Serge", "Lefeuvre, Florence", "Pires, Mat" ;
+          olac:sponsor "Ville de Paris ", "Délégation générale à la langue française et aux langues de France " ;
+          olac:transcriber "Branca-Rosoff, Sonia", "Lefeuvre, Florence", "Pires, Mat" ;
+          dc:available "2013-04-12"^^dc:W3CDTF ;
+          dc:created "start=1988; end=1989"^^dc:Period ;
+          dc:issued "2013-04-12T22:20:23+02:00"^^dc:W3CDTF ;
+          dc:modified "2014-05-10T20:16:27+02:00"^^dc:W3CDTF ;
+          dc:spatial [
+            a edm:Place ;
+            geo:lat "48.8667"^^xsd:float ;
+            geo:long "2.3333"^^xsd:float ;
+            skos:note "FR"^^dc:ISO3166, "France, Paris, Université Sorbonne Nouvelle Paris 3, site Censier"@fr ;
+            owl:sameAs <http://vocab.getty.edu/tgn/7008038>
+          ] .
+EOT
+        ,
+        'SOURCE' => <<<EOT
+        @prefix edm: <http://www.europeana.eu/schemas/edm/> .
+        @prefix dc11: <http://purl.org/dc/elements/1.1/> .
+        @prefix dc: <http://purl.org/dc/terms/> .
+        @prefix geo: <http://www.w3.org/2003/01/geo/wgs84_pos#> .
+        @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+        @prefix skos: <http://www.w3.org/2004/02/skos/core#> .
+        @prefix owl: <http://www.w3.org/2002/07/owl#> .
+
+        <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_CFPP2000>
+          a edm:Collection ;
+          dc11:title "Other title"@fr ;
+          dc:created "start=1988; end=1989"^^dc:Period ;
+          dc:issued "2013-04-12T22:20:23+02:00"^^dc:W3CDTF ;
+          dc:modified "2014-05-10T20:16:27+02:00"^^dc:W3CDTF ;
+          dc11:language <http://lexvo.org/id/iso639-3/gsw>, <http://lexvo.org/id/iso639-3/fra> ;
+          dc:spatial [
+            a edm:Place ;
+            geo:lat "89.8667"^^xsd:float ;
+            geo:long "55.3333"^^xsd:float ;
+            skos:note "FR"^^dc:ISO3166, "France, Paris, Université Sorbonne Nouvelle Paris 3, site Censier"@fr, "Other place very important"@fr ;
+            owl:sameAs <http://vocab.getty.edu/tgn/1234567890>
+          ] .
+EOT
+    ];
+
+    const TEST_INPUT_ID = "crdo-COLLECTION_CFPP2000";
+    const TEST_GRAPH_URI = "http://purl.org/poi/corpusdelaparole.huma-num.fr/crdo-COLLECTION_CFPP2000";
+    const TEST_CHO_URI = "http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_CFPP2000";
+
+
+    private $inputGraphes = [];
+    private $resGraph;
+    private $merger;
+
+    function __construct(string $name = null) {
+        parent::__construct($name);
+    }
+
+    public function setUp() {
+        parent::setUp();
+
+        foreach(CocoonCollectionRdfMergerTest::TEST_INPUT_DOCS as $key => $inputDoc) {
+            $this->inputGraphes[$key] = new Graph("http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_CFPP2000", $inputDoc);
+        }
+
+        $this->merger = new CocoonCollectionRdfMerger();
+        $this->resGraph = $this->merger->mergeGraph($this->inputGraphes['BASE'], $this->inputGraphes['SOURCE']);
+    }
+
+    public function tearDown() {
+        parent::tearDown();
+    }
+
+    /**
+     * Just test that the construct and setup are ok
+     *
+     * @return void
+     */
+    public function testInit()
+    {
+        $this->assertTrue(true);
+        echo $this->resGraph->serialise('turtle');
+    }
+
+    /**
+     * test the result graph.
+     *
+     * @return void
+     */
+    public function testResGraph() {
+        $this->assertNotNull($this->resGraph, "Res graph must not be null");
+        $this->assertEquals("http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_CFPP2000", $this->resGraph->getUri(), "graph uri must be equals to http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-CFPP2000_35_SOUND");
+    }
+
+    /**
+     * test the merged Aggregation
+     *
+     * @return void
+     */
+    public function testCollectionResource() {
+        $collectionResList = $this->resGraph->allOfType('http://www.europeana.eu/schemas/edm/Collection');
+        $this->assertCount(1, $collectionResList, "Only one Collection node");
+        $collectionRes = $collectionResList[0];
+
+        $this->assertEquals("http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_CFPP2000",$collectionRes->getUri(),"Collection node uri must be http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_CFPP2000");
+
+        $singleValuesRes = [
+            'http://purl.org/dc/elements/1.1/title' => ['size'=>1, 'val' => new Literal("Corpus de Français Parlé Parisien des années 2000 (CFPP)", "fr", null)],
+            'http://purl.org/dc/terms/available' => ['size'=>1, 'val' => new Literal("2013-04-12", null, "dc:W3CDTF")],
+            'http://purl.org/dc/terms/created' => ['size'=>1, 'val' => new Literal("start=1988; end=1989", null, "dc:Period")],
+            'http://purl.org/dc/terms/issued' => ['size'=>1, 'val' => new Literal("2013-04-12T22:20:23+02:00", null, "dc:W3CDTF")],
+            'http://purl.org/dc/terms/modified' => ['size'=>1, 'val' => new Literal("2014-05-10T20:16:27+02:00", null, "dc:W3CDTF")],
+            'http://purl.org/dc/elements/1.1/language' => ['size' => 2, 'val' => [
+                $this->resGraph->resource("http://lexvo.org/id/iso639-3/gsw"),
+                $this->resGraph->resource("http://lexvo.org/id/iso639-3/fra"),
+            ]]
+        ];
+
+        foreach($singleValuesRes as $property => $resVal) {
+            $resList = $collectionRes->all($this->inputGraphes['BASE']->resource($property));
+            $this->assertCount($resVal['size'], $resList, "$property list size $resVal[size]");
+            if($resVal['size'] == 1) {
+                $this->assertEquals($resVal['val'], $resList[0], "$property size one not equals");
+            }
+            else {
+                $this->assertEquals($resVal['val'], $resList, "$property size more than one not equals");
+            }
+        }
+
+    }
+
+    /**
+    * Test one to one mapping spatial info
+    *
+    * @return void
+    */
+    public function testProvidedCHOSpatial() {
+        $collection = $this->resGraph->get('edm:Collection', '^rdf:type');
+
+        $this->assertNotNull($collection);
+
+        $spatials = $collection->all($this->resGraph->resource('http://purl.org/dc/terms/spatial'));
+
+        $this->assertCount(1, $spatials, "Must have only one spatial node");
+        $spatial = $spatials[0];
+        $this->assertTrue($spatial->isBNode(),"spatial node must be blank");
+        $this->assertEquals("edm:Place", $spatial->type(), "spatial node type must be edm:Place");
+
+        $lats = $spatial->all('geo:lat');
+        $this->assertCount(1, $lats, "One latitude");
+        $this->assertInstanceOf("EasyRdf\Literal", $lats[0], "Latitude must be a litteral");
+        $this->assertEquals(Literal::create("48.8667", null, 'xsd:float'), $lats[0], "lat must be '48.8667'^^xsd:float");
+
+        $longs = $spatial->all('geo:long');
+        $this->assertCount(1, $longs, "One longitude");
+        $this->assertInstanceOf("EasyRdf\Literal", $longs[0], "Longitude must be a litteral");
+        $this->assertEquals(Literal::create("2.3333", null, 'xsd:float'), $longs[0], "long must be '2.3333'^^xsd:float");
+
+        $notes = $spatial->all('skos:note');
+        $this->assertCount(3, $notes, "3 notes");
+        $this->assertContainsOnlyInstancesOf("EasyRdf\Literal", $notes, "Notes mus be only literals");
+        $this->assertEquals(Literal::create("FR", null, "dc:ISO3166"), $notes[0], "notes contains 'FR'^^dc:ISO3166");
+        $this->assertEquals(Literal::create("France, Paris, Université Sorbonne Nouvelle Paris 3, site Censier", "fr", null), $notes[1], "notes contains 'France, Paris, Université Sorbonne Nouvelle Paris 3, site Censier'@fr");
+        $this->assertEquals(Literal::create("Other place very important", "fr", null), $notes[2], "notes contains 'Other place very important'@fr");
+
+        $sameas = $spatial->all('owl:sameAs');
+        $this->assertCount(1, $sameas, "1 same as");
+        $this->assertContainsOnlyInstancesOf("EasyRdf\Resource", $sameas, "Notes mus be only resources");
+        $this->assertEquals('http://vocab.getty.edu/tgn/7008038', $sameas[0]->getUri(), "uri must be http://vocab.getty.edu/tgn/7008038");
+    }
+
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/tests/libraries/Mergers/CocoonSoundRdfMergerTest.php	Tue Nov 17 13:11:55 2015 +0100
@@ -0,0 +1,334 @@
+<?php
+
+use CorpusParole\Libraries\Mergers\CocoonSoundRdfMerger;
+use CorpusParole\Libraries\CocoonUtils;
+
+use EasyRdf\Graph;
+use EasyRdf\Resource;
+use EasyRdf\Literal;
+
+use Illuminate\Foundation\Testing\WithoutMiddleware;
+use Illuminate\Foundation\Testing\DatabaseMigrations;
+use Illuminate\Foundation\Testing\DatabaseTransactions;
+
+class CocoonSoundRdfMergerTest extends TestCase
+{
+
+    const TEST_INPUT_DOCS = [
+        'BASE' => <<<EOT
+        @prefix ore: <http://www.openarchives.org/ore/terms/> .
+        @prefix edm: <http://www.europeana.eu/schemas/edm/> .
+        @prefix dc11: <http://purl.org/dc/elements/1.1/> .
+        @prefix olac: <http://www.language-archives.org/OLAC/1.1/> .
+        @prefix dc: <http://purl.org/dc/terms/> .
+        @prefix geo: <http://www.w3.org/2003/01/geo/wgs84_pos#> .
+        @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+        @prefix skos: <http://www.w3.org/2004/02/skos/core#> .
+        @prefix owl: <http://www.w3.org/2002/07/owl#> .
+
+        <http://purl.org/poi/corpusdelaparole.huma-num.fr/crdo-CFPP2000_35_SOUND>
+          a ore:Aggregation ;
+          edm:aggregatedCHO <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-CFPP2000_35_SOUND> ;
+          edm:provider "Corpus de la Parole"@fr ;
+          edm:dataProvider <http://viaf.org/viaf/142432638> ;
+          edm:isShownAt <http://cocoon.huma-num.fr/exist/crdo/meta/crdo-CFPP2000_35_SOUND> ;
+          edm:isShownBy <http://cocoon.huma-num.fr/data/archi/masters/372593.wav> ;
+          edm:rights <http://creativecommons.org/licenses/by-nc-sa/4.0/> ;
+          edm:hasView <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://purl.org/poi/crdo.vjf.cnrs.fr/crdo-CFPP2000_35_SOUND>
+          a edm:ProvidedCHO ;
+          dc11:description "Enregistrement issu du Corpus de Français Parlé Parisien des années 2000 (CFPP2000)"@fr, "Enregistrement: Caractéristiques de l'enregistrement; Identifiant : CFPP2000 [03-01] Ozgur_Kilic_H_32_alii_3e; Langue : français; Editeur : Université Paris III – Syled ; Date : 17.11.2010; Lieu de l'enregistrement : au domicile de l’enquêté Özgur KILIÇ ; Enquêteur : Sonia BRANCA-ROSOFF; Quartier(s) concerné(s) : Paris 3e, et 20e (pour l’âge adulte); Transcription : Noalig TANGUY; Anonymisation : Noalig TANGUY; Durée : 0h46’; "@fr, "Enquêteur: Etat civil; Prénom et NOM : Sonia BRANCA-ROSOFF; Sexe : féminin; Lieu de naissance : New-York (USA); Lieu la petite enfance : Bretagne, puis région parisienne, puis de 8 à 16 ans Nice; Date de naissance : 16.12.1947; Situation familiale : mariée, deux enfants; Mobilité géographique : Paris 1967-1971, Aix-en-Provence 1971-1996, Paris 1996-2012; Scolarité; Niveau : Primaire [X] Secondaire [X] ; Supérieur : Licence [X] Post-licence [X] ; Dernier diplôme, avec année d’obtention : Doctorat d’État (sciences du langage) 1987; Travail; Activité actuelle : Enseignante-chercheuse (linguistique française), Université de la Sorbonne Nouvelle-Paris III, Paris; Activités passées : ; Langues; Langue première : français; Parents (profession, lieu de naissance, scolarité…); Mère : née en 1916 à Nice (France), interprète de conférences ; licence d’anglais; Père : né en 1913 à Mananjary (Madagascar), ingénieur.; "@fr, "Enquêté 1: Etat civil; Prénom et NOM fictifs : Özgur KILIÇ ; Sexe : masculin; Lieu de naissance: Paris 11e, France; Lieu la petite enfance : Paris 11e, France; Date de naissance : 07.02.1979; Age au moment de l’enregistrement : 32 ans; Situation familiale : pacsé, deux enfants; Mobilité géographique : 3e, 18e, 20e arrondissements; Relation (parenté, ami, etc) avec Enquêteur : aucune; Relation (parenté, ami, etc) avec autres enquêtés : amis; Scolarité; Niveau : Primaire [X] Secondaire [X] ; Supérieur : Licence [X] Post-licence [X] ; Dernier diplôme, avec année d’obtention : ; Précisions : Primaire  st Merri 75003 ; Secondaire : Victor Hugo, Turgot 75003, Jean Lurçat 75013 général bac ES Supérieur. Puis St Denis université (cinéma); Travail; Activité actuelle : ingénieur du son pour l'audiovisuel; Activités passées : restauration, assistant son pour l'audiovisuel ; Langues; Langues pratiquées : français, anglais, turc; Parents (profession, lieu de naissance, scolarité…); Mère : psychothérapeute, né a Houilles région parisienne France; Père : professeur d'université, né a Istanbul en Turquie.  ; "@fr, "Enquêté 2: Etat civil; Prénom et NOM fictifs : Michel CHEVRIER; Sexe : masculin; Lieu de naissance : naissance à Boulogne-Billancourt (92); Lieu la petite enfance : rue du Temple, 3e arrondissement, Paris; Date de naissance : 01.06.1979; Age au moment de l’enregistrement : 31 ans; Situation familiale : concubinage; Mobilité géographique : 3e, puis 20e (entre 2005 et 2009) puis Romainville (depuis 2009); Relation (parenté, ami, etc) avec Enquêteur : ; Relation (parenté, ami, etc) avec Enquêté NOM : ; Relation (parenté, ami, etc) avec Enquêté NOM : ; Prénom et NOM réels : ; Réseau par lequel contacté : ; Adresse (si connue) : ; Téléphone (si connu) : ; Scolarité; Niveau : Primaire [X] Secondaire [X] ; Supérieur : Licence [X] Post-licence [X] ; Dernier diplôme, avec année d’obtention : ; Précisions : Primaire : École à aire ouverte rue St Merri 75003 ; Secondaire (Collège Victor Hugo 75003) puis Lycée Autogéré de Paris (75015) Bac Littéraire. Deux années au CIM (école de jazz) dans le 75018, puis 3 ans au conservatoire du 9eme; Travail; Activité actuelle : Musicien, Compositeur, Professeur de piano jazz ; Activités passées : Musicien; Langues; Langues pratiquées : français, anglais; Parents (profession, lieu de naissance, scolarité…); Mère : ancienne médecin généraliste pneumologue, puis sociologue, née en France; Père : enseignant en sciences de l'éducation à Paris 8 né en Belgique; "@fr, "Enquêté 3: Etat civil; Prénom et NOM fictifs : Benoît DU BREUIL-DE-PONT-EN-AUGE; Sexe : masculin; Lieu de naissance : Paris 14e; Lieu la petite enfance :  Paris 3e; Date de naissance : 28.11.1978; Age au moment de l’enregistrement : 32 ans; Situation familiale : concubinage avéré, avec papier de la mairie tamponné et signé!; Mobilité géographique : à 2 ans vit dans le 9°, puis déménage pour le 3°, est resté dans la même rue pendant 20 ans tout en changeant d'immeuble. Ensuite le 19° pendant 4 ans, puis Pantin 6 mois puis Les Lilas. ; Relation (parenté, ami, etc) avec Enquêteur : aucune; Relation (parenté, ami, etc) avec autres enquêtés : voir Scolarité, Précisions; Prénom et NOM réels : ; Réseau par lequel contacté : ; Scolarité; Niveau : Primaire [X] Secondaire [X] ; Supérieur : Licence [ ] Post-licence [ ] ; Dernier diplôme, avec année d’obtention : CAP; Précisions : Primaire école à aire ouverte (St Merri) dans le 4° avec Augustin, Ôzgur, Michel. Secondaire : collège Victor-Hugo dans le 3° avec Ôzgur ; puis CAP ; Travail; Activité actuelle : ; Activités passées : ébéniste agenceur puis ébéniste restaurateur et enfin constructeur décors (ainsi que de nombreux petits jobs ayant duré moins d'un an); Langues; Langues pratiquées : français; Parents (profession, lieu de naissance, scolarité…); Mère : à la retraite ; secrétaire de rédaction dans un grand journal, baccalauréat ; née à Montrouge; Père : conseiller à travail à pole emploi, né à Boulogne Billancourt, baccalauréat présenté 3 ou 4 fois, puis obtenu par équivalence. ; "@fr, "Enquêté 4: Etat civil; Enquêté 4; Prénom et NOM fictifs : ; Sexe : féminin / masculin; Lieu de naissance : Paris 14e; Lieu de la petite enfance : Paris 4e et 3e ; Date de naissance : 06.12.1976; Age au moment de l’enregistrement : 34 ans; Situation familiale : ; Mobilité géographique : Rue la Bruyère 75009 (1976-1978), Rambuteau 75004 (1978-1987/88) & 75003 (chgt de côté de rue 1988-1998), a quitté Paris de 1998 à 2005 ; Rue Rambuteau 75003 (2006-2010), rue Gossec 75012 (2011); Relation (parenté, ami, etc) avec Enquêteur : aucune; Relation (parenté, ami, etc) avec Enquêté 2 : ami; Relation (parenté, ami, etc) avec Enquêté NOM : ; Réseau par lequel contacté : ; Scolarité; Niveau : Primaire [X] Secondaire [X] ; Supérieur : Licence [X] Post-licence [X] ; Dernier diplôme, avec année d’obtention : ; Précisions : Primaire : Ecole St Merri 75003. Secondaire : Collège François Couperin 75004, Institut St Pierre Fourier 75012 ; Cours Charlemagne 75014 ; Travail; Activité actuelle : Superviseur Centre d'appels ; Activités passées : Animateur Club Enfant, Réceptionniste ; Langues; Langues pratiquées :; Parents (profession, lieu de naissance, scolarité…); Mère : retraitée, Paris, bac + 1/2 (?) ; Père : Conseiller Pôle Emploi, Paris, bac. ; "@fr, "Enquêté 5: Etat civil; Prénom et NOM fictifs : Étienne SALVEGAS; Sexe : masculin; Lieu de naissance : Paris 12e; Lieu de la petite enfance : Paris 3e Le Marais; Date de naissance :  16.06.1978; Age au moment de l’enregistrement : 32 ans; Situation familiale : marié 1 enfant, 12 ans de vie commune ; Mobilité géographique : 3e (1978-1999) 19e (1999-2002) 9e (2002-2011) ; Relation (parenté, ami, etc) avec Enquêteur : ; Relation (parenté, ami, etc) avec Enquêté 2 : ami ; Relation (parenté, ami, etc) avec Enquêté NOM : ; Prénom et NOM réels : ; Scolarité; Primaire [X] Secondaire [X] ; Supérieur : Licence [X] Post-licence [ ] ; Dernier diplôme, avec année d’obtention : ; Précisions : Primaire : Ecole Vertus, rue des Vertus 3ème. Secondaire Collège Montgolfier / Lycée Turgot 3ème. Supérieur Droit Univ. Paris Panthéon Sorbonne ; Travail; Activité actuelle : évènementiel; Activités passées : stagiaire journaliste sportif / relations publiques, accueil, agent de  sécurité, remplacement gardien, réceptionniste hôtellerie.; Langues; Langues pratiquées :; Parents (profession, lieu de naissance, scolarité…); Mère : né à Paris, lycée ; Père : né à Oloron (64), lycée ; "@fr ;
+          dc11:language <http://lexvo.org/id/iso639-3/fra> ;
+          dc11:publisher <http://viaf.org/viaf/142432638> ;
+          dc11:type <http://purl.org/dc/dcmitype/Sound>, "primary_text"^^olac:linguistic-type, "narrative"^^olac:discourse-type, "report"^^olac:discourse-type, "unintelligible_speech"^^olac:discourse-type ;
+          dc:license <http://creativecommons.org/licenses/by-nc-sa/3.0/> ;
+          dc11:subject "lexicography"^^olac:linguistic-field, "phonetics"^^olac:linguistic-field, "anthropological_linguistics"^^olac:linguistic-field, "general_linguistics"^^olac:linguistic-field, <http://lexvo.org/id/iso639-3/fra>, "text_and_corpus_linguistics"^^olac:linguistic-field, "phonology"^^olac:linguistic-field, "semantics"^^olac:linguistic-field, "sociolinguistics"^^olac:linguistic-field, "syntax"^^olac:linguistic-field, "typology"^^olac:linguistic-field, "discourse_analysis"^^olac:linguistic-field, "historical_linguistics"^^olac:linguistic-field, "language_documentation"^^olac:linguistic-field, "mathematical_linguistics"^^olac:linguistic-field ;
+          dc11:title "CFPP2000 [03-01] Ozgur_Kilic_H_32_alii_3e Entretien de Ozgur KILIÇ 2"@fr ;
+          dc:accessRights "Freely available for non-commercial use" ;
+          dc:extent "PT48M26S" ;
+          dc:isPartOf <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_LANGUESDEFRANCE>, <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_CFPP2000> ;
+          dc11:source "CFPP2000"@fr ;
+          dc11:coverage "Quartier concerné : 3e"@fr ;
+          olac:depositor <http://viaf.org/viaf/93752300> ;
+          dc11:contributor <http://viaf.org/viaf/93752300>, "Branca-Rosoff, Sonia", "Kiliç Ozgur", "Chevrier Michel", "du-Breuil-de-Pont-en-Auge Benoît", "du-Breuil-de-Pont-en-Auge Augustin", "Salvegas Etienne", "Tanguy Noalig" ;
+          olac:interviewer "Branca-Rosoff, Sonia" ;
+          olac:responder "Kiliç Ozgur", "Chevrier Michel", "du-Breuil-de-Pont-en-Auge Benoît", "du-Breuil-de-Pont-en-Auge Augustin", "Salvegas Etienne" ;
+          olac:transcriber "Tanguy Noalig" ;
+          dc:available "2013-10-12"^^dc:W3CDTF ;
+          dc:created "2010-11-17"^^dc:W3CDTF ;
+          dc:issued "2013-10-12T14:35:57+02:00"^^dc:W3CDTF ;
+          dc:spatial [
+            a edm:Place ;
+            geo:lat "48.83975"^^xsd:float ;
+            geo:long "2.3542"^^xsd:float ;
+            skos:note "FR"^^dc:ISO3166, "France, Paris, Université Sorbonne Nouvelle Paris 3, site Censier"@fr ;
+            owl:sameAs <http://vocab.getty.edu/tgn/7008038>
+          ] .
+
+        <http://cocoon.huma-num.fr/data/archi/masters/372593.wav>
+          a edm:WebResources ;
+          dc:extent "PT48M26S" ;
+          dc11:format "audio/x-wav"^^dc:IMT ;
+          dc:created "2010-11-17"^^dc:W3CDTF ;
+          dc:issued "2013-10-12T14:35:57+02:00"^^dc:W3CDTF .
+
+        <http://cocoon.huma-num.fr/data/cfpp2000/Ozgur_Kilic_H_32_alii_3e-2.wav>
+          a edm:WebResources ;
+          dc:extent "PT48M26S" ;
+          dc11:format "audio/x-wav"^^dc:IMT ;
+          edm:isDerivativeOf <http://cocoon.huma-num.fr/data/archi/masters/372593.wav> ;
+          dc:created "2010-11-17"^^dc:W3CDTF ;
+          dc:issued "2013-10-12T14:35:57+02:00"^^dc:W3CDTF .
+
+        <http://cocoon.huma-num.fr/data/cfpp2000/Ozgur_Kilic_H_32_alii_3e-2.mp3>
+          a edm:WebResources ;
+          dc:extent "PT48M26S" ;
+          dc11:format "audio/mpeg"^^dc:IMT ;
+          edm:isDerivativeOf <http://cocoon.huma-num.fr/data/archi/masters/372593.wav> ;
+          dc:created "2010-11-17"^^dc:W3CDTF ;
+          dc:issued "2013-10-12T14:35:57+02:00"^^dc:W3CDTF .
+EOT
+        ,
+        'SOURCE' => <<<EOT
+        @prefix ore: <http://www.openarchives.org/ore/terms/> .
+        @prefix edm: <http://www.europeana.eu/schemas/edm/> .
+        @prefix dc11: <http://purl.org/dc/elements/1.1/> .
+        @prefix olac: <http://www.language-archives.org/OLAC/1.1/> .
+        @prefix dc: <http://purl.org/dc/terms/> .
+        @prefix geo: <http://www.w3.org/2003/01/geo/wgs84_pos#> .
+        @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+        @prefix skos: <http://www.w3.org/2004/02/skos/core#> .
+        @prefix owl: <http://www.w3.org/2002/07/owl#> .
+
+        <http://purl.org/poi/corpusdelaparole.huma-num.fr/crdo-CFPP2000_35_SOUND>
+          a ore:Aggregation ;
+          edm:aggregatedCHO <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-CFPP2000_35_SOUND> ;
+          edm:provider "Corpus de la Parole"@fr ;
+          edm:dataProvider <http://viaf.org/viaf/142432638> ;
+          edm:isShownAt <http://cocoon.huma-num.fr/exist/crdo/meta/crdo-CFPP2000_35_SOUND> ;
+          edm:isShownBy <http://cocoon.huma-num.fr/exist/crdo/cfpp2000/fra/Ozgur_Kilic_H_32_alii_3e-2.xml> ;
+          edm:rights <http://creativecommons.org/licenses/by-nc-sa/4.0/> ;
+          edm:hasView <http://cocoon.huma-num.fr/exist/crdo/cfpp2000/fra/Ozgur_Kilic_H_32_alii_3e-2.xml>, <http://cocoon.huma-num.fr/exist/crdo/cfpp2000/fra/Ozgur_Kilic_H_32_alii_3e-2.xhtml>, <http://cocoon.huma-num.fr/data/cfpp2000/Ozgur_Kilic_H_32_alii_3e-2.wav> .
+
+        <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-CFPP2000_35_SOUND>
+          a edm:ProvidedCHO ;
+          dc11:description "Enregistrement issu du Corpus de Français Parlé Parisien des années 2000 (CFPP2000)"@fr, "Enregistrement: Caractéristiques de l'enregistrement; Identifiant : CFPP2000 [03-01] Ozgur_Kilic_H_32_alii_3e; Langue : français; Editeur : Université Paris III – Syled ; Date : 17.11.2010; Lieu de l'enregistrement : au domicile de l’enquêté Özgur KILIÇ ; Enquêteur : Sonia BRANCA-ROSOFF; Quartier(s) concerné(s) : Paris 3e, et 20e (pour l’âge adulte); Transcription : Noalig TANGUY; Anonymisation : Noalig TANGUY; Durée : 0h46’; "@fr, "Enquêteur: Etat civil; Prénom et NOM : Sonia BRANCA-ROSOFF; Sexe : féminin; Lieu de naissance : New-York (USA); Lieu la petite enfance : Bretagne, puis région parisienne, puis de 8 à 16 ans Nice; Date de naissance : 16.12.1947; Situation familiale : mariée, deux enfants; Mobilité géographique : Paris 1967-1971, Aix-en-Provence 1971-1996, Paris 1996-2012; Scolarité; Niveau : Primaire [X] Secondaire [X] ; Supérieur : Licence [X] Post-licence [X] ; Dernier diplôme, avec année d’obtention : Doctorat d’État (sciences du langage) 1987; Travail; Activité actuelle : Enseignante-chercheuse (linguistique française), Université de la Sorbonne Nouvelle-Paris III, Paris; Activités passées : ; Langues; Langue première : français; Parents (profession, lieu de naissance, scolarité…); Mère : née en 1916 à Nice (France), interprète de conférences ; licence d’anglais; Père : né en 1913 à Mananjary (Madagascar), ingénieur.; "@fr, "Enquêté 1: Etat civil; Prénom et NOM fictifs : Özgur KILIÇ ; Sexe : masculin; Lieu de naissance: Paris 11e, France; Lieu la petite enfance : Paris 11e, France; Date de naissance : 07.02.1979; Age au moment de l’enregistrement : 32 ans; Situation familiale : pacsé, deux enfants; Mobilité géographique : 3e, 18e, 20e arrondissements; Relation (parenté, ami, etc) avec Enquêteur : aucune; Relation (parenté, ami, etc) avec autres enquêtés : amis; Scolarité; Niveau : Primaire [X] Secondaire [X] ; Supérieur : Licence [X] Post-licence [X] ; Dernier diplôme, avec année d’obtention : ; Précisions : Primaire  st Merri 75003 ; Secondaire : Victor Hugo, Turgot 75003, Jean Lurçat 75013 général bac ES Supérieur. Puis St Denis université (cinéma); Travail; Activité actuelle : ingénieur du son pour l'audiovisuel; Activités passées : restauration, assistant son pour l'audiovisuel ; Langues; Langues pratiquées : français, anglais, turc; Parents (profession, lieu de naissance, scolarité…); Mère : psychothérapeute, né a Houilles région parisienne France; Père : professeur d'université, né a Istanbul en Turquie.  ; "@fr, "Enquêté 2: Etat civil; Prénom et NOM fictifs : Michel CHEVRIER; Sexe : masculin; Lieu de naissance : naissance à Boulogne-Billancourt (92); Lieu la petite enfance : rue du Temple, 3e arrondissement, Paris; Date de naissance : 01.06.1979; Age au moment de l’enregistrement : 31 ans; Situation familiale : concubinage; Mobilité géographique : 3e, puis 20e (entre 2005 et 2009) puis Romainville (depuis 2009); Relation (parenté, ami, etc) avec Enquêteur : ; Relation (parenté, ami, etc) avec Enquêté NOM : ; Relation (parenté, ami, etc) avec Enquêté NOM : ; Prénom et NOM réels : ; Réseau par lequel contacté : ; Adresse (si connue) : ; Téléphone (si connu) : ; Scolarité; Niveau : Primaire [X] Secondaire [X] ; Supérieur : Licence [X] Post-licence [X] ; Dernier diplôme, avec année d’obtention : ; Précisions : Primaire : École à aire ouverte rue St Merri 75003 ; Secondaire (Collège Victor Hugo 75003) puis Lycée Autogéré de Paris (75015) Bac Littéraire. Deux années au CIM (école de jazz) dans le 75018, puis 3 ans au conservatoire du 9eme; Travail; Activité actuelle : Musicien, Compositeur, Professeur de piano jazz ; Activités passées : Musicien; Langues; Langues pratiquées : français, anglais; Parents (profession, lieu de naissance, scolarité…); Mère : ancienne médecin généraliste pneumologue, puis sociologue, née en France; Père : enseignant en sciences de l'éducation à Paris 8 né en Belgique; "@fr, "Enquêté 3: Etat civil; Prénom et NOM fictifs : Benoît DU BREUIL-DE-PONT-EN-AUGE; Sexe : masculin; Lieu de naissance : Paris 14e; Lieu la petite enfance :  Paris 3e; Date de naissance : 28.11.1978; Age au moment de l’enregistrement : 32 ans; Situation familiale : concubinage avéré, avec papier de la mairie tamponné et signé!; Mobilité géographique : à 2 ans vit dans le 9°, puis déménage pour le 3°, est resté dans la même rue pendant 20 ans tout en changeant d'immeuble. Ensuite le 19° pendant 4 ans, puis Pantin 6 mois puis Les Lilas. ; Relation (parenté, ami, etc) avec Enquêteur : aucune; Relation (parenté, ami, etc) avec autres enquêtés : voir Scolarité, Précisions; Prénom et NOM réels : ; Réseau par lequel contacté : ; Scolarité; Niveau : Primaire [X] Secondaire [X] ; Supérieur : Licence [ ] Post-licence [ ] ; Dernier diplôme, avec année d’obtention : CAP; Précisions : Primaire école à aire ouverte (St Merri) dans le 4° avec Augustin, Ôzgur, Michel. Secondaire : collège Victor-Hugo dans le 3° avec Ôzgur ; puis CAP ; Travail; Activité actuelle : ; Activités passées : ébéniste agenceur puis ébéniste restaurateur et enfin constructeur décors (ainsi que de nombreux petits jobs ayant duré moins d'un an); Langues; Langues pratiquées : français; Parents (profession, lieu de naissance, scolarité…); Mère : à la retraite ; secrétaire de rédaction dans un grand journal, baccalauréat ; née à Montrouge; Père : conseiller à travail à pole emploi, né à Boulogne Billancourt, baccalauréat présenté 3 ou 4 fois, puis obtenu par équivalence. ; "@fr, "Enquêté 4: Etat civil; Enquêté 4; Prénom et NOM fictifs : ; Sexe : féminin / masculin; Lieu de naissance : Paris 14e; Lieu de la petite enfance : Paris 4e et 3e ; Date de naissance : 06.12.1976; Age au moment de l’enregistrement : 34 ans; Situation familiale : ; Mobilité géographique : Rue la Bruyère 75009 (1976-1978), Rambuteau 75004 (1978-1987/88) & 75003 (chgt de côté de rue 1988-1998), a quitté Paris de 1998 à 2005 ; Rue Rambuteau 75003 (2006-2010), rue Gossec 75012 (2011); Relation (parenté, ami, etc) avec Enquêteur : aucune; Relation (parenté, ami, etc) avec Enquêté 2 : ami; Relation (parenté, ami, etc) avec Enquêté NOM : ; Réseau par lequel contacté : ; Scolarité; Niveau : Primaire [X] Secondaire [X] ; Supérieur : Licence [X] Post-licence [X] ; Dernier diplôme, avec année d’obtention : ; Précisions : Primaire : Ecole St Merri 75003. Secondaire : Collège François Couperin 75004, Institut St Pierre Fourier 75012 ; Cours Charlemagne 75014 ; Travail; Activité actuelle : Superviseur Centre d'appels ; Activités passées : Animateur Club Enfant, Réceptionniste ; Langues; Langues pratiquées :; Parents (profession, lieu de naissance, scolarité…); Mère : retraitée, Paris, bac + 1/2 (?) ; Père : Conseiller Pôle Emploi, Paris, bac. ; "@fr, "Enquêté 5: Etat civil; Prénom et NOM fictifs : Étienne SALVEGAS; Sexe : masculin; Lieu de naissance : Paris 12e; Lieu de la petite enfance : Paris 3e Le Marais; Date de naissance :  16.06.1978; Age au moment de l’enregistrement : 32 ans; Situation familiale : marié 1 enfant, 12 ans de vie commune ; Mobilité géographique : 3e (1978-1999) 19e (1999-2002) 9e (2002-2011) ; Relation (parenté, ami, etc) avec Enquêteur : ; Relation (parenté, ami, etc) avec Enquêté 2 : ami ; Relation (parenté, ami, etc) avec Enquêté NOM : ; Prénom et NOM réels : ; Scolarité; Primaire [X] Secondaire [X] ; Supérieur : Licence [X] Post-licence [ ] ; Dernier diplôme, avec année d’obtention : ; Précisions : Primaire : Ecole Vertus, rue des Vertus 3ème. Secondaire Collège Montgolfier / Lycée Turgot 3ème. Supérieur Droit Univ. Paris Panthéon Sorbonne ; Travail; Activité actuelle : évènementiel; Activités passées : stagiaire journaliste sportif / relations publiques, accueil, agent de  sécurité, remplacement gardien, réceptionniste hôtellerie.; Langues; Langues pratiquées :; Parents (profession, lieu de naissance, scolarité…); Mère : né à Paris, lycée ; Père : né à Oloron (64), lycée ; "@fr ;
+          dc11:language <http://lexvo.org/id/iso639-3/fra> ;
+          dc11:publisher <http://viaf.org/viaf/142432638> ;
+          dc11:type "primary_text"^^olac:linguistic-type, "narrative"^^olac:discourse-type, "report"^^olac:discourse-type, "unintelligible_speech"^^olac:discourse-type ;
+          dc:license <http://creativecommons.org/licenses/by-nc-sa/3.0/> ;
+          dc11:subject "lexicography"^^olac:linguistic-field, "phonetics"^^olac:linguistic-field, "anthropological_linguistics"^^olac:linguistic-field, "general_linguistics"^^olac:linguistic-field, <http://lexvo.org/id/iso639-3/fra>, "text_and_corpus_linguistics"^^olac:linguistic-field, "phonology"^^olac:linguistic-field, "semantics"^^olac:linguistic-field, "sociolinguistics"^^olac:linguistic-field, "syntax"^^olac:linguistic-field, "typology"^^olac:linguistic-field, "discourse_analysis"^^olac:linguistic-field, "historical_linguistics"^^olac:linguistic-field, "language_documentation"^^olac:linguistic-field, "mathematical_linguistics"^^olac:linguistic-field ;
+          dc11:title "CFPP2000 [03-01] Ozgur_Kilic_H_32_alii_3e Entretien de Ozgur KILIÇ 2 (annotations)"@fr ;
+          dc:accessRights "Freely available for non-commercial use" ;
+          dc:isPartOf <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_LANGUESDEFRANCE>, <http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-COLLECTION_CFPP2000> ;
+          dc11:source "CFPP2000"@fr ;
+          dc11:coverage "Quartier concerné : 3e"@fr ;
+          olac:depositor <http://viaf.org/viaf/93752300> ;
+          dc11:contributor <http://viaf.org/viaf/93752300>, "Branca-Rosoff, Sonia", "Kiliç Ozgur", "Chevrier Michel", "du-Breuil-de-Pont-en-Auge Benoît", "du-Breuil-de-Pont-en-Auge Augustin", "Salvegas Etienne", "Tanguy Noalig" ;
+          olac:interviewer "Branca-Rosoff, Sonia" ;
+          olac:responder "Kiliç Ozgur", "Chevrier Michel", "du-Breuil-de-Pont-en-Auge Benoît", "du-Breuil-de-Pont-en-Auge Augustin", "Salvegas Etienne" ;
+          olac:transcriber "Tanguy Noalig" ;
+          dc:available "2013-11-04"^^dc:W3CDTF ;
+          dc:created "2010-11-17"^^dc:W3CDTF ;
+          dc:issued "2013-11-04T22:20:07+01:00"^^dc:W3CDTF ;
+          dc:spatial [
+            a edm:Place ;
+            geo:lat "99.83975"^^xsd:float ;
+            geo:long "25.3542"^^xsd:float ;
+            skos:note "FR"^^dc:ISO3166, "France, Paris, Université Sorbonne Nouvelle Paris 3, site Censier"@fr, "Other place very important"@fr ;
+            owl:sameAs <http://vocab.getty.edu/tgn/1234567890>
+          ] .
+
+        <http://cocoon.huma-num.fr/exist/crdo/cfpp2000/fra/Ozgur_Kilic_H_32_alii_3e-2.xml>
+          a edm:WebResources ;
+          dc11:format "application/xml"^^dc:IMT ;
+          dc:created "2010-11-17"^^dc:W3CDTF ;
+          dc:issued "2013-11-04T22:20:07+01:00"^^dc:W3CDTF .
+
+        <http://cocoon.huma-num.fr/exist/crdo/cfpp2000/fra/Ozgur_Kilic_H_32_alii_3e-2.xhtml>
+          a edm:WebResources ;
+          dc11:format "application/xhtml+xml"^^dc:IMT ;
+          dc:created "2010-11-17"^^dc:W3CDTF ;
+          dc:issued "2013-11-04T22:20:07+01:00"^^dc:W3CDTF .
+EOT
+    ];
+
+    const TEST_INPUT_ID = "crdo-ESLO1_ENT_019";
+    const TEST_GRAPH_URI = "http://purl.org/poi/corpusdelaparole.huma-num.fr/crdo-ESLO1_ENT_019";
+    const TEST_CHO_URI = "http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-ESLO1_ENT_019";
+
+
+    private $inputGraphes = [];
+    private $resGraph;
+    private $merger;
+
+    function __construct(string $name = null) {
+        parent::__construct($name);
+    }
+
+    public function setUp() {
+        parent::setUp();
+
+        foreach(CocoonSoundRdfMergerTest::TEST_INPUT_DOCS as $key => $inputDoc) {
+            $this->inputGraphes[$key] = new Graph("http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-CFPP2000_35_SOUND", $inputDoc);
+        }
+
+        $this->merger = new CocoonSoundRdfMerger();
+        $this->resGraph = $this->merger->mergeGraph($this->inputGraphes['BASE'], $this->inputGraphes['SOURCE']);
+    }
+
+    public function tearDown() {
+        parent::tearDown();
+    }
+
+    /**
+     * Just test that the construct and setup are ok
+     *
+     * @return void
+     */
+    public function testInit()
+    {
+        $this->assertTrue(true);
+        echo $this->resGraph->serialise('turtle');
+    }
+
+    /**
+     * test the result graph.
+     *
+     * @return void
+     */
+    public function testResGraph() {
+        $this->assertNotNull($this->resGraph, "Res graph must not be null");
+        $this->assertEquals("http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-CFPP2000_35_SOUND", $this->resGraph->getUri(), "graph uri must be equals to http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-CFPP2000_35_SOUND");
+    }
+
+    /**
+     * test the merged Aggregation
+     *
+     * @return void
+     */
+    public function testAggregationResource() {
+        $aggregationResList = $this->resGraph->allOfType('http://www.openarchives.org/ore/terms/Aggregation');
+        $this->assertCount(1, $aggregationResList, "Only one Aggregation node");
+        $aggregationRes = $aggregationResList[0];
+
+        $this->assertEquals("http://purl.org/poi/corpusdelaparole.huma-num.fr/crdo-CFPP2000_35_SOUND",$aggregationRes->getUri(),"Aggregation node uri must be http://purl.org/poi/corpusdelaparole.huma-num.fr/crdo-CFPP2000_35_SOUND");
+
+        $singleValuesRes = [
+            'http://www.europeana.eu/schemas/edm/aggregatedCHO' => ['size'=>1, 'val' => $this->resGraph->resource("http://purl.org/poi/crdo.vjf.cnrs.fr/crdo-CFPP2000_35_SOUND")],
+            'http://www.europeana.eu/schemas/edm/provider' => ['size'=>1, 'val' => new Literal("Corpus de la Parole", "fr", null)],
+            'http://www.europeana.eu/schemas/edm/dataProvider' => ['size'=>1, 'val' => $this->resGraph->resource("http://viaf.org/viaf/142432638")],
+            'http://www.europeana.eu/schemas/edm/isShownAt' => ['size'=>1, 'val' => $this->resGraph->resource("http://cocoon.huma-num.fr/exist/crdo/meta/crdo-CFPP2000_35_SOUND")],
+            'http://www.europeana.eu/schemas/edm/isShownBy' => ['size'=>1, 'val' => $this->resGraph->resource("http://cocoon.huma-num.fr/data/archi/masters/372593.wav")],
+            'http://www.europeana.eu/schemas/edm/rights' => ['size'=>1, 'val' => $this->resGraph->resource("http://creativecommons.org/licenses/by-nc-sa/4.0/")],
+            'http://www.europeana.eu/schemas/edm/hasView' => ['size' => 4, 'val' => [
+                $this->resGraph->resource("http://cocoon.huma-num.fr/data/cfpp2000/Ozgur_Kilic_H_32_alii_3e-2.wav"),
+                $this->resGraph->resource("http://cocoon.huma-num.fr/data/cfpp2000/Ozgur_Kilic_H_32_alii_3e-2.mp3"),
+                $this->resGraph->resource("http://cocoon.huma-num.fr/exist/crdo/cfpp2000/fra/Ozgur_Kilic_H_32_alii_3e-2.xml"),
+                $this->resGraph->resource("http://cocoon.huma-num.fr/exist/crdo/cfpp2000/fra/Ozgur_Kilic_H_32_alii_3e-2.xhtml")
+            ]]
+        ];
+
+        foreach($singleValuesRes as $property => $resVal) {
+            $resList = $aggregationRes->all($this->inputGraphes['BASE']->resource($property));
+            $this->assertCount($resVal['size'], $resList, "$property list size $resVal[size]");
+            if($resVal['size'] == 1) {
+                $this->assertEquals($resVal['val'], $resList[0], "$property size one not equals");
+            }
+            else {
+                $this->assertEquals($resVal['val'], $resList, "$property size more than one not equals");
+            }
+        }
+
+    }
+
+    /**
+     * test web resources
+     *
+     * @return void
+     */
+    public function testWebResources() {
+        $webResList = $this->resGraph->allOfType('http://www.europeana.eu/schemas/edm/WebResources');
+
+        $this->assertCount(5, $webResList, "Must have 5 webResource");
+    }
+
+
+    /**
+    * Test one to one mapping spatial info
+    *
+    * @return void
+    */
+    public function testProvidedCHOSpatial() {
+        $providedCHO = $this->resGraph->get('edm:ProvidedCHO', '^rdf:type');
+
+        $this->assertNotNull($providedCHO);
+
+        $spatials = $providedCHO->all($this->resGraph->resource('http://purl.org/dc/terms/spatial'));
+
+        $this->assertCount(1, $spatials, "Must have only one spatial node");
+        $spatial = $spatials[0];
+        $this->assertTrue($spatial->isBNode(),"spatial node must be blank");
+        $this->assertEquals("edm:Place", $spatial->type(), "spatial node type must be edm:Place");
+
+        $lats = $spatial->all('geo:lat');
+        $this->assertCount(1, $lats, "One latitude");
+        $this->assertInstanceOf("EasyRdf\Literal", $lats[0], "Latitude must be a litteral");
+        $this->assertEquals(Literal::create("48.83975", null, 'xsd:float'), $lats[0], "lat must be '48.83975'^^xsd:float");
+
+        $longs = $spatial->all('geo:long');
+        $this->assertCount(1, $longs, "One longitude");
+        $this->assertInstanceOf("EasyRdf\Literal", $longs[0], "Longitude must be a litteral");
+        $this->assertEquals(Literal::create("2.3542", null, 'xsd:float'), $longs[0], "long must be '2.3542'^^xsd:float");
+
+        $notes = $spatial->all('skos:note');
+        $this->assertCount(3, $notes, "3 notes");
+        $this->assertContainsOnlyInstancesOf("EasyRdf\Literal", $notes, "Notes mus be only literals");
+        $this->assertEquals(Literal::create("FR", null, "dc:ISO3166"), $notes[0], "notes contains 'FR'^^dc:ISO3166");
+        $this->assertEquals(Literal::create("France, Paris, Université Sorbonne Nouvelle Paris 3, site Censier", "fr", null), $notes[1], "notes contains 'France, Centre, Loiret, Orléans'@fr");
+        $this->assertEquals(Literal::create("Other place very important", "fr", null), $notes[2], "notes contains 'Other place very important'@fr");
+
+        $sameas = $spatial->all('owl:sameAs');
+        $this->assertCount(1, $sameas, "1 same as");
+        $this->assertContainsOnlyInstancesOf("EasyRdf\Resource", $sameas, "Notes mus be only resources");
+        $this->assertEquals('http://vocab.getty.edu/tgn/7008038', $sameas[0]->getUri(), "uri must be http://vocab.getty.edu/tgn/7008038");
+    }
+
+
+    /**
+     * Test one to one mapping
+     *
+     * @return void
+     */
+    public function testProvidedCHOSingleproperty() {
+
+        $properties = [
+            "http://purl.org/dc/elements/1.1/title",
+            "http://purl.org/dc/terms/extent",
+            "http://purl.org/dc/terms/available",
+            "http://purl.org/dc/terms/created",
+            "http://purl.org/dc/terms/issued"
+        ];
+
+        $providedCHO = $this->resGraph->get('edm:ProvidedCHO', '^rdf:type');
+        $baseNode = $this->inputGraphes['BASE']->get('edm:ProvidedCHO', '^rdf:type');
+
+        $this->assertNotNull($providedCHO);
+        $this->assertNotNull($baseNode);
+
+        foreach ($properties as $prop) {
+            $outputValuesStr = [];
+            foreach($providedCHO->all($this->resGraph->resource($prop)) as $outputValue) {
+                array_push($outputValuesStr, strval($outputValue));
+            }
+            $this->assertNotEmpty($outputValuesStr, "we must found some values to test $prop");
+            foreach ($baseNode->all($this->inputGraphes['BASE']->resource($prop)) as $value) {
+                $this->assertContains(strval($value), $outputValuesStr, "$prop not found in output graph");
+            }
+        }
+
+    }
+
+
+}