Skip to content

Commit 5122af1

Browse files
committed
update n3 parser
1 parent b2100dc commit 5122af1

2 files changed

Lines changed: 105 additions & 34 deletions

File tree

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"laminas/laminas-diactoros": "^2.8",
2323
"league/flysystem": "^1.0",
2424
"mjrider/flysystem-factory": "^0.7",
25+
"pietercolpaert/hardf": "^0.3.1",
2526
"pdsinterop/flysystem-rdf": "dev-feature/nextcloud24",
2627
"psr/http-factory": "^1.0",
2728
"psr/http-message": "^1.0",

src/Server.php

Lines changed: 104 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
use Psr\Http\Message\ServerRequestInterface as Request;
1313
use Throwable;
1414
use WebSocket\Client;
15+
use pietercolpaert\hardf\TriGWriter;
16+
use pietercolpaert\hardf\TriGParser;
1517

1618
class Server
1719
{
@@ -195,7 +197,7 @@ private function handle(string $method, string $path, $contents, $request): Resp
195197
break;
196198
case "text/n3":
197199
$response = $this->handleN3Update($response, $path, $contents);
198-
break;
200+
break;
199201
default:
200202
$response->getBody()->write(self::ERROR_UNHANDLED_PATCH_CONTENT_TYPE);
201203
$response = $response->withStatus(400);
@@ -361,12 +363,86 @@ private function handleSparqlUpdate(Response $response, string $path, $contents)
361363
return $response;
362364
}
363365

