Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add REST endpoint for mappings [WIP] #803

Merged
merged 5 commits into from
Jan 30, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions controller/RestController.php
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,40 @@ public function data($request)
return $this->returnDataResults($results, $format);
}

/**
* Get the mappings associated with a concept, enriched with labels and notations.
* Returns a JSKOS-compatible JSON object.
* @param Request $request
*/
public function mappings(Request $request)
{
$vocab = $request->getVocab();

if ($request->getUri()) {
$uri = $request->getUri();
} else {
return $this->returnError(400, 'Bad Request', "uri parameter missing");
}

$queryExVocabs = $request->getQueryParamBoolean('external', true);

$results = $vocab->getConceptInfo($uri, $request->getContentLang());
if (empty($results)) {
return $this->returnError(404, 'Bad Request', "no concept found with given uri");
}

$concept = $results[0];

$ret = [];
foreach ($concept->getMappingProperties() as $mappingProperty) {
foreach ($mappingProperty->getValues() as $mappingPropertyValue) {
$ret[] = $mappingPropertyValue->asJskos($queryExVocabs);
}
}

return $this->returnJson($ret);
}

/**
* Used for querying labels for a uri.
* @param Request $request
Expand Down
4 changes: 2 additions & 2 deletions model/Concept.php
Original file line number Diff line number Diff line change
Expand Up @@ -430,14 +430,14 @@ public function getMappingProperties()
}

if ($response) {
$ret[$prop]->addValue(new ConceptMappingPropertyValue($this->model, $this->vocab, $response, $prop), $this->clang);
$ret[$prop]->addValue(new ConceptMappingPropertyValue($this->model, $this->vocab, $response, $this->resource, $prop), $this->clang);

$this->processExternalResource($response);

continue;
}
}
$ret[$prop]->addValue(new ConceptMappingPropertyValue($this->model, $this->vocab, $val, $prop, $this->clang), $this->clang);
$ret[$prop]->addValue(new ConceptMappingPropertyValue($this->model, $this->vocab, $val, $this->resource, $prop, $this->clang), $this->clang);
}
}
}
Expand Down
86 changes: 81 additions & 5 deletions model/ConceptMappingPropertyValue.php
Original file line number Diff line number Diff line change
@@ -1,18 +1,32 @@
<?php

use EasyRdf\Resource;

/**
* Class for handling concept property values.
*/
class ConceptMappingPropertyValue extends VocabularyDataObject
{
/** property type */
private $type;
private $source;
private $clang;
private $labelcache;

public function __construct($model, $vocab, $resource, $prop, $clang = '')
/**
* ConceptMappingPropertyValue constructor.
*
* @param Model $model
* @param Vocabulary $vocab Target vocabulary
* @param Resource $target Target concept resource
* @param Resource $source Source concept resource
* @param string $prop Mapping property
* @param ?string $clang Preferred label language (nullable)
*/
public function __construct(Model $model, Vocabulary $vocab, Resource $target, Resource $source, string $prop, $clang = '')
{
parent::__construct($model, $vocab, $resource);
parent::__construct($model, $vocab, $target);
$this->source = $source;
$this->type = $prop;
$this->clang = $clang;
$this->labelcache = array();
Expand All @@ -30,7 +44,7 @@ public function getType()
return $this->type;
}

public function getLabel($lang = '')
public function getLabel($lang = '', $queryExVocabs = true)
{
if (isset($this->labelcache[$lang])) {
return $this->labelcache[$lang];
Expand All @@ -41,7 +55,7 @@ public function getLabel($lang = '')
return $label;
}

private function queryLabel($lang = '')
private function queryLabel($lang = '', $queryExVocabs = true)
{
if ($this->clang) {
$lang = $this->clang;
Expand All @@ -54,7 +68,7 @@ private function queryLabel($lang = '')
}

// if multiple vocabularies are found, the following method will return in priority the current vocabulary of the mapping
$exvocab = $this->model->guessVocabularyFromURI($this->resource->getUri(), $this->vocab->getId());
$exvocab = $queryExVocabs ? $this->model->guessVocabularyFromURI($this->resource->getUri(), $this->vocab->getId()) : null;

// if the resource is from another vocabulary known by the skosmos instance
if ($exvocab) {
Expand Down Expand Up @@ -148,5 +162,67 @@ public function getNotation()
return null;
}

/**
* Return the mapping as a JSKOS-compatible array.
* @return array
*/
public function asJskos($queryExVocabs = true)
{
$ret = [
'type' => [$this->type],
'from' => [
'memberSet' => [
[
'uri' => (string) $this->source->getUri(),
]
]
],
'to' => [
'memberSet' => [
[
'uri' => (string) $this->getUri()
]
]
]
];

$fromScheme = $this->vocab->getDefaultConceptScheme();
if (isset($fromScheme)) {
$ret['fromScheme'] = [
'uri' => (string) $fromScheme,
];
}

$exvocab = $this->getExvocab();
if (isset($exvocab)) {
$ret['toScheme'] = [
'uri' => (string) $exvocab->getDefaultConceptScheme(),
];
}

$notation = $this->getNotation();
if (isset($notation)) {
$ret['to']['memberSet'][0]['notation'] = (string) $notation;
}

$label = $this->getLabel($queryExVocabs);
if (isset($label)) {
if (is_string($label)) {
list($labelLang, $labelValue) = ['-', $label];
} else {
list($labelLang, $labelValue) = [$label->getLang(), $label->getValue()];
}
if ($labelValue != $this->getUri()) {
// The `queryLabel()` method above will fallback to returning the URI
// if no label was found. We don't want that here.
$ret['to']['memberSet'][0]['prefLabel'] = [
$labelLang => $labelValue,
];
}
}

return $ret;
}

}

2 changes: 2 additions & 0 deletions rest.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@
$controller->topConcepts($request);
} elseif ($parts[2] == 'data') {
$controller->data($request);
} elseif ($parts[2] == 'mappings') {
$controller->mappings($request);
} elseif ($parts[2] == 'search') {
$controller->search($request);
} elseif ($parts[2] == 'label') {
Expand Down
47 changes: 42 additions & 5 deletions tests/ConceptMappingPropertyValueTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ protected function setUp() {
*/
public function testConstructor() {
$resourcestub = $this->getMockBuilder('EasyRdf\Resource')->disableOriginalConstructor()->getMock();
$mapping = new ConceptMappingPropertyValue($this->model, $this->vocab, $resourcestub, 'skos:exactMatch');
$sourcestub = $this->getMockBuilder('EasyRdf\Resource')->disableOriginalConstructor()->getMock();
$mapping = new ConceptMappingPropertyValue($this->model, $this->vocab, $resourcestub, $sourcestub, 'skos:exactMatch');
$this->assertEquals('skos:exactMatch', $mapping->getType());
}

Expand All @@ -45,6 +46,7 @@ public function testGetLabelFromExternalVocabulary() {
* @covers ConceptMappingPropertyValue::queryLabel
*/
public function testGetLabelResortsToUri() {
$mocksource = $this->getMockBuilder('EasyRdf\Resource')->disableOriginalConstructor()->getMock();
$mockres = $this->getMockBuilder('EasyRdf\Resource')->disableOriginalConstructor()->getMock();
$labelmap = array(
array('en', null),
Expand All @@ -57,7 +59,7 @@ public function testGetLabelResortsToUri() {
);
$mockres->method('getLiteral')->will($this->returnValueMap($litmap));
$mockres->method('getUri')->will($this->returnValue('http://thisdoesntexistatalland.sefsf/2j2h4/'));
$mapping = new ConceptMappingPropertyValue($this->model, $this->vocab, $mockres, null);
$mapping = new ConceptMappingPropertyValue($this->model, $this->vocab, $mockres, $mocksource, 'skos:exactMatch');
$this->assertEquals('http://thisdoesntexistatalland.sefsf/2j2h4/', $mapping->getLabel());
}

Expand All @@ -66,14 +68,15 @@ public function testGetLabelResortsToUri() {
* @covers ConceptMappingPropertyValue::queryLabel
*/
public function testGetLabelWithAndWithoutLang() {
$mocksource = $this->getMockBuilder('EasyRdf\Resource')->disableOriginalConstructor()->getMock();
$mockres = $this->getMockBuilder('EasyRdf\Resource')->disableOriginalConstructor()->getMock();
$labelmap = array(
array('en', 'english'),
array(null, 'default')
);
$mockres->method('label')->will($this->returnValueMap($labelmap));
$mockres->method('getUri')->will($this->returnValue('http://thisdoesntexistatalland.sefsf/2j2h4/'));
$mapping = new ConceptMappingPropertyValue($this->model, $this->vocab, $mockres, null);
$mapping = new ConceptMappingPropertyValue($this->model, $this->vocab, $mockres, $mocksource, 'skos:exactMatch');
$this->assertEquals('english', $mapping->getLabel('en'));
$this->assertEquals('default', $mapping->getLabel());
}
Expand All @@ -83,6 +86,7 @@ public function testGetLabelWithAndWithoutLang() {
* @covers ConceptMappingPropertyValue::queryLabel
*/
public function testGetLabelWithLiteralAndLang() {
$mocksource = $this->getMockBuilder('EasyRdf\Resource')->disableOriginalConstructor()->getMock();
$mockres = $this->getMockBuilder('EasyRdf\Resource')->disableOriginalConstructor()->getMock();
$labelmap = array(
array('en', null),
Expand All @@ -95,7 +99,7 @@ public function testGetLabelWithLiteralAndLang() {
);
$mockres->method('getLiteral')->will($this->returnValueMap($litmap));
$mockres->method('getUri')->will($this->returnValue('http://thisdoesntexistatalland.sefsf/2j2h4/'));
$mapping = new ConceptMappingPropertyValue($this->model, $this->vocab, $mockres, null);
$mapping = new ConceptMappingPropertyValue($this->model, $this->vocab, $mockres, $mocksource, 'skos:exactMatch');
$this->assertEquals('english lit', $mapping->getLabel('en'));
$this->assertEquals('default lit', $mapping->getLabel());
}
Expand All @@ -104,6 +108,7 @@ public function testGetLabelWithLiteralAndLang() {
* @covers ConceptMappingPropertyValue::getNotation
*/
public function testGetNotation() {
$mocksource = $this->getMockBuilder('EasyRdf\Resource')->disableOriginalConstructor()->getMock();
$mockres = $this->getMockBuilder('EasyRdf\Resource')->disableOriginalConstructor()->getMock();
$mocklit = $this->getMockBuilder('EasyRdf\Literal')->disableOriginalConstructor()->getMock();
$mocklit->method('getValue')->will($this->returnValue('666'));
Expand All @@ -112,7 +117,7 @@ public function testGetNotation() {
array(null,null,null,null),
);
$mockres->method('get')->will($this->returnValueMap($map));
$mapping = new ConceptMappingPropertyValue($this->model, $this->vocab, $mockres, null);
$mapping = new ConceptMappingPropertyValue($this->model, $this->vocab, $mockres, $mocksource, 'skos:exactMatch');
$this->assertEquals(666, $mapping->getNotation());
}

Expand Down Expand Up @@ -165,4 +170,36 @@ public function testToString() {
$this->assertEquals('Eel', $propvals['Eelhttp://www.skosmos.skos/test/ta115']->__toString());
}

/**
* @covers ConceptMappingPropertyValue::asJskos
*/
public function testAsJskos() {
$propvals = $this->props['skos:exactMatch']->getValues();
$this->assertEquals([
'type' => [
'skos:exactMatch',
],
'toScheme' => [
'uri' => 'http://www.skosmos.skos/test/conceptscheme',
],
'from' => [
'memberSet' => [
[
'uri' => 'http://www.skosmos.skos/mapping/m1',
]
]
],
'to' => [
'memberSet' => [
[
'uri' => 'http://www.skosmos.skos/test/ta115',
'prefLabel' => [
'en' => 'Eel',
]
]
]
],
], $propvals['Eelhttp://www.skosmos.skos/test/ta115']->asJskos());
}

}