summaryrefslogtreecommitdiff
path: root/www/wiki/extensions/SemanticMediaWiki/src/Query/Language/Conjunction.php
diff options
context:
space:
mode:
Diffstat (limited to 'www/wiki/extensions/SemanticMediaWiki/src/Query/Language/Conjunction.php')
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/src/Query/Language/Conjunction.php182
1 files changed, 182 insertions, 0 deletions
diff --git a/www/wiki/extensions/SemanticMediaWiki/src/Query/Language/Conjunction.php b/www/wiki/extensions/SemanticMediaWiki/src/Query/Language/Conjunction.php
new file mode 100644
index 00000000..be5e8dbe
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/src/Query/Language/Conjunction.php
@@ -0,0 +1,182 @@
+<?php
+
+namespace SMW\Query\Language;
+
+/**
+ * Description of a collection of many descriptions, all of which
+ * must be satisfied (AND, conjunction).
+ *
+ * Corresponds to conjunction in OWL and SPARQL. Not available in RDFS.
+ *
+ * @license GNU GPL v2+
+ * @since 1.6
+ *
+ * @author Markus Krötzsch
+ */
+class Conjunction extends Description {
+
+ /**
+ * @var Description[]
+ */
+ protected $descriptions = [];
+
+ /**
+ * @since 1.6
+ *
+ * @param array $descriptions
+ */
+ public function __construct( array $descriptions = [] ) {
+ foreach ( $descriptions as $description ) {
+ $this->addDescription( $description );
+ }
+ }
+
+ /**
+ * @see Description::getFingerprint
+ * @since 2.5
+ *
+ * @return string
+ */
+ public function getFingerprint() {
+
+ if ( $this->fingerprint !== null ) {
+ return $this->fingerprint;
+ }
+
+ $fingerprint = [];
+
+ // Filter equal signatures
+ foreach ( $this->descriptions as $description ) {
+ $fingerprint[$description->getFingerprint()] = true;
+ }
+
+ // Sorting to generate a constant fingerprint independent of its
+ // position within a conjunction ( [Foo]][[Bar]], [[Bar]][[Foo]])
+ ksort( $fingerprint );
+
+ return $this->fingerprint = 'C:' . md5( implode( '|', array_keys( $fingerprint ) ) );
+ }
+
+ public function getDescriptions() {
+ return $this->descriptions;
+ }
+
+ public function addDescription( Description $description ) {
+
+ $this->fingerprint = null;
+
+ if ( ! ( $description instanceof ThingDescription ) ) {
+ if ( $description instanceof Conjunction ) { // absorb sub-conjunctions
+ foreach ( $description->getDescriptions() as $subdesc ) {
+ $this->descriptions[$subdesc->getFingerprint()] = $subdesc;
+ }
+ } else {
+ $this->descriptions[$description->getFingerprint()] = $description;
+ }
+
+ // move print descriptions downwards
+ ///TODO: This may not be a good solution, since it does modify $description and since it does not react to future changes
+ $this->m_printreqs = array_merge( $this->m_printreqs, $description->getPrintRequests() );
+ $description->setPrintRequests( [] );
+ }
+
+ $fingerprint = $this->getFingerprint();
+
+ foreach ( $this->descriptions as $description ) {
+ $description->setMembership( $fingerprint );
+ }
+ }
+
+ public function getQueryString( $asvalue = false ) {
+ $result = '';
+
+ foreach ( $this->descriptions as $desc ) {
+ $result .= ( $result ? ' ' : '' ) . $desc->getQueryString( false );
+ }
+
+ if ( $result === '' ) {
+ return $asvalue ? '+' : '';
+ }
+
+ // <q> not needed for stand-alone conjunctions (AND binds stronger than OR)
+ return $asvalue ? " <q>{$result}</q> " : $result;
+ }
+
+ public function isSingleton() {
+ foreach ( $this->descriptions as $d ) {
+ if ( $d->isSingleton() ) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public function getSize() {
+ $size = 0;
+
+ foreach ( $this->descriptions as $desc ) {
+ $size += $desc->getSize();
+ }
+
+ return $size;
+ }
+
+ public function getDepth() {
+ $depth = 0;
+
+ foreach ( $this->descriptions as $desc ) {
+ $depth = max( $depth, $desc->getDepth() );
+ }
+
+ return $depth;
+ }
+
+ public function getQueryFeatures() {
+ $result = SMW_CONJUNCTION_QUERY;
+
+ foreach ( $this->descriptions as $desc ) {
+ $result = $result | $desc->getQueryFeatures();
+ }
+
+ return $result;
+ }
+
+ public function prune( &$maxsize, &$maxdepth, &$log ) {
+ if ( $maxsize <= 0 ) {
+ $log[] = $this->getQueryString();
+ return new ThingDescription();
+ }
+
+ $prunelog = [];
+ $newdepth = $maxdepth;
+ $result = new Conjunction();
+
+ foreach ( $this->descriptions as $desc ) {
+ $restdepth = $maxdepth;
+ $result->addDescription( $desc->prune( $maxsize, $restdepth, $prunelog ) );
+ $newdepth = min( $newdepth, $restdepth );
+ }
+
+ if ( count( $result->getDescriptions() ) > 0 ) {
+ $log = array_merge( $log, $prunelog );
+ $maxdepth = $newdepth;
+
+ if ( count( $result->getDescriptions() ) == 1 ) { // simplify unary conjunctions!
+ $descriptions = $result->getDescriptions();
+ $result = array_shift( $descriptions );
+ }
+
+ $result->setPrintRequests( $this->getPrintRequests() );
+
+ return $result;
+ } else {
+ $log[] = $this->getQueryString();
+
+ $result = new ThingDescription();
+ $result->setPrintRequests( $this->getPrintRequests() );
+
+ return $result;
+ }
+ }
+
+}