Skip to content
This repository has been archived by the owner on Aug 5, 2020. It is now read-only.

Commit

Permalink
implement CONSTRUCT query functionality in HTTP and Virtuoso adapter; f…
Browse files Browse the repository at this point in the history
…ix #60

- adapted query related tests
- extended Store/AbstractSparqlStore.php:
- added transformEntryToNode which encapsulates the transformation
    from an array entry being part of a result which has to be
    transformed into its proper Node instance.
- made code more readible and better testable
- added tests for Sparql/Query/QueryUtils.php to cover
getQueryType method
  • Loading branch information
k00ni committed Aug 21, 2016
1 parent 4aa8d66 commit f2d609f
Show file tree
Hide file tree
Showing 18 changed files with 614 additions and 150 deletions.
130 changes: 54 additions & 76 deletions src/Saft/Addition/HttpStore/Store/Http.php
Original file line number Diff line number Diff line change
Expand Up @@ -288,21 +288,44 @@ public function query($query, array $options = array())
{
$queryObject = $this->queryFactory->createInstanceByQueryString($query);
$queryParts = $queryObject->getQueryParts();
$queryType = $this->queryUtils->getQueryType($query);

/**
* SPARQL query (usually to fetch data)
* CONSTRUCT query
*/
if ('selectQuery' == $this->queryUtils->getQueryType($query)) {
if ('constructQuery' == $queryType) {
$receivedResult = $this->sendSparqlSelectQuery($this->configuration['queryUrl'], $query);

// transform object to array
if (is_object($receivedResult)) {
$resultArray = json_decode(json_encode($receivedResult), true);
// transform json string to array
} else {
$resultArray = json_decode($receivedResult, true);
$resultArray = $this->transformResultToArray($receivedResult);

if (isset($resultArray['results']['bindings'])) {
if (0 < count($resultArray['results']['bindings'])) {

$statements = array();

// important: we assume the bindings list is ORDERED!
foreach ($resultArray['results']['bindings'] as $entries) {
$statements[] = $this->statementFactory->createStatement(
$this->transformEntryToNode($entries['s']),
$this->transformEntryToNode($entries['p']),
$this->transformEntryToNode($entries['o'])
);
}

return $this->resultFactory->createStatementResult($statements);
}
}

return $this->resultFactory->createEmptyResult();

/**
* SELECT query
*/
} elseif ('selectQuery' == $queryType) {
$receivedResult = $this->sendSparqlSelectQuery($this->configuration['queryUrl'], $query);

$resultArray = $this->transformResultToArray($receivedResult);

$entries = array();

/**
Expand All @@ -320,76 +343,16 @@ public function query($query, array $options = array())
foreach ($resultArray['results']['bindings'] as $bindingParts) {
$newEntry = array();

/**
* A part looks like:
* array(
* 'type' => 'uri',
* 'value' => '...'
* )
*/

foreach ($bindingParts as $variable => $part) {
// it seems that for instance Virtuoso returns type=literal for bnodes,
// so we manually fix that here to avoid that problem if other stores act
// the same
if (true === is_string($part['value']) && false !== strpos($part['value'], '_:')) {
$part['type'] = 'bnode';
}

switch ($part['type']) {
/**
* Literal (language'd)
*/
case 'literal':
$lang = null;
if (isset($part['xml:lang'])) {
$lang = $part['xml:lang'];
}

$newEntry[$variable] = $this->nodeFactory->createLiteral(
$part['value'],
'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString',
$lang
);

break;

/**
* Typed-Literal
*/
case 'typed-literal':
$newEntry[$variable] = $this->nodeFactory->createLiteral(
$part['value'],
$part['datatype']
);

break;

/**
* NamedNode
*/
case 'uri':
$newEntry[$variable] = $this->nodeFactory->createNamedNode($part['value']);
break;

/**
* BlankNode
*/
case 'bnode':
$newEntry[$variable] = $this->nodeFactory->createBlankNode($part['value']);
break;

default:
throw new \Exception('Unknown type given.');
break;
}
$newEntry[$variable] = $this->transformEntryToNode($part);
}

$entries[] = $newEntry;
}

$return = $this->resultFactory->createSetResult($entries);
$return->setVariables($resultArray['head']['vars']);
return $return;

/**
* SPARPQL Update query
Expand All @@ -404,28 +367,26 @@ public function query($query, array $options = array())
$decodedResult = json_decode($receivedResult, true);
}

if ('askQuery' === $this->queryUtils->getQueryType($query)) {
if ('askQuery' === $queryType) {
if (true === isset($decodedResult['boolean'])) {
$return = $this->resultFactory->createValueResult($decodedResult['boolean']);
return $this->resultFactory->createValueResult($decodedResult['boolean']);

// assumption here is, if a string was returned, something went wrong.
} elseif (0 < strlen($receivedResult)) {
throw new \Exception($receivedResult);

} else {
$return = $this->resultFactory->createEmptyResult();
return $this->resultFactory->createEmptyResult();
}

// usually a SPARQL result does not return a string. if it does anyway, assume there is an error.
} elseif (null === $decodedResult && 0 < strlen($receivedResult)) {
throw new \Exception($receivedResult);

} else {
$return = $this->resultFactory->createEmptyResult();
return $this->resultFactory->createEmptyResult();
}
}

return $return;
}

/**
Expand Down Expand Up @@ -500,4 +461,21 @@ public function setClient(Curl $httpClient)
{
$this->httpClient = $httpClient;
}

/**
* Transforms server result to aray.
*
* @param mixed $receivedResult
* @return array
*/
public function transformResultToArray($receivedResult)
{
// transform object to array
if (is_object($receivedResult)) {
return json_decode(json_encode($receivedResult), true);
// transform json string to array
} else {
return json_decode($receivedResult, true);
}
}
}
78 changes: 78 additions & 0 deletions src/Saft/Addition/HttpStore/Test/Unit/HttpTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1353,6 +1353,84 @@ public function testQueryAsk()
parent::testQueryAsk();
}

public function testQueryConstruct()
{
$this->httpClient->shouldReceive('setHeader')->times(8);

$this->httpClient
->shouldReceive('get')
->times(3)
->andReturn(
json_encode(array()),
json_encode(array()),
json_encode(array(
'boolean' => true
))
);

$this->httpClient
->shouldReceive('post')
->once()
->andReturn(json_encode(array(
'head' => array(
'vars' => array(
's', 'p', 'o'
)
),
'results' => array(
'distinct' => false,
'ordered' => true,
'bindings' => array(
array(
's' => array('type' => 'uri', 'value' => 'http://saft/testquad/p1'),
'p' => array('type' => 'uri', 'value' => 'http://saft/testquad/s1'),
'o' => array('type' => 'uri', 'value' => 'http://saft/testquad/o1')
),
array(
's' => array('type' => 'uri', 'value' => 'http://saft/testtriple/p2'),
'p' => array('type' => 'uri', 'value' => 'http://saft/testtriple/s2'),
'o' => array('type' => 'uri', 'value' => 'http://saft/testtriple/o2')
)
)
)
)));

parent::testQueryConstruct();
}

public function testQueryConstructEmptyGraph()
{
$this->httpClient->shouldReceive('setHeader')->times(8);

$this->httpClient
->shouldReceive('get')
->times(3)
->andReturn(
json_encode(array()),
json_encode(array()),
json_encode(array(
'boolean' => true
))
);

$this->httpClient
->shouldReceive('post')
->once()
->andReturn(json_encode(array(
'head' => array(
'vars' => array(
's', 'p', 'o', 'g'
)
),
'results' => array(
'bindings' => array(
)
)
)));

parent::testQueryConstructEmptyGraph();
}

public function testQueryEmptyResult()
{
$this->httpClient->shouldReceive('setHeader')->times(2);
Expand Down
Loading

0 comments on commit f2d609f

Please sign in to comment.