366+
private function normalizeN3($contents) {
367+
$parser = new TriGParser(["format" => "n3"]);
368+
$triples = $parser->parse($contents);
369+
$parsedGraph = [];
370+
foreach ($triples as $key => $value) {
371+
$graph = $value['graph'];
372+
$subject = $value['subject'];
373+
$predicate = $value['predicate'];
374+
$object = $value['object'];
375+
376+
if ($graph == '') {
377+
$graph = ':root';
378+
}
379+
if ($graph != ':root') {
380+
$value['graph'] = '';
381+
$parsedGraph[$graph] = $value;
382+
} else {
383+
if (!isset($parsedGraph[$graph])) {
384+
$parsedGraph[$graph] = [];
385+
}
386+
if (!isset($parsedGraph[$graph][$subject])) {
387+
$parsedGraph[$graph][$subject] = [];
388+
}
389+
if (!isset($parsedGraph[$graph][$subject][$predicate])) {
390+
$parsedGraph[$graph][$subject][$predicate] = [];
391+
}
392+
$parsedGraph[$graph][$subject][$predicate][] = $object;
393+
}
394+
}
395+
return $parsedGraph;
396+
}
397+
398+
private function n3Convert($contents) {
399+
$parsedGraph = $this->normalizeN3($contents);
400+
$inserts = [];
401+
foreach ($parsedGraph[':root'] as $subject) {
402+
if (
403+
isset($subject['http://www.w3.org/1999/02/22-rdf-syntax-ns#type']) &&
404+
(in_array('http://www.w3.org/ns/solid/terms#InsertDeletePatch', $subject['http://www.w3.org/1999/02/22-rdf-syntax-ns#type'])) &&
405+
isset($subject['http://www.w3.org/ns/solid/terms#inserts'])
406+
) {
407+
foreach ($subject['http://www.w3.org/ns/solid/terms#inserts'] as $target) {
408+
$inserts[] = $parsedGraph[$target];
409+
}
410+
}
411+
}
412+
413+
$deletes = [];
414+
foreach ($parsedGraph[':root'] as $subject) {
415+
if (
416+
isset($subject['http://www.w3.org/1999/02/22-rdf-syntax-ns#type']) &&
417+
(in_array('http://www.w3.org/ns/solid/terms#InsertDeletePatch', $subject['http://www.w3.org/1999/02/22-rdf-syntax-ns#type'])) &&
418+
isset($subject['http://www.w3.org/ns/solid/terms#deletes'])
419+
) {
420+
foreach ($subject['http://www.w3.org/ns/solid/terms#deletes'] as $target) {
421+
$deletes[] = $parsedGraph[$target];
422+
}
423+
}
424+
}
425+
426+
$writer = new TriGWriter(["format" => "turtle"]);
427+
$writer->addTriples($inserts);
428+
$insertTurtle = $writer->end();
429+
430+
$writer = new TriGWriter(["format" => "turtle"]);
431+
$writer->addTriples($deletes);
432+
$deleteTurtle = $writer->end();
433+
434+
return array(
435+
"insert" => $insertTurtle ?? "",
436+
"delete" => $deleteTurtle ?? ""
437+
);
438+
}
439+
364440
private function handleN3Update(Response $response, string $path, $contents): Response
365441
{
366442
$filesystem = $this->filesystem;
367443
$graph = $this->getGraph();
368444
$n3Graph = $this->getGraph();
369-
445+
370446
if ($filesystem->has($path) === false) {
371447
$data = '';
372448
} else {
@@ -380,39 +456,33 @@ private function handleN3Update(Response $response, string $path, $contents): Re
380456
$graph->parse($data, "turtle");
381457
// FIXME: Adding this base will allow us to parse <> entries; , $this->baseUrl . $this->basePath . $path), but that breaks the build.
382458
// FIXME: Use enums from namespace Pdsinterop\Rdf\Enum\Format instead of 'turtle'?
459+
$instructions = $this->n3Convert($contents);
383460

384-
$n3Graph->parse($contents, "ntriples");
385-
$matching = $n3Graph->resourcesMatching('http://www.w3.org/ns/solid/terms#InsertDeletePatch');
386-
foreach ($matching as $match) {
387-
$inserts = $match->all('<http://www.w3.org/ns/solid/terms#inserts>');
388-
$deletes = $match->all('<http://www.w3.org/ns/solid/terms#deletes>');
389-
// FIXME: do we need to so patches as well?
390-
// $patches = $match->all('<http://www.w3.org/ns/solid/terms#patches>');
391-
392-
foreach ($inserts as $triples) {
393-
$graph->parse($triples, "turtle");
394-
}
395-
foreach ($deletes as $triples) {
396-
$deleteGraph = $this->getGraph();
397-
// @CHECKME: Does the Graph Parse here also need an URI?
398-
$deleteGraph->parse($triples, "ntriples");
399-
$resources = $deleteGraph->resources();
400-
foreach ($resources as $resource) {
401-
$properties = $resource->propertyUris();
402-
foreach ($properties as $property) {
403-
$values = $resource->all($property);
404-
if (!count($values)) {
405-
$graph->delete($resource, $property);
406-
} else {
407-
foreach ($values as $value) {
408-
$count = $graph->delete($resource, $property, $value);
409-
if ($count === 0) {
410-
throw new Exception("Could not delete a value", 500);
411-
}
412-
}
413-
}
414-
}
415-
}
461+
// error_log("INSERT");
462+
// error_log($instructions['insert']);
463+
$graph->parse($instructions['insert']);
464+
465+
$deleteGraph = $this->getGraph();
466+
// error_log("DELETE");
467+
// error_log($instructions['delete']);
468+
469+
// @CHECKME: Does the Graph Parse here also need an URI?
470+
$deleteGraph->parse($instructions['delete'], "turtle");
471+
$resources = $deleteGraph->resources();
472+
foreach ($resources as $resource) {
473+
$properties = $resource->propertyUris();
474+
foreach ($properties as $property) {
475+
$values = $resource->all($property);
476+
if (!count($values)) {
477+
$graph->delete($resource, $property);
478+
} else {
479+
foreach ($values as $value) {
480+
$count = $graph->delete($resource, $property, $value);
481+
if ($count === 0) {
482+
throw new Exception("Could not delete a value", 500);
483+
}
484+
}
485+
}
416486
}
417487
// FIXME: Is there a 'patches'? What does it look like and how do we handle it?
418488
}

0 commit comments

Comments
 (0)