summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'SemanticMediaWiki/includes/export/SMW_Exp_Data.php')
-rw-r--r--SemanticMediaWiki/includes/export/SMW_Exp_Data.php255
1 files changed, 255 insertions, 0 deletions
diff --git a/SemanticMediaWiki/includes/export/SMW_Exp_Data.php b/SemanticMediaWiki/includes/export/SMW_Exp_Data.php
new file mode 100644
index 00000000..a430d490
--- /dev/null
+++ b/SemanticMediaWiki/includes/export/SMW_Exp_Data.php
@@ -0,0 +1,255 @@
+<?php
+/**
+ * SMWExpData is a class representing semantic data that is ready for easy
+ * serialisation in OWL or RDF.
+ *
+ * @author Markus Krötzsch
+ * @file
+ * @ingroup SMW
+ */
+
+/**
+ * SMWExpData is a data container for export-ready semantic content. It is
+ * organised as a tree-shaped data structure with one root subject and zero
+ * or more children connected with labelled edges to the root. Children are
+ * again SMWExpData objects, and edges are annotated with SMWExpNsElements
+ * specifying properties.
+ * @note We do not allow property element without namespace abbreviation
+ * here. Property aabbreviations are mandatory for some serialisations.
+ *
+ * @ingroup SMW
+ */
+class SMWExpData extends SMWExpElement {
+ /**
+ * The subject of the data that we store.
+ * @var SMWExpResource
+ */
+ protected $m_subject;
+ /**
+ * Array mapping property URIs to arrays their values, given as
+ * SMWExpElement objects.
+ * @var array of array of SMWElement
+ */
+ protected $m_children = array();
+ /**
+ * Array mapping property URIs to arrays their SMWExpResource
+ * @var array of SMWExpResource
+ */
+ protected $m_edges = array();
+
+ /**
+ * Constructor. $subject is the SMWExpResource for the
+ * subject about which this SMWExpData is.
+ */
+ public function __construct( SMWExpResource $subject ) {
+ parent::__construct( $subject->getDataItem() );
+ $this->m_subject = $subject;
+ }
+
+ /**
+ * Turn an array of SMWExpElements into an RDF collection.
+ *
+ * @param $elements array of SMWExpElement
+ * @return SMWExpData
+ */
+ public static function makeCollection( array $elements ) {
+ if ( count( $elements ) == 0 ) {
+ return new SMWExpData( SMWExporter::getSpecialNsResource( 'rdf', 'nil' ) );
+ } else {
+ $rdftype = SMWExporter::getSpecialNsResource( 'rdf', 'type' );
+ $rdffirst = SMWExporter::getSpecialNsResource( 'rdf', 'first' );
+ $rdfrest = SMWExporter::getSpecialNsResource( 'rdf', 'rest' );
+ $result = new SMWExpData( new SMWExpResource( '' ) ); // bnode
+ $result->addPropertyObjectValue( $rdftype, new SMWExpData( SMWExporter::getSpecialNsResource( 'rdf', 'List' ) ) );
+ $result->addPropertyObjectValue( $rdffirst, array_shift( $elements ) );
+ $result->addPropertyObjectValue( $rdfrest, SMWExpData::makeCollection( $elements ) );
+ return $result;
+ }
+ }
+
+ /**
+ * Return subject to which the stored semantic annotation refer to.
+ *
+ * @return SMWExpResource
+ */
+ public function getSubject() {
+ return $this->m_subject;
+ }
+
+ /**
+ * Store a value for a property identified by its title object. No
+ * duplicate elimination as this is usually done in SMWSemanticData
+ * already (which is typically used to generate this object).
+ *
+ * @param SMWExpNsResource $property
+ * @param SMWExpData $child
+ */
+ public function addPropertyObjectValue( SMWExpNsResource $property, SMWExpElement $child ) {
+ if ( !array_key_exists( $property->getUri(), $this->m_edges ) ) {
+ $this->m_children[$property->getUri()] = array();
+ $this->m_edges[$property->getUri()] = $property;
+ }
+ $this->m_children[$property->getUri()][] = $child;
+ }
+
+ /**
+ * Return the list of SMWExpResource objects for all properties for
+ * which some values have been given.
+ *
+ * @return array of SMWExpResource
+ */
+ public function getProperties() {
+ return $this->m_edges;
+ }
+
+ /**
+ * Return the list of SMWExpElement values associated to some property
+ * (element).
+ *
+ * @return array of SMWExpElement
+ */
+ public function getValues( SMWExpResource $property ) {
+ if ( array_key_exists( $property->getUri(), $this->m_children ) ) {
+ return $this->m_children[$property->getUri()];
+ } else {
+ return array();
+ }
+ }
+
+ /**
+ * Return the list of SMWExpData values associated to some property that is
+ * specifed by a standard namespace id and local name.
+ *
+ * @param $namespaceId string idetifying a known special namespace (e.g. "rdf")
+ * @param $localName string of local name (e.g. "type")
+ * @return array of SMWExpData
+ */
+ public function getSpecialValues( $namespaceId, $localName ) {
+ $pe = SMWExporter::getSpecialNsResource( $namespaceId, $localName );
+ return $this->getValues( $pe );
+ }
+
+ /**
+ * This function finds the main type (class) element of the subject
+ * based on the current property assignments. It returns this type
+ * element (SMWExpElement) and removes the according type assignement
+ * from the data. If no type is assigned, the element for rdf:Resource
+ * is returned.
+ *
+ * @note Under all normal conditions, the result will be an
+ * SMWExpResource.
+ *
+ * @return SMWExpElement
+ */
+ public function extractMainType() {
+ $pe = SMWExporter::getSpecialNsResource( 'rdf', 'type' );
+ if ( array_key_exists( $pe->getUri(), $this->m_children ) ) {
+ $result = array_shift( $this->m_children[$pe->getUri()] );
+ if ( count( $this->m_children[$pe->getUri()] ) == 0 ) {
+ unset( $this->m_edges[$pe->getUri()] );
+ unset( $this->m_children[$pe->getUri()] );
+ }
+ return ( $result instanceof SMWExpData ) ? $result->getSubject() : $result;
+ } else {
+ return SMWExporter::getSpecialNsResource( 'rdf', 'Resource' );
+ }
+ }
+
+ /**
+ * Check if this element encodes an RDF list, and if yes return an
+ * array of SMWExpElements corresponding to the collection elements in
+ * the specified order. Otherwise return false.
+ * The method only returns lists that can be encoded using
+ * parseType="Collection" in RDF/XML, i.e. only lists of non-literal
+ * resources.
+ *
+ * @return mixed array of SMWExpElement (but not SMWExpLiteral) or false
+ */
+ public function getCollection() {
+ $rdftypeUri = SMWExporter::getSpecialNsResource( 'rdf', 'type' )->getUri();
+ $rdffirstUri = SMWExporter::getSpecialNsResource( 'rdf', 'first' )->getUri();
+ $rdfrestUri = SMWExporter::getSpecialNsResource( 'rdf', 'rest' )->getUri();
+ $rdfnilUri = SMWExporter::getSpecialNsResource( 'rdf', 'nil' )->getUri();
+ // first check if we are basically an RDF List:
+ if ( ( $this->m_subject->isBlankNode() ) &&
+ ( count( $this->m_children ) == 3 ) &&
+ ( array_key_exists( $rdftypeUri, $this->m_children ) ) &&
+ ( count( $this->m_children[$rdftypeUri] ) == 1 ) &&
+ ( array_key_exists( $rdffirstUri, $this->m_children ) ) &&
+ ( count( $this->m_children[$rdffirstUri] ) == 1 ) &&
+ !( end( $this->m_children[$rdffirstUri] ) instanceof SMWExpLiteral ) &&
+ // (parseType collection in RDF not possible with literals :-/)
+ ( array_key_exists( $rdfrestUri, $this->m_children ) ) &&
+ ( count( $this->m_children[$rdfrestUri] ) == 1 ) ) {
+ $typedata = end( $this->m_children[$rdftypeUri] );
+ $rdflistUri = SMWExporter::getSpecialNsResource( 'rdf', 'List' )->getUri();
+ if ( $typedata->getSubject()->getUri() == $rdflistUri ) {
+ $first = end( $this->m_children[$rdffirstUri] );
+ $rest = end( $this->m_children[$rdfrestUri] );
+ if ( $rest instanceof SMWExpData ) {
+ $restlist = $rest->getCollection();
+ if ( $restlist === false ) {
+ return false;
+ } else {
+ array_unshift( $restlist, $first );
+ return $restlist;
+ }
+ } elseif ( ( $rest instanceof SMWExpResource ) &&
+ ( $rest->getUri() == $rdfnilUri ) ) {
+ return array( $first );
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ } elseif ( ( count( $this->m_children ) == 0 ) && ( $this->m_subject->getUri() == $rdfnilUri ) ) {
+ return array();
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Return an array of ternary arrays (subject predicate object) of
+ * SMWExpElements that represents the flattened version of this data.
+ *
+ * @return array of array of SMWExpElement
+ */
+ public function getTripleList( SMWExpElement $subject = null ) {
+ global $smwgBnodeCount;
+ if ( !isset( $smwgBnodeCount ) ) {
+ $smwgBnodeCount = 0;
+ }
+
+ if ( $subject == null ) {
+ $subject = $this->m_subject;
+ }
+
+ $result = array();
+
+ foreach ( $this->m_edges as $key => $edge ) {
+ foreach ( $this->m_children[$key] as $childElement ) {
+ if ( $childElement instanceof SMWExpData ) {
+ $childSubject = $childElement->getSubject();
+ } else {
+ $childSubject = $childElement;
+ }
+
+ if ( ( $childSubject instanceof SMWExpResource ) &&
+ ( $childSubject->isBlankNode() ) ) { // bnode, rename ID to avoid unifying bnodes of different contexts
+ // TODO: should we really rename bnodes of the form "_id" here?
+ $childSubject = new SMWExpResource( '_' . $smwgBnodeCount++, $childSubject->getDataItem() );
+ }
+
+ $result[] = array( $subject, $edge, $childSubject );
+ if ( $childElement instanceof SMWExpData ) { // recursively add child's triples
+ $result = array_merge( $result, $childElement->getTripleList( $childSubject ) );
+ }
+ }
+ }
+
+ return $result;
+ }
+
+}