add viaf resolver service & api
authorymh <ymh.work@gmail.com>
Thu, 10 Dec 2015 16:05:53 +0100
changeset 23 037687868bc4
parent 22 a50cbd7d702f
child 24 de47e8f66e8b
child 50 182f46ea5a56
add viaf resolver service & api - add viaf api controller - add unit test - add viaf service provider
server/src/app/Facades/GuzzleFacade.php
server/src/app/Http/Controllers/Api/ViafController.php
server/src/app/Http/routes.php
server/src/app/Libraries/Mappers/CocoonAbstractRdfMapper.php
server/src/app/Providers/GuzzleServiceProvider.php
server/src/app/Providers/ViafServiceProvider.php
server/src/app/Services/ViafResolver.php
server/src/app/Services/ViafResolverException.php
server/src/app/Services/ViafResolverInterface.php
server/src/config/app.php
server/src/config/corpusparole.php
server/src/tests/Controllers/ViafControllerTest.php
server/src/tests/Services/ViafResolverTest.php
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/app/Facades/GuzzleFacade.php	Thu Dec 10 16:05:53 2015 +0100
@@ -0,0 +1,12 @@
+<?php
+namespace CorpusParole\Facades;
+
+use Illuminate\Support\Facades\Facade;
+
+class GuzzleFacade extends Facade {
+
+    protected static function getFacadeAccessor() {
+        return 'guzzle';
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/app/Http/Controllers/Api/ViafController.php	Thu Dec 10 16:05:53 2015 +0100
@@ -0,0 +1,32 @@
+<?php
+
+namespace CorpusParole\Http\Controllers\Api;
+
+use Illuminate\Http\Request;
+use CorpusParole\Http\Requests;
+use CorpusParole\Http\Controllers\Controller;
+use CorpusParole\Services\ViafResolverInterface;
+use CorpusParole\Services\ViafResolverException;
+
+class ViafController extends Controller
+{
+    public function __construct(ViafResolverInterface $viafResolver) {
+        $this->viafResolver = $viafResolver;
+    }
+
+    /**
+     * Display the specified resource.
+     *
+     * @param  int  $id od comma separatedlist of ids
+     * @return \Illuminate\Http\Response
+     */
+    public function show($id)
+    {
+        try {
+            return response()->json(['viafids' => $this->viafResolver->getNames(explode(",", $id))]);
+        } catch (ViafResolverException $e) {
+            abort($e->getCode(), $e->getMessage());
+        }
+    }
+
+}
--- a/server/src/app/Http/routes.php	Tue Dec 01 16:49:37 2015 +0100
+++ b/server/src/app/Http/routes.php	Thu Dec 10 16:05:53 2015 +0100
@@ -38,4 +38,6 @@
 Route::group(['prefix' => 'api/v1'] , function() {
     Route::resource('documents', 'Api\DocumentController',
                     ['only' => ['index', 'show']]);
+    Route::resource('viaf', 'Api\ViafController',
+                    ['only' => ['show']]);
 });
--- a/server/src/app/Libraries/Mappers/CocoonAbstractRdfMapper.php	Tue Dec 01 16:49:37 2015 +0100
+++ b/server/src/app/Libraries/Mappers/CocoonAbstractRdfMapper.php	Thu Dec 10 16:05:53 2015 +0100
@@ -133,7 +133,7 @@
         foreach($collections as $coll) {
             if($coll instanceof Resource) {
                 $collUri = $coll->getUri();
-                if(strpos(strtolower($collUri), "collection", strlen(config('cocoon_doc_id_base_uri'))) !== FALSE) {
+                if(strpos(strtolower($collUri), "collection", strlen(config('corpusparole.cocoon_doc_id_base_uri'))) !== FALSE) {
                     $collectionGraph = new Graph($collUri);
                     $this->outputGraphes[$collUri] = $collectionGraph;
                     $collectionGraph->resource($collUri, 'edm:Collection');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/app/Providers/GuzzleServiceProvider.php	Thu Dec 10 16:05:53 2015 +0100
@@ -0,0 +1,25 @@
+<?php
+
+namespace CorpusParole\Providers;
+
+use Illuminate\Support\ServiceProvider;
+use GuzzleHttp\Client;
+
+/**
+ * guzzle Service Provider, inspired by https://github.com/urakozz/laravel-guzzle
+ */
+class GuzzleServiceProvider extends ServiceProvider
+{
+    /**
+     * Register the Guzzle provider
+     *
+     * @return GuzzleClient
+     */
+    public function register()
+    {
+        $this->app->bind('guzzle', function() {
+            $config = isset($this->app['config']['guzzle']) ? $this->app['config']['guzzle'] : [];
+            return new Client($config);
+        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/app/Providers/ViafServiceProvider.php	Thu Dec 10 16:05:53 2015 +0100
@@ -0,0 +1,24 @@
+<?php
+
+namespace CorpusParole\Providers;
+
+use Config;
+
+use Illuminate\Support\ServiceProvider;
+
+use CorpusParole\Services\ViafResolver;
+
+class ViafServiceProvider extends ServiceProvider
+{
+    /**
+     * Register the application services.
+     *
+     * @return void
+     */
+    public function register()
+    {
+        $this->app->bind('CorpusParole\Services\ViafResolverInterface', function($app) {
+            return new ViafResolver($app['guzzle']);
+        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/app/Services/ViafResolver.php	Thu Dec 10 16:05:53 2015 +0100
@@ -0,0 +1,114 @@
+<?php
+namespace CorpusParole\Services;
+
+use CorpusParole\Services\ViafResolverInterface;
+
+use Cache;
+use Config;
+use EasyRdf\Graph;
+use GuzzleHttp\Client;
+use GuzzleHttp\Exception\RequestException;
+use GuzzleHttp\Exception\ClientException;
+use GuzzleHttp\Exception\GuzzleException;
+use Illuminate\Contracts\Cache\Repository as CacheRepository;
+
+class ViafResolver implements ViafResolverInterface {
+
+    private $client = null;
+
+    public function __construct(Client $httpClient) {
+        $this->client = $httpClient;
+    }
+
+    /**
+     * make the viaf query.
+     */
+    public function queryName($id) {
+
+        $url = config('corpusparole.viaf_base_url').$id;
+
+        try {
+            $response = $this->client->get($url."/", ['headers'=>['Accept' => 'application/rdf+xml'],]);
+        }
+        catch(ClientException $e) {
+            if($e->getResponse()->getStatusCode() === 404) {
+                return null;
+            } else {
+                throw new ViafResolverException(
+                    $e->getMessage(),
+                    $e->getResponse()->getStatusCode(),
+                    $e
+                );
+            }
+        }
+        catch(RequestException $e) {
+            throw new ViafResolverException(
+                $e->getMessage(),
+                $e->hasResponse()?$e->getResponse()->getStatusCode():500,
+                $e
+            );
+        }
+
+        $graph = new Graph($url, $response->getBody());
+        $names = [];
+        foreach ($graph->allLiterals("<$url>", "schema:name") as $nameLit) {
+            $lang = $nameLit->getLang();
+            if(!$lang && !isset($names[''])) {
+                $names[''] = $nameLit->getvalue();
+            }
+            elseif (strpos($lang, 'fr') === 0 && !isset($names['fr'])) {
+                $names['fr'] = $nameLit->getvalue();
+            }
+            elseif (strpos($lang, 'en') === 0 && !isset($names['en'])) {
+                $names['en'] = $nameLit->getvalue();
+            }
+        }
+
+        return (isset($names['fr'])) ? $names['fr'] : ((isset($names['en'])) ? $names['en'] : ((isset($names['']))? $names[''] : null));
+
+    }
+
+    /**
+     * Check viaf id format
+     */
+    private function checkViafIdFormat($viafid) {
+        return ctype_digit($viafid);
+    }
+
+    /**
+     * Get name from Viaf id
+     * @param string $id The id to resolve. Can be an url starting with http://viaf.org/viaf/
+     * @return a string with the name
+     */
+    public function getName($id) {
+        $viafid = $id;
+        if(strpos($id, config('corpusparole.viaf_base_url')) === 0) {
+            $viafid = substr($id, strlen(config('corpusparole.viaf_base_url')));
+        }
+        $viafid = rtrim($viafid, '/');
+
+        if(!$this->checkViafIdFormat($viafid)) {
+            throw new ViafResolverException("ViafId not in correct format", 400);
+        }
+
+        $that = $this;
+
+        return Cache::remember("viaf:$viafid", config('corpusparole.viaf_cache_expiration'), function() use ($that, $viafid)  {
+
+            return $that->queryName($viafid);
+
+        });
+
+    }
+
+    /**
+     * Get a list of names from an array of viaf ids.
+     * @param array $ids The array of ids to resolve.
+     *                   Each id can be an url starting with http://viaf.org/viaf/
+     */
+    public function getNames(array $ids) {
+        return array_combine($ids, array_map([$this,'getName'], $ids));
+    }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/app/Services/ViafResolverException.php	Thu Dec 10 16:05:53 2015 +0100
@@ -0,0 +1,6 @@
+<?php
+namespace CorpusParole\Services;
+
+class ViafResolverException extends \Exception {
+    // just extend...
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/app/Services/ViafResolverInterface.php	Thu Dec 10 16:05:53 2015 +0100
@@ -0,0 +1,20 @@
+<?php
+namespace CorpusParole\Services;
+
+interface ViafResolverInterface {
+
+    /**
+     * Get name from Viaf id
+     * @param string $id The id to resolve. Can be an url starting with http://viaf.org/viaf/
+     * @return a string with the name
+     */
+    public function getName($id);
+
+    /**
+     * Get a list of names from an array of viaf ids.
+     * @param array $ids The array of ids to resolve.
+     *                   Each id can be an url starting with http://viaf.org/viaf/
+     */
+    public function getNames(array $ids);
+
+}
--- a/server/src/config/app.php	Tue Dec 01 16:49:37 2015 +0100
+++ b/server/src/config/app.php	Thu Dec 10 16:05:53 2015 +0100
@@ -151,6 +151,9 @@
         'CorpusParole\Providers\EventServiceProvider',
         'CorpusParole\Providers\RouteServiceProvider',
         'CorpusParole\Providers\RepositoryServiceProvider',
+        'CorpusParole\Providers\GuzzleServiceProvider',
+        'CorpusParole\Providers\ViafServiceProvider',
+
     ],
 
     /*
--- a/server/src/config/corpusparole.php	Tue Dec 01 16:49:37 2015 +0100
+++ b/server/src/config/corpusparole.php	Thu Dec 10 16:05:53 2015 +0100
@@ -78,6 +78,8 @@
                 'name' => 'Unintelligible Speech',
             ]
         ]
+    ],
 
-    ]
+    'viaf_base_url' => 'http://viaf.org/viaf/',
+    'viaf_cache_expiration' => 60*24*30
 ];
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/tests/Controllers/ViafControllerTest.php	Thu Dec 10 16:05:53 2015 +0100
@@ -0,0 +1,84 @@
+<?php
+
+use Mockery as m;
+
+use CorpusParole\Services\ViafResolverException;
+
+/**
+ *
+ */
+class ViafControllerTest extends TestCase {
+
+    private $viafResolver;
+
+    public function setUp() {
+
+        parent::setup();
+
+        // create a mock of the post repository interface and inject it into the
+        // IoC container
+        $this->viafResolver = m::mock('CorpusParole\Services\ViafResolverInterface');
+        $this->app->instance('CorpusParole\Services\ViafResolverInterface', $this->viafResolver);
+    }
+
+    public function tearDown() {
+        m::close();
+        parent::tearDown();
+    }
+
+    public function testShow() {
+        $this->viafResolver
+            ->shouldReceive('getNames')
+            ->with(['93752300', '56666014'])
+            ->once()
+            ->andReturn([
+                '56666014' => 'Guylaine Brun-Trigaud',
+                '93752300' => 'Sonia Branca-Rosoff'
+            ]);
+        $response = $this->get('/api/v1/viaf/93752300,56666014')->
+            seeJsonEquals(['viafids' => [
+                '56666014' => 'Guylaine Brun-Trigaud',
+                '93752300' => 'Sonia Branca-Rosoff'
+            ]]);
+    }
+
+    public function testShowOne() {
+        $this->viafResolver
+            ->shouldReceive('getNames')
+            ->with(['93752300'])
+            ->once()
+            ->andReturn([
+                '93752300' => 'Sonia Branca-Rosoff'
+            ]);
+        $response = $this->get('/api/v1/viaf/93752300')->
+            seeJsonEquals(['viafids' => [
+                '93752300' => 'Sonia Branca-Rosoff'
+            ]]);
+    }
+
+    public function testShowUnknown() {
+        $this->viafResolver
+            ->shouldReceive('getNames')
+            ->with(['12345'])
+            ->once()
+            ->andReturn([
+                '12345' => null
+            ]);
+        $response = $this->get('/api/v1/viaf/12345')->
+            seeJsonEquals(['viafids' => [
+                '12345' => null
+            ]]);
+    }
+
+    public function testShowMalformed() {
+        $this->viafResolver
+            ->shouldReceive('getNames')
+            ->with(['abcdef','ghij'])
+            ->once()
+            ->andThrow('CorpusParole\Services\ViafResolverException', "ViafId not in correct format", 400);
+        $response = $this->get('/api/v1/viaf/abcdef,ghij');
+
+        $this->assertResponseStatus(400);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/tests/Services/ViafResolverTest.php	Thu Dec 10 16:05:53 2015 +0100
@@ -0,0 +1,179 @@
+<?php
+
+use Illuminate\Foundation\Testing\WithoutMiddleware;
+use Illuminate\Foundation\Testing\DatabaseMigrations;
+use Illuminate\Foundation\Testing\DatabaseTransactions;
+
+use GuzzleHttp\Client;
+use GuzzleHttp\Handler\MockHandler;
+use GuzzleHttp\HandlerStack;
+use GuzzleHttp\Psr7\Response;
+use GuzzleHttp\Psr7\Request;
+use GuzzleHttp\Middleware;
+use GuzzleHttp\Exception\RequestException;
+
+
+
+class ViafResolverTest extends TestCase
+{
+    const VIAF_RDF_56666014 = <<<EOT
+<?xml version="1.0" encoding="UTF-8"?><rdf:RDF xmlns:schema="http://schema.org/" xmlns:genont="http://www.w3.org/2006/gen/ont#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:bgn="http://bibliograph.net/" xmlns:umbel="http://umbel.org/umbel#" xmlns:pto="http://www.productontology.org/id/"><rdf:Description rdf:about="http://viaf.org/viaf/56666014/"><rdf:type rdf:resource="http://xmlns.com/foaf/0.1/Document"/><rdf:type rdf:resource="http://www.w3.org/2006/gen/ont#InformationResource"/><void:inDataset xmlns:void="http://rdfs.org/ns/void#" rdf:resource="http://viaf.org/viaf/data"/><foaf:primaryTopic xmlns:foaf="http://xmlns.com/foaf/0.1/" rdf:resource="http://viaf.org/viaf/56666014"/></rdf:Description><rdf:Description rdf:about="http://viaf.org/viaf/56666014"><dcterms:identifier xmlns:dcterms="http://purl.org/dc/terms/">56666014</dcterms:identifier><rdf:type rdf:resource="http://schema.org/Person"/><rdf:type rdf:resource="http://schema.org/Person"/><rdf:type rdf:resource="http://schema.org/Person"/><rdf:type rdf:resource="http://schema.org/Person"/><rdf:type rdf:resource="http://schema.org/Person"/><schema:birthDate>1961-10-23</schema:birthDate><schema:name xml:lang="fr-FR">Guylaine Brun-Trigaud</schema:name><rdfs:comment xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xml:lang="en">Warning: skos:prefLabels are not ensured against change!</rdfs:comment><skos:prefLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#" xml:lang="fr-FR">Guylaine Brun-Trigaud</skos:prefLabel><schema:name xml:lang="nl-NL">Guylaine Brun-Trigaud</schema:name><rdfs:comment xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xml:lang="en">Warning: skos:prefLabels are not ensured against change!</rdfs:comment><skos:prefLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#" xml:lang="nl-NL">Guylaine Brun-Trigaud</skos:prefLabel><schema:name xml:lang="en-US">Guylaine Brun-Trigaud</schema:name><rdfs:comment xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xml:lang="en">Warning: skos:prefLabels are not ensured against change!</rdfs:comment><skos:prefLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#" xml:lang="en-US">Guylaine Brun-Trigaud</skos:prefLabel><schema:name xml:lang="en">Guylaine Brun-Trigaud</schema:name><schema:name xml:lang="fr-FR">Guylaine Brun-Trigaud</schema:name><schema:alternateName>Guylaine Brun- Trigaud</schema:alternateName><schema:givenName>Guylaine Brun-</schema:givenName><schema:familyName>Trigaud</schema:familyName><schema:alternateName>Trigaud</schema:alternateName><schema:sameAs><rdf:Description rdf:about="http://data.bnf.fr/ark:/12148/cb122483560#foaf:Person"/></schema:sameAs><schema:sameAs><rdf:Description rdf:about="http://id.loc.gov/authorities/names/nr92014179"/></schema:sameAs><schema:sameAs><rdf:Description rdf:about="http://www.idref.fr/031227201/id"/></schema:sameAs><schema:sameAs><rdf:Description rdf:about="http://isni.org/isni/0000000000375823"/></schema:sameAs></rdf:Description><rdf:Description rdf:about="http://viaf.org/viaf/sourceID/BNF%7C12248356#skos:Concept"><rdf:type rdf:resource="http://www.w3.org/2004/02/skos/core#Concept"/><skos:inScheme xmlns:skos="http://www.w3.org/2004/02/skos/core#" rdf:resource="http://viaf.org/authorityScheme/BNF"/><skos:prefLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#">Brun-Trigaud, Guylaine, 1961-....</skos:prefLabel><skos:altLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#">Trigaud Guylaine Brun-</skos:altLabel><foaf:focus xmlns:foaf="http://xmlns.com/foaf/0.1/" rdf:resource="http://viaf.org/viaf/56666014"/></rdf:Description><rdf:Description rdf:about="http://viaf.org/viaf/sourceID/NTA%7C072991968#skos:Concept"><rdf:type rdf:resource="http://www.w3.org/2004/02/skos/core#Concept"/><skos:inScheme xmlns:skos="http://www.w3.org/2004/02/skos/core#" rdf:resource="http://viaf.org/authorityScheme/NTA"/><skos:prefLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#">Brun-Trigaud, Guylaine</skos:prefLabel><foaf:focus xmlns:foaf="http://xmlns.com/foaf/0.1/" rdf:resource="http://viaf.org/viaf/56666014"/><schema:url>http://opc4.kb.nl/PPN?PPN=072991968</schema:url></rdf:Description><rdf:Description rdf:about="http://viaf.org/viaf/sourceID/LC%7Cnr+92014179#skos:Concept"><rdf:type rdf:resource="http://www.w3.org/2004/02/skos/core#Concept"/><skos:inScheme xmlns:skos="http://www.w3.org/2004/02/skos/core#" rdf:resource="http://viaf.org/authorityScheme/LC"/><skos:prefLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#">Brun-Trigaud, Guylaine</skos:prefLabel><skos:altLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#">Trigaud, Guylaine Brun-</skos:altLabel><foaf:focus xmlns:foaf="http://xmlns.com/foaf/0.1/" rdf:resource="http://viaf.org/viaf/56666014"/></rdf:Description><rdf:Description rdf:about="http://viaf.org/viaf/sourceID/ISNI%7C0000000000375823#skos:Concept"><rdf:type rdf:resource="http://www.w3.org/2004/02/skos/core#Concept"/><skos:inScheme xmlns:skos="http://www.w3.org/2004/02/skos/core#" rdf:resource="http://viaf.org/authorityScheme/ISNI"/><skos:prefLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#">Brun-Trigaud, Guylaine, 1961-....</skos:prefLabel><skos:altLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#">Trigaud, Guylaine Brun-</skos:altLabel><foaf:focus xmlns:foaf="http://xmlns.com/foaf/0.1/" rdf:resource="http://viaf.org/viaf/56666014"/></rdf:Description><rdf:Description rdf:about="http://viaf.org/viaf/sourceID/SUDOC%7C031227201#skos:Concept"><rdf:type rdf:resource="http://www.w3.org/2004/02/skos/core#Concept"/><skos:inScheme xmlns:skos="http://www.w3.org/2004/02/skos/core#" rdf:resource="http://viaf.org/authorityScheme/SUDOC"/><skos:prefLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#">Brun-Trigaud, Guylaine, 1961-....</skos:prefLabel><skos:altLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#">Trigaud, Guylaine Brun-</skos:altLabel><foaf:focus xmlns:foaf="http://xmlns.com/foaf/0.1/" rdf:resource="http://viaf.org/viaf/56666014"/></rdf:Description></rdf:RDF>
+EOT;
+    const VIAF_RDF_93752300 = <<<EOT
+<?xml version="1.0" encoding="UTF-8"?><rdf:RDF xmlns:schema="http://schema.org/" xmlns:genont="http://www.w3.org/2006/gen/ont#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:bgn="http://bibliograph.net/" xmlns:umbel="http://umbel.org/umbel#" xmlns:pto="http://www.productontology.org/id/"><rdf:Description rdf:about="http://viaf.org/viaf/93752300/"><rdf:type rdf:resource="http://xmlns.com/foaf/0.1/Document"/><rdf:type rdf:resource="http://www.w3.org/2006/gen/ont#InformationResource"/><void:inDataset xmlns:void="http://rdfs.org/ns/void#" rdf:resource="http://viaf.org/viaf/data"/><foaf:primaryTopic xmlns:foaf="http://xmlns.com/foaf/0.1/" rdf:resource="http://viaf.org/viaf/93752300"/></rdf:Description><rdf:Description rdf:about="http://viaf.org/viaf/93752300"><dcterms:identifier xmlns:dcterms="http://purl.org/dc/terms/">93752300</dcterms:identifier><rdf:type rdf:resource="http://schema.org/Person"/><rdf:type rdf:resource="http://schema.org/Person"/><rdf:type rdf:resource="http://schema.org/Person"/><rdf:type rdf:resource="http://schema.org/Person"/><rdf:type rdf:resource="http://schema.org/Person"/><rdf:type rdf:resource="http://schema.org/Person"/><rdf:type rdf:resource="http://schema.org/Person"/><rdf:type rdf:resource="http://schema.org/Person"/><schema:name xml:lang="fr-FR">Sonia Branca-Rosoff</schema:name><rdfs:comment xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xml:lang="en">Warning: skos:prefLabels are not ensured against change!</rdfs:comment><skos:prefLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#" xml:lang="fr-FR">Sonia Branca-Rosoff</skos:prefLabel><schema:name xml:lang="cs-CZ">Sonia Branca-Rosoff</schema:name><rdfs:comment xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xml:lang="en">Warning: skos:prefLabels are not ensured against change!</rdfs:comment><skos:prefLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#" xml:lang="cs-CZ">Sonia Branca-Rosoff</skos:prefLabel><schema:name xml:lang="en-US">Sonia Branca-Rosoff</schema:name><rdfs:comment xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xml:lang="en">Warning: skos:prefLabels are not ensured against change!</rdfs:comment><skos:prefLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#" xml:lang="en-US">Sonia Branca-Rosoff</skos:prefLabel><schema:name xml:lang="nl-NL">Sonia Branca-Rosoff</schema:name><rdfs:comment xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xml:lang="en">Warning: skos:prefLabels are not ensured against change!</rdfs:comment><skos:prefLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#" xml:lang="nl-NL">Sonia Branca-Rosoff</skos:prefLabel><schema:name xml:lang="en">Sonia Branca-Rosoff</schema:name><rdfs:comment xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">BCP47 tag for 'B2Q' is undetermined. Name is 'Sonia Branca-Rosoff'.</rdfs:comment><schema:alternateName>Sonia Branca-Rosoff</schema:alternateName><schema:name xml:lang="fr-FR">Sonia Branca-Rosoff</schema:name><schema:name xml:lang="pl-PL">Sonia Branca-Rosoff</schema:name><schema:alternateName>Sonia Branca</schema:alternateName><schema:givenName>Sonia</schema:givenName><schema:familyName>Branca</schema:familyName><schema:alternateName>Branca</schema:alternateName><schema:alternateName>Sonia Creusot</schema:alternateName><schema:givenName>Sonia</schema:givenName><schema:familyName>Creusot</schema:familyName><schema:alternateName>Sonia Rosoff</schema:alternateName><schema:givenName>Sonia</schema:givenName><schema:familyName>Rosoff</schema:familyName><schema:alternateName>Sonia Branca- Rosoff</schema:alternateName><schema:givenName>Sonia Branca-</schema:givenName><schema:familyName>Rosoff</schema:familyName><schema:alternateName>Sonia Branca- Rosoff</schema:alternateName><schema:givenName>Sonia Branca-</schema:givenName><schema:familyName>Rosoff</schema:familyName><schema:alternateName>Rosoff</schema:alternateName><schema:sameAs><rdf:Description rdf:about="http://www.idref.fr/030435358/id"/></schema:sameAs><schema:sameAs><rdf:Description rdf:about="http://data.bnf.fr/ark:/12148/cb121850323#foaf:Person"/></schema:sameAs><schema:sameAs><rdf:Description rdf:about="http://isni.org/isni/0000000066460502"/></schema:sameAs><schema:sameAs><rdf:Description rdf:about="http://id.loc.gov/authorities/names/n81045017"/></schema:sameAs><rdf:value rdf:parseType="Literal"><ns2:source xmlns="http://viaf.org/viaf/terms#" xmlns:foaf="http://xmlns.com/foaf/0.1/" xmlns:owl="http://www.w3.org/2002/07/owl#" xmlns:void="http://rdfs.org/ns/void#" xmlns:ns2="http://viaf.org/viaf/terms#" nsid="0000099925">B2Q|0000099925</ns2:source></rdf:value></rdf:Description><rdf:Description rdf:about="http://viaf.org/viaf/sourceID/BNF%7C12185032#skos:Concept"><rdf:type rdf:resource="http://www.w3.org/2004/02/skos/core#Concept"/><skos:inScheme xmlns:skos="http://www.w3.org/2004/02/skos/core#" rdf:resource="http://viaf.org/authorityScheme/BNF"/><skos:prefLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#">Branca-Rosoff, Sonia.</skos:prefLabel><skos:altLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#">Branca Sonia</skos:altLabel><skos:altLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#">Rosoff Sonia</skos:altLabel><foaf:focus xmlns:foaf="http://xmlns.com/foaf/0.1/" rdf:resource="http://viaf.org/viaf/93752300"/></rdf:Description><rdf:Description rdf:about="http://viaf.org/viaf/sourceID/NKC%7Cjo2012712459#skos:Concept"><rdf:type rdf:resource="http://www.w3.org/2004/02/skos/core#Concept"/><skos:inScheme xmlns:skos="http://www.w3.org/2004/02/skos/core#" rdf:resource="http://viaf.org/authorityScheme/NKC"/><skos:prefLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#">Branca-Rosoff, Sonia.</skos:prefLabel><skos:altLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#">Branca, Sonia</skos:altLabel><skos:altLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#">Creusot, Sonia</skos:altLabel><skos:altLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#">Rosoff, Sonia</skos:altLabel><foaf:focus xmlns:foaf="http://xmlns.com/foaf/0.1/" rdf:resource="http://viaf.org/viaf/93752300"/></rdf:Description><rdf:Description rdf:about="http://viaf.org/viaf/sourceID/LC%7Cn++81045017#skos:Concept"><rdf:type rdf:resource="http://www.w3.org/2004/02/skos/core#Concept"/><skos:inScheme xmlns:skos="http://www.w3.org/2004/02/skos/core#" rdf:resource="http://viaf.org/authorityScheme/LC"/><skos:prefLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#">Branca-Rosoff, Sonia.</skos:prefLabel><skos:altLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#">Branca, Sonia</skos:altLabel><skos:altLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#">Rosoff, Sonia Branca-</skos:altLabel><foaf:focus xmlns:foaf="http://xmlns.com/foaf/0.1/" rdf:resource="http://viaf.org/viaf/93752300"/></rdf:Description><rdf:Description rdf:about="http://viaf.org/viaf/sourceID/NTA%7C146010671#skos:Concept"><rdf:type rdf:resource="http://www.w3.org/2004/02/skos/core#Concept"/><skos:inScheme xmlns:skos="http://www.w3.org/2004/02/skos/core#" rdf:resource="http://viaf.org/authorityScheme/NTA"/><skos:prefLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#">Branca-Rosoff, Sonia.</skos:prefLabel><foaf:focus xmlns:foaf="http://xmlns.com/foaf/0.1/" rdf:resource="http://viaf.org/viaf/93752300"/><schema:url>http://opc4.kb.nl/PPN?PPN=146010671</schema:url></rdf:Description><rdf:Description rdf:about="http://viaf.org/viaf/sourceID/ISNI%7C0000000066460502#skos:Concept"><rdf:type rdf:resource="http://www.w3.org/2004/02/skos/core#Concept"/><skos:inScheme xmlns:skos="http://www.w3.org/2004/02/skos/core#" rdf:resource="http://viaf.org/authorityScheme/ISNI"/><skos:prefLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#">Branca-Rosoff, Sonia.</skos:prefLabel><skos:altLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#">Branca, Sonia</skos:altLabel><skos:altLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#">Creusot, Sonia</skos:altLabel><skos:altLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#">Rosoff, Sonia</skos:altLabel><skos:altLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#">Rosoff, Sonia Branca-</skos:altLabel><foaf:focus xmlns:foaf="http://xmlns.com/foaf/0.1/" rdf:resource="http://viaf.org/viaf/93752300"/></rdf:Description><rdf:Description rdf:about="http://viaf.org/viaf/sourceID/B2Q%7C0000099925#skos:Concept"><rdf:type rdf:resource="http://www.w3.org/2004/02/skos/core#Concept"/><skos:inScheme xmlns:skos="http://www.w3.org/2004/02/skos/core#" rdf:resource="http://viaf.org/authorityScheme/B2Q"/><skos:prefLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#">Branca-Rosoff, Sonia.</skos:prefLabel><skos:altLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#">Branca, Sonia</skos:altLabel><skos:altLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#">Rosoff, Sonia Branca-</skos:altLabel><foaf:focus xmlns:foaf="http://xmlns.com/foaf/0.1/" rdf:resource="http://viaf.org/viaf/93752300"/></rdf:Description><rdf:Description rdf:about="http://viaf.org/viaf/sourceID/SUDOC%7C030435358#skos:Concept"><rdf:type rdf:resource="http://www.w3.org/2004/02/skos/core#Concept"/><skos:inScheme xmlns:skos="http://www.w3.org/2004/02/skos/core#" rdf:resource="http://viaf.org/authorityScheme/SUDOC"/><skos:prefLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#">Branca-Rosoff, Sonia.</skos:prefLabel><skos:altLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#">Branca, Sonia</skos:altLabel><skos:altLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#">Rosoff, Sonia</skos:altLabel><foaf:focus xmlns:foaf="http://xmlns.com/foaf/0.1/" rdf:resource="http://viaf.org/viaf/93752300"/></rdf:Description><rdf:Description rdf:about="http://viaf.org/viaf/sourceID/NUKAT%7Cn+2012152967#skos:Concept"><rdf:type rdf:resource="http://www.w3.org/2004/02/skos/core#Concept"/><skos:inScheme xmlns:skos="http://www.w3.org/2004/02/skos/core#" rdf:resource="http://viaf.org/authorityScheme/NUKAT"/><skos:prefLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#">Branca-Rosoff, Sonia.</skos:prefLabel><skos:altLabel xmlns:skos="http://www.w3.org/2004/02/skos/core#">Rosoff, Sonia Branca-.</skos:altLabel><foaf:focus xmlns:foaf="http://xmlns.com/foaf/0.1/" rdf:resource="http://viaf.org/viaf/93752300"/></rdf:Description></rdf:RDF>
+EOT;
+
+//"<?"" (for syntax highliting)
+
+    function __construct(string $name = null) {
+        parent::__construct($name);
+    }
+
+    public function setUp() {
+        parent::setUp();
+        $this->container = [];
+        $history = Middleware::history($this->container);
+        $mock = new MockHandler([
+            new Response(200, [], self::VIAF_RDF_56666014),
+            new Response(200, [], self::VIAF_RDF_93752300),
+        ]);
+        $handler = HandlerStack::create($mock);
+        $handler->push($history);
+
+        $this->client = new Client(['handler' => $handler]);
+
+        $mock404 = new MockHandler([
+            new Response(404),
+        ]);
+        $this->client404 = new Client(['handler' => HandlerStack::create($mock404)]);
+
+        $mock401 = new MockHandler([
+            new Response(401, [], 'Unauthorized'),
+            new Response(500),
+        ]);
+        $this->client401 = new Client(['handler' => HandlerStack::create($mock401)]);
+
+        $mock500 = new MockHandler([
+            new Response(500, [], 'Internal Server Error'),
+        ]);
+        $this->client500 = new Client(['handler' => HandlerStack::create($mock500)]);
+
+    }
+
+    /**
+     * Jsut test the setup
+     *
+     * @return void
+     */
+    public function testSetUp() {
+        $this->assertTrue(true);
+    }
+
+    /**
+     * test getName
+     */
+    public function testGetName() {
+        $resolver = $this->app->make('CorpusParole\Services\ViafResolver', [$this->client]);
+        $name = $resolver->getName('56666014');
+
+        $this->assertEquals('Guylaine Brun-Trigaud', $name, "Name must be Guylaine Brun-Trigaud");
+
+        $this->assertCount(1, $this->container);
+
+        $this->assertEquals("http://viaf.org/viaf/56666014/", (string)$this->container[0]['request']->getUri());
+
+    }
+
+    /**
+     * test getName
+     */
+    public function testGetName93752300() {
+        $resolver = $this->app->make('CorpusParole\Services\ViafResolver', [$this->client]);
+        $name = $resolver->getName('56666014'); //first to consume responses
+
+        $name = $resolver->getName('93752300');
+
+        $this->assertEquals('Sonia Branca-Rosoff', $name, "Name must be Sonia Branca-Rosoff");
+
+        $this->assertCount(2, $this->container);
+
+        $this->assertEquals("http://viaf.org/viaf/93752300/", (string)$this->container[1]['request']->getUri());
+
+    }
+
+    /**
+     * test unknown id
+     */
+    public function testUnkownName404() {
+        $resolver = $this->app->make('CorpusParole\Services\ViafResolver', [$this->client404]);
+
+        $name = $resolver->getName('12345');
+
+        $this->assertNull($name);
+    }
+
+    /**
+     * test unknown id
+     */
+    public function testUnkownName() {
+        $resolver = $this->app->make('CorpusParole\Services\ViafResolver', [$this->client]);
+
+        $name = $resolver->getName('12345');
+
+        $this->assertNull($name);
+    }
+
+    /**
+     * Test exception 401
+     * @expectedException        CorpusParole\Services\ViafResolverException
+     * @expectedExceptionMessage Client error: 401
+     * @expectedExceptionCode 401
+     */
+    public function test401Error() {
+        $resolver = $this->app->make('CorpusParole\Services\ViafResolver', [$this->client401]);
+
+        $name = $resolver->getName('12345');
+    }
+
+
+    /**
+     * Test exception 500
+     * @expectedException        CorpusParole\Services\ViafResolverException
+     * @expectedExceptionMessage Server error: 500
+     * @expectedExceptionCode 500
+     */
+    public function test500Error() {
+        $resolver = $this->app->make('CorpusParole\Services\ViafResolver', [$this->client500]);
+
+        $name = $resolver->getName('12345');
+    }
+
+    /**
+     * Test exception malformed
+     * @expectedException        CorpusParole\Services\ViafResolverException
+     * @expectedExceptionMessage ViafId not in correct format
+     * @expectedExceptionCode 400
+     */
+    public function testMalformedError() {
+        $resolver = $this->app->make('CorpusParole\Services\ViafResolver', [$this->client]);
+
+        $name = $resolver->getName('abcd');
+    }
+
+    /**
+     * test getnames
+     */
+    public function testGetNames() {
+        $resolver = $this->app->make('CorpusParole\Services\ViafResolver', [$this->client]);
+        $names = $resolver->getNames(['56666014', '93752300']);
+
+        $this->assertCount(2, $names);
+        $this->assertArrayHasKey('56666014', $names);
+        $this->assertArrayHasKey('93752300', $names);
+
+        $this->assertEquals('Sonia Branca-Rosoff', $names['93752300']);
+        $this->assertEquals('Guylaine Brun-Trigaud', $names['56666014']);
+
+    }
+
+}