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

Commit

Permalink
added Saft/Addition/hardf (#88)
Browse files Browse the repository at this point in the history
currently only the Parser implementation is available
  • Loading branch information
k00ni committed May 29, 2017
1 parent 15df1d6 commit 3aab64f
Show file tree
Hide file tree
Showing 8 changed files with 432 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/Saft/Addition/hardf/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/vendor
/composer.lock
82 changes: 82 additions & 0 deletions src/Saft/Addition/hardf/Data/ParserFactoryHardf.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?php

namespace Saft\Addition\hardf\Data;

use Saft\Data\ParserFactory;
use Saft\Rdf\NodeFactory;
use Saft\Rdf\RdfHelpers;
use Saft\Rdf\StatementFactory;
use Saft\Rdf\StatementIteratorFactory;

class ParserFactoryHardf implements ParserFactory
{
/**
* @var array
*/
protected $serializationMap;

protected $nodeFactory;

protected $rdfHelpers;

protected $statementFactory;

protected $statementIteratorFactory;

public function __construct(
NodeFactory $nodeFactory,
StatementFactory $statementFactory,
StatementIteratorFactory $statementIteratorFactory,
RdfHelpers $rdfHelpers
) {
/**
* Map of serializations. It maps the Saft term on according the EasyRdf format.
*/
$this->serializationMap = array(
'n-triples' => 'n-triples',
'n-quads' => 'n-quads',
'turtle' => 'turtle',
);

$this->nodeFactory = $nodeFactory;
$this->RdfHelpers = $rdfHelpers;
$this->statementFactory = $statementFactory;
$this->statementIteratorFactory = $statementIteratorFactory;
}

/**
* Creates a Parser instance for a given serialization, if available.
*
* @param string $serialization The serialization you need a parser for. In case it is not
* available, an exception will be thrown.
* @return Parser Suitable parser for the requested serialization.
* @throws \Exception If parser for requested serialization is not available.
*/
public function createParserFor($serialization)
{
if (!in_array($serialization, $this->getSupportedSerializations())) {
throw new \Exception(
'Requested serialization '. $serialization .' is not available in: '.
implode(', ', $this->getSupportedSerializations())
);
}

return new ParserHardf(
$this->nodeFactory,
$this->statementFactory,
$this->statementIteratorFactory,
$this->RdfHelpers,
$serialization
);
}

/**
* Returns an array which contains supported serializations.
*
* @return array Array of supported serializations which are understood by this parser.
*/
public function getSupportedSerializations()
{
return array_keys($this->serializationMap);
}
}
200 changes: 200 additions & 0 deletions src/Saft/Addition/hardf/Data/ParserHardf.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
<?php

namespace Saft\Addition\hardf\Data;

use pietercolpaert\hardf\TriGParser;
use pietercolpaert\hardf\Util;
use Saft\Data\Parser;
use Saft\Rdf\ArrayStatementIteratorImpl;
use Saft\Rdf\NodeFactory;
use Saft\Rdf\RdfHelpers;
use Saft\Rdf\StatementFactory;
use Saft\Rdf\StatementIteratorFactory;

class ParserHardf implements Parser
{
/**
* @var NodeFactory
*/
protected $nodeFactory;

/**
* @var RdfHelpers
*/
protected $rdfHelpers;

/**
* @var string
*/
protected $serialization;

/**
* @var array
*/
protected $serializationMap;

/**
* @var StatementFactory
*/
protected $statementFactory;

/**
* Constructor.
*
* @param NodeFactory $nodeFactory
* @param StatementFactory $statementFactory
* @param StatementIteratorFactory $statementIteratorFactory
* @param RdfHelpers $rdfHelpers
* @param string $serialization
* @throws \Exception if serialization is unknown.
*/
public function __construct(
NodeFactory $nodeFactory,
StatementFactory $statementFactory,
StatementIteratorFactory $statementIteratorFactory,
RdfHelpers $rdfHelpers,
$serialization
) {
$this->RdfHelpers = $rdfHelpers;

$this->nodeFactory = $nodeFactory;
$this->statementFactory = $statementFactory;
$this->statementIteratorFactory = $statementIteratorFactory;

$this->serializationMap = array(
'n-triples' => 'triple',
'n-quads' => 'quad',
'turtle' => 'turtle',
);

$this->serialization = $this->serializationMap[$serialization];

if (false == isset($this->serializationMap[$serialization])) {
throw new \Exception(
'Unknown serialization format given: '. $serialization .'. Supported are only '.
implode(', ', array_keys($this->serializationMap))
);
}
}

/**
* Returns an array of prefixes which where found during the last parsing.
*
* @return array An associative array with a prefix mapping of the prefixes parsed so far. The key
* will be the prefix, while the values contains the according namespace URI.
*/
public function getCurrentPrefixList()
{
throw new \Exception('Currently not implement.');
}

/**
* Parses a given string and returns an iterator containing Statement instances representing the read data.
*
* @param string $inputString Data string containing RDF serialized data.
* @param string $baseUri The base URI of the parsed content. If this URI is null the inputStreams URL
* is taken as base URI.
* @return StatementIterator StatementIterator instaince containing all the Statements parsed by the
* parser to far
* @throws \Exception if the base URI $baseUri is no valid URI.
*/
public function parseStringToIterator($inputString, $baseUri = null)
{
// check $baseUri
if (null !== $baseUri && false == $this->RdfHelpers->simpleCheckURI($baseUri)) {
throw new \Exception('Parameter $baseUri is not a valid URI.');
}

$statements = array();

$parser = new TriGParser(array('format' => $this->serialization));
$triples = $parser->parse($inputString);

foreach ($triples as $triple) {
/*
* handle subject
*/
$subject = null;
if (Util::isIRI($triple['subject'])) {
$subject = $this->nodeFactory->createNamedNode($triple['subject']);
} elseif (Util::isBlank($triple['subject'])) {
$subject = $this->nodeFactory->createBlankNode(substr($triple['subject'], 2));
} else {
throw new \Exception('Invalid node type for subject found: '. $triple['subject']);
}

/*
* handle predicate
*/
$predicate = null;
if (Util::isIRI($triple['predicate'])) {
$predicate = $this->nodeFactory->createNamedNode($triple['predicate']);
} else {
throw new \Exception('Invalid node type for predicate found: '. $triple['predicate']);
}

/*
* handle object
*/
$object = null;
if (Util::isIRI($triple['object'])) {
$object = $this->nodeFactory->createNamedNode($triple['object']);

} elseif (Util::isBlank($triple['object'])) {
$object = $this->nodeFactory->createBlankNode(substr($triple['object'], 2));

} elseif (Util::isLiteral($triple['object'])) {
// safety check, to avoid fatal error about missing Error class in hardf
// FYI: https://github.com/pietercolpaert/hardf/pull/12
// TODO: remove this here, if fixed
$int = preg_match('/"(\n+\s*.*\n+\s*)"/si', $triple['object'], $match);
if (0 < $int) {
$value = $match[1];
$lang = null;
$datatype = null;

/*
* normal case
*/
} else {
// get value
preg_match('/"(.*)"/si', $triple['object'], $match);
$value = $match[1];

$lang = Util::getLiteralLanguage($triple['object']);
$lang = '' == $lang ? null : $lang;
$datatype = Util::getLiteralType($triple['object']);
}

$object = $this->nodeFactory->createLiteral($value, $datatype, $lang);
} else {
throw new \Exception('Invalid node type for object found: '. $triple['object']);
}

// add statement
$statements[] = $this->statementFactory->createStatement($subject, $predicate, $object);
}

return $this->statementIteratorFactory->createStatementIteratorFromArray($statements);
}

/**
* Parses a given stream and returns an iterator containing Statement instances representing the
* previously read data. The stream parses the data not as a whole but in chunks.
*
* @param string $inputStream Filename of the stream to parse which contains RDF serialized data.
* @param string $baseUri The base URI of the parsed content. If this URI is null the inputStreams URL
* is taken as base URI.
* @return StatementIterator A StatementIterator containing all the Statements parsed by the parser to far.
* @throws \Exception if the base URI $baseUri is no valid URI.
*/
public function parseStreamToIterator($inputStream, $baseUri = null)
{
// check $baseUri
if (null !== $baseUri && false == $this->RdfHelpers->simpleCheckURI($baseUri)) {
throw new \Exception('Parameter $baseUri is not a valid URI.');
}

return $this->parseStringToIterator(file_get_contents($inputStream), $baseUri);
}
}
51 changes: 51 additions & 0 deletions src/Saft/Addition/hardf/Test/ParserFactoryHardfTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

namespace Saft\Addition\hardf\Test;

use Saft\Addition\hardf\Data\ParserFactoryHardf;
use Saft\Data\Test\ParserFactoryAbstractTest;
use Saft\Rdf\NodeFactoryImpl;
use Saft\Rdf\RdfHelpers;
use Saft\Rdf\StatementFactoryImpl;
use Saft\Rdf\StatementIteratorFactoryImpl;

class ParserFactoryHardfTest extends ParserFactoryAbstractTest
{
/**
* This list represents all serializations that are supported by the Parsers behind the ParserFactory
* class to test.
*
* @var array
*/
protected $availableSerializations = array(
'n-triples',
'n-quads',
'turtle'
);

/**
* @return ParserFactory
*/
protected function newInstance()
{
return new ParserFactoryHardf(
new NodeFactoryImpl(new RdfHelpers()),
new StatementFactoryImpl(),
new StatementIteratorFactoryImpl(),
new RdfHelpers()
);
}

public function testBum()
{
$str = '<http://foo> <http://bar> <http://baz> ;
<http://bar2> "hey"@de ;
<http://bar3> [
<http://bar4> "hi"^^<http://xsd#string>
] .';

$instance = $this->newInstance();
$parser = $instance->createParserFor('turtle');
$iterator = $parser->parseStringToIterator($str);
}
}
34 changes: 34 additions & 0 deletions src/Saft/Addition/hardf/Test/ParserHardfTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace Saft\Addition\hardf\Test;

use Saft\Addition\hardf\Data\ParserHardf;
use Saft\Addition\hardf\Data\ParserFactoryHardf;
use Saft\Data\Test\ParserAbstractTest;
use Saft\Rdf\NodeFactoryImpl;
use Saft\Rdf\RdfHelpers;
use Saft\Rdf\StatementFactoryImpl;
use Saft\Rdf\StatementIteratorFactoryImpl;

class ParserHardfTest extends ParserAbstractTest
{
protected $factory;

public function __construct()
{
$this->factory = new ParserFactoryHardf(
new NodeFactoryImpl(new RdfHelpers()),
new StatementFactoryImpl(),
new StatementIteratorFactoryImpl(),
new RdfHelpers()
);
}

/**
* @return Parser
*/
protected function newInstance($serialization)
{
return $this->factory->createParserFor($serialization);
}
}
5 changes: 5 additions & 0 deletions src/Saft/Addition/hardf/Test/bootstrap.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php

require_once __DIR__ .'/../vendor/autoload.php';

error_reporting(E_ALL);
Loading

0 comments on commit 3aab64f

Please sign in to comment.