',$statement->getSubject(),'');
+ $this->infRules[]=$infRule;
+ $this->_addInfRule($infRule,$statementPosition);
+ break;
+
+ case OWL_URI.OWL_SAME_AS :
+ $infRule=new InfRule();
+ $infRule->setTrigger($statement->getSubject(),null,null);
+ $infRule->setEntailment($statement->getObject(),'','');
+ $this->_addInfRule($infRule,$statementPosition);
+
+ $infRule=new InfRule();
+ $infRule->setTrigger($statement->getObject(),null,null);
+ $infRule->setEntailment($statement->getSubject(),'','');
+ $this->_addInfRule($infRule,$statementPosition);
+
+ $infRule=new InfRule();
+ $infRule->setTrigger(null,$statement->getSubject(),null);
+ $infRule->setEntailment('',$statement->getObject(),'');
+ $this->_addInfRule($infRule,$statementPosition);
+
+ $infRule=new InfRule();
+ $infRule->setTrigger(null,$statement->getObject(),null);
+ $infRule->setEntailment('',$statement->getSubject(),'');
+ $this->_addInfRule($infRule,$statementPosition);
+
+ $infRule=new InfRule();
+ $infRule->setTrigger(null,null,$statement->getSubject());
+ $infRule->setEntailment('','',$statement->getObject());
+ $this->_addInfRule($infRule,$statementPosition);
+
+ $infRule=new InfRule();
+ $infRule->setTrigger(null,null,$statement->getObject());
+ $infRule->setEntailment('','
',$statement->getSubject());
+ $this->_addInfRule($infRule,$statementPosition);
+ break;
+ };
+ }
+
+ /**
+ * This function checks, which infrules were added by the statement and
+ * removes those.
+ *
+ * @param object Statement $statement
+ * @return integer
+ * @access private
+ */
+ function _removeFromInference($statement)
+ {
+ $return= array();
+ $statementPosition=-1;
+ do
+ {
+ //get the position of the statement that should be removed
+ $statementPosition=$this->findFirstMatchOff($statement->getSubject(),
+ $statement->getPredicate(),
+ $statement->getObject(),
+ $statementPosition+1);
+ if ($statementPosition!=-1)
+ {
+ //if it added any rules
+ if (isset ($this->statementRuleIndex[$statementPosition]))
+ {
+ //remove all rules
+ foreach ($this->statementRuleIndex[$statementPosition] as $key => $value)
+ {
+ //remove from Rule-Trigger Index
+ if (is_a($this,'InfModelF'))
+ {
+ $trigger=$this->infRules[$key]->getTrigger();
+
+ if(is_a($trigger['s'],'Node'))
+ {
+ $subjectLabel=$trigger['s']->getLabel();
+ } else
+ {
+ $subjectLabel='null';
+ }
+ unset ($this->infRulesTriggerIndex['s'][$subjectLabel][array_search($key,$this->infRulesTriggerIndex['s'][$subjectLabel])]);
+
+ if(is_a($trigger['p'],'Node'))
+ {
+ $predicateLabel=$trigger['p']->getLabel();
+ } else
+ {
+ $predicateLabel='null';
+ }
+ unset ($this->infRulesTriggerIndex['p'][$predicateLabel][array_search($key,$this->infRulesTriggerIndex['p'][$predicateLabel])]);
+
+ if(is_a($trigger['o'],'Node'))
+ {
+ $objectLabel=$trigger['o']->getLabel();
+ } else
+ {
+ $objectLabel='null';
+ }
+ unset ($this->infRulesTriggerIndex['o'][$objectLabel][array_search($key,$this->infRulesTriggerIndex['o'][$objectLabel])]);
+ } else
+ //remove from Rule-Entailment Index
+ {
+ $entailment=$this->infRules[$key]->getEntailment();
+
+ if(is_a($entailment['s'],'Node'))
+ {
+ $subjectLabel=$entailment['s']->getLabel();
+ } else
+ {
+ $subjectLabel='null';
+ }
+ unset ($this->infRulesEntailIndex['s'][$subjectLabel][array_search($key,$this->infRulesEntailIndex['s'][$subjectLabel])]);
+
+
+ if(is_a($entailment['p'],'Node'))
+ {
+ $predicateLabel=$entailment['p']->getLabel();
+ } else
+ {
+ $predicateLabel='null';
+ }
+ unset ($this->infRulesEntailIndex['p'][$predicateLabel][array_search($key,$this->infRulesEntailIndex['p'][$predicateLabel])]);
+
+ if(is_a($entailment['o'],'Node'))
+ {
+ $objectLabel=$entailment['o']->getLabel();
+ } else
+ {
+ $objectLabel='null';
+ }
+ unset ($this->infRulesEntailIndex['o'][$objectLabel][array_search($key,$this->infRulesEntailIndex['o'][$objectLabel])]);
+ }
+ //remove from statement-Rule Index
+ unset ($this->infRules[$key]);
+ }
+ unset($this->statementRuleIndex[$statementPosition]);
+ $return[]=$statementPosition;
+ };
+ }
+
+ } while($statementPosition!=-1);
+
+ //return the positions of the statements to be removed OR emty array
+ //if nothing was found.
+ return $return;
+ }
+
+ /**
+ * Returns a model, containing all Statements, having a Predicate, that
+ * is supported by the inference.
+ *
+ * @return object Model
+ * @access public
+ */
+ function getSchema()
+ {
+ $res=new MemModel();
+ //Search the base-model for all statements, having a Predicate, that
+ //is supported by the inference.
+ foreach ($this->supportedInference as $inferencePredicateLabel)
+ {
+ $res->addModel($this->find(null, new Resource($inferencePredicateLabel), null));
+ }
+ return $res;
+ }
+
+ /**
+ * General method to replace nodes of a MemModel.
+ * This function is disabled in the Inference Model.
+ *
+ * @param object Node $subject
+ * @param object Node $predicate
+ * @param object Node $object
+ * @param object Node $replacement
+ * @access public
+ * @throws PhpError
+ */
+ function replace($subject, $predicate, $object, $replacement)
+ {
+
+ $errmsg = RDFAPI_ERROR . '(class: InfModel; method: replace): This function is disabled in the Inference Model';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ /**
+ * Method to search for triples using Perl-style regular expressions.
+ * NULL input for any parameter will match anything.
+ * Example: $result = $m->find_regex( NULL, NULL, $regex );
+ * Finds all triples where the label of the object node matches the regular
+ * expression.
+ * Returns an empty MemModel if nothing is found.
+ *
+ * This function is disabled in the Inference Model
+ *
+ * @param string $subject_regex
+ * @param string $predicate_regex
+ * @param string $object_regex
+ * @return object MemModel
+ * @access public
+ */
+ function findRegex($subject_regex, $predicate_regex, $object_regex)
+ {
+
+ $errmsg = RDFAPI_ERROR . '(class: InfModel; method: findRegex):
+ This function is disabled in the
+ Inference Model';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ /**
+ * Returns all tripels of a certain vocabulary.
+ * $vocabulary is the namespace of the vocabulary inluding a # : / char at
+ * the end.
+ * e.g. http://www.w3.org/2000/01/rdf-schema#
+ * Returns an empty MemModel if nothing is found.
+ *
+ * This function is disabled in the Inference Model.
+ *
+ * @param string $vocabulary
+ * @return object MemModel
+ * @access public
+ */
+ function findVocabulary($vocabulary)
+ {
+
+ $errmsg = RDFAPI_ERROR . '(class: InfModel; method: findVocabulary):
+ This function is disabled in the
+ Inference Model';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+
+ /**
+ * Adds the URI or NULL to the Infrule trigger or entailment index.
+ *
+ *
+ * @param object infrule $infRule
+ * @param integer $infRulePosition
+ * @access private
+ */
+ function _addInfruleToIndex(& $infRule,& $infRulePosition)
+ {
+ //Add the rule only to the trigger index, if it is a InfFModel
+ if (is_a($this,'InfModelF'))
+ {
+ //get the trigger
+ $trigger = $infRule->getTrigger();
+ //evaluate and set the index
+ if ($trigger['s'] == null)
+ {
+ $this->infRulesTriggerIndex['s']['null'][]=$infRulePosition;
+ } else
+ {
+ $this->infRulesTriggerIndex['s'][$trigger['s']->getLabel()][]=$infRulePosition;
+ };
+
+ if ($trigger['p'] == null)
+ {
+ $this->infRulesTriggerIndex['p']['null'][]=$infRulePosition;
+ } else
+ {
+ $this->infRulesTriggerIndex['p'][$trigger['p']->getLabel()][]=$infRulePosition;
+ };
+
+ if ($trigger['o'] == null)
+ {
+ $this->infRulesTriggerIndex['o']['null'][]=$infRulePosition;
+ } else
+ {
+ $this->infRulesTriggerIndex['o'][$trigger['o']->getLabel()][]=$infRulePosition;
+ };
+ } else
+ //add to entailment Index if it is a BModel
+ {
+ //get the entailment
+ $entailment = $infRule->getEntailment();
+ //evaluate the entailment and add to index
+ if (!is_a($entailment['s'],'Node'))
+ {
+ $this->infRulesEntailIndex['s']['null'][]=$infRulePosition;
+ } else
+ {
+ $this->infRulesEntailIndex['s'][$entailment['s']->getLabel()][]=$infRulePosition;
+ };
+
+ if (!is_a($entailment['p'],'Node'))
+ {
+ $this->infRulesEntailIndex['p']['null'][]=$infRulePosition;
+ } else
+ {
+ $this->infRulesEntailIndex['p'][$entailment['p']->getLabel()][]=$infRulePosition;
+ };
+
+ if (!is_a($entailment['o'],'Node'))
+ {
+ $this->infRulesEntailIndex['o']['null'][]=$infRulePosition;
+ } else
+ {
+ $this->infRulesEntailIndex['o'][$entailment['o']->getLabel()][]=$infRulePosition;
+ };
+ };
+ }
+
+ /**
+ * Searches the trigger-index for a matching trigger and returns an
+ * array of infRule positions.
+ *
+ *
+ * @param object infrule $infRule
+ * @return array integer
+ * @access private
+ */
+ function _findRuleTriggerInIndex($statement)
+ {
+ $return=array();
+ //a statement's subject matches all triggers with null and the same URI
+ $subjectLabel=$statement->getLabelSubject();
+ $inIndexS=array();
+ if (isset($this->infRulesTriggerIndex['s']['null']))
+ $inIndexS=array_values($this->infRulesTriggerIndex['s']['null']);
+ if (isset($this->infRulesTriggerIndex['s'][$subjectLabel]))
+ $inIndexS= array_merge($inIndexS,array_values($this->infRulesTriggerIndex['s'][$subjectLabel]));
+
+ //a statement's predicate matches all triggers with null and the same URI
+ $predicateLabel=$statement->getLabelPredicate();
+ $inIndexP=array();
+ if (isset($this->infRulesTriggerIndex['p']['null']))
+ $inIndexP=array_values($this->infRulesTriggerIndex['p']['null']);
+ if (isset($this->infRulesTriggerIndex['p'][$predicateLabel]))
+ $inIndexP= array_merge($inIndexP,array_values($this->infRulesTriggerIndex['p'][$predicateLabel]));
+
+ //a statement's object matches all triggers with null and the same URI
+ $objectLabel=$statement->getLabelObject();
+ $inIndexO=array();
+ if (isset($this->infRulesTriggerIndex['o']['null']))
+ $inIndexO=array_values($this->infRulesTriggerIndex['o']['null']);
+ if (isset($this->infRulesTriggerIndex['o'][$objectLabel]))
+ $inIndexO= array_merge($inIndexO,array_values($this->infRulesTriggerIndex['o'][$objectLabel]));
+
+ //if an infrule position occurs in subject, predicate, and object index, add to result array.
+ foreach ($inIndexP as $positionP)
+ {
+ if (in_array($positionP,$inIndexO))
+ if (in_array($positionP,$inIndexS))
+ $return[]=$positionP;
+ }
+ return $return;
+ }
+
+ /**
+ * Searches the Entailment-index for a matching Entailment and returns an
+ * array of infRule positions.
+ *
+ *
+ * @param node or null $subject
+ * @param node or null $predicate
+ * @param node or null $object
+ * @return array integer
+ * @access private
+ */
+ function _findRuleEntailmentInIndex($subject,$predicate,$object)
+ {
+ $return=array();
+ //a node matches all entailments with NULL or a matching URI
+ if(is_a($subject,'Node'))
+ {
+ $subjectLabel=$subject->getLabel();
+ $inIndexS=array();
+ if (isset($this->infRulesEntailIndex['s']['null'])) $inIndexS=array_values($this->infRulesEntailIndex['s']['null']);
+ if (isset($this->infRulesEntailIndex['s'][$subjectLabel])) $inIndexS= array_merge($inIndexS,array_values($this->infRulesEntailIndex['s'][$subjectLabel]));
+ } else
+ //if the subject search pattern is NULL, every rule will match the subject search patter
+ {
+ $inIndexS=array_keys($this->infRules);
+ }
+
+ if(is_a($predicate,'Node'))
+ {
+ $predicateLabel=$predicate->getLabel();
+ $inIndexP=array();
+ if (isset($this->infRulesEntailIndex['p']['null'])) $inIndexP=array_values($this->infRulesEntailIndex['p']['null']);
+ if (isset($this->infRulesEntailIndex['p'][$predicateLabel])) $inIndexP= array_merge($inIndexP,array_values($this->infRulesEntailIndex['p'][$predicateLabel]));
+ } else
+ {
+ $inIndexP=array_keys($this->infRules);
+ }
+
+ if(is_a($object,'Node'))
+ {
+ $objectLabel=$object->getLabel();
+ $inIndexO=array();
+ if (isset($this->infRulesEntailIndex['o']['null'])) $inIndexO=array_values($this->infRulesEntailIndex['o']['null']);
+ if (isset($this->infRulesEntailIndex['o'][$objectLabel])) $inIndexO= array_merge($inIndexO,array_values($this->infRulesEntailIndex['o'][$objectLabel]));
+ } else
+ {
+ $inIndexO=array_keys($this->infRules);
+ }
+
+ //if an infrule position occurs in subject, predicate, and object index, add to result array.
+ foreach ($inIndexP as $positionP)
+ {
+ if (in_array($positionP,$inIndexO))
+ if (in_array($positionP,$inIndexS))
+ $return[]=$positionP;
+ }
+ return $return;
+ }
+
+ /**
+ * Adds an InfRule to the InfModel.
+ * $statementPosition states the positiion of the statement, that created
+ * this rule, in the model->triples array.
+ *
+ *
+ * @param object Infrule $infRule
+ * @param integer $statementPosition
+ * @access private
+ */
+ function _addInfRule($infRule, $statementPosition)
+ {
+ //add the rule
+ $this->infRules[]=$infRule;
+ //get the position of the added rule in the model
+ end($this->infRules);
+ $rulePosition=key($this->infRules);
+ //add the information to the index, that this statement
+ //added this rule.
+ $this->statementRuleIndex[$statementPosition][$rulePosition]=true;
+ //add informations to index over trigger & entailment
+ $this->_addInfruleToIndex($infRule,$rulePosition);
+ }
+ }
+?>
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/infModel/.svn/text-base/InfModelB.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/infModel/.svn/text-base/InfModelB.php.svn-base
new file mode 100755
index 00000000..1abaa989
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/infModel/.svn/text-base/InfModelB.php.svn-base
@@ -0,0 +1,515 @@
+
+
+*
+* @package infModel
+* @access public
+**/
+
+class InfModelB extends InfModel
+{
+
+ /**
+ * Array that holds combinations of inference rules with distinct
+ * find-querys, that don't lead to any inference.
+ *
+ * @var array
+ * @access private
+ */
+ var $findDeadEnds;
+
+
+ /**
+ * Constructor
+ * You can supply a base_uri
+ *
+ * @param string $baseURI
+ * @access public
+ */
+ function InfModelB($baseURI = null)
+ {
+ parent::InfModel($baseURI);
+ $this->findDeadEnds=array();
+ }
+
+ /**
+ * Adds a new triple to the Model without checking, if the statement
+ * is already in the Model. So if you want a duplicate free Model use
+ * the addWithoutDuplicates() function (which is slower then add())
+ *
+ * @param object Statement $statement
+ * @access public
+ * @throws PhpError
+ */
+ function add($statement)
+ {
+ parent::add($statement);
+ //Reset the found dead-ends.
+ $this->findDeadEnds=array();
+ }
+
+ /**
+ * General method to search for triples.
+ * NULL input for any parameter will match anything.
+ * Example: $result = $m->find( NULL, NULL, $node );
+ * Finds all triples with $node as object.
+ * Returns an empty MemModel if nothing is found.
+ * To improve the search speed with big Models, call index(INDEX_TYPE)
+ * before seaching.
+ *
+ * It recursively searches in the statements and rules to find
+ * matching statements.
+ *
+ * @param object Node $subject
+ * @param object Node $predicate
+ * @param object Node $object
+ * @return object MemModel
+ * @access public
+ * @throws PhpError
+ */
+ function find($subject,$predicate,$object)
+ {
+ $searchStringIndex=array();
+ $resultModel=new MemModel();
+
+ //add all infered statements without duplicates to the result model
+ foreach ($this->_infFind($subject,$predicate,$object,array())as $statement)
+ {
+ $resultModel->addWithoutDuplicates($statement);
+ };
+ return $resultModel;
+ }
+
+ /**
+ * This is the main inference method of the InfModelB
+ * The algorithm works as follows:
+ * Find all statements in the base model, that matches the current
+ * find-query.
+ * Check all rules, if they are able to deliver infered statements,
+ * that match the current find-query. Don't use rules with queries,
+ * that lead to dead-ends and don't use a rule-query-combination that
+ * was used before in this branch (ontology loops).
+ * If a rule is possible do deliver such statements, get a new
+ * find-query, that is possible to find those statements, that are able
+ * to trigger this rule.
+ * Call this _infFind method wirh the new find-query and entail the
+ * resulting statements.
+ * If this rule, wasn't able to return any statements with this distinct
+ * query, add this combination to the dead-ends.
+ * Return the statements from the base triples and those, which were infered.
+ *
+ * If $findOnlyFirstMatching is set to true, only the first match in
+ * the base-statements is entailed an returned (used in contains() and
+ * findFirstMatchingStatement() methods).
+ *
+ * You can set an offset to look for the first matching statement by setting the
+ * $offset var.
+ *
+ * It recursively searches in the statements and rules to find matching
+ * statements
+ *
+ * @param object Node $subject
+ * @param object Node $predicate
+ * @param object Node $object
+ * @param array $searchStringIndex
+ * @param boolean $findOnlyFirstMatching
+ * @param integer $offset
+ * @param integer $resultCount
+ * @return object array Statements
+ * @access private
+ */
+ function _infFind ($subject,$predicate,$object, $searchStringIndex, $findOnlyFirstMatching = false, $offset = 0,$resultCount = 0 )
+ {
+ $return=array();
+ //Find all matching statements in the base statements
+ $findResult=parent::find($subject,$predicate,$object);
+ //For all found statements
+ foreach ($findResult->triples as $statement)
+ {
+ $return[]=$statement;
+ $resultCount++;
+
+ //Return, if only the firstMatchingStatement was wanted
+ if ($findOnlyFirstMatching && $resultCount > $offset)
+ return $return;
+ };
+
+ //Don't infer statements about the schema (rdfs:subClass, etc..)
+ //is false
+ if ($predicate == null ||
+ (is_a($predicate,'Node') &&
+ !in_array($predicate->getLabel(),$this->supportedInference))
+ )
+ //Check only Rules, that the EntailmentIndex returned.
+ foreach ($this->_findRuleEntailmentInIndex($subject,$predicate,$object) as $ruleKey)
+ {
+ $infRule=$this->infRules[$ruleKey];
+ $serializedRuleStatement=$ruleKey.serialize($subject).serialize($predicate).serialize($object);
+ //If it is to ontology loop and no dead-end
+ if (!in_array($serializedRuleStatement, $searchStringIndex) &&
+ !in_array($serializedRuleStatement, $this->findDeadEnds))
+ {
+ //Keep this distinct rule query cobination for
+ //this branch to detect loops
+ $searchStringIndex[]=$serializedRuleStatement;
+
+ //If the rule is able to deliver statements that match
+ //this query
+ if ($infRule->checkEntailment($subject,$predicate,$object))
+ {
+ //Get a modified find-query, that matches statements,
+ //that trigger this rule
+ $modefiedFind=$infRule->getModifiedFind($subject,$predicate,$object);
+ //Call this method with the new find-query
+ $infFindResult=$this->_infFind($modefiedFind['s'],
+ $modefiedFind['p'],
+ $modefiedFind['o'],
+ $searchStringIndex,
+ $findOnlyFirstMatching,
+ $offset,
+ $resultCount) ;
+ //If it deliverd statements that matches the trigger
+ if (isset($infFindResult[0]))
+ {
+ foreach ($infFindResult as $statement)
+ {
+ //Entail the statements and check, if they are not about the
+ //ontology
+ $newStatement=$infRule->entail($statement);
+ if (!in_array($newStatement->getLabelPredicate(),$this->supportedInference))
+ //Check if, the entailed statements are, what we are looking for
+ if($this->_nodeEqualsFind($subject,$newStatement->getSubject()) &&
+ $this->_nodeEqualsFind($predicate,$newStatement->getPredicate()) &&
+ $this->_nodeEqualsFind($object,$newStatement->getObject() ) )
+ {
+ //Add to results
+ $return[]=$newStatement;
+ $resultCount++;
+
+ //or return at once
+ if ($findOnlyFirstMatching && $resultCount > $offset)
+ return $return;
+ }
+ }
+ } else
+ {
+ //If there were no results of the rule-query-combination,
+ //mark this combination as a dead-end.
+ $this->findDeadEnds[]=$serializedRuleStatement;
+ }
+ }
+ }
+ }
+ //Return the array of the found statements
+ return $return;
+ }
+
+ /**
+ * Tests if the Model contains the given triple.
+ * TRUE if the triple belongs to the Model;
+ * FALSE otherwise.
+ *
+ * @param object Statement &$statement
+ * @return boolean
+ * @access public
+ */
+ function contains(&$statement)
+ {
+ //throws an error, if $statement is not of class Statement
+ if(!is_a($statement,'Statement'))
+ trigger_error(RDFAPI_ERROR . '(class: InfModelB; method: contains):
+ $statement has to be object of class Statement', E_USER_ERROR);
+
+ //Call the _infFind method, but let it stop, if it finds the first match.
+ if (count( $this->_infFind($statement->getSubject(),
+ $statement->getPredicate(),
+ $statement->getObject(),
+ array(),true) ) >0)
+ {
+ return true;
+ } else
+ {
+ return false;
+ };
+ }
+
+ /**
+ * Searches for triples and returns the first matching statement.
+ * NULL input for any parameter will match anything.
+ * Example: $result = $m->findFirstMatchingStatement( NULL, NULL, $node );
+ * Returns the first statement of the MemModel where the object equals $node.
+ * Returns an NULL if nothing is found.
+ * You can define an offset to search for. Default = 0
+ *
+ * @param object Node $subject
+ * @param object Node $predicate
+ * @param object Node $object
+ * @param integer $offset
+ * @return object Statement
+ * @access public
+ */
+ function findFirstMatchingStatement($subject, $predicate, $object, $offset = 0)
+ {
+ //Call the _infFind method, but let it stop, if it finds the
+ //first match.
+ $res= $this->_infFind($subject,$predicate,$object,array(),true,$offset);
+
+ if (isset($res[$offset]))
+ {
+ return $res[$offset];
+ } else
+ {
+ return NULL;
+ };
+ }
+
+ /**
+ * Returns a StatementIterator for traversing the Model.
+ *
+ * @access public
+ * @return object StatementIterator
+ */
+ function & getStatementIterator()
+ {
+ // Import Package Utility
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_UTILITY);
+ // Gets a MemModel by executing a find(null,null,null) to get a
+ //inferable statements.
+ // WARNING: might be slow
+ return new StatementIterator($this->getMemModel());
+ }
+
+ /**
+ * Number of all inferable triples in the Model.
+ * WARNING: uses a find(null,null,null) to find all statements! (might take a while)
+ *
+ * @param boolean
+ * @return integer
+ * @access public
+ */
+ function size()
+ {
+ // Gets a MemModel by executing a find(null,null,null) to get a
+ //inferable statements.
+ // WARNING: might be slow
+ $res = $this->getMemModel();
+ return $res->size();
+ }
+
+ /**
+ * Create a MemModel containing all the triples (including inferred
+ * statements) of the current InfModelB.
+ *
+ * @return object MemModel
+ * @access public
+ */
+ function & getMemModel()
+ {
+
+ $return=$this->find(null,null,null);
+ $return->setBaseURI($this->baseURI);
+ $return->addParsedNamespaces($this->getParsedNamespaces());
+ return $return;
+ }
+
+ /**
+ * Create a MemModel containing only the base triples (without inferred
+ * statements) of the current InfModelB.
+ *
+ * @return object MemModel
+ * @access public
+ */
+ function & getBaseMemModel()
+ {
+ $return= new MemModel();
+ $return->setBaseURI($this->baseURI);
+ foreach ($this->triples as $statement)
+ $return->add($statement);
+
+ $retun->addParsedNamespaces($this->getParsedNamespaces());
+ return $return;
+ }
+
+ /**
+ * Short Dump of the InfModelB.
+ *
+ * @access public
+ * @return string
+ */
+ function toString()
+ {
+ return 'InfModelB[baseURI=' . $this->getBaseURI() . '; size=' . $this->size(true) . ']';
+ }
+
+ /**
+ * Dumps of the InfModelB including ALL inferable triples.
+ *
+ * @access public
+ * @return string
+ */
+ function toStringIncludingTriples()
+ {
+ $dump = $this->toString() . chr(13);
+ $stateIt=new StatementIterator($this->find(null,null,null));
+ while($statement=$stateIt->next())
+ {
+ $dump .= $statement->toString() . chr(13);
+ }
+ return $dump;
+ }
+
+ /**
+ * Saves the RDF,N3 or N-Triple serialization of the full InfModelB
+ * (including inferred triples) to a file.
+ * You can decide to which format the model should be serialized by
+ * using a corresponding suffix-string as $type parameter. If no $type
+ * parameter is placed this method will serialize the model to XML/RDF
+ * format.
+ * Returns FALSE if the InfModelB couldn't be saved to the file.
+ *
+ * @access public
+ * @param string $filename
+ * @param string $type
+ * @throws PhpError
+ * @return boolean
+ */
+ function saveAs($filename, $type ='rdf')
+ {
+
+ $memmodel=$this->getMemModel();
+ return $memmodel->saveAs($filename, $type);
+ }
+
+ /**
+ * Writes the RDF serialization of the Model including ALL inferable
+ * triples as HTML.
+ *
+ * @access public
+ */
+ function writeAsHtml()
+ {
+ require_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_RDF);
+ $ser = new RdfSerializer();
+ $rdf =& $ser->serialize($this->getMemModel());
+ $rdf = htmlspecialchars($rdf, ENT_QUOTES);
+ $rdf = str_replace(' ', ' ', $rdf);
+ $rdf = nl2br($rdf);
+ echo $rdf;
+ }
+
+ /**
+ * Writes the RDF serialization of the Model including ALL inferable
+ * triples as HTML table.
+ *
+ * @access public
+ */
+ function writeAsHtmlTable()
+ {
+ // Import Package Utility
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_UTILITY);
+ RDFUtil::writeHTMLTable($this->getMemModel());
+ }
+
+
+ /**
+ * Writes the RDF serialization of the Model including ALL inferable
+ * triples.
+ *
+ * @access public
+ * @return string
+ */
+ function writeRdfToString()
+ {
+ // Import Package Syntax
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_RDF);
+ $ser = new RdfSerializer();
+ $rdf =& $ser->serialize($this->getMemModel());
+ return $rdf;
+ }
+
+ /**
+ * Removes the triple from the MemModel.
+ * TRUE if the triple is removed.
+ * FALSE otherwise.
+ *
+ * Checks, if it touches any statements, that added inference rules
+ * to the model.
+ *
+ * @param object Statement $statement
+ * @return boolean
+ * @access public
+ * @throws PhpError
+ */
+ function remove($statement)
+ {
+ if (parent::contains($statement))
+ {
+ if (in_array($statement->getLabelPredicate(),$this->supportedInference));
+ while (count($this->_removeFromInference($statement))>0);
+
+ $this->findDeadEnds=array();
+ return parent::remove($statement);
+ } else
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Checks, if a single node matches a single find pattern.
+ * TRUE if the node matches.
+ * FALSE otherwise.
+ *
+ * Checks, if it touches any statements, that added inference rules
+ * to the model.
+ *
+ * @param object Statement $statement
+ * @return boolean
+ * @access private
+ */
+ function _nodeEqualsFind(& $find, $node)
+ {
+ //If the find pattern is a node, use the nodes equal-method and
+ //return the result.
+ if (is_a($find,'Node'))
+ return $node->equals($find);
+
+ //Null-pattern matches anything.
+ if ($find == null)
+ {
+ return true;
+ } else
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Returns a FindIterator for traversing the MemModel.
+ * Disabled in InfModelB.
+ *
+ * @access public
+ * @return object FindIterator
+ */
+ function & findAsIterator($sub=null,$pred=null,$obj=null) {
+ $errmsg = RDFAPI_ERROR . '(class: InfModelB; method: findAsIterator):
+ This function is disabled in the
+ Inference Model';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/infModel/.svn/text-base/InfModelF.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/infModel/.svn/text-base/InfModelF.php.svn-base
new file mode 100755
index 00000000..fe74c85e
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/infModel/.svn/text-base/InfModelF.php.svn-base
@@ -0,0 +1,406 @@
+
+
+*
+* @package infModel
+* @access public
+**/
+
+class InfModelF extends InfModel
+{
+
+ /**
+ * Array that holds the position of the infered statements in the model.
+ *
+ * @var array
+ * @access private
+ */
+ var $infPos;
+
+
+ /**
+ * Variable that influences the habbit when adding statements.
+ * Used by the loadModel method to increase performance.
+ *
+ * @var boolean
+ * @access private
+ */
+ var $inferenceEnabled;
+
+
+ /**
+ * Constructor
+ * You can supply a base_uri.
+ *
+ * @param string $baseURI
+ * @access public
+ */
+ function InfModelF($baseURI = NULL)
+ {
+ parent::InfModel($baseURI);
+ $this->infPos=array();
+ $this->inferenceEnabled=true;
+ }
+
+ /**
+ * Adds a new triple to the MemModel without checking if the statement
+ * is already in the MemModel.
+ * So if you want a duplicate free MemModel use the addWithoutDuplicates()
+ * function (which is slower then add())
+ * The statement is infered and all entailed statements are added.
+ *
+ * @param object Statement $statement
+ * @access public
+ * @throws PhpError
+ */
+ function add ($statement)
+ {
+ parent::add($statement);
+ if ($this->inferenceEnabled)
+ {
+ foreach ($this->entailStatement($statement) as $state)
+ {
+ //a addWithoutDublicates construct
+ if(!$this->contains($state))
+ {
+
+ parent::add($state);
+ //save the position of the infered statements
+ end($this->triples);
+ $this->infPos[]=key($this->triples);
+ };
+ };
+ //apply the complete inference to the model, if the added statement was able to add a rule
+ if (in_array($statement->getLabelPredicate(),$this->supportedInference))
+ $this->applyInference();
+ }
+ }
+
+
+ /**
+ * Checks if a new statement is already in the MemModel and adds
+ * the statement, if it is not in the MemModel.
+ * addWithoutDuplicates() is significantly slower then add().
+ * Retruns TRUE if the statement is added.
+ * FALSE otherwise.
+ * The statement is infered and all entailed statements are added.
+ *
+ * @param object Statement $statement
+ * @return boolean
+ * @access public
+ * @throws PhpError
+ */
+ function addWithoutDuplicates(& $statement)
+ {
+ if(!$this->contains($statement))
+ {
+ parent::add($statement);
+ if ($this->inferenceEnabled)
+ {
+ foreach ($this->entailStatement($statement) as $statement)
+ {
+ if(!$this->contains($statement))
+ {
+ parent::add($statement);
+ //save the position of the infered statements
+ end($this->triples);
+ $this->infPos[]=key($this->triples);
+ };
+ };
+ if (in_array($statement->getLabelPredicate(),$this->supportedInference))
+ $this->applyInference();
+ }
+ return true;
+ }
+ return false;
+ }
+
+
+
+ /**
+ * Entails every statement and adds the entailments if not already
+ * in the model.
+ *
+ * @access private
+ */
+ function applyInference()
+ {
+ //check every statement in the model
+ foreach ($this->triples as $statement)
+ {
+ //gat all statements, that it recursively entails
+ foreach ($this->entailStatement($statement) as $statement)
+ {
+ if (!$this->contains($statement))
+ {
+ parent::add($statement);
+ //add the InfStatement position to the index
+ end($this->triples);
+ $this->infPos[]=key($this->triples);
+ };
+ };
+ };
+ }
+
+
+ /**
+ * Entails a statement by recursively using the _entailStatementRec
+ * method.
+ *
+ * @param object Statement $statement
+ * @return array of statements
+ * @access public
+ */
+ function entailStatement (& $statement)
+ {
+ $infStatementsIndex=array();
+ return $this->_entailStatementRec($statement,$infStatementsIndex);
+ }
+
+ /**
+ * Recursive method, that checks the statement with the trigger of
+ * every rule. If the trigger matches and entails new statements,
+ * those statements are recursively infered too.
+ * The $infStatementsIndex array holds lready infered statements
+ * to prevent infinite loops.
+ *
+ *
+ * @param object Statement $statement
+ * @param array $infStatementsIndex
+ * @return array of statements
+ * @access private
+ */
+ function _entailStatementRec ( $statement,& $infStatementsIndex)
+ {
+ $infStatements = array();
+ $return = array();
+
+ //dont entail statements about the supported inference-schema
+ if (!in_array($statement->getLabelPredicate(),$this->supportedInference))
+ {
+ //check only the rules, that were returned by the index
+ foreach ($this->_findRuleTriggerInIndex($statement) as $key )
+ {
+ $infRule=$this->infRules[$key];
+
+ $stateString=$key.serialize($statement);
+ //If the statement wasn't infered before
+ if (!in_array($stateString,$infStatementsIndex))
+ {
+ $infStatementsIndex[]=$stateString;
+ //Check, if the Statements triggers this rule
+ if($infRule->checkTrigger($statement))
+ {
+ $infStatement=$infRule->entail($statement);
+ #if(!$this->contains($infStatement))
+ {
+ $return[]=$infStatement;
+ $return=array_merge($return,
+ $this->_entailStatementRec($infStatement,
+ $infStatementsIndex));
+ };
+
+ };
+ };
+ };
+ };
+ return $return;
+ }
+
+ /**
+ * Removes all infered statements from the model but keeps the
+ * infernece rules.
+ *
+ * @access public
+ */
+ function removeInfered()
+ {
+ $indexTmp=$this->indexed;
+ $this->index(-1);
+ foreach ($this->infPos as $key)
+ {
+ unset($this->triples[$key]);
+ };
+ $this->infPos=array();
+ $this->index($indexTmp);
+ }
+
+
+ /**
+ * Load a model from a file containing RDF, N3 or N-Triples.
+ * This function recognizes the suffix of the filename (.n3 or .rdf) and
+ * calls a suitable parser, if no $type is given as string
+ * ("rdf" "n3" "nt");
+ * If the model is not empty, the contents of the file is added to
+ * this DbModel.
+ *
+ * While loading the model, the inference entailing is disabled, but
+ * new inference rules are added to increase performance.
+ *
+ * @param string $filename
+ * @param string $type
+ * @access public
+ */
+ function load($filename, $type = NULL)
+ {
+ //Disable entailing to increase performance
+ $this->inferenceEnabled=false;
+ parent::load($filename, $type);
+ //Enable entailing
+ $this->inferenceEnabled=true;
+ //Entail all statements
+ $this->applyInference();
+ }
+
+ /**
+ * Short Dump of the InfModelF.
+ *
+ * @access public
+ * @return string
+ */
+ function toString() {
+ return 'InfModelF[baseURI=' . $this->getBaseURI() . ';
+ size=' . $this->size(true) . ']';
+ }
+
+ /**
+ * Create a MemModel containing all the triples (including inferred
+ * statements) of the current InfModelF.
+ *
+ * @return object MemModel
+ * @access public
+ */
+ function & getMemModel()
+ {
+ $return= new MemModel();
+ $return->setBaseURI($this->baseURI);
+ foreach ($this->triples as $statement)
+ $return->add($statement);
+
+ $return->addParsedNamespaces($this->getParsedNamespaces());
+ return $return;
+ }
+
+ /**
+ * Create a MemModel containing only the base triples
+ * (without inferred statements) of the current InfModelF.
+ *
+ * @return object MemModel
+ * @access public
+ */
+ function getBaseMemModel()
+ {
+ $return= new MemModel();
+ $return->setBaseURI($this->baseURI);
+ foreach ($this->triples as $key => $statement)
+ if (!in_array($key,$this->infPos))
+ $return->add($statement);
+ $retun->addParsedNamespaces($this->getParsedNamespaces());
+ return $return;
+ }
+
+
+ /**
+ * Removes the triple from the MemModel.
+ * TRUE if the triple is removed.
+ * FALSE otherwise.
+ *
+ * Checks, if it touches any statements, that added inference rules
+ * to the model
+ *
+ * @param object Statement $statement
+ * @return boolean
+ * @access public
+ * @throws PhpError
+ */
+ function remove($statement)
+ {
+ //If the statement is in the model
+ if($this->contains($statement))
+ {
+ $inferenceRulesWereTouched=false;
+ //If the statement was able to add inference rules
+ if (in_array($statement->getLabelPredicate(),$this->supportedInference))
+ {
+ $statementPositions=$this->_removeFromInference($statement);
+ $inferenceRulesWereTouched=true;
+ } else
+ //get the position of all matching statements
+ {
+ $statementPositions=array();
+ //find the positions of the statements
+ $statementPosition=-1;
+ do
+ {
+
+ $statementPosition =
+ $this->findFirstMatchOff($statement->getSubject(),
+ $statement->getPredicate(),
+ $statement->getObject(),
+ $statementPosition+1);
+
+ if ($statementPosition!=-1)
+ $statementPositions[]=$statementPosition;
+
+ } while ($statementPosition != -1);
+ }
+
+ //remove matching statements
+ parent::remove($statement);
+ foreach ($statementPositions as $statementPosition)
+ {
+ //if the statement was infered, remove it from the index of the infered statements.
+ if (in_array($statementPosition,$this->infPos))
+ unset ($this->infPos[$statementPosition]);
+ }
+ if ($inferenceRulesWereTouched)
+ {
+ //remove the statement and re-entail the model
+ $this->removeInfered();
+ $this->applyInference();
+ }
+ return true;
+ } else
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Adds another model to this MemModel.
+ * Duplicate statements are not removed.
+ * If you don't want duplicates, use unite().
+ * If any statement of the model to be added to this model contains a blankNode
+ * with an identifier already existing in this model, a new blankNode is generated.
+ *
+ * @param object Model $model
+ * @access public
+ * @throws phpErrpr
+ *
+ */
+ function addModel(&$model)
+ {
+ //Disable entailing to increase performance
+ $this->inferenceEnabled=false;
+ parent::addModel($model);
+ //Enable entailing
+ $this->inferenceEnabled=true;
+ //Entail all statements
+ $this->applyInference();
+ }
+};
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/infModel/.svn/text-base/InfModelP.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/infModel/.svn/text-base/InfModelP.php.svn-base
new file mode 100755
index 00000000..7fefd7f0
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/infModel/.svn/text-base/InfModelP.php.svn-base
@@ -0,0 +1,19 @@
+
+//
+// ----------------------------------------------------------------------------------
+
+// Include InfModel classes
+require_once( RDFAPI_INCLUDE_DIR . 'infModel/InfRule.php');
+require_once( RDFAPI_INCLUDE_DIR . 'infModel/InfStatement.php');
+require_once( RDFAPI_INCLUDE_DIR . 'infModel/InfModel.php');
+require_once( RDFAPI_INCLUDE_DIR . 'infModel/InfModelB.php');
+require_once( RDFAPI_INCLUDE_DIR . 'infModel/InfModelF.php');
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/infModel/.svn/text-base/InfRule.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/infModel/.svn/text-base/InfRule.php.svn-base
new file mode 100755
index 00000000..eac153b7
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/infModel/.svn/text-base/InfRule.php.svn-base
@@ -0,0 +1,343 @@
+
+
+ *
+ * @package infModel
+ * @access public
+ **/
+
+class InfRule
+{
+
+ /**
+ * Array, that hold the trigger subject in key ['s'], the trigger
+ * predicate in ['p'], and the trigger object in ['o'].
+ * The array values can be NULL to match anything or be a node that
+ * has to be matched.
+ *
+ * @var array
+ * @access private
+ */
+ var $trigger;
+
+ /**
+ * Array, that hold the entailment subject in key ['s'], the
+ * entailment predicate in ['p'], and the entailment object in ['o'].
+ * The array values can be a node that will be inserted in the
+ * returning statement, or '' to insert the subject,'
' to insert
+ * the predicate, or '' to insert the object of the checked statement
+ * to this position in the new returned statement.
+ *
+ * @var array
+ * @access private
+ */
+ var $entailment;
+
+
+ /**
+ * Constructor
+ *
+ *
+ * @access public
+ */
+ function infRule()
+ {
+ //initialising vars
+ $this->trigger=array();
+ $this->entailment=array();
+ }
+
+ /**
+ * Sets the trigger of this rule
+ * The values can be NULL to match anything or be a node that has to
+ * be matched.
+ *
+ * @param object Node OR NULL $subject
+ * @param object Node OR NULL $predicate
+ * @param object Node OR NULL $object
+ * @access public
+ * @throws PhpError
+ */
+ function setTrigger ($subject, $predicate, $object)
+ {
+ //throw an error if subject, predicate, or object are neither
+ //node, nor null.
+ if(!is_a($subject,'Node') && $subject != null)
+ trigger_error(RDFAPI_ERROR . '(class: Infrule; method:
+ setTrigger): $subject has to be null or of class Node'
+ , E_USER_ERROR);
+ if(!is_a($predicate,'Node') && $predicate != null)
+ trigger_error(RDFAPI_ERROR . '(class: Infrule; method:
+ setTrigger): $predicate has to be null or of class Node'
+ , E_USER_ERROR);
+ if(!is_a($object,'Node') && $object != null)
+ trigger_error(RDFAPI_ERROR . '(class: Infrule; method:
+ setTrigger): $object has to be null or of class Node'
+ , E_USER_ERROR);
+
+ //set the trigger
+ $this->trigger['s']=$subject;
+ $this->trigger['p']=$predicate;
+ $this->trigger['o']=$object;
+ }
+
+ /**
+ * Sets the entailment of this rule
+ * The values can be NULL to match anything or be a node that has to
+ * be matched.
+ *
+ * @param object Node OR NULL $subject
+ * @param object Node OR NULL $predicate
+ * @param object Node OR NULL $object
+ * @access public
+ * @throws PhpError
+ */
+ function setEntailment($subject,$predicate,$object)
+ {
+ //throw an error if subject, predicate, or object are neither node,
+ //nor ,,.
+ if(!is_a($subject,'Node') && !ereg('<[spo]>', $subject))
+ trigger_error(RDFAPI_ERROR . '(class: Infrule; method:
+ setEntailment): $subject has to be ,,or or of class Node'
+ , E_USER_ERROR);
+ if(!is_a($predicate,'Node') && !ereg('<[spo]>', $predicate))
+ trigger_error(RDFAPI_ERROR . '(class: Infrule; method:
+ setEntailment): $predicate has to be ,,or or of class Node'
+ , E_USER_ERROR);
+ if(!is_a($object,'Node') && !ereg('<[spo]>', $object))
+ trigger_error(RDFAPI_ERROR . '(class: Infrule; method:
+ setEntailment): $object has to be ,,or or of class Node'
+ , E_USER_ERROR);
+
+ $this->entailment['s']=$subject;
+ $this->entailment['p']=$predicate;
+ $this->entailment['o']=$object;
+ }
+
+ /**
+ * Checks, if the statement satisfies the trigger.
+ *
+ * @param object Statement
+ * @return boolean
+ * @access public
+ * @throws PhpError
+ */
+ function checkTrigger(& $statement)
+ {
+ //is true, if the trigger is null to match anything
+ //or equals the statement's subject
+ $shouldFireS = $this->trigger['s'] == null ||
+ $this->trigger['s']->equals($statement->getSubject());
+
+ //is true, if the trigger is null to match anything
+ //or equals the statement's predicate
+ $shouldFireP = $this->trigger['p'] == null ||
+ $this->trigger['p']->equals($statement->getPredicate());
+
+ //is true, if the trigger is null to match anything
+ //or equals the statement's object
+ $shouldFireO = $this->trigger['o'] == null ||
+ $this->trigger['o']->equals($statement->getObject());
+
+ //returns true, if ALL are true
+ return $shouldFireS && $shouldFireP && $shouldFireO;
+ }
+
+ /**
+ * Checks, if this rule could entail a statement that matches
+ * a find of $subject,$predicate,$object.
+ *
+ * @param object Statement
+ * @return boolean
+ * @access public
+ * @throws PhpError
+ */
+ function checkEntailment ($subject, $predicate, $object)
+ {
+ //true, if $subject is null, the entailment's subject matches
+ //anything, or the $subject equals the entailment-subject.
+ $matchesS= $subject == null ||
+ !is_a($this->entailment['s'],'Node') ||
+ $this->entailment['s']->equals($subject);
+
+ //true, if $predicate is null, the entailment's predicate matches
+ //anything, or the $predicate equals the entailment-predicate.
+ $matchesP= $predicate == null ||
+ !is_a($this->entailment['p'],'Node') ||
+ $this->entailment['p']->equals($predicate);
+
+ //true, if $object is null, the entailment's object matches
+ //anything, or the $object equals the entailment-object.
+ $matchesO= $object == null ||
+ !is_a($this->entailment['o'],'Node') ||
+ $this->entailment['o']->equals($object);
+
+ //returns true, if ALL are true
+ return $matchesS && $matchesP && $matchesO;
+ }
+
+ /**
+ * Returns a infered InfStatement by evaluating the statement with
+ * the entailment rule.
+ *
+ * @param object Statement
+ * @return object InfStatement
+ * @access public
+ * @throws PhpError
+ */
+ function entail(& $statement)
+ {
+ //if the entailment's subject is ,,or , put the statements
+ //subject,predicate,or object into the subject of the
+ //entailed statement. If the entailment's subject is a node,
+ //add that node to the statement.
+ switch ($this->entailment['s'])
+ {
+ case '':
+ $entailedSubject=$statement->getSubject();
+ break;
+ case '':
+ $entailedSubject=$statement->getPredicate();
+ break;
+ case '':
+ $entailedSubject=$statement->getObject();
+ break;
+ default:
+ $entailedSubject=$this->entailment['s'];
+ };
+
+ //if the entailment's predicate is ,,or , put the
+ //statements subject,predicate,or object into the predicate of
+ //the entailed statement. If the entailment's predicate is a node,
+ //add that node to the statement.
+ switch ($this->entailment['p'])
+ {
+ case '':
+ $entailedPredicate=$statement->getSubject();
+ break;
+ case '':
+ $entailedPredicate=$statement->getPredicate();
+ break;
+ case '':
+ $entailedPredicate=$statement->getObject();
+ break;
+ default:
+ $entailedPredicate=$this->entailment['p'];
+ };
+
+ //if the entailment's object is ,,or , put the
+ //statements subject,predicate,or object into the object of
+ //the entailed statement. If the entailment's object is a node,
+ //add that node to the statement.
+ switch ($this->entailment['o'])
+ {
+ case '':
+ $entailedObject=$statement->getSubject();
+ break;
+ case '':
+ $entailedObject=$statement->getPredicate();
+ break;
+ case '':
+ $entailedObject=$statement->getObject();
+ break;
+ default:
+ $entailedObject=$this->entailment['o'];
+ };
+
+ //return the infered statement
+ return (new InfStatement($entailedSubject,$entailedPredicate,$entailedObject));
+ }
+
+ /**
+ * Returns a find-query that matches statements, whose entailed
+ * statements would match the supplied find query.
+ *
+ * @param Node OR null $subject
+ * @param Node OR null $predicate
+ * @param Node OR null $object
+ * @return array
+ * @access public
+ * @throws PhpError
+ */
+ function getModifiedFind( $subject, $predicate, $object)
+ {
+ $findSubject=$this->trigger['s'];
+ $findPredicate=$this->trigger['p'];
+ $findObject=$this->trigger['o'];
+
+ switch ($this->entailment['s'])
+ {
+ case '':
+ $findSubject=$subject;
+ break;
+ case '':
+ $findPredicate=$subject;
+ break;
+ case '':
+ $findObject=$subject;
+ break;
+ };
+
+ switch ($this->entailment['p'])
+ {
+ case '':
+ $findSubject=$predicate;
+ break;
+ case '':
+ $findPredicate=$predicate;
+ break;
+ case '':
+ $findObject=$predicate;
+ break;
+ };
+
+ switch ($this->entailment['o'])
+ {
+ case '':
+ $findSubject=$object;
+ break;
+ case '':
+ $findPredicate=$object;
+ break;
+ case '':
+ $findObject=$object;
+ break;
+ };
+
+ return array('s' => $findSubject,
+ 'p' => $findPredicate,
+ 'o' => $findObject );
+ }
+
+ function getTrigger()
+ {
+ return array ( 's' => $this->trigger['s'],
+ 'p' => $this->trigger['p'],
+ 'o' => $this->trigger['o'],
+ );
+ }
+
+ function getEntailment()
+ {
+ return array ( 's' => $this->entailment['s'],
+ 'p' => $this->entailment['p'],
+ 'o' => $this->entailment['o'],
+ );
+ }
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/infModel/.svn/text-base/InfStatement.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/infModel/.svn/text-base/InfStatement.php.svn-base
new file mode 100755
index 00000000..7ea84ad7
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/infModel/.svn/text-base/InfStatement.php.svn-base
@@ -0,0 +1,18 @@
+
+ * @version $Id$
+ * @package infModel
+ */
+class InfStatement extends Statement {
+
+}
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/infModel/InfModel.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/infModel/InfModel.php
new file mode 100755
index 00000000..bc1576ab
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/infModel/InfModel.php
@@ -0,0 +1,678 @@
+
+ *
+ * @package infModel
+ * @access public
+ */
+
+class InfModel extends MemModel
+{
+ /**
+ * Array that holds the objects of the class Infrule,
+ * which were assigned by the _addToInference() function
+ *
+ * @var array
+ * @access private
+ */
+ var $infRules;
+
+ /**
+ * Array of URI-Strings that produces Infrules.
+ *
+ * @var array
+ * @access private
+ */
+ var $supportedInference;
+
+ /**
+ * Array of the connection between the infrules and the statement
+ * that assigned those rules.
+ * array[2][3]=true;array[2][5]=true means, that statement 2
+ * assigned rule 3 & 5 to the model.
+ *
+ * @var array
+ * @access private
+ */
+ var $statementRuleIndex;
+
+ /**
+ * Array of the infRule triggers and the matching infrules.
+ * $this->infRulesTriggerIndex['s'] for subject index, ['p'] for predicates,
+ * and ['o'] for objects.
+ *
+ * @var array
+ * @access private
+ */
+ var $infRulesTriggerIndex;
+
+ /**
+ * Array of the infRule entailments and the matching infrules.
+ * $this->infRulesEntailIndex['s'] for subject index, ['p'] for predicates,
+ * and ['o'] for objects.
+ *
+ * @var array
+ * @access private
+ */
+ var $infRulesEntailIndex;
+
+
+
+ /**
+ * Constructor
+ * You can supply a base_uri
+ *
+ * @param string $baseURI
+ * @access public
+ */
+ function InfModel ($baseURI = NULL)
+ {
+ //call the memmodel constructor method
+ parent::MemModel($baseURI);
+ //initialise vars
+ $this->infRulesTriggerIndex['s']=array();
+ $this->infRulesTriggerIndex['p']=array();
+ $this->infRulesTriggerIndex['o']=array();
+ $this->infRulesEntailIndex['s']=array();
+ $this->infRulesEntailIndex['p']=array();
+ $this->infRulesEntailIndex['o']=array();
+ $this->infRules=array();
+ $this->statementRuleIndex = array();
+ //arraylist of predicate labels that shall add inference rules
+ //to the model
+ //The constants, wich statements will create rules can be configured in constants.php
+ if (INF_RES_SUBCLASSOF)
+ $this->supportedInference[] = RDF_SCHEMA_URI.RDFS_SUBCLASSOF;
+
+ if (INF_RES_SUBPROPERTYOF)
+ $this->supportedInference[] = RDF_SCHEMA_URI.RDFS_SUBPROPERTYOF;
+
+ if (INF_RES_RANGE)
+ $this->supportedInference[] = RDF_SCHEMA_URI.RDFS_RANGE;
+
+ if (INF_RES_DOMAIN)
+ $this->supportedInference[] = RDF_SCHEMA_URI.RDFS_DOMAIN;
+
+ if (INF_RES_OWL_SAMEAS)
+ $this->supportedInference[] = OWL_URI.OWL_SAME_AS;
+
+ if (INF_RES_OWL_INVERSEOF)
+ $this->supportedInference[] = OWL_URI.OWL_INVERSE_OF;
+
+ //Rule: rdfs12
+ if (INF_RES_RULE_RDFS12)
+ {
+ $infRule=new InfRule();
+ $infRule->setTrigger(null,new Resource(RDF_NAMESPACE_URI.RDF_TYPE),new Resource(RDF_SCHEMA_URI.'ContainerMembershipProperty'));
+ $infRule->setEntailment('',new Resource(RDF_SCHEMA_URI.RDFS_SUBPROPERTYOF),new Resource(RDF_SCHEMA_URI.'member'));
+ $this->_addInfRule($infRule,'base');
+ }
+
+ //Rule: rdfs6
+ if (INF_RES_RULE_RDFS6)
+ {
+ $infRule=new InfRule();
+ $infRule->setTrigger(null,new Resource(RDF_NAMESPACE_URI.RDF_TYPE),new Resource(RDF_NAMESPACE_URI.RDF_PROPERTY));
+ $infRule->setEntailment('',new Resource(RDF_SCHEMA_URI.RDFS_SUBPROPERTYOF),'');
+ $this->_addInfRule($infRule,'base');
+ }
+
+ //Rule: rdfs8
+ if (INF_RES_RULE_RDFS8)
+ {
+ $infRule=new InfRule();
+ $infRule->setTrigger(null,new Resource(RDF_NAMESPACE_URI.RDF_TYPE),new Resource(RDF_SCHEMA_URI.RDFS_CLASS));
+ $infRule->setEntailment('',new Resource(RDF_SCHEMA_URI.RDFS_SUBCLASSOF),new Resource(RDF_SCHEMA_URI.RDFS_RESOURCE));
+ $this->_addInfRule($infRule,'base');
+
+ }
+
+ //Rule: rdfs10
+ if (INF_RES_RULE_RDFS10)
+ {
+ $infRule=new InfRule();
+ $infRule->setTrigger(null,new Resource(RDF_NAMESPACE_URI.RDF_TYPE),new Resource(RDF_SCHEMA_URI.RDFS_CLASS));
+ $infRule->setEntailment('',new Resource(RDF_SCHEMA_URI.RDFS_SUBCLASSOF),'');
+ $this->_addInfRule($infRule,'base');
+ }
+
+ //Rule: rdfs13
+ if (INF_RES_RULE_RDFS13)
+ {
+ $infRule=new InfRule();
+ $infRule->setTrigger(null,new Resource(RDF_NAMESPACE_URI.RDF_TYPE),new Resource(RDF_SCHEMA_URI.RDFS_DATATYPE));
+ $infRule->setEntailment('',new Resource(RDF_SCHEMA_URI.RDFS_SUBCLASSOF),new Resource(RDF_SCHEMA_URI.RDFS_LITERAL));
+ $this->_addInfRule($infRule,'base');
+ }
+
+ }
+
+ /**
+ * Adds a new triple to the Model without checking if the statement
+ * is already in the Model.
+ * So if you want a duplicate free MemModel use the addWithoutDuplicates()
+ * function (which is slower then add())
+ * If the statement's predicate label is supported by the inference,
+ * the matching rules are added.
+ *
+ * @param object Statement $statement
+ * @access public
+ * @throws PhpError
+ */
+ function add($statement)
+ {
+ parent::add($statement);
+ //if the predicate is supported by the inference
+ if (in_array($statement->getLabelPredicate(),$this->supportedInference))
+ {
+ $this->_addToInference($statement);
+ };
+ }
+
+ /**
+ * This function analyses the statement's predicate and adds the
+ * matching infrule to the model.
+ *
+ * @param object Statement $statement
+ * @access private
+ */
+ function _addToInference($statement)
+ {
+ $predicateLabel=$statement->getLabelPredicate();
+ //get the position of the the statement in the model
+ end($this->triples);
+ $statementPosition=key($this->triples);
+
+ switch ($predicateLabel)
+ {
+ case RDF_SCHEMA_URI.RDFS_SUBPROPERTYOF :
+ //create a new rule
+ $infRule=new InfRule();
+ //set the trigger to match all statements, having a
+ //predicate, that matches the subject of the statement that
+ //created this rule.
+ $infRule->setTrigger(null,$statement->getSubject(),null);
+ //set the infrule to return a statement, having the same
+ //subject and object as the statement, that asked for an
+ //entailment, and having the object of the statement,
+ //that created this rule as predicate.
+ $infRule->setEntailment('',$statement->getObject(),'');
+ //add the infule to Model, Statement/Rule-Index,
+ //and Rule/Trigger (or Rule/Entailment) index
+ $this->_addInfRule($infRule,$statementPosition);
+ break;
+
+ case RDF_SCHEMA_URI.RDFS_SUBCLASSOF :
+ $infRule=new InfRule();
+ $infRule->setTrigger(null,new Resource(RDF_NAMESPACE_URI.RDF_TYPE),$statement->getSubject());
+ $infRule->setEntailment('',new Resource(RDF_NAMESPACE_URI.RDF_TYPE),$statement->getObject());
+ $this->infRules[]=$infRule;
+ $this->_addInfRule($infRule,$statementPosition);
+ break;
+
+ case RDF_SCHEMA_URI.RDFS_DOMAIN :
+ $infRule=new InfRule();
+ $infRule->setTrigger(null,$statement->getSubject(),null);
+ $infRule->setEntailment('',new Resource(RDF_NAMESPACE_URI.RDF_TYPE),$statement->getObject());
+ $this->infRules[]=$infRule;
+ $this->_addInfRule($infRule,$statementPosition);
+ break;
+
+ case RDF_SCHEMA_URI.RDFS_RANGE :
+ $infRule=new InfRule();
+ $infRule->setTrigger(null,$statement->getSubject(),null);
+ $infRule->setEntailment('',new Resource(RDF_NAMESPACE_URI.RDF_TYPE),$statement->getObject());
+ $this->infRules[]=$infRule;
+ $this->_addInfRule($infRule,$statementPosition);
+ break;
+
+ case OWL_URI.OWL_INVERSE_OF :
+ $infRule=new InfRule();
+ $infRule->setTrigger(null,$statement->getSubject(),null);
+ $infRule->setEntailment('',$statement->getObject(),'');
+ $this->infRules[]=$infRule;
+ $this->_addInfRule($infRule,$statementPosition);
+
+ $infRule=new InfRule();
+ $infRule->setTrigger(null,$statement->getObject(),null);
+ $infRule->setEntailment('',$statement->getSubject(),'');
+ $this->infRules[]=$infRule;
+ $this->_addInfRule($infRule,$statementPosition);
+ break;
+
+ case OWL_URI.OWL_SAME_AS :
+ $infRule=new InfRule();
+ $infRule->setTrigger($statement->getSubject(),null,null);
+ $infRule->setEntailment($statement->getObject(),'','');
+ $this->_addInfRule($infRule,$statementPosition);
+
+ $infRule=new InfRule();
+ $infRule->setTrigger($statement->getObject(),null,null);
+ $infRule->setEntailment($statement->getSubject(),'','');
+ $this->_addInfRule($infRule,$statementPosition);
+
+ $infRule=new InfRule();
+ $infRule->setTrigger(null,$statement->getSubject(),null);
+ $infRule->setEntailment('',$statement->getObject(),'');
+ $this->_addInfRule($infRule,$statementPosition);
+
+ $infRule=new InfRule();
+ $infRule->setTrigger(null,$statement->getObject(),null);
+ $infRule->setEntailment('',$statement->getSubject(),'');
+ $this->_addInfRule($infRule,$statementPosition);
+
+ $infRule=new InfRule();
+ $infRule->setTrigger(null,null,$statement->getSubject());
+ $infRule->setEntailment('','',$statement->getObject());
+ $this->_addInfRule($infRule,$statementPosition);
+
+ $infRule=new InfRule();
+ $infRule->setTrigger(null,null,$statement->getObject());
+ $infRule->setEntailment('','
',$statement->getSubject());
+ $this->_addInfRule($infRule,$statementPosition);
+ break;
+ };
+ }
+
+ /**
+ * This function checks, which infrules were added by the statement and
+ * removes those.
+ *
+ * @param object Statement $statement
+ * @return integer
+ * @access private
+ */
+ function _removeFromInference($statement)
+ {
+ $return= array();
+ $statementPosition=-1;
+ do
+ {
+ //get the position of the statement that should be removed
+ $statementPosition=$this->findFirstMatchOff($statement->getSubject(),
+ $statement->getPredicate(),
+ $statement->getObject(),
+ $statementPosition+1);
+ if ($statementPosition!=-1)
+ {
+ //if it added any rules
+ if (isset ($this->statementRuleIndex[$statementPosition]))
+ {
+ //remove all rules
+ foreach ($this->statementRuleIndex[$statementPosition] as $key => $value)
+ {
+ //remove from Rule-Trigger Index
+ if (is_a($this,'InfModelF'))
+ {
+ $trigger=$this->infRules[$key]->getTrigger();
+
+ if(is_a($trigger['s'],'Node'))
+ {
+ $subjectLabel=$trigger['s']->getLabel();
+ } else
+ {
+ $subjectLabel='null';
+ }
+ unset ($this->infRulesTriggerIndex['s'][$subjectLabel][array_search($key,$this->infRulesTriggerIndex['s'][$subjectLabel])]);
+
+ if(is_a($trigger['p'],'Node'))
+ {
+ $predicateLabel=$trigger['p']->getLabel();
+ } else
+ {
+ $predicateLabel='null';
+ }
+ unset ($this->infRulesTriggerIndex['p'][$predicateLabel][array_search($key,$this->infRulesTriggerIndex['p'][$predicateLabel])]);
+
+ if(is_a($trigger['o'],'Node'))
+ {
+ $objectLabel=$trigger['o']->getLabel();
+ } else
+ {
+ $objectLabel='null';
+ }
+ unset ($this->infRulesTriggerIndex['o'][$objectLabel][array_search($key,$this->infRulesTriggerIndex['o'][$objectLabel])]);
+ } else
+ //remove from Rule-Entailment Index
+ {
+ $entailment=$this->infRules[$key]->getEntailment();
+
+ if(is_a($entailment['s'],'Node'))
+ {
+ $subjectLabel=$entailment['s']->getLabel();
+ } else
+ {
+ $subjectLabel='null';
+ }
+ unset ($this->infRulesEntailIndex['s'][$subjectLabel][array_search($key,$this->infRulesEntailIndex['s'][$subjectLabel])]);
+
+
+ if(is_a($entailment['p'],'Node'))
+ {
+ $predicateLabel=$entailment['p']->getLabel();
+ } else
+ {
+ $predicateLabel='null';
+ }
+ unset ($this->infRulesEntailIndex['p'][$predicateLabel][array_search($key,$this->infRulesEntailIndex['p'][$predicateLabel])]);
+
+ if(is_a($entailment['o'],'Node'))
+ {
+ $objectLabel=$entailment['o']->getLabel();
+ } else
+ {
+ $objectLabel='null';
+ }
+ unset ($this->infRulesEntailIndex['o'][$objectLabel][array_search($key,$this->infRulesEntailIndex['o'][$objectLabel])]);
+ }
+ //remove from statement-Rule Index
+ unset ($this->infRules[$key]);
+ }
+ unset($this->statementRuleIndex[$statementPosition]);
+ $return[]=$statementPosition;
+ };
+ }
+
+ } while($statementPosition!=-1);
+
+ //return the positions of the statements to be removed OR emty array
+ //if nothing was found.
+ return $return;
+ }
+
+ /**
+ * Returns a model, containing all Statements, having a Predicate, that
+ * is supported by the inference.
+ *
+ * @return object Model
+ * @access public
+ */
+ function getSchema()
+ {
+ $res=new MemModel();
+ //Search the base-model for all statements, having a Predicate, that
+ //is supported by the inference.
+ foreach ($this->supportedInference as $inferencePredicateLabel)
+ {
+ $res->addModel($this->find(null, new Resource($inferencePredicateLabel), null));
+ }
+ return $res;
+ }
+
+ /**
+ * General method to replace nodes of a MemModel.
+ * This function is disabled in the Inference Model.
+ *
+ * @param object Node $subject
+ * @param object Node $predicate
+ * @param object Node $object
+ * @param object Node $replacement
+ * @access public
+ * @throws PhpError
+ */
+ function replace($subject, $predicate, $object, $replacement)
+ {
+
+ $errmsg = RDFAPI_ERROR . '(class: InfModel; method: replace): This function is disabled in the Inference Model';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ /**
+ * Method to search for triples using Perl-style regular expressions.
+ * NULL input for any parameter will match anything.
+ * Example: $result = $m->find_regex( NULL, NULL, $regex );
+ * Finds all triples where the label of the object node matches the regular
+ * expression.
+ * Returns an empty MemModel if nothing is found.
+ *
+ * This function is disabled in the Inference Model
+ *
+ * @param string $subject_regex
+ * @param string $predicate_regex
+ * @param string $object_regex
+ * @return object MemModel
+ * @access public
+ */
+ function findRegex($subject_regex, $predicate_regex, $object_regex)
+ {
+
+ $errmsg = RDFAPI_ERROR . '(class: InfModel; method: findRegex):
+ This function is disabled in the
+ Inference Model';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ /**
+ * Returns all tripels of a certain vocabulary.
+ * $vocabulary is the namespace of the vocabulary inluding a # : / char at
+ * the end.
+ * e.g. http://www.w3.org/2000/01/rdf-schema#
+ * Returns an empty MemModel if nothing is found.
+ *
+ * This function is disabled in the Inference Model.
+ *
+ * @param string $vocabulary
+ * @return object MemModel
+ * @access public
+ */
+ function findVocabulary($vocabulary)
+ {
+
+ $errmsg = RDFAPI_ERROR . '(class: InfModel; method: findVocabulary):
+ This function is disabled in the
+ Inference Model';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+
+ /**
+ * Adds the URI or NULL to the Infrule trigger or entailment index.
+ *
+ *
+ * @param object infrule $infRule
+ * @param integer $infRulePosition
+ * @access private
+ */
+ function _addInfruleToIndex(& $infRule,& $infRulePosition)
+ {
+ //Add the rule only to the trigger index, if it is a InfFModel
+ if (is_a($this,'InfModelF'))
+ {
+ //get the trigger
+ $trigger = $infRule->getTrigger();
+ //evaluate and set the index
+ if ($trigger['s'] == null)
+ {
+ $this->infRulesTriggerIndex['s']['null'][]=$infRulePosition;
+ } else
+ {
+ $this->infRulesTriggerIndex['s'][$trigger['s']->getLabel()][]=$infRulePosition;
+ };
+
+ if ($trigger['p'] == null)
+ {
+ $this->infRulesTriggerIndex['p']['null'][]=$infRulePosition;
+ } else
+ {
+ $this->infRulesTriggerIndex['p'][$trigger['p']->getLabel()][]=$infRulePosition;
+ };
+
+ if ($trigger['o'] == null)
+ {
+ $this->infRulesTriggerIndex['o']['null'][]=$infRulePosition;
+ } else
+ {
+ $this->infRulesTriggerIndex['o'][$trigger['o']->getLabel()][]=$infRulePosition;
+ };
+ } else
+ //add to entailment Index if it is a BModel
+ {
+ //get the entailment
+ $entailment = $infRule->getEntailment();
+ //evaluate the entailment and add to index
+ if (!is_a($entailment['s'],'Node'))
+ {
+ $this->infRulesEntailIndex['s']['null'][]=$infRulePosition;
+ } else
+ {
+ $this->infRulesEntailIndex['s'][$entailment['s']->getLabel()][]=$infRulePosition;
+ };
+
+ if (!is_a($entailment['p'],'Node'))
+ {
+ $this->infRulesEntailIndex['p']['null'][]=$infRulePosition;
+ } else
+ {
+ $this->infRulesEntailIndex['p'][$entailment['p']->getLabel()][]=$infRulePosition;
+ };
+
+ if (!is_a($entailment['o'],'Node'))
+ {
+ $this->infRulesEntailIndex['o']['null'][]=$infRulePosition;
+ } else
+ {
+ $this->infRulesEntailIndex['o'][$entailment['o']->getLabel()][]=$infRulePosition;
+ };
+ };
+ }
+
+ /**
+ * Searches the trigger-index for a matching trigger and returns an
+ * array of infRule positions.
+ *
+ *
+ * @param object infrule $infRule
+ * @return array integer
+ * @access private
+ */
+ function _findRuleTriggerInIndex($statement)
+ {
+ $return=array();
+ //a statement's subject matches all triggers with null and the same URI
+ $subjectLabel=$statement->getLabelSubject();
+ $inIndexS=array();
+ if (isset($this->infRulesTriggerIndex['s']['null']))
+ $inIndexS=array_values($this->infRulesTriggerIndex['s']['null']);
+ if (isset($this->infRulesTriggerIndex['s'][$subjectLabel]))
+ $inIndexS= array_merge($inIndexS,array_values($this->infRulesTriggerIndex['s'][$subjectLabel]));
+
+ //a statement's predicate matches all triggers with null and the same URI
+ $predicateLabel=$statement->getLabelPredicate();
+ $inIndexP=array();
+ if (isset($this->infRulesTriggerIndex['p']['null']))
+ $inIndexP=array_values($this->infRulesTriggerIndex['p']['null']);
+ if (isset($this->infRulesTriggerIndex['p'][$predicateLabel]))
+ $inIndexP= array_merge($inIndexP,array_values($this->infRulesTriggerIndex['p'][$predicateLabel]));
+
+ //a statement's object matches all triggers with null and the same URI
+ $objectLabel=$statement->getLabelObject();
+ $inIndexO=array();
+ if (isset($this->infRulesTriggerIndex['o']['null']))
+ $inIndexO=array_values($this->infRulesTriggerIndex['o']['null']);
+ if (isset($this->infRulesTriggerIndex['o'][$objectLabel]))
+ $inIndexO= array_merge($inIndexO,array_values($this->infRulesTriggerIndex['o'][$objectLabel]));
+
+ //if an infrule position occurs in subject, predicate, and object index, add to result array.
+ foreach ($inIndexP as $positionP)
+ {
+ if (in_array($positionP,$inIndexO))
+ if (in_array($positionP,$inIndexS))
+ $return[]=$positionP;
+ }
+ return $return;
+ }
+
+ /**
+ * Searches the Entailment-index for a matching Entailment and returns an
+ * array of infRule positions.
+ *
+ *
+ * @param node or null $subject
+ * @param node or null $predicate
+ * @param node or null $object
+ * @return array integer
+ * @access private
+ */
+ function _findRuleEntailmentInIndex($subject,$predicate,$object)
+ {
+ $return=array();
+ //a node matches all entailments with NULL or a matching URI
+ if(is_a($subject,'Node'))
+ {
+ $subjectLabel=$subject->getLabel();
+ $inIndexS=array();
+ if (isset($this->infRulesEntailIndex['s']['null'])) $inIndexS=array_values($this->infRulesEntailIndex['s']['null']);
+ if (isset($this->infRulesEntailIndex['s'][$subjectLabel])) $inIndexS= array_merge($inIndexS,array_values($this->infRulesEntailIndex['s'][$subjectLabel]));
+ } else
+ //if the subject search pattern is NULL, every rule will match the subject search patter
+ {
+ $inIndexS=array_keys($this->infRules);
+ }
+
+ if(is_a($predicate,'Node'))
+ {
+ $predicateLabel=$predicate->getLabel();
+ $inIndexP=array();
+ if (isset($this->infRulesEntailIndex['p']['null'])) $inIndexP=array_values($this->infRulesEntailIndex['p']['null']);
+ if (isset($this->infRulesEntailIndex['p'][$predicateLabel])) $inIndexP= array_merge($inIndexP,array_values($this->infRulesEntailIndex['p'][$predicateLabel]));
+ } else
+ {
+ $inIndexP=array_keys($this->infRules);
+ }
+
+ if(is_a($object,'Node'))
+ {
+ $objectLabel=$object->getLabel();
+ $inIndexO=array();
+ if (isset($this->infRulesEntailIndex['o']['null'])) $inIndexO=array_values($this->infRulesEntailIndex['o']['null']);
+ if (isset($this->infRulesEntailIndex['o'][$objectLabel])) $inIndexO= array_merge($inIndexO,array_values($this->infRulesEntailIndex['o'][$objectLabel]));
+ } else
+ {
+ $inIndexO=array_keys($this->infRules);
+ }
+
+ //if an infrule position occurs in subject, predicate, and object index, add to result array.
+ foreach ($inIndexP as $positionP)
+ {
+ if (in_array($positionP,$inIndexO))
+ if (in_array($positionP,$inIndexS))
+ $return[]=$positionP;
+ }
+ return $return;
+ }
+
+ /**
+ * Adds an InfRule to the InfModel.
+ * $statementPosition states the positiion of the statement, that created
+ * this rule, in the model->triples array.
+ *
+ *
+ * @param object Infrule $infRule
+ * @param integer $statementPosition
+ * @access private
+ */
+ function _addInfRule($infRule, $statementPosition)
+ {
+ //add the rule
+ $this->infRules[]=$infRule;
+ //get the position of the added rule in the model
+ end($this->infRules);
+ $rulePosition=key($this->infRules);
+ //add the information to the index, that this statement
+ //added this rule.
+ $this->statementRuleIndex[$statementPosition][$rulePosition]=true;
+ //add informations to index over trigger & entailment
+ $this->_addInfruleToIndex($infRule,$rulePosition);
+ }
+ }
+?>
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/infModel/InfModelB.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/infModel/InfModelB.php
new file mode 100755
index 00000000..f4a36614
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/infModel/InfModelB.php
@@ -0,0 +1,515 @@
+
+
+*
+* @package infModel
+* @access public
+**/
+
+class InfModelB extends InfModel
+{
+
+ /**
+ * Array that holds combinations of inference rules with distinct
+ * find-querys, that don't lead to any inference.
+ *
+ * @var array
+ * @access private
+ */
+ var $findDeadEnds;
+
+
+ /**
+ * Constructor
+ * You can supply a base_uri
+ *
+ * @param string $baseURI
+ * @access public
+ */
+ function InfModelB($baseURI = null)
+ {
+ parent::InfModel($baseURI);
+ $this->findDeadEnds=array();
+ }
+
+ /**
+ * Adds a new triple to the Model without checking, if the statement
+ * is already in the Model. So if you want a duplicate free Model use
+ * the addWithoutDuplicates() function (which is slower then add())
+ *
+ * @param object Statement $statement
+ * @access public
+ * @throws PhpError
+ */
+ function add($statement)
+ {
+ parent::add($statement);
+ //Reset the found dead-ends.
+ $this->findDeadEnds=array();
+ }
+
+ /**
+ * General method to search for triples.
+ * NULL input for any parameter will match anything.
+ * Example: $result = $m->find( NULL, NULL, $node );
+ * Finds all triples with $node as object.
+ * Returns an empty MemModel if nothing is found.
+ * To improve the search speed with big Models, call index(INDEX_TYPE)
+ * before seaching.
+ *
+ * It recursively searches in the statements and rules to find
+ * matching statements.
+ *
+ * @param object Node $subject
+ * @param object Node $predicate
+ * @param object Node $object
+ * @return object MemModel
+ * @access public
+ * @throws PhpError
+ */
+ function find($subject,$predicate,$object)
+ {
+ $searchStringIndex=array();
+ $resultModel=new MemModel();
+
+ //add all infered statements without duplicates to the result model
+ foreach ($this->_infFind($subject,$predicate,$object,array())as $statement)
+ {
+ $resultModel->addWithoutDuplicates($statement);
+ };
+ return $resultModel;
+ }
+
+ /**
+ * This is the main inference method of the InfModelB
+ * The algorithm works as follows:
+ * Find all statements in the base model, that matches the current
+ * find-query.
+ * Check all rules, if they are able to deliver infered statements,
+ * that match the current find-query. Don't use rules with queries,
+ * that lead to dead-ends and don't use a rule-query-combination that
+ * was used before in this branch (ontology loops).
+ * If a rule is possible do deliver such statements, get a new
+ * find-query, that is possible to find those statements, that are able
+ * to trigger this rule.
+ * Call this _infFind method wirh the new find-query and entail the
+ * resulting statements.
+ * If this rule, wasn't able to return any statements with this distinct
+ * query, add this combination to the dead-ends.
+ * Return the statements from the base triples and those, which were infered.
+ *
+ * If $findOnlyFirstMatching is set to true, only the first match in
+ * the base-statements is entailed an returned (used in contains() and
+ * findFirstMatchingStatement() methods).
+ *
+ * You can set an offset to look for the first matching statement by setting the
+ * $offset var.
+ *
+ * It recursively searches in the statements and rules to find matching
+ * statements
+ *
+ * @param object Node $subject
+ * @param object Node $predicate
+ * @param object Node $object
+ * @param array $searchStringIndex
+ * @param boolean $findOnlyFirstMatching
+ * @param integer $offset
+ * @param integer $resultCount
+ * @return object array Statements
+ * @access private
+ */
+ function _infFind ($subject,$predicate,$object, $searchStringIndex, $findOnlyFirstMatching = false, $offset = 0,$resultCount = 0 )
+ {
+ $return=array();
+ //Find all matching statements in the base statements
+ $findResult=parent::find($subject,$predicate,$object);
+ //For all found statements
+ foreach ($findResult->triples as $statement)
+ {
+ $return[]=$statement;
+ $resultCount++;
+
+ //Return, if only the firstMatchingStatement was wanted
+ if ($findOnlyFirstMatching && $resultCount > $offset)
+ return $return;
+ };
+
+ //Don't infer statements about the schema (rdfs:subClass, etc..)
+ //is false
+ if ($predicate == null ||
+ (is_a($predicate,'Node') &&
+ !in_array($predicate->getLabel(),$this->supportedInference))
+ )
+ //Check only Rules, that the EntailmentIndex returned.
+ foreach ($this->_findRuleEntailmentInIndex($subject,$predicate,$object) as $ruleKey)
+ {
+ $infRule=$this->infRules[$ruleKey];
+ $serializedRuleStatement=$ruleKey.serialize($subject).serialize($predicate).serialize($object);
+ //If it is to ontology loop and no dead-end
+ if (!in_array($serializedRuleStatement, $searchStringIndex) &&
+ !in_array($serializedRuleStatement, $this->findDeadEnds))
+ {
+ //Keep this distinct rule query cobination for
+ //this branch to detect loops
+ $searchStringIndex[]=$serializedRuleStatement;
+
+ //If the rule is able to deliver statements that match
+ //this query
+ if ($infRule->checkEntailment($subject,$predicate,$object))
+ {
+ //Get a modified find-query, that matches statements,
+ //that trigger this rule
+ $modefiedFind=$infRule->getModifiedFind($subject,$predicate,$object);
+ //Call this method with the new find-query
+ $infFindResult=$this->_infFind($modefiedFind['s'],
+ $modefiedFind['p'],
+ $modefiedFind['o'],
+ $searchStringIndex,
+ $findOnlyFirstMatching,
+ $offset,
+ $resultCount) ;
+ //If it deliverd statements that matches the trigger
+ if (isset($infFindResult[0]))
+ {
+ foreach ($infFindResult as $statement)
+ {
+ //Entail the statements and check, if they are not about the
+ //ontology
+ $newStatement=$infRule->entail($statement);
+ if (!in_array($newStatement->getLabelPredicate(),$this->supportedInference))
+ //Check if, the entailed statements are, what we are looking for
+ if($this->_nodeEqualsFind($subject,$newStatement->getSubject()) &&
+ $this->_nodeEqualsFind($predicate,$newStatement->getPredicate()) &&
+ $this->_nodeEqualsFind($object,$newStatement->getObject() ) )
+ {
+ //Add to results
+ $return[]=$newStatement;
+ $resultCount++;
+
+ //or return at once
+ if ($findOnlyFirstMatching && $resultCount > $offset)
+ return $return;
+ }
+ }
+ } else
+ {
+ //If there were no results of the rule-query-combination,
+ //mark this combination as a dead-end.
+ $this->findDeadEnds[]=$serializedRuleStatement;
+ }
+ }
+ }
+ }
+ //Return the array of the found statements
+ return $return;
+ }
+
+ /**
+ * Tests if the Model contains the given triple.
+ * TRUE if the triple belongs to the Model;
+ * FALSE otherwise.
+ *
+ * @param object Statement &$statement
+ * @return boolean
+ * @access public
+ */
+ function contains(&$statement)
+ {
+ //throws an error, if $statement is not of class Statement
+ if(!is_a($statement,'Statement'))
+ trigger_error(RDFAPI_ERROR . '(class: InfModelB; method: contains):
+ $statement has to be object of class Statement', E_USER_ERROR);
+
+ //Call the _infFind method, but let it stop, if it finds the first match.
+ if (count( $this->_infFind($statement->getSubject(),
+ $statement->getPredicate(),
+ $statement->getObject(),
+ array(),true) ) >0)
+ {
+ return true;
+ } else
+ {
+ return false;
+ };
+ }
+
+ /**
+ * Searches for triples and returns the first matching statement.
+ * NULL input for any parameter will match anything.
+ * Example: $result = $m->findFirstMatchingStatement( NULL, NULL, $node );
+ * Returns the first statement of the MemModel where the object equals $node.
+ * Returns an NULL if nothing is found.
+ * You can define an offset to search for. Default = 0
+ *
+ * @param object Node $subject
+ * @param object Node $predicate
+ * @param object Node $object
+ * @param integer $offset
+ * @return object Statement
+ * @access public
+ */
+ function findFirstMatchingStatement($subject, $predicate, $object, $offset = 0)
+ {
+ //Call the _infFind method, but let it stop, if it finds the
+ //first match.
+ $res= $this->_infFind($subject,$predicate,$object,array(),true,$offset);
+
+ if (isset($res[$offset]))
+ {
+ return $res[$offset];
+ } else
+ {
+ return NULL;
+ };
+ }
+
+ /**
+ * Returns a StatementIterator for traversing the Model.
+ *
+ * @access public
+ * @return object StatementIterator
+ */
+ function & getStatementIterator()
+ {
+ // Import Package Utility
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_UTILITY);
+ // Gets a MemModel by executing a find(null,null,null) to get a
+ //inferable statements.
+ // WARNING: might be slow
+ return new StatementIterator($this->getMemModel());
+ }
+
+ /**
+ * Number of all inferable triples in the Model.
+ * WARNING: uses a find(null,null,null) to find all statements! (might take a while)
+ *
+ * @param boolean
+ * @return integer
+ * @access public
+ */
+ function size()
+ {
+ // Gets a MemModel by executing a find(null,null,null) to get a
+ //inferable statements.
+ // WARNING: might be slow
+ $res = $this->getMemModel();
+ return $res->size();
+ }
+
+ /**
+ * Create a MemModel containing all the triples (including inferred
+ * statements) of the current InfModelB.
+ *
+ * @return object MemModel
+ * @access public
+ */
+ function & getMemModel()
+ {
+
+ $return=$this->find(null,null,null);
+ $return->setBaseURI($this->baseURI);
+ $return->addParsedNamespaces($this->getParsedNamespaces());
+ return $return;
+ }
+
+ /**
+ * Create a MemModel containing only the base triples (without inferred
+ * statements) of the current InfModelB.
+ *
+ * @return object MemModel
+ * @access public
+ */
+ function & getBaseMemModel()
+ {
+ $return= new MemModel();
+ $return->setBaseURI($this->baseURI);
+ foreach ($this->triples as $statement)
+ $return->add($statement);
+
+ $retun->addParsedNamespaces($this->getParsedNamespaces());
+ return $return;
+ }
+
+ /**
+ * Short Dump of the InfModelB.
+ *
+ * @access public
+ * @return string
+ */
+ function toString()
+ {
+ return 'InfModelB[baseURI=' . $this->getBaseURI() . '; size=' . $this->size(true) . ']';
+ }
+
+ /**
+ * Dumps of the InfModelB including ALL inferable triples.
+ *
+ * @access public
+ * @return string
+ */
+ function toStringIncludingTriples()
+ {
+ $dump = $this->toString() . chr(13);
+ $stateIt=new StatementIterator($this->find(null,null,null));
+ while($statement=$stateIt->next())
+ {
+ $dump .= $statement->toString() . chr(13);
+ }
+ return $dump;
+ }
+
+ /**
+ * Saves the RDF,N3 or N-Triple serialization of the full InfModelB
+ * (including inferred triples) to a file.
+ * You can decide to which format the model should be serialized by
+ * using a corresponding suffix-string as $type parameter. If no $type
+ * parameter is placed this method will serialize the model to XML/RDF
+ * format.
+ * Returns FALSE if the InfModelB couldn't be saved to the file.
+ *
+ * @access public
+ * @param string $filename
+ * @param string $type
+ * @throws PhpError
+ * @return boolean
+ */
+ function saveAs($filename, $type ='rdf')
+ {
+
+ $memmodel=$this->getMemModel();
+ return $memmodel->saveAs($filename, $type);
+ }
+
+ /**
+ * Writes the RDF serialization of the Model including ALL inferable
+ * triples as HTML.
+ *
+ * @access public
+ */
+ function writeAsHtml()
+ {
+ require_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_RDF);
+ $ser = new RdfSerializer();
+ $rdf =& $ser->serialize($this->getMemModel());
+ $rdf = htmlspecialchars($rdf, ENT_QUOTES);
+ $rdf = str_replace(' ', ' ', $rdf);
+ $rdf = nl2br($rdf);
+ echo $rdf;
+ }
+
+ /**
+ * Writes the RDF serialization of the Model including ALL inferable
+ * triples as HTML table.
+ *
+ * @access public
+ */
+ function writeAsHtmlTable()
+ {
+ // Import Package Utility
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_UTILITY);
+ RDFUtil::writeHTMLTable($this->getMemModel());
+ }
+
+
+ /**
+ * Writes the RDF serialization of the Model including ALL inferable
+ * triples.
+ *
+ * @access public
+ * @return string
+ */
+ function writeRdfToString()
+ {
+ // Import Package Syntax
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_RDF);
+ $ser = new RdfSerializer();
+ $rdf =& $ser->serialize($this->getMemModel());
+ return $rdf;
+ }
+
+ /**
+ * Removes the triple from the MemModel.
+ * TRUE if the triple is removed.
+ * FALSE otherwise.
+ *
+ * Checks, if it touches any statements, that added inference rules
+ * to the model.
+ *
+ * @param object Statement $statement
+ * @return boolean
+ * @access public
+ * @throws PhpError
+ */
+ function remove($statement)
+ {
+ if (parent::contains($statement))
+ {
+ if (in_array($statement->getLabelPredicate(),$this->supportedInference));
+ while (count($this->_removeFromInference($statement))>0);
+
+ $this->findDeadEnds=array();
+ return parent::remove($statement);
+ } else
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Checks, if a single node matches a single find pattern.
+ * TRUE if the node matches.
+ * FALSE otherwise.
+ *
+ * Checks, if it touches any statements, that added inference rules
+ * to the model.
+ *
+ * @param object Statement $statement
+ * @return boolean
+ * @access private
+ */
+ function _nodeEqualsFind(& $find, $node)
+ {
+ //If the find pattern is a node, use the nodes equal-method and
+ //return the result.
+ if (is_a($find,'Node'))
+ return $node->equals($find);
+
+ //Null-pattern matches anything.
+ if ($find == null)
+ {
+ return true;
+ } else
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Returns a FindIterator for traversing the MemModel.
+ * Disabled in InfModelB.
+ *
+ * @access public
+ * @return object FindIterator
+ */
+ function & findAsIterator($sub=null,$pred=null,$obj=null) {
+ $errmsg = RDFAPI_ERROR . '(class: InfModelB; method: findAsIterator):
+ This function is disabled in the
+ Inference Model';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/infModel/InfModelF.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/infModel/InfModelF.php
new file mode 100755
index 00000000..d338c1cf
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/infModel/InfModelF.php
@@ -0,0 +1,406 @@
+
+
+*
+* @package infModel
+* @access public
+**/
+
+class InfModelF extends InfModel
+{
+
+ /**
+ * Array that holds the position of the infered statements in the model.
+ *
+ * @var array
+ * @access private
+ */
+ var $infPos;
+
+
+ /**
+ * Variable that influences the habbit when adding statements.
+ * Used by the loadModel method to increase performance.
+ *
+ * @var boolean
+ * @access private
+ */
+ var $inferenceEnabled;
+
+
+ /**
+ * Constructor
+ * You can supply a base_uri.
+ *
+ * @param string $baseURI
+ * @access public
+ */
+ function InfModelF($baseURI = NULL)
+ {
+ parent::InfModel($baseURI);
+ $this->infPos=array();
+ $this->inferenceEnabled=true;
+ }
+
+ /**
+ * Adds a new triple to the MemModel without checking if the statement
+ * is already in the MemModel.
+ * So if you want a duplicate free MemModel use the addWithoutDuplicates()
+ * function (which is slower then add())
+ * The statement is infered and all entailed statements are added.
+ *
+ * @param object Statement $statement
+ * @access public
+ * @throws PhpError
+ */
+ function add ($statement)
+ {
+ parent::add($statement);
+ if ($this->inferenceEnabled)
+ {
+ foreach ($this->entailStatement($statement) as $state)
+ {
+ //a addWithoutDublicates construct
+ if(!$this->contains($state))
+ {
+
+ parent::add($state);
+ //save the position of the infered statements
+ end($this->triples);
+ $this->infPos[]=key($this->triples);
+ };
+ };
+ //apply the complete inference to the model, if the added statement was able to add a rule
+ if (in_array($statement->getLabelPredicate(),$this->supportedInference))
+ $this->applyInference();
+ }
+ }
+
+
+ /**
+ * Checks if a new statement is already in the MemModel and adds
+ * the statement, if it is not in the MemModel.
+ * addWithoutDuplicates() is significantly slower then add().
+ * Retruns TRUE if the statement is added.
+ * FALSE otherwise.
+ * The statement is infered and all entailed statements are added.
+ *
+ * @param object Statement $statement
+ * @return boolean
+ * @access public
+ * @throws PhpError
+ */
+ function addWithoutDuplicates(& $statement)
+ {
+ if(!$this->contains($statement))
+ {
+ parent::add($statement);
+ if ($this->inferenceEnabled)
+ {
+ foreach ($this->entailStatement($statement) as $statement)
+ {
+ if(!$this->contains($statement))
+ {
+ parent::add($statement);
+ //save the position of the infered statements
+ end($this->triples);
+ $this->infPos[]=key($this->triples);
+ };
+ };
+ if (in_array($statement->getLabelPredicate(),$this->supportedInference))
+ $this->applyInference();
+ }
+ return true;
+ }
+ return false;
+ }
+
+
+
+ /**
+ * Entails every statement and adds the entailments if not already
+ * in the model.
+ *
+ * @access private
+ */
+ function applyInference()
+ {
+ //check every statement in the model
+ foreach ($this->triples as $statement)
+ {
+ //gat all statements, that it recursively entails
+ foreach ($this->entailStatement($statement) as $statement)
+ {
+ if (!$this->contains($statement))
+ {
+ parent::add($statement);
+ //add the InfStatement position to the index
+ end($this->triples);
+ $this->infPos[]=key($this->triples);
+ };
+ };
+ };
+ }
+
+
+ /**
+ * Entails a statement by recursively using the _entailStatementRec
+ * method.
+ *
+ * @param object Statement $statement
+ * @return array of statements
+ * @access public
+ */
+ function entailStatement (& $statement)
+ {
+ $infStatementsIndex=array();
+ return $this->_entailStatementRec($statement,$infStatementsIndex);
+ }
+
+ /**
+ * Recursive method, that checks the statement with the trigger of
+ * every rule. If the trigger matches and entails new statements,
+ * those statements are recursively infered too.
+ * The $infStatementsIndex array holds lready infered statements
+ * to prevent infinite loops.
+ *
+ *
+ * @param object Statement $statement
+ * @param array $infStatementsIndex
+ * @return array of statements
+ * @access private
+ */
+ function _entailStatementRec ( $statement,& $infStatementsIndex)
+ {
+ $infStatements = array();
+ $return = array();
+
+ //dont entail statements about the supported inference-schema
+ if (!in_array($statement->getLabelPredicate(),$this->supportedInference))
+ {
+ //check only the rules, that were returned by the index
+ foreach ($this->_findRuleTriggerInIndex($statement) as $key )
+ {
+ $infRule=$this->infRules[$key];
+
+ $stateString=$key.serialize($statement);
+ //If the statement wasn't infered before
+ if (!in_array($stateString,$infStatementsIndex))
+ {
+ $infStatementsIndex[]=$stateString;
+ //Check, if the Statements triggers this rule
+ if($infRule->checkTrigger($statement))
+ {
+ $infStatement=$infRule->entail($statement);
+ #if(!$this->contains($infStatement))
+ {
+ $return[]=$infStatement;
+ $return=array_merge($return,
+ $this->_entailStatementRec($infStatement,
+ $infStatementsIndex));
+ };
+
+ };
+ };
+ };
+ };
+ return $return;
+ }
+
+ /**
+ * Removes all infered statements from the model but keeps the
+ * infernece rules.
+ *
+ * @access public
+ */
+ function removeInfered()
+ {
+ $indexTmp=$this->indexed;
+ $this->index(-1);
+ foreach ($this->infPos as $key)
+ {
+ unset($this->triples[$key]);
+ };
+ $this->infPos=array();
+ $this->index($indexTmp);
+ }
+
+
+ /**
+ * Load a model from a file containing RDF, N3 or N-Triples.
+ * This function recognizes the suffix of the filename (.n3 or .rdf) and
+ * calls a suitable parser, if no $type is given as string
+ * ("rdf" "n3" "nt");
+ * If the model is not empty, the contents of the file is added to
+ * this DbModel.
+ *
+ * While loading the model, the inference entailing is disabled, but
+ * new inference rules are added to increase performance.
+ *
+ * @param string $filename
+ * @param string $type
+ * @access public
+ */
+ function load($filename, $type = NULL)
+ {
+ //Disable entailing to increase performance
+ $this->inferenceEnabled=false;
+ parent::load($filename, $type);
+ //Enable entailing
+ $this->inferenceEnabled=true;
+ //Entail all statements
+ $this->applyInference();
+ }
+
+ /**
+ * Short Dump of the InfModelF.
+ *
+ * @access public
+ * @return string
+ */
+ function toString() {
+ return 'InfModelF[baseURI=' . $this->getBaseURI() . ';
+ size=' . $this->size(true) . ']';
+ }
+
+ /**
+ * Create a MemModel containing all the triples (including inferred
+ * statements) of the current InfModelF.
+ *
+ * @return object MemModel
+ * @access public
+ */
+ function & getMemModel()
+ {
+ $return= new MemModel();
+ $return->setBaseURI($this->baseURI);
+ foreach ($this->triples as $statement)
+ $return->add($statement);
+
+ $return->addParsedNamespaces($this->getParsedNamespaces());
+ return $return;
+ }
+
+ /**
+ * Create a MemModel containing only the base triples
+ * (without inferred statements) of the current InfModelF.
+ *
+ * @return object MemModel
+ * @access public
+ */
+ function getBaseMemModel()
+ {
+ $return= new MemModel();
+ $return->setBaseURI($this->baseURI);
+ foreach ($this->triples as $key => $statement)
+ if (!in_array($key,$this->infPos))
+ $return->add($statement);
+ $retun->addParsedNamespaces($this->getParsedNamespaces());
+ return $return;
+ }
+
+
+ /**
+ * Removes the triple from the MemModel.
+ * TRUE if the triple is removed.
+ * FALSE otherwise.
+ *
+ * Checks, if it touches any statements, that added inference rules
+ * to the model
+ *
+ * @param object Statement $statement
+ * @return boolean
+ * @access public
+ * @throws PhpError
+ */
+ function remove($statement)
+ {
+ //If the statement is in the model
+ if($this->contains($statement))
+ {
+ $inferenceRulesWereTouched=false;
+ //If the statement was able to add inference rules
+ if (in_array($statement->getLabelPredicate(),$this->supportedInference))
+ {
+ $statementPositions=$this->_removeFromInference($statement);
+ $inferenceRulesWereTouched=true;
+ } else
+ //get the position of all matching statements
+ {
+ $statementPositions=array();
+ //find the positions of the statements
+ $statementPosition=-1;
+ do
+ {
+
+ $statementPosition =
+ $this->findFirstMatchOff($statement->getSubject(),
+ $statement->getPredicate(),
+ $statement->getObject(),
+ $statementPosition+1);
+
+ if ($statementPosition!=-1)
+ $statementPositions[]=$statementPosition;
+
+ } while ($statementPosition != -1);
+ }
+
+ //remove matching statements
+ parent::remove($statement);
+ foreach ($statementPositions as $statementPosition)
+ {
+ //if the statement was infered, remove it from the index of the infered statements.
+ if (in_array($statementPosition,$this->infPos))
+ unset ($this->infPos[$statementPosition]);
+ }
+ if ($inferenceRulesWereTouched)
+ {
+ //remove the statement and re-entail the model
+ $this->removeInfered();
+ $this->applyInference();
+ }
+ return true;
+ } else
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Adds another model to this MemModel.
+ * Duplicate statements are not removed.
+ * If you don't want duplicates, use unite().
+ * If any statement of the model to be added to this model contains a blankNode
+ * with an identifier already existing in this model, a new blankNode is generated.
+ *
+ * @param object Model $model
+ * @access public
+ * @throws phpErrpr
+ *
+ */
+ function addModel(&$model)
+ {
+ //Disable entailing to increase performance
+ $this->inferenceEnabled=false;
+ parent::addModel($model);
+ //Enable entailing
+ $this->inferenceEnabled=true;
+ //Entail all statements
+ $this->applyInference();
+ }
+};
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/infModel/InfModelP.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/infModel/InfModelP.php
new file mode 100755
index 00000000..20dc1d40
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/infModel/InfModelP.php
@@ -0,0 +1,19 @@
+
+//
+// ----------------------------------------------------------------------------------
+
+// Include InfModel classes
+require_once( RDFAPI_INCLUDE_DIR . 'infModel/InfRule.php');
+require_once( RDFAPI_INCLUDE_DIR . 'infModel/InfStatement.php');
+require_once( RDFAPI_INCLUDE_DIR . 'infModel/InfModel.php');
+require_once( RDFAPI_INCLUDE_DIR . 'infModel/InfModelB.php');
+require_once( RDFAPI_INCLUDE_DIR . 'infModel/InfModelF.php');
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/infModel/InfRule.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/infModel/InfRule.php
new file mode 100755
index 00000000..8bde1e88
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/infModel/InfRule.php
@@ -0,0 +1,343 @@
+
+
+ *
+ * @package infModel
+ * @access public
+ **/
+
+class InfRule
+{
+
+ /**
+ * Array, that hold the trigger subject in key ['s'], the trigger
+ * predicate in ['p'], and the trigger object in ['o'].
+ * The array values can be NULL to match anything or be a node that
+ * has to be matched.
+ *
+ * @var array
+ * @access private
+ */
+ var $trigger;
+
+ /**
+ * Array, that hold the entailment subject in key ['s'], the
+ * entailment predicate in ['p'], and the entailment object in ['o'].
+ * The array values can be a node that will be inserted in the
+ * returning statement, or '' to insert the subject,'
' to insert
+ * the predicate, or '' to insert the object of the checked statement
+ * to this position in the new returned statement.
+ *
+ * @var array
+ * @access private
+ */
+ var $entailment;
+
+
+ /**
+ * Constructor
+ *
+ *
+ * @access public
+ */
+ function infRule()
+ {
+ //initialising vars
+ $this->trigger=array();
+ $this->entailment=array();
+ }
+
+ /**
+ * Sets the trigger of this rule
+ * The values can be NULL to match anything or be a node that has to
+ * be matched.
+ *
+ * @param object Node OR NULL $subject
+ * @param object Node OR NULL $predicate
+ * @param object Node OR NULL $object
+ * @access public
+ * @throws PhpError
+ */
+ function setTrigger ($subject, $predicate, $object)
+ {
+ //throw an error if subject, predicate, or object are neither
+ //node, nor null.
+ if(!is_a($subject,'Node') && $subject != null)
+ trigger_error(RDFAPI_ERROR . '(class: Infrule; method:
+ setTrigger): $subject has to be null or of class Node'
+ , E_USER_ERROR);
+ if(!is_a($predicate,'Node') && $predicate != null)
+ trigger_error(RDFAPI_ERROR . '(class: Infrule; method:
+ setTrigger): $predicate has to be null or of class Node'
+ , E_USER_ERROR);
+ if(!is_a($object,'Node') && $object != null)
+ trigger_error(RDFAPI_ERROR . '(class: Infrule; method:
+ setTrigger): $object has to be null or of class Node'
+ , E_USER_ERROR);
+
+ //set the trigger
+ $this->trigger['s']=$subject;
+ $this->trigger['p']=$predicate;
+ $this->trigger['o']=$object;
+ }
+
+ /**
+ * Sets the entailment of this rule
+ * The values can be NULL to match anything or be a node that has to
+ * be matched.
+ *
+ * @param object Node OR NULL $subject
+ * @param object Node OR NULL $predicate
+ * @param object Node OR NULL $object
+ * @access public
+ * @throws PhpError
+ */
+ function setEntailment($subject,$predicate,$object)
+ {
+ //throw an error if subject, predicate, or object are neither node,
+ //nor ,,.
+ if(!is_a($subject,'Node') && !ereg('<[spo]>', $subject))
+ trigger_error(RDFAPI_ERROR . '(class: Infrule; method:
+ setEntailment): $subject has to be ,,or or of class Node'
+ , E_USER_ERROR);
+ if(!is_a($predicate,'Node') && !ereg('<[spo]>', $predicate))
+ trigger_error(RDFAPI_ERROR . '(class: Infrule; method:
+ setEntailment): $predicate has to be ,,or or of class Node'
+ , E_USER_ERROR);
+ if(!is_a($object,'Node') && !ereg('<[spo]>', $object))
+ trigger_error(RDFAPI_ERROR . '(class: Infrule; method:
+ setEntailment): $object has to be ,,or or of class Node'
+ , E_USER_ERROR);
+
+ $this->entailment['s']=$subject;
+ $this->entailment['p']=$predicate;
+ $this->entailment['o']=$object;
+ }
+
+ /**
+ * Checks, if the statement satisfies the trigger.
+ *
+ * @param object Statement
+ * @return boolean
+ * @access public
+ * @throws PhpError
+ */
+ function checkTrigger(& $statement)
+ {
+ //is true, if the trigger is null to match anything
+ //or equals the statement's subject
+ $shouldFireS = $this->trigger['s'] == null ||
+ $this->trigger['s']->equals($statement->getSubject());
+
+ //is true, if the trigger is null to match anything
+ //or equals the statement's predicate
+ $shouldFireP = $this->trigger['p'] == null ||
+ $this->trigger['p']->equals($statement->getPredicate());
+
+ //is true, if the trigger is null to match anything
+ //or equals the statement's object
+ $shouldFireO = $this->trigger['o'] == null ||
+ $this->trigger['o']->equals($statement->getObject());
+
+ //returns true, if ALL are true
+ return $shouldFireS && $shouldFireP && $shouldFireO;
+ }
+
+ /**
+ * Checks, if this rule could entail a statement that matches
+ * a find of $subject,$predicate,$object.
+ *
+ * @param object Statement
+ * @return boolean
+ * @access public
+ * @throws PhpError
+ */
+ function checkEntailment ($subject, $predicate, $object)
+ {
+ //true, if $subject is null, the entailment's subject matches
+ //anything, or the $subject equals the entailment-subject.
+ $matchesS= $subject == null ||
+ !is_a($this->entailment['s'],'Node') ||
+ $this->entailment['s']->equals($subject);
+
+ //true, if $predicate is null, the entailment's predicate matches
+ //anything, or the $predicate equals the entailment-predicate.
+ $matchesP= $predicate == null ||
+ !is_a($this->entailment['p'],'Node') ||
+ $this->entailment['p']->equals($predicate);
+
+ //true, if $object is null, the entailment's object matches
+ //anything, or the $object equals the entailment-object.
+ $matchesO= $object == null ||
+ !is_a($this->entailment['o'],'Node') ||
+ $this->entailment['o']->equals($object);
+
+ //returns true, if ALL are true
+ return $matchesS && $matchesP && $matchesO;
+ }
+
+ /**
+ * Returns a infered InfStatement by evaluating the statement with
+ * the entailment rule.
+ *
+ * @param object Statement
+ * @return object InfStatement
+ * @access public
+ * @throws PhpError
+ */
+ function entail(& $statement)
+ {
+ //if the entailment's subject is ,,or , put the statements
+ //subject,predicate,or object into the subject of the
+ //entailed statement. If the entailment's subject is a node,
+ //add that node to the statement.
+ switch ($this->entailment['s'])
+ {
+ case '':
+ $entailedSubject=$statement->getSubject();
+ break;
+ case '':
+ $entailedSubject=$statement->getPredicate();
+ break;
+ case '':
+ $entailedSubject=$statement->getObject();
+ break;
+ default:
+ $entailedSubject=$this->entailment['s'];
+ };
+
+ //if the entailment's predicate is ,,or , put the
+ //statements subject,predicate,or object into the predicate of
+ //the entailed statement. If the entailment's predicate is a node,
+ //add that node to the statement.
+ switch ($this->entailment['p'])
+ {
+ case '':
+ $entailedPredicate=$statement->getSubject();
+ break;
+ case '':
+ $entailedPredicate=$statement->getPredicate();
+ break;
+ case '':
+ $entailedPredicate=$statement->getObject();
+ break;
+ default:
+ $entailedPredicate=$this->entailment['p'];
+ };
+
+ //if the entailment's object is ,,or , put the
+ //statements subject,predicate,or object into the object of
+ //the entailed statement. If the entailment's object is a node,
+ //add that node to the statement.
+ switch ($this->entailment['o'])
+ {
+ case '':
+ $entailedObject=$statement->getSubject();
+ break;
+ case '':
+ $entailedObject=$statement->getPredicate();
+ break;
+ case '':
+ $entailedObject=$statement->getObject();
+ break;
+ default:
+ $entailedObject=$this->entailment['o'];
+ };
+
+ //return the infered statement
+ return (new InfStatement($entailedSubject,$entailedPredicate,$entailedObject));
+ }
+
+ /**
+ * Returns a find-query that matches statements, whose entailed
+ * statements would match the supplied find query.
+ *
+ * @param Node OR null $subject
+ * @param Node OR null $predicate
+ * @param Node OR null $object
+ * @return array
+ * @access public
+ * @throws PhpError
+ */
+ function getModifiedFind( $subject, $predicate, $object)
+ {
+ $findSubject=$this->trigger['s'];
+ $findPredicate=$this->trigger['p'];
+ $findObject=$this->trigger['o'];
+
+ switch ($this->entailment['s'])
+ {
+ case '':
+ $findSubject=$subject;
+ break;
+ case '':
+ $findPredicate=$subject;
+ break;
+ case '':
+ $findObject=$subject;
+ break;
+ };
+
+ switch ($this->entailment['p'])
+ {
+ case '':
+ $findSubject=$predicate;
+ break;
+ case '':
+ $findPredicate=$predicate;
+ break;
+ case '':
+ $findObject=$predicate;
+ break;
+ };
+
+ switch ($this->entailment['o'])
+ {
+ case '':
+ $findSubject=$object;
+ break;
+ case '':
+ $findPredicate=$object;
+ break;
+ case '':
+ $findObject=$object;
+ break;
+ };
+
+ return array('s' => $findSubject,
+ 'p' => $findPredicate,
+ 'o' => $findObject );
+ }
+
+ function getTrigger()
+ {
+ return array ( 's' => $this->trigger['s'],
+ 'p' => $this->trigger['p'],
+ 'o' => $this->trigger['o'],
+ );
+ }
+
+ function getEntailment()
+ {
+ return array ( 's' => $this->entailment['s'],
+ 'p' => $this->entailment['p'],
+ 'o' => $this->entailment['o'],
+ );
+ }
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/infModel/InfStatement.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/infModel/InfStatement.php
new file mode 100755
index 00000000..336504f4
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/infModel/InfStatement.php
@@ -0,0 +1,18 @@
+
+ * @version $Id: InfStatement.php 268 2006-05-15 05:28:09Z tgauss $
+ * @package infModel
+ */
+class InfStatement extends Statement {
+
+}
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/all-wcprops b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/all-wcprops
new file mode 100755
index 00000000..56e0a96f
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/all-wcprops
@@ -0,0 +1,77 @@
+K 25
+svn:wc:ra_dav:version-url
+V 59
+/svnroot/rdfapi-php/!svn/ver/551/trunk/rdfapi-php/api/model
+END
+Literal.php
+K 25
+svn:wc:ra_dav:version-url
+V 71
+/svnroot/rdfapi-php/!svn/ver/497/trunk/rdfapi-php/api/model/Literal.php
+END
+Blanknode.php
+K 25
+svn:wc:ra_dav:version-url
+V 73
+/svnroot/rdfapi-php/!svn/ver/453/trunk/rdfapi-php/api/model/Blanknode.php
+END
+DBase.php
+K 25
+svn:wc:ra_dav:version-url
+V 69
+/svnroot/rdfapi-php/!svn/ver/320/trunk/rdfapi-php/api/model/DBase.php
+END
+MemModel.php
+K 25
+svn:wc:ra_dav:version-url
+V 72
+/svnroot/rdfapi-php/!svn/ver/425/trunk/rdfapi-php/api/model/MemModel.php
+END
+Model.php
+K 25
+svn:wc:ra_dav:version-url
+V 69
+/svnroot/rdfapi-php/!svn/ver/551/trunk/rdfapi-php/api/model/Model.php
+END
+ModelP.php
+K 25
+svn:wc:ra_dav:version-url
+V 70
+/svnroot/rdfapi-php/!svn/ver/287/trunk/rdfapi-php/api/model/ModelP.php
+END
+DbStore.php
+K 25
+svn:wc:ra_dav:version-url
+V 71
+/svnroot/rdfapi-php/!svn/ver/560/trunk/rdfapi-php/api/model/DbStore.php
+END
+Statement.php
+K 25
+svn:wc:ra_dav:version-url
+V 73
+/svnroot/rdfapi-php/!svn/ver/268/trunk/rdfapi-php/api/model/Statement.php
+END
+Node.php
+K 25
+svn:wc:ra_dav:version-url
+V 68
+/svnroot/rdfapi-php/!svn/ver/348/trunk/rdfapi-php/api/model/Node.php
+END
+DbModel.php
+K 25
+svn:wc:ra_dav:version-url
+V 71
+/svnroot/rdfapi-php/!svn/ver/533/trunk/rdfapi-php/api/model/DbModel.php
+END
+Resource.php
+K 25
+svn:wc:ra_dav:version-url
+V 72
+/svnroot/rdfapi-php/!svn/ver/453/trunk/rdfapi-php/api/model/Resource.php
+END
+ModelFactory.php
+K 25
+svn:wc:ra_dav:version-url
+V 76
+/svnroot/rdfapi-php/!svn/ver/524/trunk/rdfapi-php/api/model/ModelFactory.php
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/entries b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/entries
new file mode 100755
index 00000000..cb957eb5
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/entries
@@ -0,0 +1,184 @@
+8
+
+dir
+556
+https://rdfapi-php.svn.sourceforge.net/svnroot/rdfapi-php/trunk/rdfapi-php/api/model
+https://rdfapi-php.svn.sourceforge.net/svnroot/rdfapi-php
+
+
+
+2007-11-22T19:58:35.873076Z
+551
+p_frischmuth
+
+
+svn:special svn:externals svn:needs-lock
+
+
+
+
+
+
+
+
+
+
+
+b2ee660e-c932-0410-bdee-d8da4d8102f4
+
+Literal.php
+file
+
+
+
+
+2008-02-29T14:57:44.694548Z
+07e50d371bf51f08cc393559420f7bb5
+2007-08-13T05:14:26.997510Z
+497
+cweiske
+has-props
+
+Blanknode.php
+file
+
+
+
+
+2008-02-29T14:57:44.694548Z
+b9a94ec8fba94a8b9596d97d933c5676
+2007-06-20T21:19:09.683124Z
+453
+cweiske
+has-props
+
+DBase.php
+file
+
+
+
+
+2008-02-29T14:57:44.710169Z
+5cf7f369325355185a56e9436afd7196
+2006-11-21T09:38:51.000000Z
+320
+tgauss
+has-props
+
+MemModel.php
+file
+
+
+
+
+2008-02-29T14:57:44.710169Z
+d8987f4e712da3112f962e79de1560ea
+2007-05-01T12:59:18.000000Z
+425
+cweiske
+has-props
+
+Model.php
+file
+
+
+
+
+2008-02-29T14:57:44.725790Z
+1a0d324b20bd41b98669cb1018ff1cb2
+2007-11-22T19:58:35.873076Z
+551
+p_frischmuth
+has-props
+
+ModelP.php
+file
+
+
+
+
+2008-02-29T14:57:44.725790Z
+f6593f708c9e11d2fd2f2314700b5eea
+2006-06-19T13:43:55.000000Z
+287
+tgauss
+has-props
+
+DbStore.php
+file
+560
+
+
+
+2008-02-29T15:24:22.033780Z
+fc9caada11993be6f5fe8acdbab57800
+2008-02-29T15:24:20.914639Z
+560
+cax
+has-props
+
+Statement.php
+file
+
+
+
+
+2008-02-29T14:57:44.757031Z
+5442af9a529c84b26046c997d47f69c1
+2006-05-15T05:28:09.000000Z
+268
+tgauss
+has-props
+
+Node.php
+file
+
+
+
+
+2008-02-29T14:57:44.757031Z
+f5692caf43b4025c782916c6ae049afe
+2007-03-12T10:04:10.000000Z
+348
+cweiske
+has-props
+
+DbModel.php
+file
+
+
+
+
+2008-02-29T14:57:44.772651Z
+6d1d6724938773fb6310250e4f61f8cb
+2007-08-16T09:32:03.808912Z
+533
+cweiske
+has-props
+
+Resource.php
+file
+
+
+
+
+2008-02-29T14:57:44.772651Z
+e139b4ff0d1251ab7166c8c76cfafe84
+2007-06-20T21:19:09.683124Z
+453
+cweiske
+has-props
+
+ModelFactory.php
+file
+
+
+
+
+2008-02-29T14:57:44.788272Z
+e686d0efe0faf4d3635079b922953960
+2007-08-14T11:12:45.341905Z
+524
+kobasoft
+has-props
+
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/format b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/format
new file mode 100755
index 00000000..45a4fb75
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/format
@@ -0,0 +1 @@
+8
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/prop-base/Blanknode.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/prop-base/Blanknode.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/prop-base/Blanknode.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/prop-base/DBase.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/prop-base/DBase.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/prop-base/DBase.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/prop-base/DbModel.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/prop-base/DbModel.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/prop-base/DbModel.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/prop-base/DbStore.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/prop-base/DbStore.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/prop-base/DbStore.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/prop-base/Literal.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/prop-base/Literal.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/prop-base/Literal.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/prop-base/MemModel.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/prop-base/MemModel.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/prop-base/MemModel.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/prop-base/Model.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/prop-base/Model.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/prop-base/Model.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/prop-base/ModelFactory.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/prop-base/ModelFactory.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/prop-base/ModelFactory.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/prop-base/ModelP.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/prop-base/ModelP.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/prop-base/ModelP.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/prop-base/Node.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/prop-base/Node.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/prop-base/Node.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/prop-base/Resource.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/prop-base/Resource.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/prop-base/Resource.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/prop-base/Statement.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/prop-base/Statement.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/prop-base/Statement.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/text-base/Blanknode.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/text-base/Blanknode.php.svn-base
new file mode 100755
index 00000000..5afcad7e
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/text-base/Blanknode.php.svn-base
@@ -0,0 +1,120 @@
+,
+ * Radoslaw Oldakowski
+ *
+ * @package model
+ * @access public
+ *
+ */
+ class BlankNode extends Resource {
+
+ /**
+ * Constructor
+ * You can supply a label or You supply a model and a unique ID is gernerated.
+ *
+ * @param mixed $namespace_or_uri_or_model
+ * @param string $localName
+ * @access public
+ */
+ function BlankNode($namespace_or_uri_or_model , $localName = NULL) {
+
+ if (is_a($namespace_or_uri_or_model, 'Model')) {
+ // generate identifier
+ $id = $namespace_or_uri_or_model->getUniqueResourceURI(BNODE_PREFIX);
+
+ $this->uri = $id;
+
+ } else {
+ // set identifier
+ if ($localName == NULL) {
+ $this->uri = $namespace_or_uri_or_model;
+ } else {
+ $this->uri = $namespace_or_uri_or_model . $localName;
+ }
+ }
+ }
+
+ /**
+ * Returns the ID of the blank node.
+ *
+ * @return string
+ * @access public
+ */
+ function getID() {
+ return $this->uri;
+ }
+
+ /**
+ * Returns the ID of the blank node.
+ *
+ * @return string
+ * @access public
+ */
+ function getLabel() {
+ return $this->uri;
+ }
+
+ /**
+ * Dumps bNode.
+ *
+ * @access public
+ * @return string
+ */
+ function toString() {
+
+ return 'bNode("' . $this->uri . '")';
+ }
+
+ /**
+ * Checks if two blank nodes are equal.
+ * Two blank nodes are equal, if they have the same temporary ID.
+ *
+ * @access public
+ * @param object resource $that
+ * @return boolean
+ */
+ function equals ($that) {
+
+ if ($this == $that) {
+ return true;
+ }
+ if (($that == NULL) or !(is_a($that, 'BlankNode'))) {
+ return false;
+ }
+
+ if ($this->getURI() == $that->getURI()) {
+ return true;
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Doing string magic in PHP5
+ * @return string String representation of this Blank Node
+ */
+ function __toString()
+ {
+ return $this->toString();
+ }
+
+} // end: BlankNode
+
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/text-base/DBase.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/text-base/DBase.php.svn-base
new file mode 100755
index 00000000..7f0376b2
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/text-base/DBase.php.svn-base
@@ -0,0 +1,17 @@
+
+//
+// ----------------------------------------------------------------------------------
+
+// Include DBase class
+require_once( RDFAPI_INCLUDE_DIR . 'model/DbModel.php' );
+// include adodb classes
+require_once(RDFAPI_INCLUDE_DIR .'util/adodb/adodb.inc.php');
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/text-base/DbModel.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/text-base/DbModel.php.svn-base
new file mode 100755
index 00000000..d3ddf3dc
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/text-base/DbModel.php.svn-base
@@ -0,0 +1,1318 @@
+
+*
+* @package model
+* @access public
+*/
+
+
+class DbModel extends Model{
+
+ /**
+ * Database connection object.
+ *
+ * @var object ADOConnection
+ * @access private
+ */
+ var $dbConn;
+
+ /**
+ * Unique model URI.
+ * Used to identify the DbModel.
+ *
+ * @var string
+ * @access private
+ */
+ var $modelURI;
+
+
+ /**
+ * Database internal modelID.
+ * Used to avoid JOINs.
+ *
+ * @var string
+ * @access private
+ */
+ var $modelID;
+
+
+
+
+ /**
+ * Constructor
+ * Do not call this directly.
+ * Use the method getModel,getNewModel or putModel of the Class DbStore instead.
+ *
+ * @param object ADOConnection &$dbConnection
+ * @param string $modelURI
+ * @param string $modelID
+ * @param string $baseURI
+ * @access public
+ */
+ function DbModel(&$dbConnection, $modelURI, $modelID, $baseURI=NULL) {
+
+ $this->dbConn =& $dbConnection;
+ $this->modelURI = $modelURI;
+ $this->modelID = $modelID;
+ $this->baseURI = $this->_checkBaseURI($baseURI);
+ }
+
+
+ /**
+ * Set a base URI for the DbModel.
+ * Affects creating of new resources and serialization syntax.
+ *
+ * @param string $uri
+ * @throws SqlError
+ * @access public
+ */
+ function setBaseURI($uri) {
+
+ $this->baseURI = $this->_checkBaseURI($uri);
+
+ $rs = $this->dbConn->execute("UPDATE models SET baseURI='" .$this->baseURI ."'
+ WHERE modelID=" .$this->modelID);
+ if (!$rs)
+ $this->dbConn->errorMsg();
+ }
+
+
+ /**
+ * Return the number of statements in this DbModel.
+ *
+ * @return integer
+ * @access public
+ */
+ function size() {
+
+ $count =& $this->dbConn->getOne('SELECT COUNT(modelID) FROM statements
+ WHERE modelID = ' .$this->modelID);
+ return $count;
+ }
+
+
+ /**
+ * Check if this DbModel is empty.
+ *
+ * @return boolean
+ * @access public
+ */
+ function isEmpty() {
+
+ if ($this->size() == 0)
+ return TRUE;
+ return FALSE;
+ }
+
+
+ /**
+ * Add a new triple to this DbModel.
+ *
+ * @param object Statement &$statement
+ * @throws PhpError
+ * @throws SqlError
+ * @access public
+ * @return mixed true on success, false if the statement is already in the model,
+ * error message (string) on failure
+ */
+ function add(&$statement) {
+
+ if (!is_a($statement, 'Statement')) {
+ $errmsg = RDFAPI_ERROR . '(class: DbModel; method: add): Statement expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ if (!$this->contains($statement)) {
+
+ $subject_is = $this->_getNodeFlag($statement->subject());
+ $sql = "INSERT INTO statements
+ (modelID, subject, predicate, object, l_language, l_datatype, subject_is, object_is)
+ VALUES
+ (" .$this->modelID .","
+ . $this->dbConn->qstr($statement->getLabelSubject()) .","
+ . $this->dbConn->qstr($statement->getLabelPredicate()) .",";
+
+ if (is_a($statement->object(), 'Literal')) {
+ $quotedLiteral = $this->dbConn->qstr($statement->obj->getLabel());
+ $sql .= $quotedLiteral .","
+ ."'" .$statement->obj->getLanguage() ."',"
+ ."'" .$statement->obj->getDatatype() ."',"
+ ."'" .$subject_is ."',"
+ ."'l')";
+ }else{
+ $object_is = $this->_getNodeFlag($statement->object());
+ $sql .= $this->dbConn->qstr($statement->obj->getLabel()) .","
+ ."'',"
+ ."'',"
+ ."'" .$subject_is ."',"
+ ."'" .$object_is ."')";
+ }
+ $rs =& $this->dbConn->execute($sql);
+ if (!$rs) {
+ return $this->dbConn->errorMsg();
+ } else {
+ return true;
+ }
+ } else {
+ return false;
+ }
+ }
+
+
+ /**
+ * Alias for the method add().
+ *
+ * @param object Statement &$statement
+ * @throws PhpError
+ * @throws SqlError
+ * @access public
+ */
+ function addWithoutDuplicates(&$statement) {
+
+ $this->add($statement);
+ }
+
+
+ /**
+ * Remove the given triple from this DbModel.
+ *
+ * @param object Statement &$statement
+ * @throws PhpError
+ * @throws SqlError
+ * @access public
+ */
+ function remove(&$statement) {
+
+ if (!is_a($statement, 'Statement')) {
+ $errmsg = RDFAPI_ERROR . '(class: DbModel; method: remove): Statement expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ $sql = 'DELETE FROM statements
+ WHERE modelID=' .$this->modelID;
+ $sql .= $this->_createDynSqlPart_SPO ($statement->subj, $statement->pred, $statement->obj);
+
+ $rs =& $this->dbConn->execute($sql);
+ if (!$rs)
+ $this->dbConn->errorMsg();
+ }
+
+
+ /**
+ * Short dump of the DbModel.
+ *
+ * @return string
+ * @access public
+ */
+ function toString() {
+
+ return 'DbModel[modelURI=' .$this->modelURI .'; baseURI=' .$this->getBaseURI() .'; size=' .$this->size() .']';
+ }
+
+
+ /**
+ * Dump of the DbModel including all triples.
+ *
+ * @return string
+ * @access public
+ */
+ function toStringIncludingTriples() {
+
+ $memModel =& $this->getMemModel();
+ return $memModel->toStringIncludingTriples();
+ }
+
+
+
+ /**
+ * Create a MemModel containing all the triples of the current DbModel.
+ *
+ * @return object MemModel
+ * @access public
+ */
+ function & getMemModel() {
+
+ $recordSet = $this->_getRecordSet($this);
+ $m = $this->_convertRecordSetToMemModel($recordSet);
+ return $m;
+ }
+
+
+
+ /**
+ * Returns the model id
+ *
+ * @return int Model id number
+ * @access public
+ */
+ function getModelID()
+ {
+ return $this->modelID;
+ }
+
+
+
+ /**
+ * Returns the database connection object
+ *
+ * @return ADOdb Database object
+ * @access public
+ */
+ function &getDbConn()
+ {
+ return $this->dbConn;
+ }
+
+
+
+ /**
+ * Write the RDF serialization of the _DbModel as HTML.
+ *
+ * @access public
+ */
+ function writeAsHtml() {
+
+ $memModel =& $this->getMemModel();
+ $memModel->writeAsHtml();
+ }
+
+
+ /**
+ * Write the RDF serialization of the DbModel as HTML table.
+ *
+ * @access public
+ */
+ function writeAsHtmlTable() {
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_UTILITY);
+ $memModel =& $this->getMemModel();
+ RDFUtil::writeHTMLTable($memModel);
+ }
+
+
+ /**
+ * Write the RDF serialization of the DbModel to string.
+ *
+ * @return string
+ * @access public
+ */
+ function writeRdfToString() {
+
+ $memModel =& $this->getMemModel();
+ return $memModel->writeRdfToString();
+ }
+
+
+ /**
+ * Saves the RDF,N3 or N-Triple serialization of the DbModel to a file.
+ * You can decide to which format the model should be serialized by using a
+ * corresponding suffix-string as $type parameter. If no $type parameter
+ * is placed this method will serialize the model to XML/RDF format.
+ * Returns FALSE if the DbModel couldn't be saved to the file.
+ *
+ * @access public
+ * @param string $filename
+ * @param string $type
+ * @throws PhpError
+ * @return boolean
+ */
+ function saveAs($filename, $type ='rdf') {
+
+ $memModel = $this->getMemModel();
+ $memModel->saveAs($filename, $type);
+
+ }
+
+
+ /**
+ * Check if the DbModel contains the given statement.
+ *
+ * @param object Statement &$statement
+ * @return boolean
+ * @access public
+ */
+ function contains(&$statement) {
+
+ $sql = 'SELECT modelID FROM statements
+ WHERE modelID = ' .$this->modelID;
+ $sql .= $this->_createDynSqlPart_SPO($statement->subj, $statement->pred, $statement->obj);
+
+ $res =& $this->dbConn->getOne($sql);
+
+ if (!$res)
+ return FALSE;
+ return TRUE;
+ }
+
+
+ /**
+ * Determine if all of the statements in the given model are also contained in this DbModel.
+ *
+ * @param object Model &$model
+ * @return boolean
+ * @access public
+ */
+ function containsAll(&$model) {
+
+ if (is_a($model, 'MemModel')) {
+
+ foreach($model->triples as $statement)
+ if(!$this->contains($statement))
+ return FALSE;
+ return TRUE;
+ }
+
+ elseif (is_a($model, 'DbModel')) {
+
+ $recordSet =& $this->_getRecordSet($model);
+ while (!$recordSet->EOF) {
+ if (!$this->_containsRow($recordSet->fields))
+ return FALSE;
+ $recordSet->moveNext();
+ }
+ return TRUE;
+ }
+
+ $errmsg = RDFAPI_ERROR . '(class: DbModel; method: containsAll): Model expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+
+ /**
+ * Determine if any of the statements in the given model are also contained in this DbModel.
+ *
+ * @param object Model &$model
+ * @return boolean
+ * @access public
+ */
+ function containsAny(&$model) {
+
+ if (is_a($model, 'MemModel')) {
+
+ foreach($model->triples as $statement)
+ if($this->contains($statement))
+ return TRUE;
+ return FALSE;
+ }
+
+ elseif (is_a($model, 'DbModel')) {
+
+ $recordSet =& $this->_getRecordSet($model);
+ while (!$recordSet->EOF) {
+ if ($this->_containsRow($recordSet->fields))
+ return TRUE;
+ $recordSet->moveNext();
+ }
+ return FALSE;
+ }
+
+ $errmsg = RDFAPI_ERROR . '(class: DbModel; method: containsAny): Model expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+
+ /**
+ * General method to search for triples in the DbModel.
+ * NULL input for any parameter will match anything.
+ * Example: $result = $m->find( NULL, NULL, $node );
+ * Finds all triples with $node as object.
+ *
+ * @param object Resource $subject
+ * @param object Resource $predicate
+ * @param object Node $object
+ * @return object MemModel
+ * @throws PhpError
+ * @throws SqlError
+ * @access public
+ */
+ function find($subject, $predicate, $object) {
+
+ if ((!is_a($subject, 'Resource') && $subject != NULL) ||
+ (!is_a($predicate, 'Resource') && $predicate != NULL) ||
+ (!is_a($object, 'Node') && $object != NULL)) {
+
+ $errmsg = RDFAPI_ERROR . '(class: DbModel; method: find): Parameters must be subclasses of Node or NULL';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ // static part of the sql statement
+ $sql = 'SELECT subject, predicate, object, l_language, l_datatype, subject_is, object_is
+ FROM statements
+ WHERE modelID = ' .$this->modelID;
+
+ // dynamic part of the sql statement
+ $sql .= $this->_createDynSqlPart_SPO($subject, $predicate, $object);
+
+ // execute the query
+ $recordSet =& $this->dbConn->execute($sql);
+
+ if (!$recordSet)
+ echo $this->dbConn->errorMsg();
+
+ // write the recordSet into memory Model
+ else
+ return $this->_convertRecordSetToMemModel($recordSet);
+ }
+
+
+ /**
+ * Method to search for triples using Perl-style regular expressions.
+ * NULL input for any parameter will match anything.
+ * Example: $result = $m->find_regex( NULL, NULL, $regex );
+ * Finds all triples where the label of the object node matches
+ *the regular expression.
+ * Return an empty MemModel if nothing is found.
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * WARNING: Mhis method loads a DbModel into memory and performs the search
+ * on a MemModel, which can be slow with large models.
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ *
+ * @param string $subject_regex
+ * @param string $predicate_regex
+ * @param string $object_regex
+ * @return object MemModel
+ * @throws PhpError
+ * @throws SqlError
+ * @access public
+ */
+ function findRegex($subject_regex, $predicate_regex, $object_regex) {
+
+ $mm =& $this->getMemModel();
+
+ return $mm->findRegex($subject_regex, $predicate_regex, $object_regex);
+ }
+
+
+ /**
+ * Return all tripels of a certain vocabulary.
+ * $vocabulary is the namespace of the vocabulary inluding a # : / char at the end.
+ * e.g. http://www.w3.org/2000/01/rdf-schema#
+ * Return an empty model if nothing is found.
+ *
+ * @param string $vocabulary
+ * @return object MemModel
+ * @throws PhpError
+ * @throws SqlError
+ * @access public
+ */
+ function findVocabulary($vocabulary) {
+
+ $sql = "SELECT subject, predicate, object, l_language, l_datatype, subject_is, object_is
+ FROM statements
+ WHERE modelID = " .$this->modelID ."
+ AND predicate LIKE '" .$vocabulary ."%'";
+
+ $recordSet =& $this->dbConn->execute($sql);
+
+ if (!$recordSet)
+ echo $this->dbConn->errorMsg();
+
+ // write the recordSet into memory Model
+ else
+ return $this->_convertRecordSetToMemModel($recordSet);
+ }
+
+
+ /**
+ * Search for triples and return the first matching statement.
+ * NULL input for any parameter will match anything.
+ * Return an NULL if nothing is found.
+ * You can set an search offset with $offset.
+ *
+ * @param object Resource $subject
+ * @param object Resource $predicate
+ * @param object Node $object
+ * @param integer $offset
+ * @return object Statement
+ * @throws PhpError
+ * @throws SqlError
+ * @access public
+ */
+ function findFirstMatchingStatement($subject, $predicate, $object, $offset = -1) {
+
+ if ((!is_a($subject, 'Resource') && $subject != NULL) ||
+ (!is_a($predicate, 'Resource') && $predicate != NULL) ||
+ (!is_a($object, 'Node') && $object != NULL)) {
+
+ $errmsg = RDFAPI_ERROR . '(class: DbModel; method: find): Parameters must be subclasses of Node or NULL';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ // static part of the sql statement
+ $sql = 'SELECT subject, predicate, object, l_language, l_datatype, subject_is, object_is
+ FROM statements
+ WHERE modelID = ' .$this->modelID;
+
+ // dynamic part of the sql statement
+ $sql .= $this->_createDynSqlPart_SPO($subject, $predicate, $object);
+
+ // execute the query
+ $recordSet =& $this->dbConn->selectLimit($sql,1,($offset));
+
+ if (!$recordSet)
+ echo $this->dbConn->errorMsg();
+ else {
+ if (!$recordSet->fields)
+ return NULL;
+ else {
+ $memModel = $this->_convertRecordSetToMemModel($recordSet);
+ return $memModel->triples[0];
+ }
+ }
+ }
+
+
+ /**
+ * Search for triples and return the number of matches.
+ * NULL input for any parameter will match anything.
+ *
+ * @param object Resource $subject
+ * @param object Resource $predicate
+ * @param object Node $object
+ * @return integer
+ * @throws PhpError
+ * @throws SqlError
+ * @access public
+ */
+ function findCount($subject, $predicate, $object) {
+
+ if ((!is_a($subject, 'Resource') && $subject != NULL) ||
+ (!is_a($predicate, 'Resource') && $predicate != NULL) ||
+ (!is_a($object, 'Node') && $object != NULL)) {
+
+ $errmsg = RDFAPI_ERROR . '(class: DbModel; method: find): Parameters must be subclasses of Node or NULL';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ // static part of the sql statement
+ $sql = 'SELECT COUNT(*)
+ FROM statements
+ WHERE modelID = ' .$this->modelID;
+
+ // dynamic part of the sql statement
+ $sql .= $this->_createDynSqlPart_SPO($subject, $predicate, $object);
+
+ // execute the query
+ $recordSet =& $this->dbConn->execute($sql);
+
+ if (!$recordSet)
+ echo $this->dbConn->errorMsg();
+ else
+ return $recordSet->fields[0];
+ }
+
+
+ /**
+ * Perform an RDQL query on this DbModel.
+ * This method returns an associative array of variable bindings.
+ * The values of the query variables can either be RAP's objects (instances of Node)
+ * if $returnNodes set to TRUE, or their string serialization.
+ *
+ * @access public
+ * @param string $queryString
+ * @param boolean $returnNodes
+ * @return array [][?VARNAME] = object Node (if $returnNodes = TRUE)
+ * OR array [][?VARNAME] = string
+ *
+ */
+ function rdqlQuery($queryString, $returnNodes = TRUE) {
+ require_once(RDFAPI_INCLUDE_DIR.PACKAGE_RDQL);
+ $parser = new RdqlParser();
+ $parsedQuery =& $parser->parseQuery($queryString);
+
+ // this method can only query this DbModel
+ // if another model was specified in the from clause throw an error
+ if (isset($parsedQuery['sources'][0]))
+ if($parsedQuery['sources'][0] != $this->modelURI) {
+ $errmsg = RDFAPI_ERROR . '(class: DbModel; method: rdqlQuery):';
+ $errmsg .= ' this method can only query this DbModel';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ $engine = new RdqlDbEngine();
+ $res =& $engine->queryModel($this, $parsedQuery, $returnNodes);
+
+ return $res;
+ }
+
+
+ /**
+ * Perform an RDQL query on this DBModel.
+ * This method returns an RdqlResultIterator of variable bindings.
+ * The values of the query variables can either be RAP's objects (instances of Node)
+ * if $returnNodes set to TRUE, or their string serialization.
+ *
+ * @access public
+ * @param string $queryString
+ * @param boolean $returnNodes
+ * @return object RdqlResultIterator = with values as object Node (if $returnNodes = TRUE)
+ * OR object RdqlResultIterator = with values as strings if (if $returnNodes = FALSE)
+ *
+ */
+ function rdqlQueryAsIterator($queryString, $returnNodes = TRUE) {
+ require_once(RDFAPI_INCLUDE_DIR.PACKAGE_RDQL);
+ return new RdqlResultIterator($this->rdqlQuery($queryString, $returnNodes));
+ }
+
+ /**
+ * General method to replace nodes of a DbModel.
+ * NULL input for any parameter will match nothing.
+ * Example: $m->replace($resource, NULL, $node, $replacement);
+ * Replaces all $node objects beeing subject or object in
+ * any triple of the model with the $replacement node.
+ * Throw an error in case of a paramter mismatch.
+ *
+ * @param object Resource $subject
+ * @param object Resource $predicate
+ * @param object Node $object
+ * @param object Node $replacement
+ * @throws PhpError
+ * @throws SqlError
+ * @access public
+ */
+ function replace($subject, $predicate, $object, $replacement) {
+
+ // check the correctness of the passed parameters
+ if ( ((!is_a($subject, 'Resource') && $subject != NULL) ||
+ (!is_a($predicate, 'Resource') && $predicate != NULL) ||
+ (!is_a($object, 'Node') && $object != NULL)) ||
+ (($subject != NULL && is_a($replacement, 'Literal')) ||
+ ($predicate != NULL && (is_a($replacement, 'Literal') ||
+ is_a($replacement, 'BlankNode')))) )
+ {
+ $errmsg = RDFAPI_ERROR . '(class: DbModel; method: find): Parameter mismatch';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ if (!(!$subject && !$predicate && !$object)) {
+
+ // create an update sql statement
+ $comma = '';
+ $sql = 'UPDATE statements
+ SET ';
+ if ($subject) {
+ $sql .= " subject ='" .$replacement->getLabel() ."', "
+ ." subject_is='" .$this->_getNodeFlag($replacement) ."' ";
+ $comma = ',';
+ }
+ if ($predicate) {
+ $sql .= $comma ." predicate='" .$replacement->getLabel() ."' ";
+ $comma = ',';
+ }
+ if ($object) {
+ $quotedObject = $this->dbConn->qstr($replacement->getLabel());
+ $sql .= $comma .' object=' .$quotedObject
+ .", object_is='" .$this->_getNodeFlag($replacement) ."' ";
+ if (is_a($replacement, 'Literal')) {
+ $sql .= ", l_language='" .$replacement->getLanguage() ."' "
+ .", l_datatype='" .$replacement->getDataType() ."' ";
+ }
+ }
+ $sql .= 'WHERE modelID = ' .$this->modelID;
+ $sql .= $this->_createDynSqlPart_SPO($subject, $predicate, $object);
+
+ // execute the query
+ $rs =& $this->dbConn->execute($sql);
+
+ if (!$rs)
+ echo $this->dbConn->errorMsg();
+ }
+ }
+
+
+ /**
+ * Check if two models are equal.
+ * Two models are equal if and only if the two RDF graphs they represent are isomorphic.
+ *
+ * Warning: This method doesn't work correct with models where the same blank node has different
+ * identifiers in the two models. We will correct this in a future version.
+ *
+ * @param object model &$that
+ * @return boolean
+ * @throws PhpError
+ * @access public
+ */
+
+ function equals(&$that) {
+
+ if (!is_a($that, 'Model')) {
+ $errmsg = RDFAPI_ERROR . '(class: DbModel; method: equals): Model expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ if ($this->size() != $that->size())
+ return FALSE;
+
+ include_once(RDFAPI_INCLUDE_DIR. "util/ModelComparator.php");
+ return ModelComparator::compare($this,$that);
+ }
+
+
+ /**
+ * Return a new MemModel that is the set-union the model with another model.
+ *
+ * The result of taking the set-union of two or more RDF graphs (i.e. sets of triples)
+ * is another graph, which we will call the merge of the graphs.
+ * Each of the original graphs is a subgraph of the merged graph. Notice that when forming
+ * a merged graph, two occurrences of a given uriref or literal as nodes in two different
+ * graphs become a single node in the union graph (since by definition they are the same
+ * uriref or literal) but blank nodes are not 'merged' in this way; and arcs are of course
+ * never merged. In particular, this means that every blank node in a merged graph can be
+ * identified as coming from one particular graph in the original set of graphs.
+ *
+ * Notice that one does not, in general, obtain the merge of a set of graphs by concatenating
+ * their corresponding N-triples documents and constructing the graph described by the merged
+ * document, since if some of the documents use the same node identifiers, the merged document
+ * will describe a graph in which some of the blank nodes have been 'accidentally' merged.
+ * To merge Ntriples documents it is necessary to check if the same nodeID is used in two or
+ * more documents, and to replace it with a distinct nodeID in each of them, before merging the
+ * documents. (Not implemented yet !!!!!!!!!!!)
+ *
+ * @param object Model $model
+ * @return object MemModel
+ * @throws PhpError
+ * @access public
+ *
+ */
+ function & unite(&$model) {
+
+ if (!is_a($model, 'Model')) {
+ $errmsg = RDFAPI_ERROR . '(class: DbModel; method: unite): Model expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ if (is_a($model, 'MemModel')) {
+
+ $thisModel =& $this->getMemModel();
+ return $thisModel->unite($model);
+ }
+
+ elseif (is_a($model, 'DbModel')) {
+
+ $thisModel =& $this->getMemModel();
+ $thatModel =& $model->getMemModel();
+ return $thisModel->unite($thatModel);
+ }
+ }
+
+
+ /**
+ * Return a new MemModel that is the subtraction of another model from this DbModel.
+ *
+ * @param object Model $model
+ * @return object MemModel
+ * @throws PhpError
+ * @access public
+ */
+
+ function & subtract(&$model) {
+
+ if (!is_a($model, 'Model')) {
+ $errmsg = RDFAPI_ERROR . '(class: DbModel; method: subtract): Model expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ if (is_a($model, 'MemModel')) {
+
+ $thisModel =& $this->getMemModel();
+ return $thisModel->subtract($model);
+ }
+
+ elseif (is_a($model, 'DbModel')) {
+
+ $thisModel =& $this->getMemModel();
+ $thatModel =& $model->getMemModel();
+ return $thisModel->subtract($thatModel);
+ }
+ }
+
+
+ /**
+ * Return a new MemModel containing all the statements which are in both
+ * this model and the given model.
+ *
+ * @param object Model $model
+ * @return object MemModel
+ * @throws PhpError
+ * @access public
+ */
+ function & intersect(&$model) {
+
+ if (is_a($model, 'MemModel')) {
+
+ $thisModel =& $this->getMemModel();
+ return $thisModel->intersect($model);
+ }
+
+ elseif (is_a($model, 'DbModel')) {
+
+ $thisModel =& $this->getMemModel();
+ $thatModel =& $model->getMemModel();
+ return $thisModel->intersect($thatModel);
+ }
+
+ $errmsg = RDFAPI_ERROR . '(class: DbModel; method: intersect: Model expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+
+ /**
+ * Add the given model to this DbModel.
+ * This function monitors for SQL errors, and will commit if no errors have occured,
+ * otherwise it will rollback.
+ * If any statement of the model to be added to this model contains a blankNode
+ * with an identifier already existing in this model, a new blankNode is generated.
+ *
+ * @param object Model $model
+ * @throws PhpError
+ * @access public
+ */
+ function addModel(&$model) {
+
+ if (!is_a($model, 'Model')) {
+ $errmsg = RDFAPI_ERROR . '(class: DbModel; method: addModel): Model expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ $blankNodes_tmp = array();
+
+ if (is_a($model, 'MemModel')) {
+
+ $this->dbConn->startTrans();
+ foreach ($model->triples as $statement)
+ $this->_addStatementFromAnotherModel($statement, $blankNodes_tmp);
+ $this->addParsedNamespaces($model->getParsedNamespaces());
+
+ $this->dbConn->completeTrans();
+ }
+
+ elseif (is_a($model, 'DbModel')) {
+
+ $this->dbConn->startTrans();
+ $memModel =& $model->getMemModel();
+ foreach($memModel->triples as $statement)
+ $this->_addStatementFromAnotherModel($statement, $blankNodes_tmp);
+ $this->addParsedNamespaces($model->getParsedNamespaces());
+ $this->dbConn->completeTrans();
+ }
+ }
+
+
+ /**
+ * Reify the DbModel.
+ * Return a new MemModel that contains the reifications of all statements of this DbModel.
+ *
+ * @return object MemModel
+ * @access public
+ */
+ function & reify() {
+
+ $memModel =& $this->getMemModel();
+ return $memModel->reify();
+ }
+
+ /**
+ * Remove this DbModel from database and clean up.
+ * This function monitors for SQL errors, and will commit if no errors have occured,
+ * otherwise it will rollback.
+ *
+ * @throws SqlError
+ * @access public
+ */
+ function delete() {
+
+ $this->dbConn->startTrans();
+ $this->dbConn->execute('DELETE FROM models
+ WHERE modelID=' .$this->modelID);
+ $this->dbConn->execute('DELETE FROM statements
+ WHERE modelID=' .$this->modelID);
+ $this->dbConn->execute('DELETE FROM namespaces
+ WHERE modelID=' .$this->modelID);
+
+ if (!$this->dbConn->completeTrans())
+ echo $this->dbConn->errorMsg();
+ else
+ $this->close();
+ }
+
+
+ /**
+ * Close this DbModel
+ *
+ * @access public
+ */
+ function close() {
+
+ unset($this);
+ }
+
+
+ // =============================================================================
+ // **************************** private methods ********************************
+ // =============================================================================
+
+
+
+
+
+ /**
+ * If the URI doesn't end with # : or /, then a # is added to the URI.
+ * Used at setting the baseURI of this DbModel.
+ *
+ * @param string $uri
+ * @return string
+ * @access private
+ */
+ function _checkBaseURI($uri) {
+
+ if ($uri != NULL) {
+ $c = substr($uri, strlen($uri)-1 ,1);
+ if (!($c=='#' || $c==':' || $c=='/' || $c=="\\"))
+ $uri .= '#';
+ }
+ return $uri;
+ }
+
+
+ /**'
+ * Return the flag of the Node object.
+ * r - Resource, b - BlankNode, l - Literal
+ *
+ * @param object Node $object
+ * @return string
+ * @access private
+ */
+ function _getNodeFlag($object) {
+
+ return is_a($object,'BlankNode')?'b':(is_a($object,'Resource')?'r':'l');
+ }
+
+
+ /**
+ * Convert an ADORecordSet to a memory Model.
+ *
+ * Every successful database query returns an ADORecordSet object which is actually
+ * a cursor that holds the current row in the array fields[].
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * !!! This method can only be applied to a RecordSet with array fields[]
+ * !!! containing a representation of the database table: statements,
+ * !!! with an index corresponding to following table columns:
+ * !!! [0] - subject, [1] - predicate, [2] - object, [3] - l_language,
+ * !!! [4] - l_datatype, [5] - subject_is, [6] - object_is
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ *
+ * @param object ADORecordSet
+ * @return object MemModel
+ * @access private
+ */
+ function _convertRecordSetToMemModel(&$recordSet) {
+
+ $res = new MemModel($this->baseURI);
+ while (!$recordSet->EOF) {
+
+ // subject
+ if ($recordSet->fields[5] == 'r')
+ $sub = new Resource($recordSet->fields[0]);
+ else
+ $sub = new BlankNode($recordSet->fields[0]);
+
+ // predicate
+ $pred = new Resource($recordSet->fields[1]);
+
+ // object
+ if ($recordSet->fields[6] == 'r')
+ $obj = new Resource($recordSet->fields[2]);
+ elseif ($recordSet->fields[6] == 'b')
+ $obj = new BlankNode($recordSet->fields[2]);
+ else {
+ $obj = new Literal($recordSet->fields[2], $recordSet->fields[3]);
+ if ($recordSet->fields[4])
+ $obj->setDatatype($recordSet->fields[4]);
+ }
+
+ $statement = new Statement($sub, $pred, $obj);
+ $res->add($statement);
+
+ $recordSet->moveNext();
+ }
+ $res->addParsedNamespaces($this->getParsedNamespaces());
+ return $res;
+ }
+
+
+ /**
+ * Create the dynamic part of an sql statement selecting triples with the
+ * given parameters ($subject, $predicate, $object).
+ *
+ * @param object Resource $subject
+ * @param object Resource $predicate
+ * @param object Node $object
+ * @return string
+ * @access private
+ */
+ function _createDynSqlPart_SPO($subject, $predicate, $object) {
+
+ // conditions derived from the parameters passed to the function
+
+ $subject_is=is_a($subject,'BlankNode')?'b':(is_a($subject,'Resource')?'r':'l');
+ $sql='';
+ if ($subject != NULL)
+ $sql .= " AND subject='" .$subject->getLabel() ."'
+ AND subject_is='" .$subject_is ."'";
+ if ($predicate != NULL)
+ $sql .= " AND predicate='" .$predicate->getLabel() ."'";
+ if ($object != NULL) {
+ $object_is = is_a($object,'BlankNode')?'b':(is_a($object,'Resource')?'r':'l');
+ if (is_a($object, 'Resource'))
+ $sql .= " AND object='" .$object->getLabel() ."'
+ AND object_is ='" .$object_is ."'";
+ else {
+ $quotedLiteral = $this->dbConn->qstr($object->getLabel());
+ $sql .= " AND object=" .$quotedLiteral ."
+ AND l_language='" .$object->getLanguage() ."'
+ AND l_datatype='" .$object->getDataType() ."'
+ AND object_is ='" .$object_is ."'";
+ }
+ }
+ return $sql;
+ }
+
+
+ /**
+ * Get an ADORecordSet with array fields[] containing a representation of
+ * the given DbModel stored in the table: statements, with an index corresponding
+ * to following table columns:
+ * [0] - subject, [1] - predicate, [2] - object, [3] - l_language,
+ * [4] - l_datatype, [5] - subject_is, [6] - object_is
+ * (This method operates on data from a DbModel without loading it into a memory model
+ * in order to save resources and improve speed).
+ *
+ * @param object DbModel $DbModel
+ * @return object ADORecordSet
+ * @access private
+ */
+ function _getRecordSet (&$dbModel) {
+
+ $sql = 'SELECT subject, predicate, object, l_language, l_datatype, subject_is, object_is
+ FROM statements
+ WHERE modelID = ' .$dbModel->modelID;
+
+ return $recordSet =& $this->dbConn->execute($sql);
+ }
+
+
+ /**
+ * Check if this DbModel contains the given row from the array fields[] of an ADORecordSet
+ * The array index corresponds to following table columns:
+ * [0] - subject, [1] - predicate, [2] - object, [3] - l_language,
+ * [4] - l_datatype, [5] - subject_is, [6] - object_is
+ *
+ * @param array $row
+ * @return boolean
+ * @access private
+ */
+ function _containsRow ($row) {
+
+ $sql = "SELECT modelID FROM statements
+ WHERE modelID = " .$this->modelID ."
+ AND subject =" .$this->dbConn->qstr($row[0]) ."
+ AND predicate =" .$this->dbConn->qstr($row[1]) ."
+ AND object =" .$this->dbConn->qstr($row[2]) ."
+ AND l_language=" .$this->dbConn->qstr($row[3]) ."
+ AND l_datatype=" .$this->dbConn->qstr($row[4]) ."
+ AND subject_is=" .$this->dbConn->qstr($row[5]) ."
+ AND object_is=" .$this->dbConn->qstr($row[6]);
+
+ $res =& $this->dbConn->getOne($sql);
+
+ if (!$res)
+ return FALSE;
+ return TRUE;
+ }
+
+
+
+
+
+ /**
+ * Returns the models namespaces.
+ *
+ * @author Tobias Gauss
+ * @return mixed Array of key-value pairs. Namespace is the key,
+ * prefix the value. If no namespaces are found,
+ * boolean false is returned.
+ *
+ * @access public
+ */
+ function getParsedNamespaces(){
+ $sql = "SELECT * FROM namespaces
+ WHERE modelID = " .$this->modelID;
+ $temp = false;
+ $res = $this->dbConn->execute($sql);
+ if($res){
+ while (!$res->EOF) {
+ $temp[$res->fields[1]]=$res->fields[2];
+ $res->moveNext();
+ }
+ }
+ return $temp;
+ }
+
+
+
+ /**
+ * Adds the namespaces to the model. This method is called by
+ * the parser. !!!! addParsedNamespaces() not overwrites manual
+ * added namespaces in the model !!!!
+ *
+ * @author Tobias Gauss
+ * @param array $newNs Array of namespace => prefix assignments
+ *
+ * @access public
+ */
+ function addParsedNamespaces($newNs){
+ if($newNs)
+ foreach($newNs as $namespace => $prefix){
+ $this->addNamespace($prefix, $namespace);
+ }
+ }
+
+
+ /**
+ * Adds a namespace and prefix to the model.
+ *
+ * @author Tobias Gauss
+ * @param string $prefix Prefix
+ * @param string $nmsp Namespace URI
+ *
+ * @access public
+ */
+ function addNamespace($prefix,$nmsp){
+
+ if($nmsp != '' && $prefix !=''){
+ if($this->_checkNamespace($nmsp)){
+ $sql = "UPDATE namespaces SET prefix=".$this->dbConn->qstr($prefix)." WHERE
+ modelID=".$this->modelID." AND namespace=".$this->dbConn->qstr($nmsp);
+ }else{
+ $sql = "INSERT INTO namespaces
+ (modelID, namespace, prefix)
+ VALUES
+ (" .$this->modelID .','
+ . $this->dbConn->qstr($nmsp) . ','
+ . $this->dbConn->qstr($prefix) . ')';
+ }
+
+ $rs =& $this->dbConn->execute($sql);
+ if (!$rs)
+ $this->dbConn->errorMsg();
+ }
+ }
+
+ /**
+ * checks if a namespace is already in the model.
+ *
+ * @author Tobias Gau�
+ * @access private
+ * @param Array $newNs
+ */
+ function _checkNamespace($nmsp){
+ $res = true;
+ $sql = "SELECT * FROM namespaces
+ WHERE modelID = " .$this->modelID." AND
+ namespace=" . $this->dbConn->qstr($nmsp);
+ $rs =& $this->dbConn->execute($sql);
+ if (!$rs){
+ $this->dbConn->errorMsg();
+ }else{
+ if($rs->fields == false)
+ $res = false;
+ }
+ return $res;
+
+
+ }
+
+ /**
+ * Returns a FindIterator for traversing the MemModel.
+ * @access public
+ * @return object FindIterator
+ */
+ function & iterFind($sub=null,$pred=null,$obj=null) {
+ // Import Package Utility
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_UTILITY);
+
+ $if = new IterFind($this,$sub,$pred,$obj);
+ return $if;
+ }
+
+ /**
+ * Removes a single namespace from the model
+ *
+ * @author Tobias Gauss
+ * @param string $nmsp Namespace URI
+ *
+ * @return mixed True if all went well, error message otherwise
+ *
+ * @access public
+ */
+ function removeNamespace($nmsp){
+
+ $sql = 'DELETE FROM namespaces
+ WHERE modelID=' .$this->modelID." AND namespace=". $this->dbConn->qstr($nmsp);
+
+ $rs =& $this->dbConn->execute($sql);
+ if (!$rs)
+ return $this->dbConn->errorMsg();
+ else {
+ return true;
+ }
+ }
+
+
+
+
+ /**
+ * Add the given row from the array fields[] of an ADORecordSet to this DbModel
+ * The array index corresponds to following table columns:
+ * [0] - subject, [1] - predicate, [2] - object, [3] - l_language,
+ * [4] - l_datatype, [5] - subject_is, [6] - object_is
+ *
+ * @param array $row
+ * @throws SqlError
+ * @access private
+ *
+ function _insertRow ($row) {
+
+ $quotedObject = $this->dbConn->qstr($row[2]);
+ $sql = "INSERT INTO statements VALUES
+ (" .$this->modelID .","
+ ."'" .$row[0] ."',"
+ ."'" .$row[1] ."',"
+ ."" .$quotedObject .","
+ ."'" .$row[3] ."',"
+ ."'" .$row[4] ."',"
+ ."'" .$row[5] ."',"
+ ."'" .$row[6] ."')";
+
+ $rs =& $this->dbConn->execute($sql);
+ if (!$rs)
+ $this->dbConn->errorMsg();
+ }
+ */
+
+} // end: Class DbModel
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/text-base/DbStore.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/text-base/DbStore.php.svn-base
new file mode 100755
index 00000000..a065097b
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/text-base/DbStore.php.svn-base
@@ -0,0 +1,917 @@
+
+ * @author Daniel Westphal (http://www.d-westphal.de)
+ *
+ * @package model
+ * @access public
+ */
+
+
+class DbStore extends Object
+{
+ /**
+ * Array with all supported database types
+ *
+ * @var array
+ */
+ public static $arSupportedDbTypes = array(
+ "MySQL",
+ "MySQLi",
+ "MSSQL",
+ 'MsAccess'
+ );
+
+ /**
+ * Database connection object
+ *
+ * @var object ADOConnection
+ * @access private
+ */
+ var $dbConn;
+
+ /**
+ * Database driver name
+ *
+ * @var string
+ */
+ protected $driver = null;
+
+ /**
+ * SparqlParser so we can re-use it
+ * @var Parser
+ */
+ var $queryParser = null;
+
+
+/**
+ * Constructor:
+ * Set the database connection with the given parameters.
+ *
+ * @param string $dbDriver
+ * @param string $host
+ * @param string $dbName
+ * @param string $user
+ * @param string $password
+ * @access public
+ */
+ function DbStore ($dbDriver=ADODB_DB_DRIVER, $host=ADODB_DB_HOST, $dbName=ADODB_DB_NAME,
+ $user=ADODB_DB_USER, $password=ADODB_DB_PASSWORD) {
+
+ // include DBase Package
+ require_once(RDFAPI_INCLUDE_DIR.PACKAGE_DBASE);
+
+ // create a new connection object
+ $this->dbConn =& ADONewConnection($dbDriver);
+ $this->driver = $dbDriver;
+
+ //activate the ADOdb DEBUG mode
+ if (ADODB_DEBUG_MODE == '1')
+ $this->dbConn->debug = true;
+
+ // connect to database
+ $r = $this->dbConn->NConnect($host, $user, $password, $dbName);
+ if ($r !== true) {
+ throw new Exception('Could not connect to database');
+ }
+
+ // optimized for speed
+ $this->dbConn->setFetchMode(ADODB_FETCH_NUM);
+ //$ADODB_COUNTRECS = FALSE;
+ }
+
+
+
+/**
+ * List all DbModels stored in the database.
+ *
+ * @return array
+ * @throws SqlError
+ * @access public
+ */
+ function listModels() {
+
+ $recordSet =& $this->dbConn->execute("SELECT modelURI, baseURI
+ FROM models");
+ if (!$recordSet)
+ echo $this->dbConn->errorMsg();
+ else {
+ $models = array();
+ $i=0;
+ while (!$recordSet->EOF) {
+
+ $models[$i]['modelURI'] = $recordSet->fields[0];
+ $models[$i]['baseURI'] = $recordSet->fields[1];
+
+ ++$i;
+ $recordSet->moveNext();
+ }
+ return $models;
+ }
+ }
+
+
+/**
+ * Check if the DbModel with the given modelURI is already stored in the database
+ *
+ * @param string $modelURI
+ * @return boolean
+ * @throws SqlError
+ * @access public
+ */
+ function modelExists($modelURI) {
+
+ $res =& $this->dbConn->execute("SELECT COUNT(*) FROM models
+ WHERE modelURI = '" .$modelURI ."'");
+ if (!$res)
+ echo $this->dbConn->errorMsg();
+ else {
+ if (!$res->fields[0]) {
+ $res->Close();
+ return FALSE;
+ } else {
+ $res->Close();
+ return TRUE;
+ }
+ }
+ }
+
+
+
+ /**
+ * Returns the database connection object
+ *
+ * @return ADOdb Database object
+ * @access public
+ */
+ function &getDbConn()
+ {
+ return $this->dbConn;
+ }
+
+
+/**
+ * Create a new instance of DbModel with the given $modelURI and
+ * load the corresponding values of modelID and baseURI from the database.
+ * Return FALSE if the DbModel does not exist.
+ *
+ * @param string $modelURI
+ * @return object DbModel
+ * @access public
+ */
+ function getModel($modelURI) {
+
+ if (!$this->modelExists($modelURI))
+ return FALSE;
+ else {
+ $modelVars =& $this->dbConn->execute("SELECT modelURI, modelID, baseURI
+ FROM models
+ WHERE modelURI='" .$modelURI ."'");
+
+ return new DbModel($this->dbConn, $modelVars->fields[0],
+ $modelVars->fields[1], $modelVars->fields[2]);
+ }
+ }
+
+
+/**
+ * Create a new instance of DbModel with the given $modelURI
+ * and insert the DbModel variables into the database.
+ * Return FALSE if there is already a model with the given URI.
+ *
+ * @param string $modelURI
+ * @param string $baseURI
+ * @return object DbModel
+ * @throws SqlError
+ * @access public
+ */
+ function getNewModel($modelURI, $baseURI=NULL) {
+
+ if ($this->modelExists($modelURI))
+ return FALSE;
+ else {
+ $modelID = $this->_createUniqueModelID();
+
+ $rs =& $this->dbConn->execute("INSERT INTO models
+ (modelID, modelURI, baseURI)
+ VALUES (" .$modelID .",
+ " .$this->dbConn->qstr($modelURI) .",
+ " .$this->dbConn->qstr($baseURI) .")");
+
+ if (!$rs)
+ return $this->dbConn->errorMsg();
+ else
+ return new DbModel($this->dbConn, $modelURI, $modelID, $baseURI);
+ }
+ }
+
+
+/**
+ * Store a MemModel or another DbModel from a different DbStore in the database.
+ * Return FALSE if there is already a model with modelURI matching the modelURI
+ * of the given model.
+ *
+ * @param object Model &$model
+ * @param string $modelURI
+ * @return boolean
+ * @access public
+ */
+ function putModel(&$model, $modelURI=NULL) {
+
+ if (!$modelURI) {
+ if (is_a($model, 'MemModel'))
+ $modelURI = 'DbModel-' .$this->_createUniqueModelID();
+ else
+ $modelURI = $model->modelURI;
+ }else
+ if ($this->modelExists($modelURI))
+ return FALSE;
+
+
+ $newDbModel = $this->getNewModel($modelURI, $model->getBaseURI());
+ $newDbModel->addModel($model);
+ }
+
+
+/**
+ * Close the DbStore.
+ * !!! Warning: If you close the DbStore all active instances of DbModel from this
+ * !!! DbStore will lose their database connection !!!
+ *
+ * @access public
+ */
+ function close() {
+
+ $this->dbConn->close();
+ unset($this);
+ }
+
+
+// =============================================================================
+// **************************** private methods ********************************
+// =============================================================================
+
+
+/**
+ * Create a unique ID for the DbModel to be insert into the models table.
+ * This method was implemented because some databases do not support auto-increment.
+ *
+ * @return integer
+ * @access private
+ */
+ function _createUniqueModelID() {
+
+ $maxModelID =& $this->dbConn->GetOne('SELECT MAX(modelID) FROM models');
+ return ++$maxModelID;
+ }
+
+ /**
+ * Create a unique ID for the dataset to be insert into the datasets table.
+ * This method was implemented because some databases do not support auto-increment.
+ *
+ * @return integer
+ * @access private
+ */
+ function _createUniqueDatasetID() {
+
+ $maxDatasetID =& $this->dbConn->GetOne('SELECT MAX(datasetId) FROM datasets');
+ return ++$maxDatasetID;
+ }
+
+
+
+ /**
+ * Sets up tables for RAP.
+ * DOES NOT CHECK IF TABLES ALREADY EXIST
+ *
+ * @param string $databaseType Database driver name (e.g. MySQL)
+ *
+ * @throws Exception If database type is unsupported
+ * @access public
+ **/
+ public function createTables($databaseType = null)
+ {
+ $driver = $this->getDriver($databaseType);
+ self::assertDriverSupported($driver);
+
+ $createFunc = '_createTables_' . $driver;
+ return $this->$createFunc();
+ }//public function createTables($databaseType="MySQL")
+
+
+
+ /**
+ * Create tables and indexes for MsAccess database
+ *
+ * @return boolean true If all is ok
+ *
+ * @throws Exception
+ */
+ protected function _createTables_MsAccess()
+ {
+ $this->dbConn->startTrans();
+
+ $this->dbConn->execute('CREATE TABLE models
+ (modelID long primary key,
+ modelURI varchar not null,
+ baseURI varchar)');
+
+ $this->dbConn->execute('CREATE UNIQUE INDEX m_modURI_idx ON models (modelURI)');
+
+ $this->dbConn->execute('CREATE TABLE statements
+ (modelID long,
+ subject varchar,
+ predicate varchar,
+ object Memo,
+ l_language varchar,
+ l_datatype varchar,
+ subject_is varchar(1),
+ object_is varchar(1),
+ primary key (modelID, subject, predicate, object,
+ l_language, l_datatype))');
+
+ $this->dbConn->execute('CREATE INDEX s_mod_idx ON statements (modelID)');
+ $this->dbConn->execute('CREATE INDEX s_sub_idx ON statements (subject)');
+ $this->dbConn->execute('CREATE INDEX s_pred_idx ON statements (predicate)');
+ $this->dbConn->execute('CREATE INDEX s_obj_idx ON statements (object)');
+
+ $this->dbConn->execute('CREATE TABLE namespaces
+ (modelID long,
+ namespace varchar,
+ prefix varchar,
+ primary key (modelID, namespace, prefix))');
+
+ $this->dbConn->execute('CREATE INDEX n_name_idx ON namespaces (namespace)');
+ $this->dbConn->execute('CREATE INDEX n_pref_idx ON namespaces (prefix)');
+
+ $this->dbConn->execute("CREATE TABLE datasets
+ (datasetName varchar,
+ defaultModelUri varchar,
+ primary key (datasetName))");
+
+ $this->dbConn->execute('CREATE INDEX nGS_idx1 ON datasets (datasetName)');
+
+
+ $this->dbConn->execute("CREATE TABLE `dataset_model` (
+ datasetName varchar,
+ modelId long,
+ graphURI varchar,
+ PRIMARY KEY (modelId,datasetName))");
+
+
+ if (!$this->dbConn->completeTrans()) {
+ throw new Exception($this->dbConn->errorMsg());
+ }
+ return true;
+ }
+
+
+
+ /**
+ * Create tables and indexes for MySQL database
+ *
+ * @return boolean true If all is ok
+ *
+ * @throws Exception
+ */
+ function _createTables_MySQL()
+ {
+
+ $this->dbConn->startTrans();
+
+ $this->dbConn->execute("CREATE TABLE models
+ (modelID bigint NOT NULL,
+ modelURI varchar(255) NOT NULL,
+ baseURI varchar(255) DEFAULT '',
+ primary key (modelID))");
+
+ $this->dbConn->execute('CREATE UNIQUE INDEX m_modURI_idx ON models (modelURI)');
+
+ $this->dbConn->execute("CREATE TABLE statements
+ (modelID bigint NOT NULL,
+ subject varchar(255) NOT NULL,
+ predicate varchar(255) NOT NULL,
+ object text,
+ l_language varchar(255) DEFAULT '',
+ l_datatype varchar(255) DEFAULT '',
+ subject_is varchar(1) NOT NULL,
+ object_is varchar(1) NOT NULL)");
+
+ $this->dbConn->execute("CREATE TABLE namespaces
+ (modelID bigint NOT NULL,
+ namespace varchar(255) NOT NULL,
+ prefix varchar(255) NOT NULL,
+ primary key (modelID,namespace))");
+
+ $this->dbConn->execute("CREATE TABLE `dataset_model` (
+ `datasetName` varchar(255) NOT NULL default '0',
+ `modelId` bigint(20) NOT NULL default '0',
+ `graphURI` varchar(255) NOT NULL default '',
+ PRIMARY KEY (`modelId`,`datasetName`))");
+
+ $this->dbConn->execute("CREATE TABLE `datasets` (
+ `datasetName` varchar(255) NOT NULL default '',
+ `defaultModelUri` varchar(255) NOT NULL default '0',
+ PRIMARY KEY (`datasetName`),
+ KEY `datasetName` (`datasetName`))");
+
+ $this->dbConn->execute('CREATE INDEX s_mod_idx ON statements (modelID)');
+ $this->dbConn->execute('CREATE INDEX n_mod_idx ON namespaces (modelID)');
+
+ $this->dbConn->execute('CREATE INDEX s_sub_pred_idx ON statements
+ (subject(200),predicate(200))');
+
+ $this->dbConn->execute('CREATE INDEX s_sub_idx ON statements (subject(200))');
+ $this->dbConn->execute('CREATE INDEX s_pred_idx ON statements (predicate(200))');
+ $this->dbConn->execute('CREATE INDEX s_obj_idx ON statements (object(250))');
+
+ $this->dbConn->execute('CREATE FULLTEXT INDEX s_obj_ftidx ON statements (object)');
+
+ if (!$this->dbConn->completeTrans()) {
+ throw new Exception($this->dbConn->errorMsg());
+ }
+ return true;
+ }
+
+
+
+ /**
+ * Creates tables on a MySQLi database
+ */
+ function _createTables_MySQLi()
+ {
+ return $this->_createTables_MySQL();
+ }//function _createTables_MySQLi()
+
+
+
+ /**
+ * Create tables and indexes for MSSQL database
+ *
+ * @return boolean true If all is ok
+ *
+ * @throws Exception
+ */
+ function _createTables_MSSQL()
+ {
+ $this->dbConn->startTrans();
+
+ $this->dbConn->execute("CREATE TABLE [dbo].[models] (
+ [modelID] [int] NOT NULL ,
+ [modelURI] [nvarchar] (200) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
+ [baseURI] [nvarchar] (200) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
+ ) ON [PRIMARY]");
+
+ $this->dbConn->execute("CREATE TABLE [dbo].[statements] (
+ [modelID] [int] NOT NULL ,
+ [subject] [nvarchar] (200) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
+ [predicate] [nvarchar] (200) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
+ [object] [text] COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
+ [l_language] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
+ [l_datatype] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
+ [subject_is] [nchar] (1) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
+ [object_is] [nchar] (1) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
+ ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]");
+
+
+ $this->dbConn->execute("CREATE TABLE [dbo].[namespaces] (
+ [modelID] [int] NOT NULL ,
+ [namespace] [nvarchar] (200) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
+ [prefix] [nvarchar] (200) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
+ ) ON [PRIMARY]");
+
+ $this->dbConn->execute("ALTER TABLE [dbo].[models] WITH NOCHECK ADD
+ CONSTRAINT [PK_models] PRIMARY KEY CLUSTERED
+ (
+ [modelID]
+ ) ON [PRIMARY] ");
+ $this->dbConn->execute("ALTER TABLE [dbo].[namespaces] WITH NOCHECK ADD
+ CONSTRAINT [PK_namespaces] PRIMARY KEY CLUSTERED
+ (
+ [modelID],[namespace]
+ ) ON [PRIMARY] ");
+
+ $this->dbConn->execute("CREATE INDEX [joint index on subject and predicate] ON [dbo].[statements]([subject], [predicate]) ON [PRIMARY]");
+
+
+ if (!$this->dbConn->completeTrans()) {
+ throw new Exception($this->dbConn->errorMsg());
+ }
+ return true;
+ }
+
+
+
+ /**
+ * Checks if tables are setup for RAP
+ *
+ * @param string $databaseType
+ * @throws Exception If database type is unsupported
+ * @access public
+ **/
+ public function isSetup($databaseType = null)
+ {
+ $driver = $this->getDriver($databaseType);
+ self::assertDriverSupported($driver);
+
+ $issetupFunc = '_isSetup_' . $driver;
+ return $this->$issetupFunc();
+ }//public function isSetup($databaseType="MySQL")
+
+
+
+ /**
+ * Returns the driver for the database type.
+ * You can pass NULL or omit the parameter to
+ * use the parameter from the dbstore constructor
+ *
+ * @param string $databaseType Database driver name (e.g. MySQL)
+ *
+ * @return string Database driver string (e.g. MySQL)
+ */
+ public function getDriver($databaseType = null)
+ {
+ if ($databaseType === null) {
+ if ($this->driver === null) {
+ //backward compatibility
+ $databaseType = 'MySQL';
+ } else {
+ $databaseType = $this->driver;
+ }
+ }
+ if (!self::isDriverSupported($databaseType)) {
+ //check if it is a known driver in wrong case
+ $arLowercases = array_map('strtolower', self::$arSupportedDbTypes);
+ $arMapping = array_combine($arLowercases, self::$arSupportedDbTypes);
+ if (isset($arMapping[strtolower($databaseType)])) {
+ $databaseType = $arMapping[strtolower($databaseType)];
+ }
+ }
+ return $databaseType;
+ }//public function getDriver($databaseType = null)
+
+
+
+ /**
+ * Returns if the given driver is supported
+ *
+ * @return boolean True if it supported, false if not
+ */
+ public static function isDriverSupported($databaseType)
+ {
+ return in_array($databaseType, self::$arSupportedDbTypes);
+ }//public static function isDriverSupported($databaseType)
+
+
+
+ /**
+ * Checks if the given driver is supported and throws an
+ * Exception if not.
+ *
+ * @param string $databaseType Database driver name (e.g. MySQL)
+ *
+ * @return true If it does not fail
+ *
+ * @throws Exception If the driver is not supported
+ */
+ public static function assertDriverSupported($databaseType)
+ {
+ if (!self::isDriverSupported($databaseType)) {
+ throw new Exception(
+ 'Unsupported database type, only supported: '
+ . implode(', ', self::$arSupportedDbTypes)
+ );
+ }
+ return true;
+ }//public static function assertDriverSupported($databaseType)
+
+
+
+ /**
+ * Checks if tables are setup for RAP (MySql)
+ *
+ * @throws SqlError
+ * @access private
+ **/
+ function _isSetup_MySQL()
+ {
+ $recordSet =& $this->dbConn->execute("SHOW TABLES");
+ if (!$recordSet) {
+ throw new Exception($this->dbConn->errorMsg());
+ } else {
+ $tables = array();
+ while (!$recordSet->EOF) {
+ $tables[]= $recordSet->fields[0];
+ if (isset($i)) {
+ ++$i;
+ }
+ $recordSet->moveNext();
+ }
+ if (in_array("models",$tables) && in_array("statements",$tables)
+ && in_array("namespaces",$tables)) {
+ return true;
+ }
+ }
+ return false;
+ }//function _isSetup_MySQL()
+
+
+
+ /**
+ * Checks if tables are setup for RAP (MySQLi)
+ *
+ * @see _isSetup_MySQL()
+ */
+ function _isSetup_MySQLi()
+ {
+ return $this->_isSetup_MySQL();
+ }//function _isSetup_MySQLi()
+
+
+
+ /**
+ * Checks if tables are setup for RAP (MsAccess)
+ *
+ * @throws SqlError
+ * @access private
+ **/
+ function _isSetup_MsAccess()
+ {
+ $tables =& $this->dbConn->MetaTables();
+ if (!$tables) {
+ throw new Exception($this->dbConn->errorMsg());
+ }
+ if (count($tables) == 0) {
+ return false;
+ } else {
+ if (in_array("models",$tables) && in_array("statements",$tables)
+ && in_array("namespaces",$tables)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }//function _isSetup_MsAccess()
+
+
+
+ /**
+ * Checks if tables are setup for RAP (MSSQL)
+ *
+ * @throws SqlError
+ * @access private
+ **/
+ function _isSetup_MSSQL()
+ {
+ $tables =& $this->dbConn->MetaTables();
+ if (!$tables) {
+ throw new Exception($this->dbConn->errorMsg());
+ }
+ if (count($tables) == 0) {
+ return false;
+ } else {
+ if (in_array("models",$tables) && in_array("statements",$tables)
+ && in_array("namespaces",$tables)){
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }//function _isSetup_MSSQL()
+
+
+ /**
+ * Create a new instance of DatasetDb with the given $datasetName
+ * and insert the DatasetDb variables into the database.
+ * Return FALSE if there is already a model with the given URI.
+ *
+ * @param $datasetName string
+ * @return object DatasetDB
+ * @throws SqlError
+ * @access public
+ */
+ function & getNewDatasetDb($datasetName)
+ {
+
+ require_once(RDFAPI_INCLUDE_DIR . PACKAGE_DATASET);
+
+ if ($this->datasetExists($datasetName))
+ return FALSE;
+ else
+ {
+ $defaultModelUri=uniqid('http://rdfapi-php/dataset_defaultmodel_');
+ $defaultModel=$this->getNewModel($defaultModelUri);
+
+ $rs =& $this->dbConn->execute("INSERT INTO datasets
+ VALUES ('" .$this->dbConn->qstr($datasetName) ."',
+ '" .$this->dbConn->qstr($defaultModelUri)."')");
+
+ if (!$rs)
+ $this->dbConn->errorMsg();
+ else
+ $return=new DatasetDb($this->dbConn, $this, $datasetName);
+ return ($return);
+ }
+ }
+
+ /**
+ * Check if the Dataset with the given $datasetName is already stored in the database
+ *
+ * @param $datasetName string
+ * @return boolean
+ * @throws SqlError
+ * @access public
+ */
+function datasetExists($datasetName) {
+
+ $res =& $this->dbConn->execute("SELECT COUNT(*) FROM datasets
+ WHERE datasetName = '" .$datasetName ."'");
+ if (!$res)
+ echo $this->dbConn->errorMsg();
+ else {
+ if (!$res->fields[0])
+ return FALSE;
+ return TRUE;
+ }
+ }
+
+
+ /**
+ * Create a new instance of DatasetDb with the given $datasetName and
+ * load the corresponding values from the database.
+ * Return FALSE if the DbModel does not exist.
+ *
+ * @param $datasetId string
+ * @return object DatasetDb
+ * @access public
+ */
+ function &getDatasetDb($datasetName) {
+ require_once(RDFAPI_INCLUDE_DIR . PACKAGE_DATASET);
+
+ if (!$this->datasetExists($datasetName)) {
+ return FALSE;
+ } else {
+ $return = new DatasetDb($this->dbConn, $this, $datasetName);
+ return ($return);
+ }
+ }
+
+ /**
+ * Create a new instance of namedGraphDb with the given $modelURI and graphName and
+ * load the corresponding values of modelID and baseURI from the database.
+ * Return FALSE if the DbModel does not exist.
+ *
+ * @param $modelURI string
+ * @param $graphName string
+ * @return object NamedGraphMem
+ * @access public
+ */
+ function getNamedGraphDb($modelURI, $graphName)
+ {
+ require_once(RDFAPI_INCLUDE_DIR . PACKAGE_DATASET);
+
+ if (!$this->modelExists($modelURI))
+ return FALSE;
+ else {
+ $modelVars =& $this->dbConn->execute("SELECT modelURI, modelID, baseURI
+ FROM models
+ WHERE modelURI='" .$modelURI ."'");
+
+ return new NamedGraphDb($this->dbConn, $modelVars->fields[0],
+ $modelVars->fields[1], $graphName ,$modelVars->fields[2]);
+ }
+ }
+
+ /**
+ * Create a new instance of namedGraphDb with the given $modelURI and graphName
+ * and insert the DbModel variables into the database (not the graphName. This
+ * is only stored persistently, when added to dataset).
+ * Return FALSE if there is already a model with the given URI.
+ *
+ * @param $modelURI string
+ * @param $graphName string
+ * @param $baseURI string
+ * @return object namedGraphDb
+ * @throws SqlError
+ * @access public
+ */
+ function getNewNamedGraphDb($modelURI, $graphName, $baseURI=NULL) {
+
+ if ($this->modelExists($modelURI))
+ return FALSE;
+ else {
+ $modelID = $this->_createUniqueModelID();
+
+ $rs =& $this->dbConn->execute("INSERT INTO models
+ (modelID, modelURI, baseURI)
+ VALUES (" .$modelID ."',
+ " .$this->dbConn->qstr($modelURI) ."',
+ " .$this->dbConn->qstr($baseURI) .")");
+ if (!$rs)
+ $this->dbConn->errorMsg();
+ else
+ return new NamedGraphDb($this->dbConn, $modelURI, $modelID, $graphName, $baseURI);
+ }
+ }
+
+ /**
+ * Removes the graph with all statements from the database.
+ * Warning: A single namedGraph can be added to several datasets. So it'll be
+ * removed from all datasets.
+ *
+ * @param $modelURI string
+ * @return boolean
+ * @throws SqlError
+ * @access public
+ */
+ function removeNamedGraphDb($modelURI)
+ {
+ if (!$this->modelExists($modelURI))
+ return FALSE;
+
+ $modelID = $this->dbConn->GetOne("SELECT modelID FROM models WHERE modelURI='".$modelURI."'");
+
+ $this->dbConn->execute("DELETE FROM models WHERE modelID=".$modelID);
+ $this->dbConn->execute("DELETE FROM dataset_model WHERE modelId=".$modelID);
+ $this->dbConn->execute("DELETE FROM statements WHERE modelID=".$modelID);
+
+ return true;
+ }
+
+
+
+ /**
+ * Performs a SPARQL query against a model. The model is converted to
+ * an RDF Dataset. The result can be retrived in SPARQL Query Results XML Format or
+ * as an array containing the variables an their bindings.
+ *
+ * @param string $query Sparql query string
+ * @param mixed $arModelIds Array of modelIDs, or NULL to use all models
+ * @param string $resultform Result form ('xml' for SPARQL Query Results XML Format)
+ * @return string/array
+ */
+ function sparqlQuery($query, $arModelIds = null, $resultform = false)
+ {
+ $engine = $this->_prepareSparql($arModelIds);
+ return $engine->queryModel(
+ null,
+ $this->_parseSparqlQuery($query),
+ $resultform
+ );
+ }//function sparqlQuery($query,$resultform = false)
+
+
+
+ /**
+ * Prepares everything for SparqlEngine-usage
+ * Loads the files, creates instances for SparqlEngine and
+ * Dataset...
+ *
+ * @return SparqlEngineDb
+ */
+ function _prepareSparql($arModelIds)
+ {
+ require_once RDFAPI_INCLUDE_DIR . 'sparql/SparqlEngineDb.php';
+ return new SparqlEngineDb($this, $arModelIds);
+ }//function _prepareSparql()
+
+
+
+ /**
+ * Parses an query and returns the parsed form.
+ * If the query is not a string but a Query object,
+ * it will just be returned.
+ *
+ * @param $query mixed String or Query object
+ * @return Query query object
+ * @throws Exception If $query is no string and no Query object
+ */
+ function _parseSparqlQuery($query)
+ {
+ if ($this->queryParser === null) {
+ require_once RDFAPI_INCLUDE_DIR . 'sparql/SparqlParser.php';
+ $this->queryParser = new SparqlParser();
+ }
+ return $this->queryParser->parse($query);
+ }//function _parseSparqlQuery($query)
+
+} // end: Class DbStore
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/text-base/Literal.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/text-base/Literal.php.svn-base
new file mode 100755
index 00000000..cc9b6365
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/text-base/Literal.php.svn-base
@@ -0,0 +1,188 @@
+
+ * @author Daniel Westphal
+ *
+ * @package model
+ * @access public
+ *
+ */
+ class Literal extends Node {
+
+ /**
+ * Label of the literal
+ * @var string
+ * @access private
+ */
+ var $label;
+ /**
+ * Language of the literal
+ * @var string
+ * @access private
+ */
+ var $lang;
+
+ /**
+ * Datatype of the literal
+ * @var string
+ * @access private
+ */
+ var $dtype;
+
+
+ /**
+ * Constructor
+ *
+ * @param string $str label of the literal
+ * @param string $language optional language identifier
+ * @param string $datatype optional datatype
+ *
+ */
+ function Literal($str, $language = NULL, $datatype = null)
+ {
+ $this->label = $str;
+
+ if ($language != NULL) {
+ $this->lang = $language;
+ } else {
+ $this->lang = NULL;
+ }
+
+ if ($datatype != null) {
+ $this->dtype = $datatype;
+ } else {
+ $this->dtype = NULL;
+ }
+ }
+
+ /**
+ * Returns the string value of the literal.
+ *
+ * @access public
+ * @return string value of the literal
+ */
+ function getLabel() {
+
+ return $this->label;
+ }
+
+ /**
+ * Returns the language of the literal.
+ *
+ * @access public
+ * @return string language of the literal
+ */
+ function getLanguage() {
+
+ return $this->lang;
+ }
+
+ /**
+ * Sets the language of the literal.
+ *
+ * @access public
+ * @param string $lang
+ */
+ function setLanguage($lang) {
+
+ $this->lang = $lang;
+ }
+
+ /**
+ * Returns the datatype of the literal.
+ *
+ * @access public
+ * @return string datatype of the literal
+ */
+ function getDatatype() {
+
+ return $this->dtype;
+ }
+
+ /**
+ * Sets the datatype of the literal.
+ * Instead of datatype URI, you can also use an datatype shortcuts like STRING or INTEGER.
+ * The array $short_datatype with the possible shortcuts is definded in ../constants.php
+ *
+ * @access public
+ * @param string URI of XML datatype or datatype shortcut
+ *
+ */
+ function setDatatype($datatype) {
+ GLOBAL $short_datatype;
+ if (stristr($datatype,DATATYPE_SHORTCUT_PREFIX)) {
+ $this->dtype = $short_datatype[substr($datatype,strlen(DATATYPE_SHORTCUT_PREFIX)) ];}
+ else
+ $this->dtype = $datatype;
+ }
+
+ /**
+ * Checks if ihe literal equals another literal.
+ * Two literals are equal, if they have the same label and they
+ * have the same language/datatype or both have no language/datatype property set.
+ *
+ * @access public
+ * @param object literal $that
+ * @return boolean
+ */
+ function equals ($that) {
+
+ if (($that == NULL) or !(is_a($that, 'Literal'))) {
+ return false;
+ }
+
+ if ( ($this->label == $that->getLabel()) && ( ( ($this->lang == $that->getLanguage()) ||
+ ($this->lang == NULL && $that->getLanguage() == NULL) ) &&
+
+ (
+ ($this->dtype == $that->getDatatype() ||
+ ($this->dtype == NULL && $that->getDatatype() == NULL)) ) ) )
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Dumps literal.
+ *
+ * @access public
+ * @return string
+ */
+ function toString() {
+ $dump = 'Literal("' . $this->label .'"';
+ if ($this->lang != NULL)
+ $dump .= ', lang="' . $this->lang .'"';
+ if ($this->dtype != NULL)
+ $dump .= ', datatype="' . $this->dtype .'"';
+ $dump .= ')';
+ return $dump;
+ }
+
+
+
+ /**
+ * Doing string magic in PHP5
+ * @return string String representation of this Literal
+ */
+ function __toString()
+ {
+ return $this->toString();
+ }
+
+
+} // end: Literal
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/text-base/MemModel.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/text-base/MemModel.php.svn-base
new file mode 100755
index 00000000..17faaa45
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/text-base/MemModel.php.svn-base
@@ -0,0 +1,1460 @@
+
+* @author Gunnar AAstrand Grimnes
+* @author Radoslaw Oldakowski
+* @author Daniel Westphal
+* @author Tobias Gauß
+*
+* @package model
+* @access public
+*/
+
+class MemModel extends Model {
+
+ /**
+ * Triples of the MemModel
+ * @var array
+ * @access private
+ */
+ var $triples = array();
+
+ /**
+ * Array containing the search indices
+ * @var array['INDEX_TYPE'][]['label'][]['PosInModel']
+ *
+ * @access private
+ */
+ var $indexArr ;
+
+
+ /**
+ * depending on which index is used this variable is -1,0,1,2 or 3
+ *
+ * -1 : no index
+ * 0 : default indices over subject, predicate, object separate
+ * 1 : index over subject+predicate+object
+ * 2 : index over subject+predicate
+ * 3 : index over subject+object
+ *
+ * @var int
+ * @access private
+ */
+ var $indexed;
+
+
+
+ /**
+ * Array of namespaces
+ *
+ * @var array
+ * @access private
+ */
+ var $parsedNamespaces=array();
+
+
+
+ /**
+ * Constructor
+ * You can supply a base_uri
+ *
+ * @param string $baseURI
+ * @access public
+ */
+ function MemModel($baseURI = NULL) {
+ $this->setBaseURI($baseURI);
+ $this->indexed = INDEX_TYPE;
+ }
+
+ /**
+ * Set a base URI for the MemModel.
+ * Affects creating of new resources and serialization syntax.
+ * If the URI doesn't end with # : or /, then a # is added to the URI.
+ * @param string $uri
+ * @access public
+ */
+ function setBaseURI($uri) {
+
+ if ($uri != NULL) {
+ $c = substr($uri, strlen($uri)-1 ,1);
+ if (!($c=='#' || $c==':' || $c=='/' || $c=="\\"))
+ $uri .= '#';
+ }
+ $this->baseURI = $uri;
+ }
+
+
+ /**
+ * Number of triples in the MemModel
+ *
+ * @return integer
+ * @access public
+ */
+ function size() {
+ return count($this->triples);
+ }
+
+ /**
+ * Checks if MemModel is empty
+ *
+ * @return boolean
+ * @access public
+ */
+ function isEmpty() {
+ if (count($this->triples) == 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ };
+ }
+
+
+ /**
+ * Adds a new triple to the MemModel without checking if the statement is already in the MemModel.
+ * So if you want a duplicate free MemModel use the addWithoutDuplicates() function (which is slower then add())
+ *
+ * @param object Statement $statement
+ * @access public
+ * @throws PhpError
+ */
+ function add($statement) {
+ if (!is_a($statement, 'Statement')) {
+ $errmsg = RDFAPI_ERROR . '(class: MemModel; method: add): Statement expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ if($this->indexed != -1){
+ $this->triples[] = $statement;
+ end($this->triples);
+ $k=key($this->triples);
+ if($this->indexed==0){
+ // index over S
+ $this->_indexOpr($statement,$k,4,1);
+ // index over P
+ $this->_indexOpr($statement,$k,5,1);
+ // index over O
+ $this->_indexOpr($statement,$k,6,1);
+ }else{
+ $this->_indexOpr($statement,$k,$this->indexed,1);
+ }
+
+ }else{
+ $this->triples[] = $statement;
+ }
+ }
+
+
+
+ /**
+ * Checks if a new statement is already in the MemModel and adds the statement, if it is not in the MemModel.
+ * addWithoutDuplicates() is significantly slower then add().
+ * Retruns TRUE if the statement is added.
+ * FALSE otherwise.
+ *
+ * @param object Statement $statement
+ * @return boolean
+ * @access public
+ * @throws PhpError
+ */
+ function addWithoutDuplicates($statement) {
+
+ if (!is_a($statement, 'Statement')) {
+ $errmsg = RDFAPI_ERROR . '(class: MemModel; method: addWithoutDuplicates): Statement expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ if (!$this->contains($statement)) {
+ $this->add($statement);
+ return true;
+ }else{
+ return false;
+ }
+ }
+
+ /**
+ * Removes the triple from the MemModel.
+ * TRUE if the triple is removed.
+ * FALSE otherwise.
+ *
+ * @param object Statement $statement
+ * @return boolean
+ * @access public
+ * @throws PhpError
+ */
+ function remove($statement) {
+
+ if (!is_a($statement, 'Statement')) {
+ $errmsg = RDFAPI_ERROR . '(class: MemModel; method: remove): Statement expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+ if($this->indexed==-1){
+ $pass=false;
+ foreach($this->triples as $key => $value) {
+ if ($this->matchStatement($value, $statement->subject(), $statement->predicate(), $statement->object())) {
+ unset($this->triples[$key]);
+ $pass= true;
+ }
+ }
+ return $pass;
+ }else{
+ $k= null;
+ if($this->indexed==0){
+ $pass=false;
+ $del=false;
+ while($del!=-1){
+ // index over S
+ $del=$this->_indexOpr($statement,$k,4,0);
+ // index over P
+ $this->_indexOpr($statement,$k,5,0);
+ // index over O
+ $this->_indexOpr($statement,$k,6,0);
+ if($del!=-1){
+ unset($this->triples[$del]);
+ $pass=true;
+ }
+ }
+ return $pass;
+ }else{
+ $pass=false;
+ $del=false;
+ while($del!=-1){
+ $del=$this->_indexOpr($statement,$k,$this->indexed,0);
+ if($del!=-1){
+ unset($this->triples[$del]);
+ $pass=true;
+ }
+ }
+ return $pass;
+ }
+ }
+ }
+
+ /**
+ * Short Dump of the MemModel.
+ *
+ * @access public
+ * @return string
+ */
+ function toString() {
+ return 'MemModel[baseURI=' . $this->getBaseURI() . '; size=' . $this->size() . ']';
+ }
+
+ /**
+ * Dumps of the MemModel including all triples.
+ *
+ * @access public
+ * @return string
+ */
+ function toStringIncludingTriples() {
+ $dump = $this->toString() . chr(13);
+ foreach($this->triples as $value) {
+ $dump .= $value->toString() . chr(13);
+ }
+ return $dump;
+ }
+
+
+
+
+ /**
+ * Writes the RDF serialization of the MemModel as HTML.
+ *
+ * @access public
+ */
+ function writeAsHtml() {
+ require_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_RDF);
+ $ser = new RdfSerializer();
+ $rdf =& $ser->serialize($this);
+ $rdf = htmlspecialchars($rdf, ENT_QUOTES);
+ $rdf = str_replace(' ', ' ', $rdf);
+ $rdf = nl2br($rdf);
+ echo $rdf;
+ }
+
+ /**
+ * Writes the RDF serialization of the MemModel as HTML table.
+ *
+ * @access public
+ */
+ function writeAsHtmlTable() {
+ // Import Package Utility
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_UTILITY);
+ RDFUtil::writeHTMLTable($this);
+ }
+
+
+ /**
+ * Writes the RDF serialization of the MemModel as HTML table.
+ *
+ * @access public
+ * @return string
+ */
+ function writeRdfToString() {
+ // Import Package Syntax
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_RDF);
+ $ser = new RdfSerializer();
+ $rdf =& $ser->serialize($this);
+ return $rdf;
+ }
+
+
+ /**
+ * Saves the RDF,N3 or N-Triple serialization of the MemModel to a file.
+ * You can decide to which format the model should be serialized by using a
+ * corresponding suffix-string as $type parameter. If no $type parameter
+ * is placed this method will serialize the model to XML/RDF format.
+ * Returns FALSE if the MemModel couldn't be saved to the file.
+ *
+ * @access public
+ * @param string $filename
+ * @param string $type
+ * @throws PhpError
+ * @return boolean
+ */
+ function saveAs($filename, $type ='rdf') {
+
+
+ // get suffix and create a corresponding serializer
+ if ($type=='rdf') {
+ // Import Package Syntax
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_RDF);
+ $ser=new RdfSerializer();
+ }elseif ($type=='nt') {
+ // Import Package Syntax
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_N3);
+ $ser=new NTripleSerializer();
+ }elseif ($type=='n3') {
+ // Import Package Syntax
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_N3);
+ $ser=new N3Serializer();
+ }else {
+ print ('Serializer type not properly defined. Use the strings "rdf","n3" or "nt".');
+ return false;
+ };
+
+ return $ser->saveAs($this, $filename);
+ }
+
+
+ /**
+ * Tests if the MemModel contains the given triple.
+ * TRUE if the triple belongs to the MemModel;
+ * FALSE otherwise.
+ *
+ * @param object Statement &$statement
+ * @return boolean
+ * @access public
+ */
+ function contains(&$statement) {
+
+ // no index ->linear contains
+ if ($this->indexed==-1){
+ foreach($this->triples as $value) {
+ if ($value->equals($statement)){
+ return TRUE; }
+ }
+ return false;
+ }
+ if ($this->indexed==0){
+ $res = $this->_containsIndex($statement,4);
+ return $res;
+ }else{
+ return $this->_containsIndex($statement,$this->indexed);
+ }
+ }
+
+
+ /**
+ * Determine if all of the statements in a model are also contained in this MemModel.
+ * True if all of the statements in $model are also contained in this MemModel and false otherwise.
+ *
+ * @param object Model &$model
+ * @return boolean
+ * @access public
+ */
+ function containsAll(&$model) {
+
+ if (is_a($model, 'MemModel')) {
+
+ foreach($model->triples as $statement)
+ if(!$this->contains($statement))
+ return FALSE;
+ return TRUE;
+
+ }elseif (is_a($model, 'DbModel'))
+
+ return $model->containsAll($this);
+
+ $errmsg = RDFAPI_ERROR . '(class: MemModel; method: containsAll): Model expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ /**
+ * Determine if any of the statements in a model are also contained in this MemModel.
+ * True if any of the statements in $model are also contained in this MemModel and false otherwise.
+ *
+ * @param object Model &$model
+ * @return boolean
+ * @access public
+ */
+ function containsAny(&$model) {
+
+ if (is_a($model, 'MemModel')) {
+
+ foreach($model->triples as $modelStatement)
+ if($this->contains($modelStatement))
+ return TRUE;
+ return FALSE;
+
+ }elseif (is_a($model, 'DbModel'))
+
+ return $model->containsAny($this);
+
+ $errmsg = RDFAPI_ERROR . '(class: MemModel; method: containsAll): Model expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+
+ /**
+ * Builds a search index for the statements in the MemModel.
+ * The index is used by the find(),contains(),add() and remove() functions.
+ * Performance example using a model with 43000 statements on a Linux machine:
+ * Find without index takes 1.7 seconds.
+ * Indexing takes 1.8 seconds.
+ * Find with index takes 0.001 seconds.
+ * So if you want to query a model more then once, build a index first.
+ * The defaultindex is indices over subject, predicate, object seperate.
+ *
+ * mode = 0 : indices over subject,predicate,object (default)
+ * mode = 1 : index over subject+predicate+object
+ * mode = 2 : index over subject+predicate
+ * mode = 3 : index over subject+object
+ *
+ * @param int $mode
+ * @access public
+ */
+ function index($mode) {
+
+ unset($this->indexArr);
+ $this->indexArr=array();
+ switch($mode){
+ // unset indices
+ case -1:
+ $this->indexed=-1;
+ unset($this->indexArr);
+ break;
+ // index over SPO
+ case 0:
+ $this->indexed=0;
+ foreach($this->triples as $k => $t) {
+ // index over S
+ $this->_indexOpr($t,$k,4,1);
+ // index over P
+ $this->_indexOpr($t,$k,5,1);
+ // index over O
+ $this->_indexOpr($t,$k,6,1);
+ }
+ break;
+ default:
+ $this->indexed=$mode;
+ foreach($this->triples as $k => $t) {
+ $this->_indexOpr($t,$k,$this->indexed,1);
+ }
+ break;
+ }
+ }
+
+
+ /**
+ * Returns true if there is an index, false if not.
+ *
+ * @return boolean
+ * @access public
+ */
+ function isIndexed() {
+ if($this->indexed!=-1){
+ return TRUE;
+ }else{
+ return FALSE;
+ }
+ }
+
+ /**
+ * Returns the indextype:
+ * -1 if there is no index, 0 if there are indices over S,P,O(separate),
+ * 1 if there is an index over SPO, 2 if there is an index over SP and 3 if
+ * there is an index over SO.
+ *
+ * @return int
+ * @access public
+ *
+ */
+ function getIndexType(){
+ return $this->indexed;
+ }
+
+ /**
+ * General method to search for triples.
+ * NULL input for any parameter will match anything.
+ * Example: $result = $m->find( NULL, NULL, $node );
+ * Finds all triples with $node as object.
+ * Returns an empty MemModel if nothing is found.
+ *
+ * @param object Node $subject
+ * @param object Node $predicate
+ * @param object Node $object
+ * @return object MemModel
+ * @access public
+ * @throws PhpError
+ */
+
+ function find($subject,$predicate,$object) {
+
+ if (
+ (!is_a($subject, 'Resource') && $subject != NULL) ||
+ (!is_a($predicate, 'Resource') && $predicate != NULL) ||
+ (!is_a($object, 'Node') && $object != NULL)
+ ) {
+ $errmsg = RDFAPI_ERROR . '(class: MemModel; method: find): Parameters must be subclasses of Node or NULL';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ $res = new MemModel($this->getBaseURI());
+ $res->indexed=-1;
+
+ if($this->isEmpty())
+ return $res;
+
+ if($subject == NULL && $predicate == NULL && $object == NULL)
+ return $this;
+
+ switch($this->indexed){
+ case 1:
+ if($subject!=NULL && $predicate != NULL && $object != NULL){
+ $pos=$subject->getLabel().$predicate->getLabel().$object->getLabel();
+ return $this->_findInIndex($pos,$subject,$predicate,$object,1);
+ }else{
+ break;
+ }
+
+ case 2:
+ if($subject!=NULL && $predicate != NULL){
+ $pos=$subject->getLabel().$predicate->getLabel();
+ return $this->_findInIndex($pos,$subject,$predicate,$object,2);
+ }else{
+ break;
+ }
+
+ case 3:
+ if($subject!=NULL && $object != NULL){
+ $pos=$subject->getLabel().$object->getLabel();
+ return $this->_findInIndex($pos,$subject,$predicate,$object,3);
+ }else{
+ break;
+ }
+ case 0:
+ if($subject!= null){
+ $pos=$subject->getLabel();
+ return $this->_findInIndex($pos,$subject,$predicate,$object,4);
+ }
+ if($predicate!= null){
+ $pos=$predicate->getLabel();
+ return $this->_findInIndex($pos,$subject,$predicate,$object,5);
+ }
+ if($object!= null){
+ $pos=$object->getLabel();
+ return $this->_findInIndex($pos,$subject,$predicate,$object,6);
+ }
+ }
+ // if no index: linear search
+ foreach($this->triples as $value) {
+ if ($this->matchStatement($value, $subject, $predicate, $object))
+ $res->add($value);
+ }
+ return $res;
+
+ }
+
+
+
+
+
+ /**
+ * Method to search for triples using Perl-style regular expressions.
+ * NULL input for any parameter will match anything.
+ * Example: $result = $m->find_regex( NULL, NULL, $regex );
+ * Finds all triples where the label of the object node matches the regular expression.
+ * Returns an empty MemModel if nothing is found.
+ *
+ * @param string $subject_regex
+ * @param string $predicate_regex
+ * @param string $object_regex
+ * @return object MemModel
+ * @access public
+ */
+ function findRegex($subject_regex, $predicate_regex, $object_regex) {
+
+ $res = new MemModel($this->getBaseURI());
+
+ if($this->size() == 0)
+ return $res;
+
+ if($subject_regex == NULL && $predicate_regex == NULL && $object_regex == NULL)
+ return $this;
+
+ foreach($this->triples as $value) {
+ if (
+ ($subject_regex == NULL || preg_match($subject_regex, $value->subj->getLabel())) &&
+ ($predicate_regex == NULL || preg_match($predicate_regex, $value->pred->getLabel())) &&
+ ($object_regex == NULL || preg_match($object_regex, $value->obj->getLabel()))
+ ) $res->add($value);
+ }
+
+ return $res;
+
+ }
+
+ /**
+ * Returns all tripels of a certain vocabulary.
+ * $vocabulary is the namespace of the vocabulary inluding a # : / char at the end.
+ * e.g. http://www.w3.org/2000/01/rdf-schema#
+ * Returns an empty MemModel if nothing is found.
+ *
+ * @param string $vocabulary
+ * @return object MemModel
+ * @access public
+ */
+ function findVocabulary($vocabulary) {
+
+ if($this->size() == 0)
+ return new MemModel();
+ if($vocabulary == NULL || $vocabulary == '')
+ return $this;
+
+ $res = new MemModel($this->getBaseURI());
+ if($this->indexed==0){
+ foreach($this->indexArr[5] as $key => $value){
+ $pos=strpos($key,'#')+1;
+ if(substr($key,0,$pos)==$vocabulary){
+ for($i=1;$i<=$value[0];$i++){
+ $res->add($this->triples[$value[$i]]);
+ }
+ }
+ }
+ return $res;
+ }else{
+ // Import Package Utility
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_UTILITY);
+ foreach($this->triples as $value) {
+ if (RDFUtil::getNamespace($value->getPredicate()) == $vocabulary)
+ $res->add($value);
+ }
+ return $res;
+ }
+ }
+
+ /**
+ * Searches for triples and returns the first matching statement.
+ * NULL input for any parameter will match anything.
+ * Example: $result = $m->findFirstMatchingStatement( NULL, NULL, $node );
+ * Returns the first statement of the MemModel where the object equals $node.
+ * Returns an NULL if nothing is found.
+ * You can define an offset to search for. Default = 0
+ *
+ * @param object Node $subject
+ * @param object Node $predicate
+ * @param object Node $object
+ * @param integer $offset
+ * @return object Statement
+ * @access public
+ */
+ function findFirstMatchingStatement($subject, $predicate, $object, $offset = 0) {
+
+ $currentOffset = 0;
+ for($i=0;$i<=$offset;$i++)
+ {
+ $res = $this->findFirstMatchOff($subject, $predicate, $object, $currentOffset);
+ $currentOffset=$res+1;
+ }
+ if ($res != -1) {
+ return $this->triples[$res];
+ } else {
+ return NULL;
+ }
+ }
+
+
+
+
+ /**
+ * Searches for triples and returns the first matching statement from a given offset.
+ * This method is used by the util/findIterator. NULL input for any parameter will match anything.
+ * Example: $result = $m->findFirstMatchingStatement( NULL, NULL, $node, $off );
+ * Returns the position of the first statement of the MemModel where the object equals $node from the given
+ * offset.
+ * Returns an -1 if nothing is found.
+ *
+ * @param object Node $subject
+ * @param object Node $predicate
+ * @param object Node $object
+ * @param int $off
+ * @return int
+ * @access private
+ */
+ function findFirstMatchOff($subject,$predicate, $object,$off) {
+
+ if (
+ (!is_a($subject, 'Resource') && $subject != NULL) ||
+ (!is_a($predicate, 'Resource') && $predicate != NULL) ||
+ (!is_a($object, 'Node') && $object != NULL)
+ ) {
+ $errmsg = RDFAPI_ERROR . '(class: MemModel; method: find): Parameters must be subclasses of Node or NULL';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ $match=-1;
+ $ind=$this->indexed;
+ if($subject == NULL && $predicate == NULL && $object == NULL)
+ {
+ foreach ($this->triples as $key => $statement)
+ {
+ if ($key >= $off)
+ return $key;
+ }
+ return -1;
+ }
+
+ switch($ind){
+ case 1:
+ if($subject!=NULL && $predicate != NULL && $object != NULL){
+ $pos=$subject->getLabel().$predicate->getLabel().$object->getLabel();
+ return $this->_findMatchIndex($pos,$subject,$predicate,$object,1,$off);
+ }else{
+ break;
+ }
+
+ case 2:
+ if($subject!=NULL && $predicate != NULL){
+ $pos=$subject->getLabel().$predicate->getLabel();
+ return $this->_findMatchIndex($pos,$subject,$predicate,$object,2,$off);
+ }else{
+ break;
+ }
+
+ case 3:
+ if($subject!=NULL && $object != NULL){
+ $pos=$subject->getLabel().$object->getLabel();
+ return $this->_findMatchIndex($pos,$subject,$predicate,$object,3,$off);
+ }else{
+ break;
+ }
+ case 0:
+ if($subject!= null){
+ $pos=$subject->getLabel();
+ return $this->_findMatchIndex($pos,$subject,$predicate,$object,4,$off);
+ }
+ if($predicate!= null){
+ $pos=$predicate->getLabel();
+ return $this->_findMatchIndex($pos,$subject,$predicate,$object,5,$off);
+ }
+ if($object!= null){
+ $pos=$object->getLabel();
+ return $this->_findMatchIndex($pos,$subject,$predicate,$object,6,$off);
+ }
+ break;
+ }
+ // if no index: linear search
+ foreach($this->triples as $key => $value){
+ if ($this->matchStatement($value, $subject, $predicate, $object)){
+ if($off<=$key){
+ $match=$key;
+ break;
+ }
+ }
+ }
+ return $match;
+ }
+
+
+ /**
+ * Searches for triples and returns the number of matches.
+ * NULL input for any parameter will match anything.
+ * Example: $result = $m->findCount( NULL, NULL, $node );
+ * Finds all triples with $node as object.
+ *
+ * @param object Node $subject
+ * @param object Node $predicate
+ * @param object Node $object
+ * @return integer
+ * @access public
+ */
+ function findCount($subject, $predicate, $object) {
+
+ $res = $this->find($subject, $predicate, $object);
+ return $res->size();
+
+ }
+
+
+ /**
+ * Perform an RDQL query on this MemModel.
+ * This method returns an associative array of variable bindings.
+ * The values of the query variables can either be RAP's objects (instances of Node)
+ * if $returnNodes set to TRUE, or their string serialization.
+ *
+ * @access public
+ * @param string $queryString
+ * @param boolean $returnNodes
+ * @return array [][?VARNAME] = object Node (if $returnNodes = TRUE)
+ * OR array [][?VARNAME] = string
+ *
+ */
+ function rdqlQuery($queryString, $returnNodes = TRUE) {
+
+ // Import RDQL Package
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_RDQL);
+
+ $parser = new RdqlParser();
+ $parsedQuery =& $parser->parseQuery($queryString);
+
+ // this method can only query this MemModel
+ // if another model was specified in the from clause throw an error
+ if (isset($parsedQuery['sources'][1])) {
+ $errmsg = RDFAPI_ERROR . '(class: MemModel; method: rdqlQuery):';
+ $errmsg .= ' this method can only query this MemModel';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ $engine = new RdqlMemEngine();
+ $res =& $engine->queryModel($this, $parsedQuery, $returnNodes);
+
+ return $res;
+ }
+
+ /**
+ * Perform an RDQL query on this MemModel.
+ * This method returns an RdqlResultIterator of variable bindings.
+ * The values of the query variables can either be RAP's objects (instances of Node)
+ * if $returnNodes set to TRUE, or their string serialization.
+ *
+ * @access public
+ * @param string $queryString
+ * @param boolean $returnNodes
+ * @return object RdqlResultIterator = with values as object Node (if $returnNodes = TRUE)
+ * OR object RdqlResultIterator = with values as strings if (if $returnNodes = FALSE)
+ *
+ */
+ function rdqlQueryAsIterator($queryString, $returnNodes = TRUE) {
+ // Import RDQL Package
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_RDQL);
+ return new RdqlResultIterator($this->rdqlQuery($queryString, $returnNodes));
+ }
+
+ /**
+ * General method to replace nodes of a MemModel.
+ * NULL input for any parameter will match nothing.
+ * Example: $m->replace($node, NULL, $node, $replacement);
+ * Replaces all $node objects beeing subject or object in
+ * any triple of the MemModel with the $needle node.
+ *
+ * @param object Node $subject
+ * @param object Node $predicate
+ * @param object Node $object
+ * @param object Node $replacement
+ * @access public
+ * @throws PhpError
+ */
+ function replace($subject, $predicate, $object, $replacement) {
+
+ if (
+ (!is_a($replacement, 'Node')) ||
+ (!is_a($subject, 'Resource') && $subject != NULL) ||
+ (!is_a($predicate, 'Resource') && $predicate != NULL) ||
+ (!is_a($object, 'Node') && $object != NULL)
+ ) {
+ $errmsg = RDFAPI_ERROR . '(class: MemModel; method: replace): Parameters must be subclasses of Node or NULL';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ if($this->size() == 0)
+ break;
+ foreach($this->triples as $key => $value) {
+ if ($this->triples[$key]->subj->equals($subject)) {
+ $this->triples[$key]->subj = $replacement;
+ }
+ if ($this->triples[$key]->pred->equals($predicate))
+ $this->triples[$key]->pred = $replacement;
+ if ($this->triples[$key]->obj->equals($object))
+ $this->triples[$key]->obj = $replacement;
+
+ }
+ $this->index($this->indexed);
+ }
+
+
+ /**
+ * Internal method that checks, if a statement matches a S, P, O or NULL combination.
+ * NULL input for any parameter will match anything.
+ *
+ * @param object Statement $statement
+ * @param object Node $subject
+ * @param object Node $predicate
+ * @param object Node $object
+ * @return boolean
+ * @access private
+ */
+ function matchStatement($statement, $subject, $predicate, $object) {
+
+ if(($subject != NULL) AND !($statement->subj->equals($subject)))
+ return false;
+
+ if($predicate != NULL && !($statement->pred->equals($predicate)))
+ return false;
+
+ if($object != NULL && !($statement->obj->equals($object)))
+ return false;
+
+ return true;
+ }
+
+
+
+
+ /**
+ * Checks if two models are equal.
+ * Two models are equal if and only if the two RDF graphs they represent are isomorphic.
+ *
+ * @access public
+ * @param object model &$that
+ * @throws phpErrpr
+ * @return boolean
+ */
+
+ function equals(&$that) {
+
+ if (!is_a($that, 'Model')) {
+ $errmsg = RDFAPI_ERROR . '(class: MemModel; method: equals): Model expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ if ($this->size() != $that->size())
+ return FALSE;
+ /*
+ if (!$this->containsAll($that))
+ return FALSE;
+ return TRUE;
+ */
+ include_once(RDFAPI_INCLUDE_DIR. "util/ModelComparator.php");
+ return ModelComparator::compare($this,$that);
+ }
+
+ /**
+ * Returns a new MemModel that is the set-union of the MemModel with another model.
+ * Duplicate statements are removed. If you want to allow duplicates, use addModel() which is much faster.
+ *
+ * The result of taking the set-union of two or more RDF graphs (i.e. sets of triples)
+ * is another graph, which we will call the merge of the graphs.
+ * Each of the original graphs is a subgraph of the merged graph. Notice that when forming
+ * a merged graph, two occurrences of a given uriref or literal as nodes in two different
+ * graphs become a single node in the union graph (since by definition they are the same
+ * uriref or literal) but blank nodes are not 'merged' in this way; and arcs are of course
+ * never merged. In particular, this means that every blank node in a merged graph can be
+ * identified as coming from one particular graph in the original set of graphs.
+ *
+ * Notice that one does not, in general, obtain the merge of a set of graphs by concatenating
+ * their corresponding N-triples documents and constructing the graph described by the merged
+ * document, since if some of the documents use the same node identifiers, the merged document
+ * will describe a graph in which some of the blank nodes have been 'accidentally' merged.
+ * To merge Ntriples documents it is necessary to check if the same nodeID is used in two or
+ * more documents, and to replace it with a distinct nodeID in each of them, before merging the
+ * documents. (Not implemented yet !!!!!!!!!!!)
+ *
+ * @param object Model $model
+ * @return object MemModel
+ * @access public
+ * @throws phpErrpr
+ *
+ */
+ function & unite(&$model) {
+
+ if (!is_a($model, 'Model')) {
+ $errmsg = RDFAPI_ERROR . '(class: MemModel; method: unite): Model expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ $res = $this;
+
+ if (is_a($model, 'MemModel')) {
+ require_once RDFAPI_INCLUDE_DIR . 'util/StatementIterator.php';
+ $stateIt=new StatementIterator($model);
+ while($statement=$stateIt->next())
+ {
+ $res->addWithoutDuplicates($statement);
+ }
+ }
+
+ elseif (is_a($model, 'DbModel')) {
+ $memModel =& $model->getMemModel();
+ foreach($memModel->triples as $value)
+ $res->addWithoutDuplicates($value);
+ }
+
+ return $res;
+ }
+
+ /**
+ * Returns a new MemModel that is the subtraction of another model from this MemModel.
+ *
+ * @param object Model $model
+ * @return object MemModel
+ * @access public
+ * @throws phpErrpr
+ */
+
+ function & subtract(&$model) {
+
+ if (!is_a($model, 'Model')) {
+ $errmsg = RDFAPI_ERROR . '(class: MemModel; method: subtract): Model expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ $res = $this;
+
+
+ if (is_a($model, 'MemModel'))
+ {
+ require_once RDFAPI_INCLUDE_DIR . 'util/StatementIterator.php';
+ $stateIt=new StatementIterator($model);
+ while($statement=$stateIt->next())
+ {
+ $res->remove($statement);
+ }
+ }
+ elseif (is_a($model, 'DbModel'))
+ {
+ $memModel =& $model->getMemModel();
+ foreach($memModel->triples as $value)
+ $res->remove($value);
+ }
+
+
+ return $res;
+ }
+
+ /**
+ * Returns a new MemModel containing all the statements which are in both this MemModel and another.
+ *
+ * @param object Model $model
+ * @return object MemModel
+ * @access public
+ * @throws phpErrpr
+ */
+ function & intersect(&$model) {
+
+ if (!is_a($model, 'Model')) {
+ $errmsg = RDFAPI_ERROR . '(class: MemModel; method: intersect: Model expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ $res = new MemModel($this->getBaseURI());
+
+ if (is_a($model, 'DbModel') || is_a($model, 'RDFSBModel'))
+ {
+ $memModel =& $model->getMemModel();
+ foreach($memModel->triples as $value) {
+ if ($this->contains($value))
+ $res->add($value);
+ }
+ }
+
+ elseif (is_a($model, 'MemModel'))
+ {
+ foreach($model->triples as $value) {
+ if ($this->contains($value))
+ $res->add($value);
+ }
+ }
+
+
+
+ return $res;
+ }
+
+
+ /**
+ * Adds another model to this MemModel.
+ * Duplicate statements are not removed.
+ * If you don't want duplicates, use unite().
+ * If any statement of the model to be added to this model contains a blankNode
+ * with an identifier already existing in this model, a new blankNode is generated.
+ *
+ * @param object Model $model
+ * @access public
+ * @throws phpErrpr
+ *
+ */
+ function addModel(&$model) {
+
+ if (!is_a($model, 'Model')) {
+ $errmsg = RDFAPI_ERROR . '(class: MemModel; method: addModel): Model expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ $blankNodes_tmp = array();
+
+ if (is_a($model, 'MemModel')) {
+ require_once RDFAPI_INCLUDE_DIR . 'util/StatementIterator.php';
+ $stateIt=new StatementIterator($model);
+ while($statement=$stateIt->next())
+ {
+ $this->_addStatementFromAnotherModel($statement, $blankNodes_tmp);
+ };
+ $this->addParsedNamespaces($model->getParsedNamespaces());
+ }
+
+ elseif (is_a($model, 'DbModel')) {
+ $memModel =& $model->getMemModel();
+ foreach($memModel->triples as $value)
+ $this->_addStatementFromAnotherModel($value, $blankNodes_tmp);
+ }
+ $this->index($this->indexed);
+ }
+
+
+ /**
+ * Reifies the MemModel.
+ * Returns a new MemModel that contains the reifications of all statements of this MemModel.
+ *
+ * @access public
+ * @return object MemModel
+ */
+ function & reify() {
+ $res = new MemModel($this->getBaseURI());
+
+ $stateIt=$this->getStatementIterator();
+ while($statement=$stateIt->next())
+ {
+ $pointer =& $statement->reify($res);
+ $res->addModel($pointer);
+ };
+
+ return $res;
+ }
+
+ /**
+ * Returns a StatementIterator for traversing the MemModel.
+ * @access public
+ * @return object StatementIterator
+ */
+ function & getStatementIterator() {
+ // Import Package Utility
+ require_once RDFAPI_INCLUDE_DIR . 'util/StatementIterator.php';
+
+ $si = new StatementIterator($this);
+ return $si;
+ }
+
+ /**
+ * Returns a FindIterator for traversing the MemModel.
+ * @access public
+ * @return object FindIterator
+ */
+ function & findAsIterator($sub=null,$pred=null,$obj=null) {
+ // Import Package Utility
+ require_once RDFAPI_INCLUDE_DIR . 'util/FindIterator.php';
+
+ $if = new FindIterator($this,$sub,$pred,$obj);
+ return $if;
+ }
+
+ /**
+ * Returns a FindIterator for traversing the MemModel.
+ * @access public
+ * @return object FindIterator
+ */
+ function & iterFind($sub=null,$pred=null,$obj=null) {
+ // Import Package Utility
+ require_once RDFAPI_INCLUDE_DIR . 'util/IterFind.php';
+
+ $if = new IterFind($this,$sub,$pred,$obj);
+ return $if;
+ }
+
+
+ /**
+ * Returns the models namespaces.
+ *
+ * @author Tobias Gau�
+ * @access public
+ * @return Array
+ */
+ function getParsedNamespaces(){
+ if(count($this->parsedNamespaces)!=0){
+ return $this->parsedNamespaces;
+ }else{
+ return false;
+ }
+ }
+
+
+
+ /**
+ * Adds the namespaces to the model. This method is called by
+ * the parser. !!!! addParsedNamespaces() not overwrites manual
+ * added namespaces in the model !!!!
+ *
+ * @author Tobias Gau�
+ * @access public
+ * @param Array $newNs
+ */
+ function addParsedNamespaces($newNs){
+ if($newNs)
+ $this->parsedNamespaces = $this->parsedNamespaces + $newNs;
+ }
+
+
+ /**
+ * Adds a namespace and prefix to the model.
+ *
+ * @author Tobias Gau�
+ * @access public
+ * @param String
+ * @param String
+ */
+ function addNamespace($prefix, $nmsp){
+ $this->parsedNamespaces[$nmsp]=$prefix;
+ }
+
+ /**
+ * removes a single namespace from the model
+ *
+ * @author Tobias Gau�
+ * @access public
+ * @param String $nmsp
+ */
+ function removeNamespace($nmsp){
+ if(isset($this->parsedNamespaces[$nmsp])){
+ unset($this->parsedNamespaces[$nmsp]);
+ return true;
+ }else{
+ return false;
+ }
+ }
+
+
+
+ /**
+ * Close the MemModel and free up resources held.
+ *
+ * @access public
+ */
+ function close() {
+ unset( $this->baseURI );
+ unset( $this->triples );
+ }
+
+ // =============================================================================
+ // *************************** helper functions ********************************
+ // =============================================================================
+ /**
+ * Checks if $statement is in index
+ *
+ * @param int $ind
+ * @param Statement &$statement
+ * @return boolean
+ * @access private
+ */
+ function _containsIndex(&$statement,$ind){
+ switch($ind){
+ case 4:
+ $sub=$statement->getSubject();
+ $pos=$sub->getLabel();
+ break;
+ case 1:
+ $sub=$statement->getSubject();
+ $pred=$statement->getPredicate();
+ $obj=$statement->getObject();
+ $pos=$sub->getLabel().$pred->getLabel().$obj->getLabel();
+ break;
+ case 2:
+ $sub=$statement->getSubject();
+ $pred=$statement->getPredicate();
+ $pos=$sub->getLabel().$pred->getLabel();
+ break;
+ case 3:
+ $sub=$statement->getSubject();
+ $obj=$statement->getObject();
+ $pos=$sub->getLabel().$obj->getLabel();
+ break;
+ }
+
+ if (!isset($this->indexArr[$ind][$pos]))
+ return FALSE;
+ foreach ($this->indexArr[$ind][$pos] as $key => $value) {
+ $t=$this->triples[$value];
+ if ($t->equals($statement))
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+
+
+
+
+ /**
+ * finds a statement in an index. $pos is the Position in the index
+ * and $ind the adequate searchindex
+ *
+ * @param String $pos
+ * @param Object Subject &$subject
+ * @param Object Predicate &$predicate
+ * @param Object Object &$object
+ * @param int &ind
+ * @return MemModel $res
+ * @access private
+ */
+ function _findInIndex($pos,&$subject,&$predicate,&$object,$ind){
+ $res = new MemModel($this->getBaseURI());
+ $res->indexed=-1;
+ if (!isset($this->indexArr[$ind][$pos]))
+ return $res;
+ foreach($this->indexArr[$ind][$pos] as $key =>$value){
+ $t=$this->triples[$value];
+ if ($this->matchStatement($t,$subject,$predicate,$object))
+ $res->add($t);
+ }
+ return $res;
+ }
+ /**
+ * adds/removes a statement into/from an index.
+ * mode=0 removes the statement from the index;
+ * mode=1 adds the statement into the index.
+ * returns the statements position.
+ *
+ * @param Object Statement &$statement
+ * @param int $k
+ * @param int $ind
+ * @param int $mode
+ * @return int $k
+ * @access private
+ */
+ function _indexOpr(&$statement,$k,$ind,$mode){
+ // determine position in adequate index
+ switch($ind){
+ case 1:
+ $s=$statement->getSubject();
+ $p=$statement->getPredicate();
+ $o=$statement->getObject();
+ $pos=$s->getLabel().$p->getLabel().$o->getLabel();
+ break;
+ case 2:
+ $s=$statement->getSubject();
+ $p=$statement->getPredicate();
+ $pos=$s->getLabel().$p->getLabel();
+ break;
+ case 3:
+ $s=$statement->getSubject();
+ $o=$statement->getObject();
+ $pos=$s->getLabel().$o->getLabel();
+ break;
+ case 4:
+ $s=$statement->getSubject();
+ $pos=$s->getLabel();
+ break;
+ case 5:
+ $p=$statement->getPredicate();
+ $pos=$p->getLabel();
+ break;
+ case 6:
+ $o=$statement->getObject();
+ $pos=$o->getLabel();
+ break;
+ }
+ switch($mode){
+ // add in Index
+ case 1:
+ if(isset($this->indexArr[$ind][$pos])){
+ $this->indexArr[$ind][$pos][] = $k;
+ }else{
+ $this->indexArr[$ind][$pos][0] = $k;
+ }
+ break;
+ // remove from Index
+ case 0:
+ $subject=$statement->getSubject();
+ $predicate=$statement->getPredicate();
+ $object=$statement->getObject();
+ $k=-1;
+ if(!isset($this->indexArr[$ind][$pos])){
+ return -1;
+ }
+ $num=count($this->indexArr[$ind][$pos]);
+ foreach($this->indexArr[$ind][$pos] as $key => $value){
+ $t=$this->triples[$value];
+ if($this->matchStatement($t,$subject,$predicate,$object)){
+ $k=$value;
+ if($num==1){
+ unset($this->indexArr[$ind][$pos]);
+ }else{
+ unset($this->indexArr[$ind][$pos][$key]);
+ }
+ return $k;
+ }
+ }
+ break;
+ }
+ return $k;
+ }
+
+
+ /**
+ * finds next or previous matching statement.
+ * Returns Position in model or -1 if there is no match.
+ *
+ *
+ * @param String
+ * @param object Subject
+ * @param object Predicate
+ * @param object Object
+ * @param integer
+ * @param integer
+ * @return integer
+ * @access private
+ */
+ function _findMatchIndex($pos,&$s,&$p,&$o,$ind,$off){
+ $match=-1;
+ if (!isset($this->indexArr[$ind][$pos])) {
+ return $match;}
+ foreach($this->indexArr[$ind][$pos] as $key =>$value){
+ $t=$this->triples[$value];
+ if ($this->matchStatement($t,$s,$p,$o)){
+ if($off <= $value){
+ $match= $value;
+ return $match;
+ }
+ }
+ }
+
+ return $match;
+
+ }
+
+
+
+
+} // end: MemModel
+
+
+?>
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/text-base/Model.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/text-base/Model.php.svn-base
new file mode 100755
index 00000000..f61e31a1
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/text-base/Model.php.svn-base
@@ -0,0 +1,566 @@
+ triples, where P is a uriref, S is either
+ * a uriref or a blank node, and O is either a uriref, a blank node, or a literal.
+ *
+ *
+ * @version $Id$
+ * @author Radoslaw Oldakowski
+ * @author Daniel Westphal
+ *
+ * @package model
+ * @access public
+ */
+class Model extends Object
+{
+ /**
+ * Base URI of the Model.
+ * Affects creating of new resources and serialization syntax.
+ *
+ * @var string
+ * @access private
+ */
+ var $baseURI;
+
+ /**
+ * Number of the last assigned bNode.
+ *
+ * @var integer
+ * @access private
+ */
+ var $bNodeCount;
+
+ /**
+ * SparqlParser so we can re-use it
+ * @var Parser
+ */
+ var $queryParser = null;
+
+
+
+ /**
+ * Notice for people who are used to work with older versions of RAP.
+ *
+ * @throws PHPError
+ * @access public
+ */
+ function Model()
+ {
+
+ $errmsg = 'Since RAP 0.6 the class for manipulating memory models has been renamed to MemModel.';
+ $errmsg .= '
Sorry for this inconvenience.
';
+
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+
+
+ /**
+ * Return current baseURI.
+ *
+ * @return string
+ * @access public
+ */
+ function getBaseURI()
+ {
+ return $this->baseURI;
+ }
+
+
+
+ /**
+ * Load a model from a file containing RDF, N3, N-Triples or a xhtml document containing RDF.
+ * This function recognizes the suffix of the filename (.n3 or .rdf) and
+ * calls a suitable parser, if no $type is given as string ("rdf" "n3" "nt");
+ * If the model is not empty, the contents of the file is added to this DbModel.
+ *
+ * @param string $filename
+ * @param string $type
+ * @param boolean $stream
+ * @access public
+ */
+ function load($filename, $type = NULL, $stream=false)
+ {
+ if ((isset($type)) && ($type =='n3') OR ($type =='nt')) {
+ // Import Package Syntax
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_N3);
+ $parser = new N3Parser();
+ }elseif ((isset($type)) && ($type =='rdf')) {
+ // Import Package Syntax
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_RDF);
+ $parser = new RdfParser();
+ }elseif ((isset($type)) && ($type =='grddl')) {
+ // Import Package Syntax
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_GRDDL);
+ $parser = new GRDDLParser();
+ }elseif ((isset($type)) && ($type =='rss')) {
+ // Import Package Syntax
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_RSS);
+ $parser = new RssParser();
+ }else {
+ // create a parser according to the suffix of the filename
+ // if there is no suffix assume the file to be XML/RDF
+ preg_match("/\.([a-zA-Z0-9_]+)$/", $filename, $suffix);
+ if (isset($suffix[1]) && (strtolower($suffix[1]) == 'n3' OR strtolower($suffix[1]) == 'nt')){
+ // Import Package Syntax
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_N3);
+ $parser = new N3Parser();
+ }elseif (isset($suffix[1]) && (strtolower($suffix[1]) == 'htm' OR strtolower($suffix[1]) == 'html' OR strtolower($suffix[1]) == 'xhtml')){
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_GRDDL);
+ $parser = new GRDDLParser();
+ }else{
+ // Import Package Syntax
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_RDF);
+ $parser = new RdfParser();
+ }
+ };
+
+ if (($stream && $type=='rdf')||($stream && $type=='n3')) {
+ $temp=&$parser->generateModel($filename,false,$this);
+ } else{
+ $temp=&$parser->generateModel($filename);
+ }
+ $this->addModel($temp);
+ if($this->getBaseURI()== null)
+ $this->setBaseURI($temp->getBaseURI());
+ }
+
+ /**
+ * This method takes a string conatining data and adds the parsed data to this model.
+ *
+ * @param string $str The string containing the data to be parsed and loaded.
+ * @param type $type The type of the string, currently only 'json' is supported.
+ */
+ function loadFromString($str, $type) {
+
+ switch ($type) {
+ case 'json':
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_JSON);
+ $parser = new JsonParser();
+ break;
+ case 'n3':
+ case 'nt':
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_N3);
+ $parser = new N3Parser();
+ break;
+ case 'rdf':
+ case 'rdfxml':
+ case 'xml':
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_RDF);
+ $parser = new RdfParser();
+ break;
+ case 'grddl':
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_GRDDL);
+ $parser = new GRDDLParser();
+ break;
+ case 'rss':
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_RSS);
+ $parser = new RssParser();
+ break;
+ default:
+ trigger_error('(class: Model; method: loadFromString): type ' . $type . 'is currently not supported',
+ E_USER_ERROR);
+ }
+
+ if ($parser instanceof JsonParser) {
+ $parser->generateModelFromString($str, $this);
+ } else {
+ $parser->generateModel($str, false, $this);
+ }
+ }
+
+ /**
+ * Adds a statement from another model to this model.
+ * If the statement to be added contains a blankNode with an identifier
+ * already existing in this model, a new blankNode is generated.
+ *
+ * @param Object Statement $statement
+ * @access private
+ */
+ function _addStatementFromAnotherModel($statement, &$blankNodes_tmp)
+ {
+ $subject = $statement->getSubject();
+ $object = $statement->getObject();
+
+ if (is_a($subject, "BlankNode")) {
+ $label = $subject->getLabel();
+ if (!array_key_exists($label, $blankNodes_tmp))
+ {
+ if ($this->findFirstMatchingStatement($subject, NULL, NULL)
+ || $this->findFirstMatchingStatement(NULL, NULL, $subject))
+ {
+ $blankNodes_tmp[$label] = new BlankNode($this);
+ $statement->subj = $blankNodes_tmp[$label];
+ } else {
+ $blankNodes_tmp[$label] = $subject;
+ }
+ } else
+ $statement->subj = $blankNodes_tmp[$label];
+ }
+
+ if (is_a($object, "BlankNode")) {
+ $label = $object->getLabel();
+ if (!array_key_exists($label, $blankNodes_tmp))
+ {
+ if ($this->findFirstMatchingStatement($object, NULL, NULL)
+ || $this->findFirstMatchingStatement(NULL, NULL, $object))
+ {
+ $blankNodes_tmp[$label] = new BlankNode($this);
+ $statement->obj = $blankNodes_tmp[$label];
+ } else {
+ $blankNodes_tmp[$label] = $object;
+ }
+ } else
+ $statement->obj = $blankNodes_tmp[$label];
+ }
+ $this->add($statement);
+ }
+
+
+
+ /**
+ * Internal method, that returns a resource URI that is unique for the Model.
+ * URIs are generated using the base_uri of the DbModel, the prefix and a unique number.
+ * If no prefix is defined, the bNode prefix, defined in constants.php, is used.
+ *
+ * @param string $prefix
+ * @return string
+ * @access private
+ */
+ function getUniqueResourceURI($prefix = false)
+ {
+ static $bNodeCount;
+ if(!$bNodeCount)
+ $bNodeCount = 0;
+
+ if(!$prefix)
+ $prefix=BNODE_PREFIX;
+
+ return $prefix.++$bNodeCount;
+ }
+
+
+
+ /**
+ * Returns a ResModel with this model as baseModel. This is the same as
+ * ModelFactory::getResModelForBaseModel($this).
+ *
+ * @return object ResModel
+ * @access public
+ */
+ function & getResModel()
+ {
+ return ModelFactory::getResModelForBaseModel($this);
+ }
+
+
+
+ /**
+ * Returns an OntModel with this model as baseModel.
+ * $vocabulary has to be one of the following constants (currently only one is supported):
+ * RDFS_VOCABULARY to select a RDFS Vocabulary.
+ *
+ * This is the same as ModelFactory::getOntModelForBaseModel($this, $vocabulary).
+ *
+ * @param constant $vocabulary
+ * @return object OntModel
+ * @access public
+ */
+ function & getOntModel($vocabulary)
+ {
+ return ModelFactory::getOntModelForBaseModel($this, $vocabulary);
+ }
+
+
+
+ /**
+ * Searches for triples using find() and tracks forward blank nodes
+ * until the final objects in the retrieved subgraphs are all named resources.
+ * The method calls itself recursivly until the result is complete.
+ * NULL input for subject, predicate or object will match anything.
+ * Inputparameters are ignored for recursivly found statements.
+ * Returns a new MemModel or adds (without checking for duplicates)
+ * the found statements to a given MemModel.
+ * Returns an empty MemModel, if nothing is found.
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * WARNING: This method can be slow with large models.
+ * NOTE: Blank nodes are not renamed, they keep the same nodeIDs
+ * as in the queried model!
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ *
+ * @author Anton Koestlbacher
+ * @param object Node $subject
+ * @param object Node $predicate
+ * @param object Node $object
+ * @param object MemModel $object
+ * @return object MemModel
+ * @access public
+ * @throws PhpError
+ */
+ function findForward($subject, $predicate, $object, &$newModel = NULL)
+ {
+ if (!is_a($newModel, "MemModel"))
+ {
+ $newModel = New MemModel;
+ }
+
+ if (is_a($this, "DbModel"))
+ {
+ $model = $this;
+ $res = $model->find($subject, $predicate, $object);
+ $it = $res->getStatementIterator();
+ }
+ elseif (is_a($this, "MemModel")) {
+ $model = $this;
+ $it = $model->findAsIterator($subject, $predicate, $object);
+ }
+ elseif (is_a($this, "ResModel")) {
+ $model = $this->model;
+ $it = $model->findAsIterator($subject, $predicate, $object);
+ }
+
+ while ($it->hasNext())
+ {
+ $statement = $it->next();
+ $newModel->add($statement);
+ if (is_a($statement->object(),'BlankNode'))
+ {
+ $model->findForward($statement->object(), NULL, NULL, $newModel);
+ }
+ }
+ return $newModel;
+ }
+
+
+
+ /**
+ * Perform an RDQL query on this Model. Should work with all types of models.
+ * This method returns a MemModel containing the result statements.
+ * If $closure is set to TRUE, the result will additionally contain
+ * statements found by the findForward-method for blank nodes.
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * WARNING: If called with $closure = TRUE this method
+ * can be slow with large models.
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ *
+ * @author Anton K�tlbacher
+ * @author code snippets taken from the RAP Netapi by Phil Dawes and Chris Bizer
+ * @access public
+ * @param string $queryString
+ * @param boolean $closure
+ * @return object MemModel
+ *
+ */
+ function & getMemModelByRDQL($queryString, $closure = FALSE)
+ {
+ require_once(RDFAPI_INCLUDE_DIR.PACKAGE_RDQL);
+ $parser = new RdqlParser();
+ $parsedQuery =& $parser->parseQuery($queryString);
+
+ // If there are variables used in the pattern but not
+ // in the select clause, add them to the select clause
+ foreach ($parsedQuery['patterns'] as $n => $pattern)
+ {
+ foreach ($pattern as $key => $val_1)
+ {
+ if ($val_1['value']{0}=='?')
+ {
+ if (!in_array($val_1['value'],$parsedQuery['selectVars']))
+ {
+ array_push($parsedQuery['selectVars'],$val_1['value']);
+ }
+ }
+ }
+ }
+
+ if (is_a($this, "DbModel"))
+ {
+ $engine = new RdqlDbEngine();
+ $model = $this;
+ }
+ elseif (is_a($this, "MemModel"))
+ {
+ $engine = new RdqlMemEngine();
+ $model = $this;
+ }
+ elseif (is_a($this, "ResModel"))
+ {
+ $engine = new RdqlMemEngine();
+ $model = $this->model;
+ }
+
+ $res = $engine->queryModel($model,$parsedQuery,TRUE);
+ $rdqlIter = new RdqlResultIterator($res);
+ $newModel = new MemModel();
+
+ // Build statements from RdqlResultIterator
+ while ($rdqlIter->hasNext()) {
+ $result = $rdqlIter->next();
+ foreach ($parsedQuery['patterns'] as $n => $pattern)
+ {
+ if (substr($pattern['subject']['value'], 0, 1) == '?')
+ {
+ $subj = $result[$pattern['subject']['value']];
+ }
+ else
+ {
+ $subj = new Resource($pattern['subject']['value']);
+ }
+ if (substr($pattern['predicate']['value'], 0, 1) == '?')
+ {
+ $pred = $result[$pattern['predicate']['value']];
+ }
+ else
+ {
+ $pred = new Resource($pattern['predicate']['value']);
+ }
+
+ if (substr($pattern['object']['value'], 0, 1) == '?')
+ {
+ $obj = $result[$pattern['object']['value']];
+ }
+ else
+ {
+ if (isset($pattern['object']['is_literal']))
+ {
+ $obj = new Literal($pattern['object']['value']);
+ $obj->setDatatype($pattern['object']['l_dtype']);
+ $obj->setLanguage($pattern['object']['l_lang']);
+ }
+ else
+ {
+ $obj = new Resource($pattern['object']['value']);
+ }
+ }
+
+ $statement = new Statement($subj,$pred,$obj);
+ $newModel->add($statement);
+
+ // findForward() Statements containing an eventually given blank node
+ // and add them to the result, if closure = true
+ if (is_a($statement->object(),'BlankNode') && $closure == True)
+ {
+ $newModel = $model->findForward($statement->object(),NULL,NULL, $newModel);
+ }
+ if (is_a($statement->subject(),'BlankNode') && $closure == True)
+ {
+ $newModel = $model->findForward($statement->subject(),NULL,NULL, $newModel);
+ }
+ }
+ }
+ return $newModel;
+ }
+
+
+
+ /**
+ * Alias for RDFUtil::visualiseGraph(&$model, $format, $short_prefix)
+ *
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * Note: See RDFUtil for further Information.
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ *
+ * @author Anton K�tlbacher
+ * @param string $format
+ * @param boolean $short_prefix
+ * @return string, binary
+ * @access public
+ * @throws PhpError
+ */
+ function visualize($format = "dot", $short_prefix = TRUE)
+ {
+ return RDFUtil::visualizeGraph($this, $format, $short_prefix);
+ }
+
+
+ /**
+ * Performs a SPARQL query against a model. The model is converted to
+ * an RDF Dataset. The result can be retrived in SPARQL Query Results XML Format or
+ * as an array containing the variables an their bindings.
+ *
+ * @param string $query the sparql query string
+ * @param string $resultform the result form ('xml' for SPARQL Query Results XML Format)
+ * @return string/array
+ */
+ function sparqlQuery($query, $resultform = false)
+ {
+ list($engine, $dataset) = $this->_prepareSparql();
+ return $engine->queryModel(
+ $dataset,
+ $this->_parseSparqlQuery($query),
+ $resultform
+ );
+ }//function sparqlQuery($query,$resultform = false)
+
+
+
+ /**
+ * Prepares a sparql query and returns a prepared statement
+ * that can be executed with data later on.
+ *
+ * @param string $query Sparql query to prepare.
+ * @return SparqlEngine_PreparedStatement prepared statement object
+ */
+ function sparqlPrepare($query)
+ {
+ list($engine, $dataset) = $this->_prepareSparql();
+ return $engine->prepare(
+ $dataset,
+ $this->_parseSparqlQuery($query)
+ );
+ }//function sparqlPrepare($query)
+
+
+
+ /**
+ * Prepares everything for SparqlEngine-usage
+ * Loads the files, creates instances for SparqlEngine and
+ * Dataset...
+ *
+ * @return array First value is the sparql engine, second the dataset
+ */
+ function _prepareSparql()
+ {
+ require_once RDFAPI_INCLUDE_DIR . 'sparql/SparqlEngine.php';
+ require_once RDFAPI_INCLUDE_DIR . 'dataset/DatasetMem.php';
+
+ $dataset = new DatasetMem();
+ $dataset->setDefaultGraph($this);
+
+ return array(
+ SparqlEngine::factory($this),
+ $dataset
+ );
+ }//function _prepareSparql()
+
+
+
+ /**
+ * Parses an query and returns the parsed form.
+ * If the query is not a string but a Query object,
+ * it will just be returned.
+ *
+ * @param $query mixed String or Query object
+ * @return Query query object
+ * @throws Exception If $query is no string and no Query object
+ */
+ function _parseSparqlQuery($query)
+ {
+ if ($this->queryParser === null) {
+ require_once RDFAPI_INCLUDE_DIR . 'sparql/SparqlParser.php';
+ $this->queryParser = new SparqlParser();
+ }
+ return $this->queryParser->parse($query);
+ }//function _parseSparqlQuery($query)
+
+} // end: Model
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/text-base/ModelFactory.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/text-base/ModelFactory.php.svn-base
new file mode 100755
index 00000000..b3dd1601
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/text-base/ModelFactory.php.svn-base
@@ -0,0 +1,288 @@
+
+* @author Richard Cyganiak
+*
+*
+* @package model
+* @access public
+**/
+class ModelFactory
+{
+ /**
+ * Returns a MemModel.
+ * You can supply a base URI
+ *
+ * @param string $baseURI
+ * @return object MemModel
+ * @access public
+ */
+ function & getDefaultModel($baseURI = null)
+ {
+ return ModelFactory::getMemModel($baseURI);
+ }
+
+ /**
+ * Returns a NamedGraphSetMem.
+ * You can supply a GraphSet name.
+ *
+ * @param string $graphSetId
+ * @param string $uri
+ * @access public
+ */
+ function & getDatasetMem($graphSetId = null)
+ {
+ require_once RDFAPI_INCLUDE_DIR . 'dataset/DatasetMem.php';
+ $m = new DatasetMem($graphSetId);
+ return $m;
+ }
+
+ /**
+ * Returns a MemModel.
+ * You can supply a base URI
+ *
+ * @param string $baseURI
+ * @return object MemModel
+ * @access public
+ */
+ function & getMemModel($baseURI = null)
+ {
+ require_once RDFAPI_INCLUDE_DIR . 'model/MemModel.php';
+ $m = new MemModel($baseURI);
+ return $m;
+ }
+
+ /**
+ * Returns a DbModel with the database connection
+ * defined in constants.php.
+ * You can supply a base URI. If a model with the given base
+ * URI exists in the DbStore, it'll be opened.
+ * If not, a new model will be created.
+ *
+ * @param string $baseURI
+ * @return object DbModel
+ * @access public
+ */
+ function & getDefaultDbModel($baseURI = null)
+ {
+ $dbStore = ModelFactory::getDbStore();
+ $m = ModelFactory::getDbModel($dbStore,$baseURI);
+ return $m;
+ }
+
+ /**
+ * Returns a new DbModel using the database connection
+ * supplied by $dbStore.
+ * You can supply a base URI. If a model with the given base
+ * URI exists in the DbStore, it'll be opened.
+ * If not, a new model will be created.
+ *
+ * @param object DbStore $dbStore
+ * @param string $baseURI
+ * @return object DbModel
+ * @access public
+ */
+ function & getDbModel($dbStore, $baseURI = null)
+ {
+ if ($dbStore->modelExists($baseURI)) {
+ return $dbStore->getModel($baseURI);
+ }
+
+ return $dbStore->getNewModel($baseURI);
+ }
+
+ /**
+ * Returns a database connection with the given parameters.
+ * Paramters, which are not defined are taken from the constants.php
+ *
+ * @param string $dbDriver
+ * @param string $host
+ * @param string $dbName
+ * @param string $user
+ * @param string $password
+ * @return object DbStore
+ * @access public
+ */
+ function & getDbStore($dbDriver=ADODB_DB_DRIVER, $host=ADODB_DB_HOST, $dbName=ADODB_DB_NAME,
+ $user=ADODB_DB_USER, $password=ADODB_DB_PASSWORD)
+ {
+ $dbs = new DbStore($dbDriver, $host, $dbName,$user, $password);
+ return $dbs;
+ }
+
+ /**
+ * Returns a InfModelF.
+ * (MemModel with forward chaining inference engine)
+ * Configurations can be done in constants.php
+ * You can supply a base URI
+ *
+ * @param string $baseURI
+ * @return object MemModel
+ * @access public
+ */
+ function & getInfModelF($baseURI = null)
+ {
+ require_once RDFAPI_INCLUDE_DIR . 'infModel/InfModelF.php';
+ $mod = new InfModelF($baseURI);
+ return $mod;
+ }
+
+ /**
+ * Returns a InfModelB.
+ * (MemModel with backward chaining inference engine)
+ * Configurations can be done in constants.php
+ * You can supply a base URI
+ *
+ * @param string $baseURI
+ * @return object MemModel
+ * @access public
+ */
+ function & getInfModelB($baseURI = null)
+ {
+ require_once RDFAPI_INCLUDE_DIR . 'infModel/InfModelB.php';
+ $mod = new InfModelB($baseURI);
+ return $mod;
+ }
+
+ /**
+ * Returns a ResModel.
+ * $modelType has to be one of the following constants:
+ * MEMMODEL,DBMODEL,INFMODELF,INFMODELB to create a resmodel with a new
+ * model from defined type.
+ * You can supply a base URI
+ *
+ * @param constant $modelType
+ * @param string $baseURI
+ * @return object ResModel
+ * @access public
+ */
+ function & getResModel($modelType, $baseURI = null)
+ {
+ switch ($modelType) {
+ case DBMODEL:
+ $baseModel = ModelFactory::getDefaultDbModel($baseURI);
+ break;
+
+ case INFMODELF:
+ $baseModel = ModelFactory::getInfModelF($baseURI);
+ break;
+
+ case INFMODELB:
+ $baseModel = ModelFactory::getInfModelB($baseURI);
+ break;
+
+ default:
+ $baseModel = ModelFactory::getMemModel($baseURI);
+ break;
+ }
+ return ModelFactory::getResModelForBaseModel($baseModel);
+ }
+
+ /**
+ * Creates a ResModel that wraps an existing base model.
+ *
+ * @param object Model $baseModel
+ * @return object ResModel
+ * @access public
+ */
+ function &getResModelForBaseModel(&$baseModel) {
+ require_once RDFAPI_INCLUDE_DIR . 'resModel/ResModel.php';
+ $mod = new ResModel($baseModel);
+ return $mod;
+ }
+
+ /**
+ * Returns an OntModel.
+ * $modelType has to be one of the following constants:
+ * MEMMODEL, DBMODEL, INFMODELF, INFMODELB to create a OntModel
+ * with a new model from defined type.
+ * $vocabulary defines the ontology language. Currently only
+ * RDFS_VOCABULARY is supported. You can supply a model base URI.
+ *
+ * @param constant $modelType
+ * @param constant $vocabulary
+ * @param string $baseURI
+ * @return object OntModel
+ * @access public
+ */
+ function & getOntModel($modelType,$vocabulary, $baseURI = null)
+ {
+ switch ($modelType)
+ {
+ case DBMODEL:
+ $baseModel = ModelFactory::getDefaultDbModel($baseURI);
+ break;
+
+ case INFMODELF:
+ $baseModel = ModelFactory::getInfModelF($baseURI);
+ break;
+
+ case INFMODELB:
+ $baseModel = ModelFactory::getInfModelB($baseURI);
+ break;
+
+ default:
+ $baseModel = ModelFactory::getMemModel($baseURI);;
+ }
+
+ $mod = ModelFactory::getOntModelForBaseModel($baseModel, $vocabulary);
+ return $mod;
+ }
+
+ /**
+ * Creates an OntModel that wraps an existing base model.
+ * $vocabulary defines the ontology language. Currently only
+ * RDFS_VOCABULARY is supported.
+ *
+ * @param object Model $baseModel
+ * @param constant $vocabulary
+ * @return object OntModel
+ * @access public
+ */
+ function &getOntModelForBaseModel(&$baseModel, $vocabulary)
+ {
+ require_once RDFAPI_INCLUDE_DIR . 'ontModel/OntModel.php';
+
+ switch ($vocabulary)
+ {
+ case RDFS_VOCABULARY:
+ require_once(RDFAPI_INCLUDE_DIR.'ontModel/'.RDFS_VOCABULARY);
+ $vocab_object = new RdfsVocabulary();
+ break;
+ default:
+ trigger_error("Unknown vocabulary constant '$vocabulary'; only RDFS_VOCABULARY is supported", E_USER_WARNING);
+ $vocab_object = null;
+ break;
+ }
+ $mod = new OntModel($baseModel, $vocab_object);
+ return $mod;
+ }
+
+
+
+ /**
+ * Creates a SparqlClient.
+ *
+ * @param String $server Link to a SPARQL endpoint.
+ * @return SparqlClient the SparqlClient object.
+ * @access public
+ */
+ function & getSparqlClient($server){
+ $cl = new SparqlClient($server);
+ return $cl;
+ }
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/text-base/ModelP.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/text-base/ModelP.php.svn-base
new file mode 100755
index 00000000..ff3067f0
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/text-base/ModelP.php.svn-base
@@ -0,0 +1,27 @@
+
+//
+// ----------------------------------------------------------------------------------
+
+// Include Model classes
+require_once( RDFAPI_INCLUDE_DIR . 'model/Node.php' );
+require_once( RDFAPI_INCLUDE_DIR . 'model/Literal.php' );
+require_once( RDFAPI_INCLUDE_DIR . 'model/Resource.php' );
+require_once( RDFAPI_INCLUDE_DIR . 'model/Blanknode.php' );
+require_once( RDFAPI_INCLUDE_DIR . 'model/Statement.php' );
+require_once( RDFAPI_INCLUDE_DIR . 'model/Model.php' );
+require_once( RDFAPI_INCLUDE_DIR . 'model/MemModel.php' );
+require_once( RDFAPI_INCLUDE_DIR . 'model/DbStore.php' );
+require_once( RDFAPI_INCLUDE_DIR . 'util/StatementIterator.php' );
+require_once( RDFAPI_INCLUDE_DIR . 'model/ModelFactory.php' );
+require_once( RDFAPI_INCLUDE_DIR . 'sparql/SparqlClient.php' );
+require_once( RDFAPI_INCLUDE_DIR . 'sparql/ClientQuery.php' );
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/text-base/Node.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/text-base/Node.php.svn-base
new file mode 100755
index 00000000..94ee9b5b
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/text-base/Node.php.svn-base
@@ -0,0 +1,25 @@
+
+ * @package model
+ * @abstract
+ *
+ */
+ class Node extends Object {
+ } // end:RDFNode
+
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/text-base/Resource.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/text-base/Resource.php.svn-base
new file mode 100755
index 00000000..a9a0d403
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/text-base/Resource.php.svn-base
@@ -0,0 +1,142 @@
+
+ *
+ * @package model
+ * @access public
+ *
+ */
+ class Resource extends Node {
+
+ /**
+ * URIref to the resource
+ * @var string
+ * @access private
+ */
+ var $uri;
+
+
+ /**
+ * Constructor
+ * Takes an URI or a namespace/localname combination
+ *
+ * @param string $namespace_or_uri
+ * @param string $localName
+ * @access public
+ */
+ function Resource($namespace_or_uri , $localName = NULL) {
+ if ($localName == NULL) {
+ $this->uri = $namespace_or_uri;
+ } else {
+ $this->uri = $namespace_or_uri . $localName;
+ }
+ }
+
+
+ /**
+ * Returns the URI of the resource.
+ * @return string
+ * @access public
+ */
+ function getURI() {
+ return $this->uri;
+ }
+
+ /**
+ * Returns the label of the resource, which is the URI of the resource.
+ * @access public
+ * @return string
+ */
+ function getLabel() {
+ return $this->getURI();
+ }
+
+ /**
+ * Returns the namespace of the resource. May return null.
+ * @access public
+ * @return string
+ */
+ function getNamespace() {
+ // Import Package Utility
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_UTILITY);
+
+ return RDFUtil::guessNamespace($this->uri);
+ }
+
+ /**
+ * Returns the local name of the resource.
+ * @access public
+ * @return string
+ */
+ function getLocalName() {
+ // Import Package Utility
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_UTILITY);
+
+ return RDFUtil::guessName($this->uri);
+ }
+
+ /**
+ * Dumps resource.
+ * @access public
+ * @return string
+ */
+ function toString() {
+ return 'Resource("' . $this->uri .'")';
+ }
+
+ /**
+ * Checks if the resource equals another resource.
+ * Two resources are equal, if they have the same URI
+ *
+ * @access public
+ * @param object resource $that
+ * @return boolean
+ */
+ function equals ($that) {
+
+ if ($this == $that) {
+ return true;
+ }
+
+ if (($that == NULL) or !(is_a($that, 'Resource')) or (is_a($that, 'BlankNode'))) {
+ return false;
+ }
+
+ if ($this->getURI() == $that->getURI()) {
+ return true;
+ }
+
+ return false;
+ }
+
+
+
+
+ /**
+ * Doing string magic in PHP5
+ * @return string String representation of this Resource
+ */
+ function __toString()
+ {
+ return $this->toString();
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/text-base/Statement.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/text-base/Statement.php.svn-base
new file mode 100755
index 00000000..f788bec8
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/.svn/text-base/Statement.php.svn-base
@@ -0,0 +1,313 @@
+
+ * @version $Id$
+ * @package model
+ */
+class Statement extends Object {
+
+ /**
+ * Subject of the statement
+ *
+ * @var object resource
+ * @access private
+ */
+ var $subj;
+
+ /**
+ * Predicate of the statement
+ *
+ * @var object resource
+ * @access private
+ */
+ var $pred;
+
+ /**
+ * Object of the statement
+ *
+ * @var object node
+ * @access private
+ */
+ var $obj;
+
+ /**
+ * The parameters to constructor are instances of classes and not just strings
+ *
+ * @param object node $subj
+ * @param object node $pred
+ * @param object node $obj
+ * @throws PhpError
+ */
+ function Statement($subj, $pred, $obj) {
+
+ if (!is_a($subj, 'Resource')) {
+ $errmsg = RDFAPI_ERROR .
+ '(class: Statement; method: new): Resource expected as subject.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+ if (!is_a($pred, 'Resource') || is_a($pred, 'BlankNode')) {
+ $errmsg = RDFAPI_ERROR .
+ '(class: Statement; method: new): Resource expected as predicate, no blank node allowed.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+ if (!(is_a($obj, 'Resource') or is_a($obj, 'Literal'))) {
+ $errmsg = RDFAPI_ERROR .
+ '(class: Statement; method: new): Resource or Literal expected as object.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ $this->pred = $pred;
+ $this->subj = $subj;
+ $this->obj = $obj;
+ }
+
+ /**
+ * Returns the subject of the triple.
+ * @access public
+ * @return object node
+ */
+ function getSubject() {
+ return $this->subj;
+ }
+
+ /**
+ * Returns the predicate of the triple.
+ * @access public
+ * @return object node
+ */
+ function getPredicate() {
+ return $this->pred;
+ }
+
+ /**
+ * Returns the object of the triple.
+ * @access public
+ * @return object node
+ */
+ function getObject() {
+ return $this->obj;
+ }
+
+ /**
+ * Alias for getSubject()
+ * @access public
+ * @return object node
+ */
+ function subject() {
+ return $this->subj;
+ }
+
+ /**
+ * Alias for getPredicate()
+ * @access public
+ * @return object node
+ */
+ function predicate() {
+ return $this->pred;
+ }
+
+ /**
+ * Alias for getObject()
+ * @access public
+ * @return object node
+ */
+ function object() {
+ return $this->obj;
+ }
+ /**
+ * Retruns the hash code of the triple.
+ * @access public
+ * @return string
+ */
+ function hashCode() {
+ return md5($this->subj->getLabel() . $this->pred->getLabel() . $this->obj->getLabel());
+ }
+
+ /**
+ * Dumps the triple.
+ * @access public
+ * @return string
+ */
+
+ function toString() {
+ return 'Triple(' . $this->subj->toString() . ', ' . $this->pred->toString() . ', ' . $this->obj->toString() . ')';
+
+ }
+
+ /**
+ * Returns a toString() serialization of the statements's subject.
+ *
+ * @access public
+ * @return string
+ */
+ function toStringSubject() {
+ return $this->subj->toString();
+ }
+
+ /**
+ * Returns a toString() serialization of the statements's predicate.
+ *
+ * @access public
+ * @return string
+ */
+ function toStringPredicate() {
+ return $this->pred->toString();
+ }
+
+ /**
+ * Reurns a toString() serialization of the statements's object.
+ *
+ * @access public
+ * @return string
+ */
+ function toStringObject() {
+ return $this->obj->toString();
+ }
+
+ /**
+ * Returns the URI or bNode identifier of the statements's subject.
+ *
+ * @access public
+ * @return string
+ */
+ function getLabelSubject() {
+ return $this->subj->getLabel();
+ }
+
+ /**
+ * Returns the URI of the statements's predicate.
+ *
+ * @access public
+ * @return string
+ */
+ function getLabelPredicate() {
+ return $this->pred->getLabel();
+ }
+
+ /**
+ * Reurns the URI, text or bNode identifier of the statements's object.
+ *
+ * @access public
+ * @return string
+ */
+ function getLabelObject() {
+ return $this->obj->getLabel();
+ }
+
+ /**
+ * Checks if two statements are equal.
+ * Two statements are considered to be equal if they have the
+ * same subject, predicate and object. A statement can only be equal
+ * to another statement object.
+ * @access public
+ * @param object statement $that
+ * @return boolean
+ */
+
+ function equals ($that) {
+
+ if ($this == $that) {
+ return true;
+ }
+ if ($that == NULL || !(is_a($that, 'Statement'))) {
+ return false;
+ }
+
+ return
+ $this->subj->equals($that->subject()) &&
+ $this->pred->equals($that->predicate()) &&
+ $this->obj->equals($that->object());
+ }
+
+ /**
+ * Compares two statements and returns integer less than, equal to, or greater than zero.
+ * Can be used for writing sorting function for models or with the PHP function usort().
+ *
+ * @access public
+ * @param object statement &$that
+ * @return boolean
+ */
+
+ function compare(&$that) {
+ return statementsorter($this, $that);
+ // statementsorter function see below
+ }
+
+
+ /**
+ * Reifies a statement.
+ * Returns a new MemModel that is the reification of the statement.
+ * For naming the statement's bNode a Model or bNodeID must be passed to the method.
+ *
+ * @access public
+ * @param mixed &$model_or_bNodeID
+ * @return object model
+ */
+
+ function & reify(&$model_or_bNodeID) {
+
+ if (is_a($model_or_bNodeID, 'MemModel')) {
+ // parameter is model
+ $statementModel = new MemModel($model_or_bNodeID->getBaseURI());
+ $thisStatement = new BlankNode($model_or_bNodeID);
+ } else {
+ // parameter is bNodeID
+ $statementModel = new MemModel();
+ $thisStatement = &$model_or_bNodeID;
+ }
+
+ $RDFstatement = new Resource(RDF_NAMESPACE_URI . RDF_STATEMENT);
+ $RDFtype = new Resource(RDF_NAMESPACE_URI . RDF_TYPE);
+ $RDFsubject = new Resource(RDF_NAMESPACE_URI . RDF_SUBJECT);
+ $RDFpredicate = new Resource(RDF_NAMESPACE_URI . RDF_PREDICATE);
+ $RDFobject = new Resource(RDF_NAMESPACE_URI . RDF_OBJECT);
+
+ $statementModel->add(new Statement($thisStatement, $RDFtype, $RDFstatement));
+ $statementModel->add(new Statement($thisStatement, $RDFsubject, $this->getSubject()));
+ $statementModel->add(new Statement($thisStatement, $RDFpredicate, $this->getPredicate()));
+ $statementModel->add(new Statement($thisStatement, $RDFobject, $this->Object()));
+
+ return $statementModel;
+ }
+
+} // end: Statement
+
+
+/**
+* Comparison function for comparing two statements.
+* statementsorter() is used by the PHP function usort ( array array, callback cmp_function)
+*
+* @access private
+* @param object Statement $a
+* @param object Statement $b
+* @return integer less than, equal to, or greater than zero
+* @throws phpErrpr
+*/
+function statementsorter($a,$b) {
+ //Compare subjects
+ $x=$a->getSubject();
+ $y=$b->getSubject();
+ $r=strcmp($x->getLabel(),$y->getLabel());
+ if ($r!=0) return $r;
+ //Compare predicates
+ $x=$a->getPredicate();
+ $y=$b->getPredicate();
+ $r=strcmp($x->getURI(),$y->getURI());
+ if ($r!=0) return $r;
+ //Final resort, compare objects
+ $x=$a->getObject();
+ $y=$b->getObject();
+ return strcmp($x->toString(),$y->toString());
+}
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/Blanknode.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/Blanknode.php
new file mode 100755
index 00000000..9ea26f19
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/Blanknode.php
@@ -0,0 +1,120 @@
+,
+ * Radoslaw Oldakowski
+ *
+ * @package model
+ * @access public
+ *
+ */
+ class BlankNode extends Resource {
+
+ /**
+ * Constructor
+ * You can supply a label or You supply a model and a unique ID is gernerated.
+ *
+ * @param mixed $namespace_or_uri_or_model
+ * @param string $localName
+ * @access public
+ */
+ function BlankNode($namespace_or_uri_or_model , $localName = NULL) {
+
+ if (is_a($namespace_or_uri_or_model, 'Model')) {
+ // generate identifier
+ $id = $namespace_or_uri_or_model->getUniqueResourceURI(BNODE_PREFIX);
+
+ $this->uri = $id;
+
+ } else {
+ // set identifier
+ if ($localName == NULL) {
+ $this->uri = $namespace_or_uri_or_model;
+ } else {
+ $this->uri = $namespace_or_uri_or_model . $localName;
+ }
+ }
+ }
+
+ /**
+ * Returns the ID of the blank node.
+ *
+ * @return string
+ * @access public
+ */
+ function getID() {
+ return $this->uri;
+ }
+
+ /**
+ * Returns the ID of the blank node.
+ *
+ * @return string
+ * @access public
+ */
+ function getLabel() {
+ return $this->uri;
+ }
+
+ /**
+ * Dumps bNode.
+ *
+ * @access public
+ * @return string
+ */
+ function toString() {
+
+ return 'bNode("' . $this->uri . '")';
+ }
+
+ /**
+ * Checks if two blank nodes are equal.
+ * Two blank nodes are equal, if they have the same temporary ID.
+ *
+ * @access public
+ * @param object resource $that
+ * @return boolean
+ */
+ function equals ($that) {
+
+ if ($this == $that) {
+ return true;
+ }
+ if (($that == NULL) or !(is_a($that, 'BlankNode'))) {
+ return false;
+ }
+
+ if ($this->getURI() == $that->getURI()) {
+ return true;
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Doing string magic in PHP5
+ * @return string String representation of this Blank Node
+ */
+ function __toString()
+ {
+ return $this->toString();
+ }
+
+} // end: BlankNode
+
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/DBase.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/DBase.php
new file mode 100755
index 00000000..87d9b474
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/DBase.php
@@ -0,0 +1,17 @@
+
+//
+// ----------------------------------------------------------------------------------
+
+// Include DBase class
+require_once( RDFAPI_INCLUDE_DIR . 'model/DbModel.php' );
+// include adodb classes
+require_once(RDFAPI_INCLUDE_DIR .'util/adodb/adodb.inc.php');
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/DbModel.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/DbModel.php
new file mode 100755
index 00000000..3f199719
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/DbModel.php
@@ -0,0 +1,1318 @@
+
+*
+* @package model
+* @access public
+*/
+
+
+class DbModel extends Model{
+
+ /**
+ * Database connection object.
+ *
+ * @var object ADOConnection
+ * @access private
+ */
+ var $dbConn;
+
+ /**
+ * Unique model URI.
+ * Used to identify the DbModel.
+ *
+ * @var string
+ * @access private
+ */
+ var $modelURI;
+
+
+ /**
+ * Database internal modelID.
+ * Used to avoid JOINs.
+ *
+ * @var string
+ * @access private
+ */
+ var $modelID;
+
+
+
+
+ /**
+ * Constructor
+ * Do not call this directly.
+ * Use the method getModel,getNewModel or putModel of the Class DbStore instead.
+ *
+ * @param object ADOConnection &$dbConnection
+ * @param string $modelURI
+ * @param string $modelID
+ * @param string $baseURI
+ * @access public
+ */
+ function DbModel(&$dbConnection, $modelURI, $modelID, $baseURI=NULL) {
+
+ $this->dbConn =& $dbConnection;
+ $this->modelURI = $modelURI;
+ $this->modelID = $modelID;
+ $this->baseURI = $this->_checkBaseURI($baseURI);
+ }
+
+
+ /**
+ * Set a base URI for the DbModel.
+ * Affects creating of new resources and serialization syntax.
+ *
+ * @param string $uri
+ * @throws SqlError
+ * @access public
+ */
+ function setBaseURI($uri) {
+
+ $this->baseURI = $this->_checkBaseURI($uri);
+
+ $rs = $this->dbConn->execute("UPDATE models SET baseURI='" .$this->baseURI ."'
+ WHERE modelID=" .$this->modelID);
+ if (!$rs)
+ $this->dbConn->errorMsg();
+ }
+
+
+ /**
+ * Return the number of statements in this DbModel.
+ *
+ * @return integer
+ * @access public
+ */
+ function size() {
+
+ $count =& $this->dbConn->getOne('SELECT COUNT(modelID) FROM statements
+ WHERE modelID = ' .$this->modelID);
+ return $count;
+ }
+
+
+ /**
+ * Check if this DbModel is empty.
+ *
+ * @return boolean
+ * @access public
+ */
+ function isEmpty() {
+
+ if ($this->size() == 0)
+ return TRUE;
+ return FALSE;
+ }
+
+
+ /**
+ * Add a new triple to this DbModel.
+ *
+ * @param object Statement &$statement
+ * @throws PhpError
+ * @throws SqlError
+ * @access public
+ * @return mixed true on success, false if the statement is already in the model,
+ * error message (string) on failure
+ */
+ function add(&$statement) {
+
+ if (!is_a($statement, 'Statement')) {
+ $errmsg = RDFAPI_ERROR . '(class: DbModel; method: add): Statement expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ if (!$this->contains($statement)) {
+
+ $subject_is = $this->_getNodeFlag($statement->subject());
+ $sql = "INSERT INTO statements
+ (modelID, subject, predicate, object, l_language, l_datatype, subject_is, object_is)
+ VALUES
+ (" .$this->modelID .","
+ . $this->dbConn->qstr($statement->getLabelSubject()) .","
+ . $this->dbConn->qstr($statement->getLabelPredicate()) .",";
+
+ if (is_a($statement->object(), 'Literal')) {
+ $quotedLiteral = $this->dbConn->qstr($statement->obj->getLabel());
+ $sql .= $quotedLiteral .","
+ ."'" .$statement->obj->getLanguage() ."',"
+ ."'" .$statement->obj->getDatatype() ."',"
+ ."'" .$subject_is ."',"
+ ."'l')";
+ }else{
+ $object_is = $this->_getNodeFlag($statement->object());
+ $sql .= $this->dbConn->qstr($statement->obj->getLabel()) .","
+ ."'',"
+ ."'',"
+ ."'" .$subject_is ."',"
+ ."'" .$object_is ."')";
+ }
+ $rs =& $this->dbConn->execute($sql);
+ if (!$rs) {
+ return $this->dbConn->errorMsg();
+ } else {
+ return true;
+ }
+ } else {
+ return false;
+ }
+ }
+
+
+ /**
+ * Alias for the method add().
+ *
+ * @param object Statement &$statement
+ * @throws PhpError
+ * @throws SqlError
+ * @access public
+ */
+ function addWithoutDuplicates(&$statement) {
+
+ $this->add($statement);
+ }
+
+
+ /**
+ * Remove the given triple from this DbModel.
+ *
+ * @param object Statement &$statement
+ * @throws PhpError
+ * @throws SqlError
+ * @access public
+ */
+ function remove(&$statement) {
+
+ if (!is_a($statement, 'Statement')) {
+ $errmsg = RDFAPI_ERROR . '(class: DbModel; method: remove): Statement expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ $sql = 'DELETE FROM statements
+ WHERE modelID=' .$this->modelID;
+ $sql .= $this->_createDynSqlPart_SPO ($statement->subj, $statement->pred, $statement->obj);
+
+ $rs =& $this->dbConn->execute($sql);
+ if (!$rs)
+ $this->dbConn->errorMsg();
+ }
+
+
+ /**
+ * Short dump of the DbModel.
+ *
+ * @return string
+ * @access public
+ */
+ function toString() {
+
+ return 'DbModel[modelURI=' .$this->modelURI .'; baseURI=' .$this->getBaseURI() .'; size=' .$this->size() .']';
+ }
+
+
+ /**
+ * Dump of the DbModel including all triples.
+ *
+ * @return string
+ * @access public
+ */
+ function toStringIncludingTriples() {
+
+ $memModel =& $this->getMemModel();
+ return $memModel->toStringIncludingTriples();
+ }
+
+
+
+ /**
+ * Create a MemModel containing all the triples of the current DbModel.
+ *
+ * @return object MemModel
+ * @access public
+ */
+ function & getMemModel() {
+
+ $recordSet = $this->_getRecordSet($this);
+ $m = $this->_convertRecordSetToMemModel($recordSet);
+ return $m;
+ }
+
+
+
+ /**
+ * Returns the model id
+ *
+ * @return int Model id number
+ * @access public
+ */
+ function getModelID()
+ {
+ return $this->modelID;
+ }
+
+
+
+ /**
+ * Returns the database connection object
+ *
+ * @return ADOdb Database object
+ * @access public
+ */
+ function &getDbConn()
+ {
+ return $this->dbConn;
+ }
+
+
+
+ /**
+ * Write the RDF serialization of the _DbModel as HTML.
+ *
+ * @access public
+ */
+ function writeAsHtml() {
+
+ $memModel =& $this->getMemModel();
+ $memModel->writeAsHtml();
+ }
+
+
+ /**
+ * Write the RDF serialization of the DbModel as HTML table.
+ *
+ * @access public
+ */
+ function writeAsHtmlTable() {
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_UTILITY);
+ $memModel =& $this->getMemModel();
+ RDFUtil::writeHTMLTable($memModel);
+ }
+
+
+ /**
+ * Write the RDF serialization of the DbModel to string.
+ *
+ * @return string
+ * @access public
+ */
+ function writeRdfToString() {
+
+ $memModel =& $this->getMemModel();
+ return $memModel->writeRdfToString();
+ }
+
+
+ /**
+ * Saves the RDF,N3 or N-Triple serialization of the DbModel to a file.
+ * You can decide to which format the model should be serialized by using a
+ * corresponding suffix-string as $type parameter. If no $type parameter
+ * is placed this method will serialize the model to XML/RDF format.
+ * Returns FALSE if the DbModel couldn't be saved to the file.
+ *
+ * @access public
+ * @param string $filename
+ * @param string $type
+ * @throws PhpError
+ * @return boolean
+ */
+ function saveAs($filename, $type ='rdf') {
+
+ $memModel = $this->getMemModel();
+ $memModel->saveAs($filename, $type);
+
+ }
+
+
+ /**
+ * Check if the DbModel contains the given statement.
+ *
+ * @param object Statement &$statement
+ * @return boolean
+ * @access public
+ */
+ function contains(&$statement) {
+
+ $sql = 'SELECT modelID FROM statements
+ WHERE modelID = ' .$this->modelID;
+ $sql .= $this->_createDynSqlPart_SPO($statement->subj, $statement->pred, $statement->obj);
+
+ $res =& $this->dbConn->getOne($sql);
+
+ if (!$res)
+ return FALSE;
+ return TRUE;
+ }
+
+
+ /**
+ * Determine if all of the statements in the given model are also contained in this DbModel.
+ *
+ * @param object Model &$model
+ * @return boolean
+ * @access public
+ */
+ function containsAll(&$model) {
+
+ if (is_a($model, 'MemModel')) {
+
+ foreach($model->triples as $statement)
+ if(!$this->contains($statement))
+ return FALSE;
+ return TRUE;
+ }
+
+ elseif (is_a($model, 'DbModel')) {
+
+ $recordSet =& $this->_getRecordSet($model);
+ while (!$recordSet->EOF) {
+ if (!$this->_containsRow($recordSet->fields))
+ return FALSE;
+ $recordSet->moveNext();
+ }
+ return TRUE;
+ }
+
+ $errmsg = RDFAPI_ERROR . '(class: DbModel; method: containsAll): Model expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+
+ /**
+ * Determine if any of the statements in the given model are also contained in this DbModel.
+ *
+ * @param object Model &$model
+ * @return boolean
+ * @access public
+ */
+ function containsAny(&$model) {
+
+ if (is_a($model, 'MemModel')) {
+
+ foreach($model->triples as $statement)
+ if($this->contains($statement))
+ return TRUE;
+ return FALSE;
+ }
+
+ elseif (is_a($model, 'DbModel')) {
+
+ $recordSet =& $this->_getRecordSet($model);
+ while (!$recordSet->EOF) {
+ if ($this->_containsRow($recordSet->fields))
+ return TRUE;
+ $recordSet->moveNext();
+ }
+ return FALSE;
+ }
+
+ $errmsg = RDFAPI_ERROR . '(class: DbModel; method: containsAny): Model expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+
+ /**
+ * General method to search for triples in the DbModel.
+ * NULL input for any parameter will match anything.
+ * Example: $result = $m->find( NULL, NULL, $node );
+ * Finds all triples with $node as object.
+ *
+ * @param object Resource $subject
+ * @param object Resource $predicate
+ * @param object Node $object
+ * @return object MemModel
+ * @throws PhpError
+ * @throws SqlError
+ * @access public
+ */
+ function find($subject, $predicate, $object) {
+
+ if ((!is_a($subject, 'Resource') && $subject != NULL) ||
+ (!is_a($predicate, 'Resource') && $predicate != NULL) ||
+ (!is_a($object, 'Node') && $object != NULL)) {
+
+ $errmsg = RDFAPI_ERROR . '(class: DbModel; method: find): Parameters must be subclasses of Node or NULL';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ // static part of the sql statement
+ $sql = 'SELECT subject, predicate, object, l_language, l_datatype, subject_is, object_is
+ FROM statements
+ WHERE modelID = ' .$this->modelID;
+
+ // dynamic part of the sql statement
+ $sql .= $this->_createDynSqlPart_SPO($subject, $predicate, $object);
+
+ // execute the query
+ $recordSet =& $this->dbConn->execute($sql);
+
+ if (!$recordSet)
+ echo $this->dbConn->errorMsg();
+
+ // write the recordSet into memory Model
+ else
+ return $this->_convertRecordSetToMemModel($recordSet);
+ }
+
+
+ /**
+ * Method to search for triples using Perl-style regular expressions.
+ * NULL input for any parameter will match anything.
+ * Example: $result = $m->find_regex( NULL, NULL, $regex );
+ * Finds all triples where the label of the object node matches
+ *the regular expression.
+ * Return an empty MemModel if nothing is found.
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * WARNING: Mhis method loads a DbModel into memory and performs the search
+ * on a MemModel, which can be slow with large models.
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ *
+ * @param string $subject_regex
+ * @param string $predicate_regex
+ * @param string $object_regex
+ * @return object MemModel
+ * @throws PhpError
+ * @throws SqlError
+ * @access public
+ */
+ function findRegex($subject_regex, $predicate_regex, $object_regex) {
+
+ $mm =& $this->getMemModel();
+
+ return $mm->findRegex($subject_regex, $predicate_regex, $object_regex);
+ }
+
+
+ /**
+ * Return all tripels of a certain vocabulary.
+ * $vocabulary is the namespace of the vocabulary inluding a # : / char at the end.
+ * e.g. http://www.w3.org/2000/01/rdf-schema#
+ * Return an empty model if nothing is found.
+ *
+ * @param string $vocabulary
+ * @return object MemModel
+ * @throws PhpError
+ * @throws SqlError
+ * @access public
+ */
+ function findVocabulary($vocabulary) {
+
+ $sql = "SELECT subject, predicate, object, l_language, l_datatype, subject_is, object_is
+ FROM statements
+ WHERE modelID = " .$this->modelID ."
+ AND predicate LIKE '" .$vocabulary ."%'";
+
+ $recordSet =& $this->dbConn->execute($sql);
+
+ if (!$recordSet)
+ echo $this->dbConn->errorMsg();
+
+ // write the recordSet into memory Model
+ else
+ return $this->_convertRecordSetToMemModel($recordSet);
+ }
+
+
+ /**
+ * Search for triples and return the first matching statement.
+ * NULL input for any parameter will match anything.
+ * Return an NULL if nothing is found.
+ * You can set an search offset with $offset.
+ *
+ * @param object Resource $subject
+ * @param object Resource $predicate
+ * @param object Node $object
+ * @param integer $offset
+ * @return object Statement
+ * @throws PhpError
+ * @throws SqlError
+ * @access public
+ */
+ function findFirstMatchingStatement($subject, $predicate, $object, $offset = -1) {
+
+ if ((!is_a($subject, 'Resource') && $subject != NULL) ||
+ (!is_a($predicate, 'Resource') && $predicate != NULL) ||
+ (!is_a($object, 'Node') && $object != NULL)) {
+
+ $errmsg = RDFAPI_ERROR . '(class: DbModel; method: find): Parameters must be subclasses of Node or NULL';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ // static part of the sql statement
+ $sql = 'SELECT subject, predicate, object, l_language, l_datatype, subject_is, object_is
+ FROM statements
+ WHERE modelID = ' .$this->modelID;
+
+ // dynamic part of the sql statement
+ $sql .= $this->_createDynSqlPart_SPO($subject, $predicate, $object);
+
+ // execute the query
+ $recordSet =& $this->dbConn->selectLimit($sql,1,($offset));
+
+ if (!$recordSet)
+ echo $this->dbConn->errorMsg();
+ else {
+ if (!$recordSet->fields)
+ return NULL;
+ else {
+ $memModel = $this->_convertRecordSetToMemModel($recordSet);
+ return $memModel->triples[0];
+ }
+ }
+ }
+
+
+ /**
+ * Search for triples and return the number of matches.
+ * NULL input for any parameter will match anything.
+ *
+ * @param object Resource $subject
+ * @param object Resource $predicate
+ * @param object Node $object
+ * @return integer
+ * @throws PhpError
+ * @throws SqlError
+ * @access public
+ */
+ function findCount($subject, $predicate, $object) {
+
+ if ((!is_a($subject, 'Resource') && $subject != NULL) ||
+ (!is_a($predicate, 'Resource') && $predicate != NULL) ||
+ (!is_a($object, 'Node') && $object != NULL)) {
+
+ $errmsg = RDFAPI_ERROR . '(class: DbModel; method: find): Parameters must be subclasses of Node or NULL';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ // static part of the sql statement
+ $sql = 'SELECT COUNT(*)
+ FROM statements
+ WHERE modelID = ' .$this->modelID;
+
+ // dynamic part of the sql statement
+ $sql .= $this->_createDynSqlPart_SPO($subject, $predicate, $object);
+
+ // execute the query
+ $recordSet =& $this->dbConn->execute($sql);
+
+ if (!$recordSet)
+ echo $this->dbConn->errorMsg();
+ else
+ return $recordSet->fields[0];
+ }
+
+
+ /**
+ * Perform an RDQL query on this DbModel.
+ * This method returns an associative array of variable bindings.
+ * The values of the query variables can either be RAP's objects (instances of Node)
+ * if $returnNodes set to TRUE, or their string serialization.
+ *
+ * @access public
+ * @param string $queryString
+ * @param boolean $returnNodes
+ * @return array [][?VARNAME] = object Node (if $returnNodes = TRUE)
+ * OR array [][?VARNAME] = string
+ *
+ */
+ function rdqlQuery($queryString, $returnNodes = TRUE) {
+ require_once(RDFAPI_INCLUDE_DIR.PACKAGE_RDQL);
+ $parser = new RdqlParser();
+ $parsedQuery =& $parser->parseQuery($queryString);
+
+ // this method can only query this DbModel
+ // if another model was specified in the from clause throw an error
+ if (isset($parsedQuery['sources'][0]))
+ if($parsedQuery['sources'][0] != $this->modelURI) {
+ $errmsg = RDFAPI_ERROR . '(class: DbModel; method: rdqlQuery):';
+ $errmsg .= ' this method can only query this DbModel';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ $engine = new RdqlDbEngine();
+ $res =& $engine->queryModel($this, $parsedQuery, $returnNodes);
+
+ return $res;
+ }
+
+
+ /**
+ * Perform an RDQL query on this DBModel.
+ * This method returns an RdqlResultIterator of variable bindings.
+ * The values of the query variables can either be RAP's objects (instances of Node)
+ * if $returnNodes set to TRUE, or their string serialization.
+ *
+ * @access public
+ * @param string $queryString
+ * @param boolean $returnNodes
+ * @return object RdqlResultIterator = with values as object Node (if $returnNodes = TRUE)
+ * OR object RdqlResultIterator = with values as strings if (if $returnNodes = FALSE)
+ *
+ */
+ function rdqlQueryAsIterator($queryString, $returnNodes = TRUE) {
+ require_once(RDFAPI_INCLUDE_DIR.PACKAGE_RDQL);
+ return new RdqlResultIterator($this->rdqlQuery($queryString, $returnNodes));
+ }
+
+ /**
+ * General method to replace nodes of a DbModel.
+ * NULL input for any parameter will match nothing.
+ * Example: $m->replace($resource, NULL, $node, $replacement);
+ * Replaces all $node objects beeing subject or object in
+ * any triple of the model with the $replacement node.
+ * Throw an error in case of a paramter mismatch.
+ *
+ * @param object Resource $subject
+ * @param object Resource $predicate
+ * @param object Node $object
+ * @param object Node $replacement
+ * @throws PhpError
+ * @throws SqlError
+ * @access public
+ */
+ function replace($subject, $predicate, $object, $replacement) {
+
+ // check the correctness of the passed parameters
+ if ( ((!is_a($subject, 'Resource') && $subject != NULL) ||
+ (!is_a($predicate, 'Resource') && $predicate != NULL) ||
+ (!is_a($object, 'Node') && $object != NULL)) ||
+ (($subject != NULL && is_a($replacement, 'Literal')) ||
+ ($predicate != NULL && (is_a($replacement, 'Literal') ||
+ is_a($replacement, 'BlankNode')))) )
+ {
+ $errmsg = RDFAPI_ERROR . '(class: DbModel; method: find): Parameter mismatch';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ if (!(!$subject && !$predicate && !$object)) {
+
+ // create an update sql statement
+ $comma = '';
+ $sql = 'UPDATE statements
+ SET ';
+ if ($subject) {
+ $sql .= " subject ='" .$replacement->getLabel() ."', "
+ ." subject_is='" .$this->_getNodeFlag($replacement) ."' ";
+ $comma = ',';
+ }
+ if ($predicate) {
+ $sql .= $comma ." predicate='" .$replacement->getLabel() ."' ";
+ $comma = ',';
+ }
+ if ($object) {
+ $quotedObject = $this->dbConn->qstr($replacement->getLabel());
+ $sql .= $comma .' object=' .$quotedObject
+ .", object_is='" .$this->_getNodeFlag($replacement) ."' ";
+ if (is_a($replacement, 'Literal')) {
+ $sql .= ", l_language='" .$replacement->getLanguage() ."' "
+ .", l_datatype='" .$replacement->getDataType() ."' ";
+ }
+ }
+ $sql .= 'WHERE modelID = ' .$this->modelID;
+ $sql .= $this->_createDynSqlPart_SPO($subject, $predicate, $object);
+
+ // execute the query
+ $rs =& $this->dbConn->execute($sql);
+
+ if (!$rs)
+ echo $this->dbConn->errorMsg();
+ }
+ }
+
+
+ /**
+ * Check if two models are equal.
+ * Two models are equal if and only if the two RDF graphs they represent are isomorphic.
+ *
+ * Warning: This method doesn't work correct with models where the same blank node has different
+ * identifiers in the two models. We will correct this in a future version.
+ *
+ * @param object model &$that
+ * @return boolean
+ * @throws PhpError
+ * @access public
+ */
+
+ function equals(&$that) {
+
+ if (!is_a($that, 'Model')) {
+ $errmsg = RDFAPI_ERROR . '(class: DbModel; method: equals): Model expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ if ($this->size() != $that->size())
+ return FALSE;
+
+ include_once(RDFAPI_INCLUDE_DIR. "util/ModelComparator.php");
+ return ModelComparator::compare($this,$that);
+ }
+
+
+ /**
+ * Return a new MemModel that is the set-union the model with another model.
+ *
+ * The result of taking the set-union of two or more RDF graphs (i.e. sets of triples)
+ * is another graph, which we will call the merge of the graphs.
+ * Each of the original graphs is a subgraph of the merged graph. Notice that when forming
+ * a merged graph, two occurrences of a given uriref or literal as nodes in two different
+ * graphs become a single node in the union graph (since by definition they are the same
+ * uriref or literal) but blank nodes are not 'merged' in this way; and arcs are of course
+ * never merged. In particular, this means that every blank node in a merged graph can be
+ * identified as coming from one particular graph in the original set of graphs.
+ *
+ * Notice that one does not, in general, obtain the merge of a set of graphs by concatenating
+ * their corresponding N-triples documents and constructing the graph described by the merged
+ * document, since if some of the documents use the same node identifiers, the merged document
+ * will describe a graph in which some of the blank nodes have been 'accidentally' merged.
+ * To merge Ntriples documents it is necessary to check if the same nodeID is used in two or
+ * more documents, and to replace it with a distinct nodeID in each of them, before merging the
+ * documents. (Not implemented yet !!!!!!!!!!!)
+ *
+ * @param object Model $model
+ * @return object MemModel
+ * @throws PhpError
+ * @access public
+ *
+ */
+ function & unite(&$model) {
+
+ if (!is_a($model, 'Model')) {
+ $errmsg = RDFAPI_ERROR . '(class: DbModel; method: unite): Model expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ if (is_a($model, 'MemModel')) {
+
+ $thisModel =& $this->getMemModel();
+ return $thisModel->unite($model);
+ }
+
+ elseif (is_a($model, 'DbModel')) {
+
+ $thisModel =& $this->getMemModel();
+ $thatModel =& $model->getMemModel();
+ return $thisModel->unite($thatModel);
+ }
+ }
+
+
+ /**
+ * Return a new MemModel that is the subtraction of another model from this DbModel.
+ *
+ * @param object Model $model
+ * @return object MemModel
+ * @throws PhpError
+ * @access public
+ */
+
+ function & subtract(&$model) {
+
+ if (!is_a($model, 'Model')) {
+ $errmsg = RDFAPI_ERROR . '(class: DbModel; method: subtract): Model expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ if (is_a($model, 'MemModel')) {
+
+ $thisModel =& $this->getMemModel();
+ return $thisModel->subtract($model);
+ }
+
+ elseif (is_a($model, 'DbModel')) {
+
+ $thisModel =& $this->getMemModel();
+ $thatModel =& $model->getMemModel();
+ return $thisModel->subtract($thatModel);
+ }
+ }
+
+
+ /**
+ * Return a new MemModel containing all the statements which are in both
+ * this model and the given model.
+ *
+ * @param object Model $model
+ * @return object MemModel
+ * @throws PhpError
+ * @access public
+ */
+ function & intersect(&$model) {
+
+ if (is_a($model, 'MemModel')) {
+
+ $thisModel =& $this->getMemModel();
+ return $thisModel->intersect($model);
+ }
+
+ elseif (is_a($model, 'DbModel')) {
+
+ $thisModel =& $this->getMemModel();
+ $thatModel =& $model->getMemModel();
+ return $thisModel->intersect($thatModel);
+ }
+
+ $errmsg = RDFAPI_ERROR . '(class: DbModel; method: intersect: Model expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+
+ /**
+ * Add the given model to this DbModel.
+ * This function monitors for SQL errors, and will commit if no errors have occured,
+ * otherwise it will rollback.
+ * If any statement of the model to be added to this model contains a blankNode
+ * with an identifier already existing in this model, a new blankNode is generated.
+ *
+ * @param object Model $model
+ * @throws PhpError
+ * @access public
+ */
+ function addModel(&$model) {
+
+ if (!is_a($model, 'Model')) {
+ $errmsg = RDFAPI_ERROR . '(class: DbModel; method: addModel): Model expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ $blankNodes_tmp = array();
+
+ if (is_a($model, 'MemModel')) {
+
+ $this->dbConn->startTrans();
+ foreach ($model->triples as $statement)
+ $this->_addStatementFromAnotherModel($statement, $blankNodes_tmp);
+ $this->addParsedNamespaces($model->getParsedNamespaces());
+
+ $this->dbConn->completeTrans();
+ }
+
+ elseif (is_a($model, 'DbModel')) {
+
+ $this->dbConn->startTrans();
+ $memModel =& $model->getMemModel();
+ foreach($memModel->triples as $statement)
+ $this->_addStatementFromAnotherModel($statement, $blankNodes_tmp);
+ $this->addParsedNamespaces($model->getParsedNamespaces());
+ $this->dbConn->completeTrans();
+ }
+ }
+
+
+ /**
+ * Reify the DbModel.
+ * Return a new MemModel that contains the reifications of all statements of this DbModel.
+ *
+ * @return object MemModel
+ * @access public
+ */
+ function & reify() {
+
+ $memModel =& $this->getMemModel();
+ return $memModel->reify();
+ }
+
+ /**
+ * Remove this DbModel from database and clean up.
+ * This function monitors for SQL errors, and will commit if no errors have occured,
+ * otherwise it will rollback.
+ *
+ * @throws SqlError
+ * @access public
+ */
+ function delete() {
+
+ $this->dbConn->startTrans();
+ $this->dbConn->execute('DELETE FROM models
+ WHERE modelID=' .$this->modelID);
+ $this->dbConn->execute('DELETE FROM statements
+ WHERE modelID=' .$this->modelID);
+ $this->dbConn->execute('DELETE FROM namespaces
+ WHERE modelID=' .$this->modelID);
+
+ if (!$this->dbConn->completeTrans())
+ echo $this->dbConn->errorMsg();
+ else
+ $this->close();
+ }
+
+
+ /**
+ * Close this DbModel
+ *
+ * @access public
+ */
+ function close() {
+
+ unset($this);
+ }
+
+
+ // =============================================================================
+ // **************************** private methods ********************************
+ // =============================================================================
+
+
+
+
+
+ /**
+ * If the URI doesn't end with # : or /, then a # is added to the URI.
+ * Used at setting the baseURI of this DbModel.
+ *
+ * @param string $uri
+ * @return string
+ * @access private
+ */
+ function _checkBaseURI($uri) {
+
+ if ($uri != NULL) {
+ $c = substr($uri, strlen($uri)-1 ,1);
+ if (!($c=='#' || $c==':' || $c=='/' || $c=="\\"))
+ $uri .= '#';
+ }
+ return $uri;
+ }
+
+
+ /**'
+ * Return the flag of the Node object.
+ * r - Resource, b - BlankNode, l - Literal
+ *
+ * @param object Node $object
+ * @return string
+ * @access private
+ */
+ function _getNodeFlag($object) {
+
+ return is_a($object,'BlankNode')?'b':(is_a($object,'Resource')?'r':'l');
+ }
+
+
+ /**
+ * Convert an ADORecordSet to a memory Model.
+ *
+ * Every successful database query returns an ADORecordSet object which is actually
+ * a cursor that holds the current row in the array fields[].
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * !!! This method can only be applied to a RecordSet with array fields[]
+ * !!! containing a representation of the database table: statements,
+ * !!! with an index corresponding to following table columns:
+ * !!! [0] - subject, [1] - predicate, [2] - object, [3] - l_language,
+ * !!! [4] - l_datatype, [5] - subject_is, [6] - object_is
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ *
+ * @param object ADORecordSet
+ * @return object MemModel
+ * @access private
+ */
+ function _convertRecordSetToMemModel(&$recordSet) {
+
+ $res = new MemModel($this->baseURI);
+ while (!$recordSet->EOF) {
+
+ // subject
+ if ($recordSet->fields[5] == 'r')
+ $sub = new Resource($recordSet->fields[0]);
+ else
+ $sub = new BlankNode($recordSet->fields[0]);
+
+ // predicate
+ $pred = new Resource($recordSet->fields[1]);
+
+ // object
+ if ($recordSet->fields[6] == 'r')
+ $obj = new Resource($recordSet->fields[2]);
+ elseif ($recordSet->fields[6] == 'b')
+ $obj = new BlankNode($recordSet->fields[2]);
+ else {
+ $obj = new Literal($recordSet->fields[2], $recordSet->fields[3]);
+ if ($recordSet->fields[4])
+ $obj->setDatatype($recordSet->fields[4]);
+ }
+
+ $statement = new Statement($sub, $pred, $obj);
+ $res->add($statement);
+
+ $recordSet->moveNext();
+ }
+ $res->addParsedNamespaces($this->getParsedNamespaces());
+ return $res;
+ }
+
+
+ /**
+ * Create the dynamic part of an sql statement selecting triples with the
+ * given parameters ($subject, $predicate, $object).
+ *
+ * @param object Resource $subject
+ * @param object Resource $predicate
+ * @param object Node $object
+ * @return string
+ * @access private
+ */
+ function _createDynSqlPart_SPO($subject, $predicate, $object) {
+
+ // conditions derived from the parameters passed to the function
+
+ $subject_is=is_a($subject,'BlankNode')?'b':(is_a($subject,'Resource')?'r':'l');
+ $sql='';
+ if ($subject != NULL)
+ $sql .= " AND subject='" .$subject->getLabel() ."'
+ AND subject_is='" .$subject_is ."'";
+ if ($predicate != NULL)
+ $sql .= " AND predicate='" .$predicate->getLabel() ."'";
+ if ($object != NULL) {
+ $object_is = is_a($object,'BlankNode')?'b':(is_a($object,'Resource')?'r':'l');
+ if (is_a($object, 'Resource'))
+ $sql .= " AND object='" .$object->getLabel() ."'
+ AND object_is ='" .$object_is ."'";
+ else {
+ $quotedLiteral = $this->dbConn->qstr($object->getLabel());
+ $sql .= " AND object=" .$quotedLiteral ."
+ AND l_language='" .$object->getLanguage() ."'
+ AND l_datatype='" .$object->getDataType() ."'
+ AND object_is ='" .$object_is ."'";
+ }
+ }
+ return $sql;
+ }
+
+
+ /**
+ * Get an ADORecordSet with array fields[] containing a representation of
+ * the given DbModel stored in the table: statements, with an index corresponding
+ * to following table columns:
+ * [0] - subject, [1] - predicate, [2] - object, [3] - l_language,
+ * [4] - l_datatype, [5] - subject_is, [6] - object_is
+ * (This method operates on data from a DbModel without loading it into a memory model
+ * in order to save resources and improve speed).
+ *
+ * @param object DbModel $DbModel
+ * @return object ADORecordSet
+ * @access private
+ */
+ function _getRecordSet (&$dbModel) {
+
+ $sql = 'SELECT subject, predicate, object, l_language, l_datatype, subject_is, object_is
+ FROM statements
+ WHERE modelID = ' .$dbModel->modelID;
+
+ return $recordSet =& $this->dbConn->execute($sql);
+ }
+
+
+ /**
+ * Check if this DbModel contains the given row from the array fields[] of an ADORecordSet
+ * The array index corresponds to following table columns:
+ * [0] - subject, [1] - predicate, [2] - object, [3] - l_language,
+ * [4] - l_datatype, [5] - subject_is, [6] - object_is
+ *
+ * @param array $row
+ * @return boolean
+ * @access private
+ */
+ function _containsRow ($row) {
+
+ $sql = "SELECT modelID FROM statements
+ WHERE modelID = " .$this->modelID ."
+ AND subject =" .$this->dbConn->qstr($row[0]) ."
+ AND predicate =" .$this->dbConn->qstr($row[1]) ."
+ AND object =" .$this->dbConn->qstr($row[2]) ."
+ AND l_language=" .$this->dbConn->qstr($row[3]) ."
+ AND l_datatype=" .$this->dbConn->qstr($row[4]) ."
+ AND subject_is=" .$this->dbConn->qstr($row[5]) ."
+ AND object_is=" .$this->dbConn->qstr($row[6]);
+
+ $res =& $this->dbConn->getOne($sql);
+
+ if (!$res)
+ return FALSE;
+ return TRUE;
+ }
+
+
+
+
+
+ /**
+ * Returns the models namespaces.
+ *
+ * @author Tobias Gauss
+ * @return mixed Array of key-value pairs. Namespace is the key,
+ * prefix the value. If no namespaces are found,
+ * boolean false is returned.
+ *
+ * @access public
+ */
+ function getParsedNamespaces(){
+ $sql = "SELECT * FROM namespaces
+ WHERE modelID = " .$this->modelID;
+ $temp = false;
+ $res = $this->dbConn->execute($sql);
+ if($res){
+ while (!$res->EOF) {
+ $temp[$res->fields[1]]=$res->fields[2];
+ $res->moveNext();
+ }
+ }
+ return $temp;
+ }
+
+
+
+ /**
+ * Adds the namespaces to the model. This method is called by
+ * the parser. !!!! addParsedNamespaces() not overwrites manual
+ * added namespaces in the model !!!!
+ *
+ * @author Tobias Gauss
+ * @param array $newNs Array of namespace => prefix assignments
+ *
+ * @access public
+ */
+ function addParsedNamespaces($newNs){
+ if($newNs)
+ foreach($newNs as $namespace => $prefix){
+ $this->addNamespace($prefix, $namespace);
+ }
+ }
+
+
+ /**
+ * Adds a namespace and prefix to the model.
+ *
+ * @author Tobias Gauss
+ * @param string $prefix Prefix
+ * @param string $nmsp Namespace URI
+ *
+ * @access public
+ */
+ function addNamespace($prefix,$nmsp){
+
+ if($nmsp != '' && $prefix !=''){
+ if($this->_checkNamespace($nmsp)){
+ $sql = "UPDATE namespaces SET prefix=".$this->dbConn->qstr($prefix)." WHERE
+ modelID=".$this->modelID." AND namespace=".$this->dbConn->qstr($nmsp);
+ }else{
+ $sql = "INSERT INTO namespaces
+ (modelID, namespace, prefix)
+ VALUES
+ (" .$this->modelID .','
+ . $this->dbConn->qstr($nmsp) . ','
+ . $this->dbConn->qstr($prefix) . ')';
+ }
+
+ $rs =& $this->dbConn->execute($sql);
+ if (!$rs)
+ $this->dbConn->errorMsg();
+ }
+ }
+
+ /**
+ * checks if a namespace is already in the model.
+ *
+ * @author Tobias Gau�
+ * @access private
+ * @param Array $newNs
+ */
+ function _checkNamespace($nmsp){
+ $res = true;
+ $sql = "SELECT * FROM namespaces
+ WHERE modelID = " .$this->modelID." AND
+ namespace=" . $this->dbConn->qstr($nmsp);
+ $rs =& $this->dbConn->execute($sql);
+ if (!$rs){
+ $this->dbConn->errorMsg();
+ }else{
+ if($rs->fields == false)
+ $res = false;
+ }
+ return $res;
+
+
+ }
+
+ /**
+ * Returns a FindIterator for traversing the MemModel.
+ * @access public
+ * @return object FindIterator
+ */
+ function & iterFind($sub=null,$pred=null,$obj=null) {
+ // Import Package Utility
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_UTILITY);
+
+ $if = new IterFind($this,$sub,$pred,$obj);
+ return $if;
+ }
+
+ /**
+ * Removes a single namespace from the model
+ *
+ * @author Tobias Gauss
+ * @param string $nmsp Namespace URI
+ *
+ * @return mixed True if all went well, error message otherwise
+ *
+ * @access public
+ */
+ function removeNamespace($nmsp){
+
+ $sql = 'DELETE FROM namespaces
+ WHERE modelID=' .$this->modelID." AND namespace=". $this->dbConn->qstr($nmsp);
+
+ $rs =& $this->dbConn->execute($sql);
+ if (!$rs)
+ return $this->dbConn->errorMsg();
+ else {
+ return true;
+ }
+ }
+
+
+
+
+ /**
+ * Add the given row from the array fields[] of an ADORecordSet to this DbModel
+ * The array index corresponds to following table columns:
+ * [0] - subject, [1] - predicate, [2] - object, [3] - l_language,
+ * [4] - l_datatype, [5] - subject_is, [6] - object_is
+ *
+ * @param array $row
+ * @throws SqlError
+ * @access private
+ *
+ function _insertRow ($row) {
+
+ $quotedObject = $this->dbConn->qstr($row[2]);
+ $sql = "INSERT INTO statements VALUES
+ (" .$this->modelID .","
+ ."'" .$row[0] ."',"
+ ."'" .$row[1] ."',"
+ ."" .$quotedObject .","
+ ."'" .$row[3] ."',"
+ ."'" .$row[4] ."',"
+ ."'" .$row[5] ."',"
+ ."'" .$row[6] ."')";
+
+ $rs =& $this->dbConn->execute($sql);
+ if (!$rs)
+ $this->dbConn->errorMsg();
+ }
+ */
+
+} // end: Class DbModel
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/DbStore.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/DbStore.php
new file mode 100755
index 00000000..a845d308
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/DbStore.php
@@ -0,0 +1,917 @@
+
+ * @author Daniel Westphal (http://www.d-westphal.de)
+ *
+ * @package model
+ * @access public
+ */
+
+
+class DbStore extends Object
+{
+ /**
+ * Array with all supported database types
+ *
+ * @var array
+ */
+ public static $arSupportedDbTypes = array(
+ "MySQL",
+ "MySQLi",
+ "MSSQL",
+ 'MsAccess'
+ );
+
+ /**
+ * Database connection object
+ *
+ * @var object ADOConnection
+ * @access private
+ */
+ var $dbConn;
+
+ /**
+ * Database driver name
+ *
+ * @var string
+ */
+ protected $driver = null;
+
+ /**
+ * SparqlParser so we can re-use it
+ * @var Parser
+ */
+ var $queryParser = null;
+
+
+/**
+ * Constructor:
+ * Set the database connection with the given parameters.
+ *
+ * @param string $dbDriver
+ * @param string $host
+ * @param string $dbName
+ * @param string $user
+ * @param string $password
+ * @access public
+ */
+ function DbStore ($dbDriver=ADODB_DB_DRIVER, $host=ADODB_DB_HOST, $dbName=ADODB_DB_NAME,
+ $user=ADODB_DB_USER, $password=ADODB_DB_PASSWORD) {
+
+ // include DBase Package
+ require_once(RDFAPI_INCLUDE_DIR.PACKAGE_DBASE);
+
+ // create a new connection object
+ $this->dbConn =& ADONewConnection($dbDriver);
+ $this->driver = $dbDriver;
+
+ //activate the ADOdb DEBUG mode
+ if (ADODB_DEBUG_MODE == '1')
+ $this->dbConn->debug = true;
+
+ // connect to database
+ $r = $this->dbConn->NConnect($host, $user, $password, $dbName);
+ if ($r !== true) {
+ throw new Exception('Could not connect to database');
+ }
+
+ // optimized for speed
+ $this->dbConn->setFetchMode(ADODB_FETCH_NUM);
+ //$ADODB_COUNTRECS = FALSE;
+ }
+
+
+
+/**
+ * List all DbModels stored in the database.
+ *
+ * @return array
+ * @throws SqlError
+ * @access public
+ */
+ function listModels() {
+
+ $recordSet =& $this->dbConn->execute("SELECT modelURI, baseURI
+ FROM models");
+ if (!$recordSet)
+ echo $this->dbConn->errorMsg();
+ else {
+ $models = array();
+ $i=0;
+ while (!$recordSet->EOF) {
+
+ $models[$i]['modelURI'] = $recordSet->fields[0];
+ $models[$i]['baseURI'] = $recordSet->fields[1];
+
+ ++$i;
+ $recordSet->moveNext();
+ }
+ return $models;
+ }
+ }
+
+
+/**
+ * Check if the DbModel with the given modelURI is already stored in the database
+ *
+ * @param string $modelURI
+ * @return boolean
+ * @throws SqlError
+ * @access public
+ */
+ function modelExists($modelURI) {
+
+ $res =& $this->dbConn->execute("SELECT COUNT(*) FROM models
+ WHERE modelURI = '" .$modelURI ."'");
+ if (!$res)
+ echo $this->dbConn->errorMsg();
+ else {
+ if (!$res->fields[0]) {
+ $res->Close();
+ return FALSE;
+ } else {
+ $res->Close();
+ return TRUE;
+ }
+ }
+ }
+
+
+
+ /**
+ * Returns the database connection object
+ *
+ * @return ADOdb Database object
+ * @access public
+ */
+ function &getDbConn()
+ {
+ return $this->dbConn;
+ }
+
+
+/**
+ * Create a new instance of DbModel with the given $modelURI and
+ * load the corresponding values of modelID and baseURI from the database.
+ * Return FALSE if the DbModel does not exist.
+ *
+ * @param string $modelURI
+ * @return object DbModel
+ * @access public
+ */
+ function getModel($modelURI) {
+
+ if (!$this->modelExists($modelURI))
+ return FALSE;
+ else {
+ $modelVars =& $this->dbConn->execute("SELECT modelURI, modelID, baseURI
+ FROM models
+ WHERE modelURI='" .$modelURI ."'");
+
+ return new DbModel($this->dbConn, $modelVars->fields[0],
+ $modelVars->fields[1], $modelVars->fields[2]);
+ }
+ }
+
+
+/**
+ * Create a new instance of DbModel with the given $modelURI
+ * and insert the DbModel variables into the database.
+ * Return FALSE if there is already a model with the given URI.
+ *
+ * @param string $modelURI
+ * @param string $baseURI
+ * @return object DbModel
+ * @throws SqlError
+ * @access public
+ */
+ function getNewModel($modelURI, $baseURI=NULL) {
+
+ if ($this->modelExists($modelURI))
+ return FALSE;
+ else {
+ $modelID = $this->_createUniqueModelID();
+
+ $rs =& $this->dbConn->execute("INSERT INTO models
+ (modelID, modelURI, baseURI)
+ VALUES (" .$modelID .",
+ " .$this->dbConn->qstr($modelURI) .",
+ " .$this->dbConn->qstr($baseURI) .")");
+
+ if (!$rs)
+ return $this->dbConn->errorMsg();
+ else
+ return new DbModel($this->dbConn, $modelURI, $modelID, $baseURI);
+ }
+ }
+
+
+/**
+ * Store a MemModel or another DbModel from a different DbStore in the database.
+ * Return FALSE if there is already a model with modelURI matching the modelURI
+ * of the given model.
+ *
+ * @param object Model &$model
+ * @param string $modelURI
+ * @return boolean
+ * @access public
+ */
+ function putModel(&$model, $modelURI=NULL) {
+
+ if (!$modelURI) {
+ if (is_a($model, 'MemModel'))
+ $modelURI = 'DbModel-' .$this->_createUniqueModelID();
+ else
+ $modelURI = $model->modelURI;
+ }else
+ if ($this->modelExists($modelURI))
+ return FALSE;
+
+
+ $newDbModel = $this->getNewModel($modelURI, $model->getBaseURI());
+ $newDbModel->addModel($model);
+ }
+
+
+/**
+ * Close the DbStore.
+ * !!! Warning: If you close the DbStore all active instances of DbModel from this
+ * !!! DbStore will lose their database connection !!!
+ *
+ * @access public
+ */
+ function close() {
+
+ $this->dbConn->close();
+ unset($this);
+ }
+
+
+// =============================================================================
+// **************************** private methods ********************************
+// =============================================================================
+
+
+/**
+ * Create a unique ID for the DbModel to be insert into the models table.
+ * This method was implemented because some databases do not support auto-increment.
+ *
+ * @return integer
+ * @access private
+ */
+ function _createUniqueModelID() {
+
+ $maxModelID =& $this->dbConn->GetOne('SELECT MAX(modelID) FROM models');
+ return ++$maxModelID;
+ }
+
+ /**
+ * Create a unique ID for the dataset to be insert into the datasets table.
+ * This method was implemented because some databases do not support auto-increment.
+ *
+ * @return integer
+ * @access private
+ */
+ function _createUniqueDatasetID() {
+
+ $maxDatasetID =& $this->dbConn->GetOne('SELECT MAX(datasetId) FROM datasets');
+ return ++$maxDatasetID;
+ }
+
+
+
+ /**
+ * Sets up tables for RAP.
+ * DOES NOT CHECK IF TABLES ALREADY EXIST
+ *
+ * @param string $databaseType Database driver name (e.g. MySQL)
+ *
+ * @throws Exception If database type is unsupported
+ * @access public
+ **/
+ public function createTables($databaseType = null)
+ {
+ $driver = $this->getDriver($databaseType);
+ self::assertDriverSupported($driver);
+
+ $createFunc = '_createTables_' . $driver;
+ return $this->$createFunc();
+ }//public function createTables($databaseType="MySQL")
+
+
+
+ /**
+ * Create tables and indexes for MsAccess database
+ *
+ * @return boolean true If all is ok
+ *
+ * @throws Exception
+ */
+ protected function _createTables_MsAccess()
+ {
+ $this->dbConn->startTrans();
+
+ $this->dbConn->execute('CREATE TABLE models
+ (modelID long primary key,
+ modelURI varchar not null,
+ baseURI varchar)');
+
+ $this->dbConn->execute('CREATE UNIQUE INDEX m_modURI_idx ON models (modelURI)');
+
+ $this->dbConn->execute('CREATE TABLE statements
+ (modelID long,
+ subject varchar,
+ predicate varchar,
+ object Memo,
+ l_language varchar,
+ l_datatype varchar,
+ subject_is varchar(1),
+ object_is varchar(1),
+ primary key (modelID, subject, predicate, object,
+ l_language, l_datatype))');
+
+ $this->dbConn->execute('CREATE INDEX s_mod_idx ON statements (modelID)');
+ $this->dbConn->execute('CREATE INDEX s_sub_idx ON statements (subject)');
+ $this->dbConn->execute('CREATE INDEX s_pred_idx ON statements (predicate)');
+ $this->dbConn->execute('CREATE INDEX s_obj_idx ON statements (object)');
+
+ $this->dbConn->execute('CREATE TABLE namespaces
+ (modelID long,
+ namespace varchar,
+ prefix varchar,
+ primary key (modelID, namespace, prefix))');
+
+ $this->dbConn->execute('CREATE INDEX n_name_idx ON namespaces (namespace)');
+ $this->dbConn->execute('CREATE INDEX n_pref_idx ON namespaces (prefix)');
+
+ $this->dbConn->execute("CREATE TABLE datasets
+ (datasetName varchar,
+ defaultModelUri varchar,
+ primary key (datasetName))");
+
+ $this->dbConn->execute('CREATE INDEX nGS_idx1 ON datasets (datasetName)');
+
+
+ $this->dbConn->execute("CREATE TABLE `dataset_model` (
+ datasetName varchar,
+ modelId long,
+ graphURI varchar,
+ PRIMARY KEY (modelId,datasetName))");
+
+
+ if (!$this->dbConn->completeTrans()) {
+ throw new Exception($this->dbConn->errorMsg());
+ }
+ return true;
+ }
+
+
+
+ /**
+ * Create tables and indexes for MySQL database
+ *
+ * @return boolean true If all is ok
+ *
+ * @throws Exception
+ */
+ function _createTables_MySQL()
+ {
+
+ $this->dbConn->startTrans();
+
+ $this->dbConn->execute("CREATE TABLE models
+ (modelID bigint NOT NULL,
+ modelURI varchar(255) NOT NULL,
+ baseURI varchar(255) DEFAULT '',
+ primary key (modelID))");
+
+ $this->dbConn->execute('CREATE UNIQUE INDEX m_modURI_idx ON models (modelURI)');
+
+ $this->dbConn->execute("CREATE TABLE statements
+ (modelID bigint NOT NULL,
+ subject varchar(255) NOT NULL,
+ predicate varchar(255) NOT NULL,
+ object text,
+ l_language varchar(255) DEFAULT '',
+ l_datatype varchar(255) DEFAULT '',
+ subject_is varchar(1) NOT NULL,
+ object_is varchar(1) NOT NULL)");
+
+ $this->dbConn->execute("CREATE TABLE namespaces
+ (modelID bigint NOT NULL,
+ namespace varchar(255) NOT NULL,
+ prefix varchar(255) NOT NULL,
+ primary key (modelID,namespace))");
+
+ $this->dbConn->execute("CREATE TABLE `dataset_model` (
+ `datasetName` varchar(255) NOT NULL default '0',
+ `modelId` bigint(20) NOT NULL default '0',
+ `graphURI` varchar(255) NOT NULL default '',
+ PRIMARY KEY (`modelId`,`datasetName`))");
+
+ $this->dbConn->execute("CREATE TABLE `datasets` (
+ `datasetName` varchar(255) NOT NULL default '',
+ `defaultModelUri` varchar(255) NOT NULL default '0',
+ PRIMARY KEY (`datasetName`),
+ KEY `datasetName` (`datasetName`))");
+
+ $this->dbConn->execute('CREATE INDEX s_mod_idx ON statements (modelID)');
+ $this->dbConn->execute('CREATE INDEX n_mod_idx ON namespaces (modelID)');
+
+ $this->dbConn->execute('CREATE INDEX s_sub_pred_idx ON statements
+ (subject(200),predicate(200))');
+
+ $this->dbConn->execute('CREATE INDEX s_sub_idx ON statements (subject(200))');
+ $this->dbConn->execute('CREATE INDEX s_pred_idx ON statements (predicate(200))');
+ $this->dbConn->execute('CREATE INDEX s_obj_idx ON statements (object(250))');
+
+ $this->dbConn->execute('CREATE FULLTEXT INDEX s_obj_ftidx ON statements (object)');
+
+ if (!$this->dbConn->completeTrans()) {
+ throw new Exception($this->dbConn->errorMsg());
+ }
+ return true;
+ }
+
+
+
+ /**
+ * Creates tables on a MySQLi database
+ */
+ function _createTables_MySQLi()
+ {
+ return $this->_createTables_MySQL();
+ }//function _createTables_MySQLi()
+
+
+
+ /**
+ * Create tables and indexes for MSSQL database
+ *
+ * @return boolean true If all is ok
+ *
+ * @throws Exception
+ */
+ function _createTables_MSSQL()
+ {
+ $this->dbConn->startTrans();
+
+ $this->dbConn->execute("CREATE TABLE [dbo].[models] (
+ [modelID] [int] NOT NULL ,
+ [modelURI] [nvarchar] (200) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
+ [baseURI] [nvarchar] (200) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
+ ) ON [PRIMARY]");
+
+ $this->dbConn->execute("CREATE TABLE [dbo].[statements] (
+ [modelID] [int] NOT NULL ,
+ [subject] [nvarchar] (200) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
+ [predicate] [nvarchar] (200) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
+ [object] [text] COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
+ [l_language] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
+ [l_datatype] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
+ [subject_is] [nchar] (1) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
+ [object_is] [nchar] (1) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
+ ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]");
+
+
+ $this->dbConn->execute("CREATE TABLE [dbo].[namespaces] (
+ [modelID] [int] NOT NULL ,
+ [namespace] [nvarchar] (200) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
+ [prefix] [nvarchar] (200) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
+ ) ON [PRIMARY]");
+
+ $this->dbConn->execute("ALTER TABLE [dbo].[models] WITH NOCHECK ADD
+ CONSTRAINT [PK_models] PRIMARY KEY CLUSTERED
+ (
+ [modelID]
+ ) ON [PRIMARY] ");
+ $this->dbConn->execute("ALTER TABLE [dbo].[namespaces] WITH NOCHECK ADD
+ CONSTRAINT [PK_namespaces] PRIMARY KEY CLUSTERED
+ (
+ [modelID],[namespace]
+ ) ON [PRIMARY] ");
+
+ $this->dbConn->execute("CREATE INDEX [joint index on subject and predicate] ON [dbo].[statements]([subject], [predicate]) ON [PRIMARY]");
+
+
+ if (!$this->dbConn->completeTrans()) {
+ throw new Exception($this->dbConn->errorMsg());
+ }
+ return true;
+ }
+
+
+
+ /**
+ * Checks if tables are setup for RAP
+ *
+ * @param string $databaseType
+ * @throws Exception If database type is unsupported
+ * @access public
+ **/
+ public function isSetup($databaseType = null)
+ {
+ $driver = $this->getDriver($databaseType);
+ self::assertDriverSupported($driver);
+
+ $issetupFunc = '_isSetup_' . $driver;
+ return $this->$issetupFunc();
+ }//public function isSetup($databaseType="MySQL")
+
+
+
+ /**
+ * Returns the driver for the database type.
+ * You can pass NULL or omit the parameter to
+ * use the parameter from the dbstore constructor
+ *
+ * @param string $databaseType Database driver name (e.g. MySQL)
+ *
+ * @return string Database driver string (e.g. MySQL)
+ */
+ public function getDriver($databaseType = null)
+ {
+ if ($databaseType === null) {
+ if ($this->driver === null) {
+ //backward compatibility
+ $databaseType = 'MySQL';
+ } else {
+ $databaseType = $this->driver;
+ }
+ }
+ if (!self::isDriverSupported($databaseType)) {
+ //check if it is a known driver in wrong case
+ $arLowercases = array_map('strtolower', self::$arSupportedDbTypes);
+ $arMapping = array_combine($arLowercases, self::$arSupportedDbTypes);
+ if (isset($arMapping[strtolower($databaseType)])) {
+ $databaseType = $arMapping[strtolower($databaseType)];
+ }
+ }
+ return $databaseType;
+ }//public function getDriver($databaseType = null)
+
+
+
+ /**
+ * Returns if the given driver is supported
+ *
+ * @return boolean True if it supported, false if not
+ */
+ public static function isDriverSupported($databaseType)
+ {
+ return in_array($databaseType, self::$arSupportedDbTypes);
+ }//public static function isDriverSupported($databaseType)
+
+
+
+ /**
+ * Checks if the given driver is supported and throws an
+ * Exception if not.
+ *
+ * @param string $databaseType Database driver name (e.g. MySQL)
+ *
+ * @return true If it does not fail
+ *
+ * @throws Exception If the driver is not supported
+ */
+ public static function assertDriverSupported($databaseType)
+ {
+ if (!self::isDriverSupported($databaseType)) {
+ throw new Exception(
+ 'Unsupported database type, only supported: '
+ . implode(', ', self::$arSupportedDbTypes)
+ );
+ }
+ return true;
+ }//public static function assertDriverSupported($databaseType)
+
+
+
+ /**
+ * Checks if tables are setup for RAP (MySql)
+ *
+ * @throws SqlError
+ * @access private
+ **/
+ function _isSetup_MySQL()
+ {
+ $recordSet =& $this->dbConn->execute("SHOW TABLES");
+ if (!$recordSet) {
+ throw new Exception($this->dbConn->errorMsg());
+ } else {
+ $tables = array();
+ while (!$recordSet->EOF) {
+ $tables[]= $recordSet->fields[0];
+ if (isset($i)) {
+ ++$i;
+ }
+ $recordSet->moveNext();
+ }
+ if (in_array("models",$tables) && in_array("statements",$tables)
+ && in_array("namespaces",$tables)) {
+ return true;
+ }
+ }
+ return false;
+ }//function _isSetup_MySQL()
+
+
+
+ /**
+ * Checks if tables are setup for RAP (MySQLi)
+ *
+ * @see _isSetup_MySQL()
+ */
+ function _isSetup_MySQLi()
+ {
+ return $this->_isSetup_MySQL();
+ }//function _isSetup_MySQLi()
+
+
+
+ /**
+ * Checks if tables are setup for RAP (MsAccess)
+ *
+ * @throws SqlError
+ * @access private
+ **/
+ function _isSetup_MsAccess()
+ {
+ $tables =& $this->dbConn->MetaTables();
+ if (!$tables) {
+ throw new Exception($this->dbConn->errorMsg());
+ }
+ if (count($tables) == 0) {
+ return false;
+ } else {
+ if (in_array("models",$tables) && in_array("statements",$tables)
+ && in_array("namespaces",$tables)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }//function _isSetup_MsAccess()
+
+
+
+ /**
+ * Checks if tables are setup for RAP (MSSQL)
+ *
+ * @throws SqlError
+ * @access private
+ **/
+ function _isSetup_MSSQL()
+ {
+ $tables =& $this->dbConn->MetaTables();
+ if (!$tables) {
+ throw new Exception($this->dbConn->errorMsg());
+ }
+ if (count($tables) == 0) {
+ return false;
+ } else {
+ if (in_array("models",$tables) && in_array("statements",$tables)
+ && in_array("namespaces",$tables)){
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }//function _isSetup_MSSQL()
+
+
+ /**
+ * Create a new instance of DatasetDb with the given $datasetName
+ * and insert the DatasetDb variables into the database.
+ * Return FALSE if there is already a model with the given URI.
+ *
+ * @param $datasetName string
+ * @return object DatasetDB
+ * @throws SqlError
+ * @access public
+ */
+ function & getNewDatasetDb($datasetName)
+ {
+
+ require_once(RDFAPI_INCLUDE_DIR . PACKAGE_DATASET);
+
+ if ($this->datasetExists($datasetName))
+ return FALSE;
+ else
+ {
+ $defaultModelUri=uniqid('http://rdfapi-php/dataset_defaultmodel_');
+ $defaultModel=$this->getNewModel($defaultModelUri);
+
+ $rs =& $this->dbConn->execute("INSERT INTO datasets
+ VALUES ('" .$this->dbConn->qstr($datasetName) ."',
+ '" .$this->dbConn->qstr($defaultModelUri)."')");
+
+ if (!$rs)
+ $this->dbConn->errorMsg();
+ else
+ $return=new DatasetDb($this->dbConn, $this, $datasetName);
+ return ($return);
+ }
+ }
+
+ /**
+ * Check if the Dataset with the given $datasetName is already stored in the database
+ *
+ * @param $datasetName string
+ * @return boolean
+ * @throws SqlError
+ * @access public
+ */
+function datasetExists($datasetName) {
+
+ $res =& $this->dbConn->execute("SELECT COUNT(*) FROM datasets
+ WHERE datasetName = '" .$datasetName ."'");
+ if (!$res)
+ echo $this->dbConn->errorMsg();
+ else {
+ if (!$res->fields[0])
+ return FALSE;
+ return TRUE;
+ }
+ }
+
+
+ /**
+ * Create a new instance of DatasetDb with the given $datasetName and
+ * load the corresponding values from the database.
+ * Return FALSE if the DbModel does not exist.
+ *
+ * @param $datasetId string
+ * @return object DatasetDb
+ * @access public
+ */
+ function &getDatasetDb($datasetName) {
+ require_once(RDFAPI_INCLUDE_DIR . PACKAGE_DATASET);
+
+ if (!$this->datasetExists($datasetName)) {
+ return FALSE;
+ } else {
+ $return = new DatasetDb($this->dbConn, $this, $datasetName);
+ return ($return);
+ }
+ }
+
+ /**
+ * Create a new instance of namedGraphDb with the given $modelURI and graphName and
+ * load the corresponding values of modelID and baseURI from the database.
+ * Return FALSE if the DbModel does not exist.
+ *
+ * @param $modelURI string
+ * @param $graphName string
+ * @return object NamedGraphMem
+ * @access public
+ */
+ function getNamedGraphDb($modelURI, $graphName)
+ {
+ require_once(RDFAPI_INCLUDE_DIR . PACKAGE_DATASET);
+
+ if (!$this->modelExists($modelURI))
+ return FALSE;
+ else {
+ $modelVars =& $this->dbConn->execute("SELECT modelURI, modelID, baseURI
+ FROM models
+ WHERE modelURI='" .$modelURI ."'");
+
+ return new NamedGraphDb($this->dbConn, $modelVars->fields[0],
+ $modelVars->fields[1], $graphName ,$modelVars->fields[2]);
+ }
+ }
+
+ /**
+ * Create a new instance of namedGraphDb with the given $modelURI and graphName
+ * and insert the DbModel variables into the database (not the graphName. This
+ * is only stored persistently, when added to dataset).
+ * Return FALSE if there is already a model with the given URI.
+ *
+ * @param $modelURI string
+ * @param $graphName string
+ * @param $baseURI string
+ * @return object namedGraphDb
+ * @throws SqlError
+ * @access public
+ */
+ function getNewNamedGraphDb($modelURI, $graphName, $baseURI=NULL) {
+
+ if ($this->modelExists($modelURI))
+ return FALSE;
+ else {
+ $modelID = $this->_createUniqueModelID();
+
+ $rs =& $this->dbConn->execute("INSERT INTO models
+ (modelID, modelURI, baseURI)
+ VALUES (" .$modelID ."',
+ " .$this->dbConn->qstr($modelURI) ."',
+ " .$this->dbConn->qstr($baseURI) .")");
+ if (!$rs)
+ $this->dbConn->errorMsg();
+ else
+ return new NamedGraphDb($this->dbConn, $modelURI, $modelID, $graphName, $baseURI);
+ }
+ }
+
+ /**
+ * Removes the graph with all statements from the database.
+ * Warning: A single namedGraph can be added to several datasets. So it'll be
+ * removed from all datasets.
+ *
+ * @param $modelURI string
+ * @return boolean
+ * @throws SqlError
+ * @access public
+ */
+ function removeNamedGraphDb($modelURI)
+ {
+ if (!$this->modelExists($modelURI))
+ return FALSE;
+
+ $modelID = $this->dbConn->GetOne("SELECT modelID FROM models WHERE modelURI='".$modelURI."'");
+
+ $this->dbConn->execute("DELETE FROM models WHERE modelID=".$modelID);
+ $this->dbConn->execute("DELETE FROM dataset_model WHERE modelId=".$modelID);
+ $this->dbConn->execute("DELETE FROM statements WHERE modelID=".$modelID);
+
+ return true;
+ }
+
+
+
+ /**
+ * Performs a SPARQL query against a model. The model is converted to
+ * an RDF Dataset. The result can be retrived in SPARQL Query Results XML Format or
+ * as an array containing the variables an their bindings.
+ *
+ * @param string $query Sparql query string
+ * @param mixed $arModelIds Array of modelIDs, or NULL to use all models
+ * @param string $resultform Result form ('xml' for SPARQL Query Results XML Format)
+ * @return string/array
+ */
+ function sparqlQuery($query, $arModelIds = null, $resultform = false)
+ {
+ $engine = $this->_prepareSparql($arModelIds);
+ return $engine->queryModel(
+ null,
+ $this->_parseSparqlQuery($query),
+ $resultform
+ );
+ }//function sparqlQuery($query,$resultform = false)
+
+
+
+ /**
+ * Prepares everything for SparqlEngine-usage
+ * Loads the files, creates instances for SparqlEngine and
+ * Dataset...
+ *
+ * @return SparqlEngineDb
+ */
+ function _prepareSparql($arModelIds)
+ {
+ require_once RDFAPI_INCLUDE_DIR . 'sparql/SparqlEngineDb.php';
+ return new SparqlEngineDb($this, $arModelIds);
+ }//function _prepareSparql()
+
+
+
+ /**
+ * Parses an query and returns the parsed form.
+ * If the query is not a string but a Query object,
+ * it will just be returned.
+ *
+ * @param $query mixed String or Query object
+ * @return Query query object
+ * @throws Exception If $query is no string and no Query object
+ */
+ function _parseSparqlQuery($query)
+ {
+ if ($this->queryParser === null) {
+ require_once RDFAPI_INCLUDE_DIR . 'sparql/SparqlParser.php';
+ $this->queryParser = new SparqlParser();
+ }
+ return $this->queryParser->parse($query);
+ }//function _parseSparqlQuery($query)
+
+} // end: Class DbStore
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/Literal.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/Literal.php
new file mode 100755
index 00000000..4f31a427
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/Literal.php
@@ -0,0 +1,188 @@
+
+ * @author Daniel Westphal
+ *
+ * @package model
+ * @access public
+ *
+ */
+ class Literal extends Node {
+
+ /**
+ * Label of the literal
+ * @var string
+ * @access private
+ */
+ var $label;
+ /**
+ * Language of the literal
+ * @var string
+ * @access private
+ */
+ var $lang;
+
+ /**
+ * Datatype of the literal
+ * @var string
+ * @access private
+ */
+ var $dtype;
+
+
+ /**
+ * Constructor
+ *
+ * @param string $str label of the literal
+ * @param string $language optional language identifier
+ * @param string $datatype optional datatype
+ *
+ */
+ function Literal($str, $language = NULL, $datatype = null)
+ {
+ $this->label = $str;
+
+ if ($language != NULL) {
+ $this->lang = $language;
+ } else {
+ $this->lang = NULL;
+ }
+
+ if ($datatype != null) {
+ $this->dtype = $datatype;
+ } else {
+ $this->dtype = NULL;
+ }
+ }
+
+ /**
+ * Returns the string value of the literal.
+ *
+ * @access public
+ * @return string value of the literal
+ */
+ function getLabel() {
+
+ return $this->label;
+ }
+
+ /**
+ * Returns the language of the literal.
+ *
+ * @access public
+ * @return string language of the literal
+ */
+ function getLanguage() {
+
+ return $this->lang;
+ }
+
+ /**
+ * Sets the language of the literal.
+ *
+ * @access public
+ * @param string $lang
+ */
+ function setLanguage($lang) {
+
+ $this->lang = $lang;
+ }
+
+ /**
+ * Returns the datatype of the literal.
+ *
+ * @access public
+ * @return string datatype of the literal
+ */
+ function getDatatype() {
+
+ return $this->dtype;
+ }
+
+ /**
+ * Sets the datatype of the literal.
+ * Instead of datatype URI, you can also use an datatype shortcuts like STRING or INTEGER.
+ * The array $short_datatype with the possible shortcuts is definded in ../constants.php
+ *
+ * @access public
+ * @param string URI of XML datatype or datatype shortcut
+ *
+ */
+ function setDatatype($datatype) {
+ GLOBAL $short_datatype;
+ if (stristr($datatype,DATATYPE_SHORTCUT_PREFIX)) {
+ $this->dtype = $short_datatype[substr($datatype,strlen(DATATYPE_SHORTCUT_PREFIX)) ];}
+ else
+ $this->dtype = $datatype;
+ }
+
+ /**
+ * Checks if ihe literal equals another literal.
+ * Two literals are equal, if they have the same label and they
+ * have the same language/datatype or both have no language/datatype property set.
+ *
+ * @access public
+ * @param object literal $that
+ * @return boolean
+ */
+ function equals ($that) {
+
+ if (($that == NULL) or !(is_a($that, 'Literal'))) {
+ return false;
+ }
+
+ if ( ($this->label == $that->getLabel()) && ( ( ($this->lang == $that->getLanguage()) ||
+ ($this->lang == NULL && $that->getLanguage() == NULL) ) &&
+
+ (
+ ($this->dtype == $that->getDatatype() ||
+ ($this->dtype == NULL && $that->getDatatype() == NULL)) ) ) )
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Dumps literal.
+ *
+ * @access public
+ * @return string
+ */
+ function toString() {
+ $dump = 'Literal("' . $this->label .'"';
+ if ($this->lang != NULL)
+ $dump .= ', lang="' . $this->lang .'"';
+ if ($this->dtype != NULL)
+ $dump .= ', datatype="' . $this->dtype .'"';
+ $dump .= ')';
+ return $dump;
+ }
+
+
+
+ /**
+ * Doing string magic in PHP5
+ * @return string String representation of this Literal
+ */
+ function __toString()
+ {
+ return $this->toString();
+ }
+
+
+} // end: Literal
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/MemModel.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/MemModel.php
new file mode 100755
index 00000000..1545785c
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/MemModel.php
@@ -0,0 +1,1460 @@
+
+* @author Gunnar AAstrand Grimnes
+* @author Radoslaw Oldakowski
+* @author Daniel Westphal
+* @author Tobias Gauß
+*
+* @package model
+* @access public
+*/
+
+class MemModel extends Model {
+
+ /**
+ * Triples of the MemModel
+ * @var array
+ * @access private
+ */
+ var $triples = array();
+
+ /**
+ * Array containing the search indices
+ * @var array['INDEX_TYPE'][]['label'][]['PosInModel']
+ *
+ * @access private
+ */
+ var $indexArr ;
+
+
+ /**
+ * depending on which index is used this variable is -1,0,1,2 or 3
+ *
+ * -1 : no index
+ * 0 : default indices over subject, predicate, object separate
+ * 1 : index over subject+predicate+object
+ * 2 : index over subject+predicate
+ * 3 : index over subject+object
+ *
+ * @var int
+ * @access private
+ */
+ var $indexed;
+
+
+
+ /**
+ * Array of namespaces
+ *
+ * @var array
+ * @access private
+ */
+ var $parsedNamespaces=array();
+
+
+
+ /**
+ * Constructor
+ * You can supply a base_uri
+ *
+ * @param string $baseURI
+ * @access public
+ */
+ function MemModel($baseURI = NULL) {
+ $this->setBaseURI($baseURI);
+ $this->indexed = INDEX_TYPE;
+ }
+
+ /**
+ * Set a base URI for the MemModel.
+ * Affects creating of new resources and serialization syntax.
+ * If the URI doesn't end with # : or /, then a # is added to the URI.
+ * @param string $uri
+ * @access public
+ */
+ function setBaseURI($uri) {
+
+ if ($uri != NULL) {
+ $c = substr($uri, strlen($uri)-1 ,1);
+ if (!($c=='#' || $c==':' || $c=='/' || $c=="\\"))
+ $uri .= '#';
+ }
+ $this->baseURI = $uri;
+ }
+
+
+ /**
+ * Number of triples in the MemModel
+ *
+ * @return integer
+ * @access public
+ */
+ function size() {
+ return count($this->triples);
+ }
+
+ /**
+ * Checks if MemModel is empty
+ *
+ * @return boolean
+ * @access public
+ */
+ function isEmpty() {
+ if (count($this->triples) == 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ };
+ }
+
+
+ /**
+ * Adds a new triple to the MemModel without checking if the statement is already in the MemModel.
+ * So if you want a duplicate free MemModel use the addWithoutDuplicates() function (which is slower then add())
+ *
+ * @param object Statement $statement
+ * @access public
+ * @throws PhpError
+ */
+ function add($statement) {
+ if (!is_a($statement, 'Statement')) {
+ $errmsg = RDFAPI_ERROR . '(class: MemModel; method: add): Statement expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ if($this->indexed != -1){
+ $this->triples[] = $statement;
+ end($this->triples);
+ $k=key($this->triples);
+ if($this->indexed==0){
+ // index over S
+ $this->_indexOpr($statement,$k,4,1);
+ // index over P
+ $this->_indexOpr($statement,$k,5,1);
+ // index over O
+ $this->_indexOpr($statement,$k,6,1);
+ }else{
+ $this->_indexOpr($statement,$k,$this->indexed,1);
+ }
+
+ }else{
+ $this->triples[] = $statement;
+ }
+ }
+
+
+
+ /**
+ * Checks if a new statement is already in the MemModel and adds the statement, if it is not in the MemModel.
+ * addWithoutDuplicates() is significantly slower then add().
+ * Retruns TRUE if the statement is added.
+ * FALSE otherwise.
+ *
+ * @param object Statement $statement
+ * @return boolean
+ * @access public
+ * @throws PhpError
+ */
+ function addWithoutDuplicates($statement) {
+
+ if (!is_a($statement, 'Statement')) {
+ $errmsg = RDFAPI_ERROR . '(class: MemModel; method: addWithoutDuplicates): Statement expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ if (!$this->contains($statement)) {
+ $this->add($statement);
+ return true;
+ }else{
+ return false;
+ }
+ }
+
+ /**
+ * Removes the triple from the MemModel.
+ * TRUE if the triple is removed.
+ * FALSE otherwise.
+ *
+ * @param object Statement $statement
+ * @return boolean
+ * @access public
+ * @throws PhpError
+ */
+ function remove($statement) {
+
+ if (!is_a($statement, 'Statement')) {
+ $errmsg = RDFAPI_ERROR . '(class: MemModel; method: remove): Statement expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+ if($this->indexed==-1){
+ $pass=false;
+ foreach($this->triples as $key => $value) {
+ if ($this->matchStatement($value, $statement->subject(), $statement->predicate(), $statement->object())) {
+ unset($this->triples[$key]);
+ $pass= true;
+ }
+ }
+ return $pass;
+ }else{
+ $k= null;
+ if($this->indexed==0){
+ $pass=false;
+ $del=false;
+ while($del!=-1){
+ // index over S
+ $del=$this->_indexOpr($statement,$k,4,0);
+ // index over P
+ $this->_indexOpr($statement,$k,5,0);
+ // index over O
+ $this->_indexOpr($statement,$k,6,0);
+ if($del!=-1){
+ unset($this->triples[$del]);
+ $pass=true;
+ }
+ }
+ return $pass;
+ }else{
+ $pass=false;
+ $del=false;
+ while($del!=-1){
+ $del=$this->_indexOpr($statement,$k,$this->indexed,0);
+ if($del!=-1){
+ unset($this->triples[$del]);
+ $pass=true;
+ }
+ }
+ return $pass;
+ }
+ }
+ }
+
+ /**
+ * Short Dump of the MemModel.
+ *
+ * @access public
+ * @return string
+ */
+ function toString() {
+ return 'MemModel[baseURI=' . $this->getBaseURI() . '; size=' . $this->size() . ']';
+ }
+
+ /**
+ * Dumps of the MemModel including all triples.
+ *
+ * @access public
+ * @return string
+ */
+ function toStringIncludingTriples() {
+ $dump = $this->toString() . chr(13);
+ foreach($this->triples as $value) {
+ $dump .= $value->toString() . chr(13);
+ }
+ return $dump;
+ }
+
+
+
+
+ /**
+ * Writes the RDF serialization of the MemModel as HTML.
+ *
+ * @access public
+ */
+ function writeAsHtml() {
+ require_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_RDF);
+ $ser = new RdfSerializer();
+ $rdf =& $ser->serialize($this);
+ $rdf = htmlspecialchars($rdf, ENT_QUOTES);
+ $rdf = str_replace(' ', ' ', $rdf);
+ $rdf = nl2br($rdf);
+ echo $rdf;
+ }
+
+ /**
+ * Writes the RDF serialization of the MemModel as HTML table.
+ *
+ * @access public
+ */
+ function writeAsHtmlTable() {
+ // Import Package Utility
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_UTILITY);
+ RDFUtil::writeHTMLTable($this);
+ }
+
+
+ /**
+ * Writes the RDF serialization of the MemModel as HTML table.
+ *
+ * @access public
+ * @return string
+ */
+ function writeRdfToString() {
+ // Import Package Syntax
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_RDF);
+ $ser = new RdfSerializer();
+ $rdf =& $ser->serialize($this);
+ return $rdf;
+ }
+
+
+ /**
+ * Saves the RDF,N3 or N-Triple serialization of the MemModel to a file.
+ * You can decide to which format the model should be serialized by using a
+ * corresponding suffix-string as $type parameter. If no $type parameter
+ * is placed this method will serialize the model to XML/RDF format.
+ * Returns FALSE if the MemModel couldn't be saved to the file.
+ *
+ * @access public
+ * @param string $filename
+ * @param string $type
+ * @throws PhpError
+ * @return boolean
+ */
+ function saveAs($filename, $type ='rdf') {
+
+
+ // get suffix and create a corresponding serializer
+ if ($type=='rdf') {
+ // Import Package Syntax
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_RDF);
+ $ser=new RdfSerializer();
+ }elseif ($type=='nt') {
+ // Import Package Syntax
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_N3);
+ $ser=new NTripleSerializer();
+ }elseif ($type=='n3') {
+ // Import Package Syntax
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_N3);
+ $ser=new N3Serializer();
+ }else {
+ print ('Serializer type not properly defined. Use the strings "rdf","n3" or "nt".');
+ return false;
+ };
+
+ return $ser->saveAs($this, $filename);
+ }
+
+
+ /**
+ * Tests if the MemModel contains the given triple.
+ * TRUE if the triple belongs to the MemModel;
+ * FALSE otherwise.
+ *
+ * @param object Statement &$statement
+ * @return boolean
+ * @access public
+ */
+ function contains(&$statement) {
+
+ // no index ->linear contains
+ if ($this->indexed==-1){
+ foreach($this->triples as $value) {
+ if ($value->equals($statement)){
+ return TRUE; }
+ }
+ return false;
+ }
+ if ($this->indexed==0){
+ $res = $this->_containsIndex($statement,4);
+ return $res;
+ }else{
+ return $this->_containsIndex($statement,$this->indexed);
+ }
+ }
+
+
+ /**
+ * Determine if all of the statements in a model are also contained in this MemModel.
+ * True if all of the statements in $model are also contained in this MemModel and false otherwise.
+ *
+ * @param object Model &$model
+ * @return boolean
+ * @access public
+ */
+ function containsAll(&$model) {
+
+ if (is_a($model, 'MemModel')) {
+
+ foreach($model->triples as $statement)
+ if(!$this->contains($statement))
+ return FALSE;
+ return TRUE;
+
+ }elseif (is_a($model, 'DbModel'))
+
+ return $model->containsAll($this);
+
+ $errmsg = RDFAPI_ERROR . '(class: MemModel; method: containsAll): Model expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ /**
+ * Determine if any of the statements in a model are also contained in this MemModel.
+ * True if any of the statements in $model are also contained in this MemModel and false otherwise.
+ *
+ * @param object Model &$model
+ * @return boolean
+ * @access public
+ */
+ function containsAny(&$model) {
+
+ if (is_a($model, 'MemModel')) {
+
+ foreach($model->triples as $modelStatement)
+ if($this->contains($modelStatement))
+ return TRUE;
+ return FALSE;
+
+ }elseif (is_a($model, 'DbModel'))
+
+ return $model->containsAny($this);
+
+ $errmsg = RDFAPI_ERROR . '(class: MemModel; method: containsAll): Model expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+
+ /**
+ * Builds a search index for the statements in the MemModel.
+ * The index is used by the find(),contains(),add() and remove() functions.
+ * Performance example using a model with 43000 statements on a Linux machine:
+ * Find without index takes 1.7 seconds.
+ * Indexing takes 1.8 seconds.
+ * Find with index takes 0.001 seconds.
+ * So if you want to query a model more then once, build a index first.
+ * The defaultindex is indices over subject, predicate, object seperate.
+ *
+ * mode = 0 : indices over subject,predicate,object (default)
+ * mode = 1 : index over subject+predicate+object
+ * mode = 2 : index over subject+predicate
+ * mode = 3 : index over subject+object
+ *
+ * @param int $mode
+ * @access public
+ */
+ function index($mode) {
+
+ unset($this->indexArr);
+ $this->indexArr=array();
+ switch($mode){
+ // unset indices
+ case -1:
+ $this->indexed=-1;
+ unset($this->indexArr);
+ break;
+ // index over SPO
+ case 0:
+ $this->indexed=0;
+ foreach($this->triples as $k => $t) {
+ // index over S
+ $this->_indexOpr($t,$k,4,1);
+ // index over P
+ $this->_indexOpr($t,$k,5,1);
+ // index over O
+ $this->_indexOpr($t,$k,6,1);
+ }
+ break;
+ default:
+ $this->indexed=$mode;
+ foreach($this->triples as $k => $t) {
+ $this->_indexOpr($t,$k,$this->indexed,1);
+ }
+ break;
+ }
+ }
+
+
+ /**
+ * Returns true if there is an index, false if not.
+ *
+ * @return boolean
+ * @access public
+ */
+ function isIndexed() {
+ if($this->indexed!=-1){
+ return TRUE;
+ }else{
+ return FALSE;
+ }
+ }
+
+ /**
+ * Returns the indextype:
+ * -1 if there is no index, 0 if there are indices over S,P,O(separate),
+ * 1 if there is an index over SPO, 2 if there is an index over SP and 3 if
+ * there is an index over SO.
+ *
+ * @return int
+ * @access public
+ *
+ */
+ function getIndexType(){
+ return $this->indexed;
+ }
+
+ /**
+ * General method to search for triples.
+ * NULL input for any parameter will match anything.
+ * Example: $result = $m->find( NULL, NULL, $node );
+ * Finds all triples with $node as object.
+ * Returns an empty MemModel if nothing is found.
+ *
+ * @param object Node $subject
+ * @param object Node $predicate
+ * @param object Node $object
+ * @return object MemModel
+ * @access public
+ * @throws PhpError
+ */
+
+ function find($subject,$predicate,$object) {
+
+ if (
+ (!is_a($subject, 'Resource') && $subject != NULL) ||
+ (!is_a($predicate, 'Resource') && $predicate != NULL) ||
+ (!is_a($object, 'Node') && $object != NULL)
+ ) {
+ $errmsg = RDFAPI_ERROR . '(class: MemModel; method: find): Parameters must be subclasses of Node or NULL';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ $res = new MemModel($this->getBaseURI());
+ $res->indexed=-1;
+
+ if($this->isEmpty())
+ return $res;
+
+ if($subject == NULL && $predicate == NULL && $object == NULL)
+ return $this;
+
+ switch($this->indexed){
+ case 1:
+ if($subject!=NULL && $predicate != NULL && $object != NULL){
+ $pos=$subject->getLabel().$predicate->getLabel().$object->getLabel();
+ return $this->_findInIndex($pos,$subject,$predicate,$object,1);
+ }else{
+ break;
+ }
+
+ case 2:
+ if($subject!=NULL && $predicate != NULL){
+ $pos=$subject->getLabel().$predicate->getLabel();
+ return $this->_findInIndex($pos,$subject,$predicate,$object,2);
+ }else{
+ break;
+ }
+
+ case 3:
+ if($subject!=NULL && $object != NULL){
+ $pos=$subject->getLabel().$object->getLabel();
+ return $this->_findInIndex($pos,$subject,$predicate,$object,3);
+ }else{
+ break;
+ }
+ case 0:
+ if($subject!= null){
+ $pos=$subject->getLabel();
+ return $this->_findInIndex($pos,$subject,$predicate,$object,4);
+ }
+ if($predicate!= null){
+ $pos=$predicate->getLabel();
+ return $this->_findInIndex($pos,$subject,$predicate,$object,5);
+ }
+ if($object!= null){
+ $pos=$object->getLabel();
+ return $this->_findInIndex($pos,$subject,$predicate,$object,6);
+ }
+ }
+ // if no index: linear search
+ foreach($this->triples as $value) {
+ if ($this->matchStatement($value, $subject, $predicate, $object))
+ $res->add($value);
+ }
+ return $res;
+
+ }
+
+
+
+
+
+ /**
+ * Method to search for triples using Perl-style regular expressions.
+ * NULL input for any parameter will match anything.
+ * Example: $result = $m->find_regex( NULL, NULL, $regex );
+ * Finds all triples where the label of the object node matches the regular expression.
+ * Returns an empty MemModel if nothing is found.
+ *
+ * @param string $subject_regex
+ * @param string $predicate_regex
+ * @param string $object_regex
+ * @return object MemModel
+ * @access public
+ */
+ function findRegex($subject_regex, $predicate_regex, $object_regex) {
+
+ $res = new MemModel($this->getBaseURI());
+
+ if($this->size() == 0)
+ return $res;
+
+ if($subject_regex == NULL && $predicate_regex == NULL && $object_regex == NULL)
+ return $this;
+
+ foreach($this->triples as $value) {
+ if (
+ ($subject_regex == NULL || preg_match($subject_regex, $value->subj->getLabel())) &&
+ ($predicate_regex == NULL || preg_match($predicate_regex, $value->pred->getLabel())) &&
+ ($object_regex == NULL || preg_match($object_regex, $value->obj->getLabel()))
+ ) $res->add($value);
+ }
+
+ return $res;
+
+ }
+
+ /**
+ * Returns all tripels of a certain vocabulary.
+ * $vocabulary is the namespace of the vocabulary inluding a # : / char at the end.
+ * e.g. http://www.w3.org/2000/01/rdf-schema#
+ * Returns an empty MemModel if nothing is found.
+ *
+ * @param string $vocabulary
+ * @return object MemModel
+ * @access public
+ */
+ function findVocabulary($vocabulary) {
+
+ if($this->size() == 0)
+ return new MemModel();
+ if($vocabulary == NULL || $vocabulary == '')
+ return $this;
+
+ $res = new MemModel($this->getBaseURI());
+ if($this->indexed==0){
+ foreach($this->indexArr[5] as $key => $value){
+ $pos=strpos($key,'#')+1;
+ if(substr($key,0,$pos)==$vocabulary){
+ for($i=1;$i<=$value[0];$i++){
+ $res->add($this->triples[$value[$i]]);
+ }
+ }
+ }
+ return $res;
+ }else{
+ // Import Package Utility
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_UTILITY);
+ foreach($this->triples as $value) {
+ if (RDFUtil::getNamespace($value->getPredicate()) == $vocabulary)
+ $res->add($value);
+ }
+ return $res;
+ }
+ }
+
+ /**
+ * Searches for triples and returns the first matching statement.
+ * NULL input for any parameter will match anything.
+ * Example: $result = $m->findFirstMatchingStatement( NULL, NULL, $node );
+ * Returns the first statement of the MemModel where the object equals $node.
+ * Returns an NULL if nothing is found.
+ * You can define an offset to search for. Default = 0
+ *
+ * @param object Node $subject
+ * @param object Node $predicate
+ * @param object Node $object
+ * @param integer $offset
+ * @return object Statement
+ * @access public
+ */
+ function findFirstMatchingStatement($subject, $predicate, $object, $offset = 0) {
+
+ $currentOffset = 0;
+ for($i=0;$i<=$offset;$i++)
+ {
+ $res = $this->findFirstMatchOff($subject, $predicate, $object, $currentOffset);
+ $currentOffset=$res+1;
+ }
+ if ($res != -1) {
+ return $this->triples[$res];
+ } else {
+ return NULL;
+ }
+ }
+
+
+
+
+ /**
+ * Searches for triples and returns the first matching statement from a given offset.
+ * This method is used by the util/findIterator. NULL input for any parameter will match anything.
+ * Example: $result = $m->findFirstMatchingStatement( NULL, NULL, $node, $off );
+ * Returns the position of the first statement of the MemModel where the object equals $node from the given
+ * offset.
+ * Returns an -1 if nothing is found.
+ *
+ * @param object Node $subject
+ * @param object Node $predicate
+ * @param object Node $object
+ * @param int $off
+ * @return int
+ * @access private
+ */
+ function findFirstMatchOff($subject,$predicate, $object,$off) {
+
+ if (
+ (!is_a($subject, 'Resource') && $subject != NULL) ||
+ (!is_a($predicate, 'Resource') && $predicate != NULL) ||
+ (!is_a($object, 'Node') && $object != NULL)
+ ) {
+ $errmsg = RDFAPI_ERROR . '(class: MemModel; method: find): Parameters must be subclasses of Node or NULL';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ $match=-1;
+ $ind=$this->indexed;
+ if($subject == NULL && $predicate == NULL && $object == NULL)
+ {
+ foreach ($this->triples as $key => $statement)
+ {
+ if ($key >= $off)
+ return $key;
+ }
+ return -1;
+ }
+
+ switch($ind){
+ case 1:
+ if($subject!=NULL && $predicate != NULL && $object != NULL){
+ $pos=$subject->getLabel().$predicate->getLabel().$object->getLabel();
+ return $this->_findMatchIndex($pos,$subject,$predicate,$object,1,$off);
+ }else{
+ break;
+ }
+
+ case 2:
+ if($subject!=NULL && $predicate != NULL){
+ $pos=$subject->getLabel().$predicate->getLabel();
+ return $this->_findMatchIndex($pos,$subject,$predicate,$object,2,$off);
+ }else{
+ break;
+ }
+
+ case 3:
+ if($subject!=NULL && $object != NULL){
+ $pos=$subject->getLabel().$object->getLabel();
+ return $this->_findMatchIndex($pos,$subject,$predicate,$object,3,$off);
+ }else{
+ break;
+ }
+ case 0:
+ if($subject!= null){
+ $pos=$subject->getLabel();
+ return $this->_findMatchIndex($pos,$subject,$predicate,$object,4,$off);
+ }
+ if($predicate!= null){
+ $pos=$predicate->getLabel();
+ return $this->_findMatchIndex($pos,$subject,$predicate,$object,5,$off);
+ }
+ if($object!= null){
+ $pos=$object->getLabel();
+ return $this->_findMatchIndex($pos,$subject,$predicate,$object,6,$off);
+ }
+ break;
+ }
+ // if no index: linear search
+ foreach($this->triples as $key => $value){
+ if ($this->matchStatement($value, $subject, $predicate, $object)){
+ if($off<=$key){
+ $match=$key;
+ break;
+ }
+ }
+ }
+ return $match;
+ }
+
+
+ /**
+ * Searches for triples and returns the number of matches.
+ * NULL input for any parameter will match anything.
+ * Example: $result = $m->findCount( NULL, NULL, $node );
+ * Finds all triples with $node as object.
+ *
+ * @param object Node $subject
+ * @param object Node $predicate
+ * @param object Node $object
+ * @return integer
+ * @access public
+ */
+ function findCount($subject, $predicate, $object) {
+
+ $res = $this->find($subject, $predicate, $object);
+ return $res->size();
+
+ }
+
+
+ /**
+ * Perform an RDQL query on this MemModel.
+ * This method returns an associative array of variable bindings.
+ * The values of the query variables can either be RAP's objects (instances of Node)
+ * if $returnNodes set to TRUE, or their string serialization.
+ *
+ * @access public
+ * @param string $queryString
+ * @param boolean $returnNodes
+ * @return array [][?VARNAME] = object Node (if $returnNodes = TRUE)
+ * OR array [][?VARNAME] = string
+ *
+ */
+ function rdqlQuery($queryString, $returnNodes = TRUE) {
+
+ // Import RDQL Package
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_RDQL);
+
+ $parser = new RdqlParser();
+ $parsedQuery =& $parser->parseQuery($queryString);
+
+ // this method can only query this MemModel
+ // if another model was specified in the from clause throw an error
+ if (isset($parsedQuery['sources'][1])) {
+ $errmsg = RDFAPI_ERROR . '(class: MemModel; method: rdqlQuery):';
+ $errmsg .= ' this method can only query this MemModel';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ $engine = new RdqlMemEngine();
+ $res =& $engine->queryModel($this, $parsedQuery, $returnNodes);
+
+ return $res;
+ }
+
+ /**
+ * Perform an RDQL query on this MemModel.
+ * This method returns an RdqlResultIterator of variable bindings.
+ * The values of the query variables can either be RAP's objects (instances of Node)
+ * if $returnNodes set to TRUE, or their string serialization.
+ *
+ * @access public
+ * @param string $queryString
+ * @param boolean $returnNodes
+ * @return object RdqlResultIterator = with values as object Node (if $returnNodes = TRUE)
+ * OR object RdqlResultIterator = with values as strings if (if $returnNodes = FALSE)
+ *
+ */
+ function rdqlQueryAsIterator($queryString, $returnNodes = TRUE) {
+ // Import RDQL Package
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_RDQL);
+ return new RdqlResultIterator($this->rdqlQuery($queryString, $returnNodes));
+ }
+
+ /**
+ * General method to replace nodes of a MemModel.
+ * NULL input for any parameter will match nothing.
+ * Example: $m->replace($node, NULL, $node, $replacement);
+ * Replaces all $node objects beeing subject or object in
+ * any triple of the MemModel with the $needle node.
+ *
+ * @param object Node $subject
+ * @param object Node $predicate
+ * @param object Node $object
+ * @param object Node $replacement
+ * @access public
+ * @throws PhpError
+ */
+ function replace($subject, $predicate, $object, $replacement) {
+
+ if (
+ (!is_a($replacement, 'Node')) ||
+ (!is_a($subject, 'Resource') && $subject != NULL) ||
+ (!is_a($predicate, 'Resource') && $predicate != NULL) ||
+ (!is_a($object, 'Node') && $object != NULL)
+ ) {
+ $errmsg = RDFAPI_ERROR . '(class: MemModel; method: replace): Parameters must be subclasses of Node or NULL';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ if($this->size() == 0)
+ break;
+ foreach($this->triples as $key => $value) {
+ if ($this->triples[$key]->subj->equals($subject)) {
+ $this->triples[$key]->subj = $replacement;
+ }
+ if ($this->triples[$key]->pred->equals($predicate))
+ $this->triples[$key]->pred = $replacement;
+ if ($this->triples[$key]->obj->equals($object))
+ $this->triples[$key]->obj = $replacement;
+
+ }
+ $this->index($this->indexed);
+ }
+
+
+ /**
+ * Internal method that checks, if a statement matches a S, P, O or NULL combination.
+ * NULL input for any parameter will match anything.
+ *
+ * @param object Statement $statement
+ * @param object Node $subject
+ * @param object Node $predicate
+ * @param object Node $object
+ * @return boolean
+ * @access private
+ */
+ function matchStatement($statement, $subject, $predicate, $object) {
+
+ if(($subject != NULL) AND !($statement->subj->equals($subject)))
+ return false;
+
+ if($predicate != NULL && !($statement->pred->equals($predicate)))
+ return false;
+
+ if($object != NULL && !($statement->obj->equals($object)))
+ return false;
+
+ return true;
+ }
+
+
+
+
+ /**
+ * Checks if two models are equal.
+ * Two models are equal if and only if the two RDF graphs they represent are isomorphic.
+ *
+ * @access public
+ * @param object model &$that
+ * @throws phpErrpr
+ * @return boolean
+ */
+
+ function equals(&$that) {
+
+ if (!is_a($that, 'Model')) {
+ $errmsg = RDFAPI_ERROR . '(class: MemModel; method: equals): Model expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ if ($this->size() != $that->size())
+ return FALSE;
+ /*
+ if (!$this->containsAll($that))
+ return FALSE;
+ return TRUE;
+ */
+ include_once(RDFAPI_INCLUDE_DIR. "util/ModelComparator.php");
+ return ModelComparator::compare($this,$that);
+ }
+
+ /**
+ * Returns a new MemModel that is the set-union of the MemModel with another model.
+ * Duplicate statements are removed. If you want to allow duplicates, use addModel() which is much faster.
+ *
+ * The result of taking the set-union of two or more RDF graphs (i.e. sets of triples)
+ * is another graph, which we will call the merge of the graphs.
+ * Each of the original graphs is a subgraph of the merged graph. Notice that when forming
+ * a merged graph, two occurrences of a given uriref or literal as nodes in two different
+ * graphs become a single node in the union graph (since by definition they are the same
+ * uriref or literal) but blank nodes are not 'merged' in this way; and arcs are of course
+ * never merged. In particular, this means that every blank node in a merged graph can be
+ * identified as coming from one particular graph in the original set of graphs.
+ *
+ * Notice that one does not, in general, obtain the merge of a set of graphs by concatenating
+ * their corresponding N-triples documents and constructing the graph described by the merged
+ * document, since if some of the documents use the same node identifiers, the merged document
+ * will describe a graph in which some of the blank nodes have been 'accidentally' merged.
+ * To merge Ntriples documents it is necessary to check if the same nodeID is used in two or
+ * more documents, and to replace it with a distinct nodeID in each of them, before merging the
+ * documents. (Not implemented yet !!!!!!!!!!!)
+ *
+ * @param object Model $model
+ * @return object MemModel
+ * @access public
+ * @throws phpErrpr
+ *
+ */
+ function & unite(&$model) {
+
+ if (!is_a($model, 'Model')) {
+ $errmsg = RDFAPI_ERROR . '(class: MemModel; method: unite): Model expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ $res = $this;
+
+ if (is_a($model, 'MemModel')) {
+ require_once RDFAPI_INCLUDE_DIR . 'util/StatementIterator.php';
+ $stateIt=new StatementIterator($model);
+ while($statement=$stateIt->next())
+ {
+ $res->addWithoutDuplicates($statement);
+ }
+ }
+
+ elseif (is_a($model, 'DbModel')) {
+ $memModel =& $model->getMemModel();
+ foreach($memModel->triples as $value)
+ $res->addWithoutDuplicates($value);
+ }
+
+ return $res;
+ }
+
+ /**
+ * Returns a new MemModel that is the subtraction of another model from this MemModel.
+ *
+ * @param object Model $model
+ * @return object MemModel
+ * @access public
+ * @throws phpErrpr
+ */
+
+ function & subtract(&$model) {
+
+ if (!is_a($model, 'Model')) {
+ $errmsg = RDFAPI_ERROR . '(class: MemModel; method: subtract): Model expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ $res = $this;
+
+
+ if (is_a($model, 'MemModel'))
+ {
+ require_once RDFAPI_INCLUDE_DIR . 'util/StatementIterator.php';
+ $stateIt=new StatementIterator($model);
+ while($statement=$stateIt->next())
+ {
+ $res->remove($statement);
+ }
+ }
+ elseif (is_a($model, 'DbModel'))
+ {
+ $memModel =& $model->getMemModel();
+ foreach($memModel->triples as $value)
+ $res->remove($value);
+ }
+
+
+ return $res;
+ }
+
+ /**
+ * Returns a new MemModel containing all the statements which are in both this MemModel and another.
+ *
+ * @param object Model $model
+ * @return object MemModel
+ * @access public
+ * @throws phpErrpr
+ */
+ function & intersect(&$model) {
+
+ if (!is_a($model, 'Model')) {
+ $errmsg = RDFAPI_ERROR . '(class: MemModel; method: intersect: Model expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ $res = new MemModel($this->getBaseURI());
+
+ if (is_a($model, 'DbModel') || is_a($model, 'RDFSBModel'))
+ {
+ $memModel =& $model->getMemModel();
+ foreach($memModel->triples as $value) {
+ if ($this->contains($value))
+ $res->add($value);
+ }
+ }
+
+ elseif (is_a($model, 'MemModel'))
+ {
+ foreach($model->triples as $value) {
+ if ($this->contains($value))
+ $res->add($value);
+ }
+ }
+
+
+
+ return $res;
+ }
+
+
+ /**
+ * Adds another model to this MemModel.
+ * Duplicate statements are not removed.
+ * If you don't want duplicates, use unite().
+ * If any statement of the model to be added to this model contains a blankNode
+ * with an identifier already existing in this model, a new blankNode is generated.
+ *
+ * @param object Model $model
+ * @access public
+ * @throws phpErrpr
+ *
+ */
+ function addModel(&$model) {
+
+ if (!is_a($model, 'Model')) {
+ $errmsg = RDFAPI_ERROR . '(class: MemModel; method: addModel): Model expected.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ $blankNodes_tmp = array();
+
+ if (is_a($model, 'MemModel')) {
+ require_once RDFAPI_INCLUDE_DIR . 'util/StatementIterator.php';
+ $stateIt=new StatementIterator($model);
+ while($statement=$stateIt->next())
+ {
+ $this->_addStatementFromAnotherModel($statement, $blankNodes_tmp);
+ };
+ $this->addParsedNamespaces($model->getParsedNamespaces());
+ }
+
+ elseif (is_a($model, 'DbModel')) {
+ $memModel =& $model->getMemModel();
+ foreach($memModel->triples as $value)
+ $this->_addStatementFromAnotherModel($value, $blankNodes_tmp);
+ }
+ $this->index($this->indexed);
+ }
+
+
+ /**
+ * Reifies the MemModel.
+ * Returns a new MemModel that contains the reifications of all statements of this MemModel.
+ *
+ * @access public
+ * @return object MemModel
+ */
+ function & reify() {
+ $res = new MemModel($this->getBaseURI());
+
+ $stateIt=$this->getStatementIterator();
+ while($statement=$stateIt->next())
+ {
+ $pointer =& $statement->reify($res);
+ $res->addModel($pointer);
+ };
+
+ return $res;
+ }
+
+ /**
+ * Returns a StatementIterator for traversing the MemModel.
+ * @access public
+ * @return object StatementIterator
+ */
+ function & getStatementIterator() {
+ // Import Package Utility
+ require_once RDFAPI_INCLUDE_DIR . 'util/StatementIterator.php';
+
+ $si = new StatementIterator($this);
+ return $si;
+ }
+
+ /**
+ * Returns a FindIterator for traversing the MemModel.
+ * @access public
+ * @return object FindIterator
+ */
+ function & findAsIterator($sub=null,$pred=null,$obj=null) {
+ // Import Package Utility
+ require_once RDFAPI_INCLUDE_DIR . 'util/FindIterator.php';
+
+ $if = new FindIterator($this,$sub,$pred,$obj);
+ return $if;
+ }
+
+ /**
+ * Returns a FindIterator for traversing the MemModel.
+ * @access public
+ * @return object FindIterator
+ */
+ function & iterFind($sub=null,$pred=null,$obj=null) {
+ // Import Package Utility
+ require_once RDFAPI_INCLUDE_DIR . 'util/IterFind.php';
+
+ $if = new IterFind($this,$sub,$pred,$obj);
+ return $if;
+ }
+
+
+ /**
+ * Returns the models namespaces.
+ *
+ * @author Tobias Gau�
+ * @access public
+ * @return Array
+ */
+ function getParsedNamespaces(){
+ if(count($this->parsedNamespaces)!=0){
+ return $this->parsedNamespaces;
+ }else{
+ return false;
+ }
+ }
+
+
+
+ /**
+ * Adds the namespaces to the model. This method is called by
+ * the parser. !!!! addParsedNamespaces() not overwrites manual
+ * added namespaces in the model !!!!
+ *
+ * @author Tobias Gau�
+ * @access public
+ * @param Array $newNs
+ */
+ function addParsedNamespaces($newNs){
+ if($newNs)
+ $this->parsedNamespaces = $this->parsedNamespaces + $newNs;
+ }
+
+
+ /**
+ * Adds a namespace and prefix to the model.
+ *
+ * @author Tobias Gau�
+ * @access public
+ * @param String
+ * @param String
+ */
+ function addNamespace($prefix, $nmsp){
+ $this->parsedNamespaces[$nmsp]=$prefix;
+ }
+
+ /**
+ * removes a single namespace from the model
+ *
+ * @author Tobias Gau�
+ * @access public
+ * @param String $nmsp
+ */
+ function removeNamespace($nmsp){
+ if(isset($this->parsedNamespaces[$nmsp])){
+ unset($this->parsedNamespaces[$nmsp]);
+ return true;
+ }else{
+ return false;
+ }
+ }
+
+
+
+ /**
+ * Close the MemModel and free up resources held.
+ *
+ * @access public
+ */
+ function close() {
+ unset( $this->baseURI );
+ unset( $this->triples );
+ }
+
+ // =============================================================================
+ // *************************** helper functions ********************************
+ // =============================================================================
+ /**
+ * Checks if $statement is in index
+ *
+ * @param int $ind
+ * @param Statement &$statement
+ * @return boolean
+ * @access private
+ */
+ function _containsIndex(&$statement,$ind){
+ switch($ind){
+ case 4:
+ $sub=$statement->getSubject();
+ $pos=$sub->getLabel();
+ break;
+ case 1:
+ $sub=$statement->getSubject();
+ $pred=$statement->getPredicate();
+ $obj=$statement->getObject();
+ $pos=$sub->getLabel().$pred->getLabel().$obj->getLabel();
+ break;
+ case 2:
+ $sub=$statement->getSubject();
+ $pred=$statement->getPredicate();
+ $pos=$sub->getLabel().$pred->getLabel();
+ break;
+ case 3:
+ $sub=$statement->getSubject();
+ $obj=$statement->getObject();
+ $pos=$sub->getLabel().$obj->getLabel();
+ break;
+ }
+
+ if (!isset($this->indexArr[$ind][$pos]))
+ return FALSE;
+ foreach ($this->indexArr[$ind][$pos] as $key => $value) {
+ $t=$this->triples[$value];
+ if ($t->equals($statement))
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+
+
+
+
+ /**
+ * finds a statement in an index. $pos is the Position in the index
+ * and $ind the adequate searchindex
+ *
+ * @param String $pos
+ * @param Object Subject &$subject
+ * @param Object Predicate &$predicate
+ * @param Object Object &$object
+ * @param int &ind
+ * @return MemModel $res
+ * @access private
+ */
+ function _findInIndex($pos,&$subject,&$predicate,&$object,$ind){
+ $res = new MemModel($this->getBaseURI());
+ $res->indexed=-1;
+ if (!isset($this->indexArr[$ind][$pos]))
+ return $res;
+ foreach($this->indexArr[$ind][$pos] as $key =>$value){
+ $t=$this->triples[$value];
+ if ($this->matchStatement($t,$subject,$predicate,$object))
+ $res->add($t);
+ }
+ return $res;
+ }
+ /**
+ * adds/removes a statement into/from an index.
+ * mode=0 removes the statement from the index;
+ * mode=1 adds the statement into the index.
+ * returns the statements position.
+ *
+ * @param Object Statement &$statement
+ * @param int $k
+ * @param int $ind
+ * @param int $mode
+ * @return int $k
+ * @access private
+ */
+ function _indexOpr(&$statement,$k,$ind,$mode){
+ // determine position in adequate index
+ switch($ind){
+ case 1:
+ $s=$statement->getSubject();
+ $p=$statement->getPredicate();
+ $o=$statement->getObject();
+ $pos=$s->getLabel().$p->getLabel().$o->getLabel();
+ break;
+ case 2:
+ $s=$statement->getSubject();
+ $p=$statement->getPredicate();
+ $pos=$s->getLabel().$p->getLabel();
+ break;
+ case 3:
+ $s=$statement->getSubject();
+ $o=$statement->getObject();
+ $pos=$s->getLabel().$o->getLabel();
+ break;
+ case 4:
+ $s=$statement->getSubject();
+ $pos=$s->getLabel();
+ break;
+ case 5:
+ $p=$statement->getPredicate();
+ $pos=$p->getLabel();
+ break;
+ case 6:
+ $o=$statement->getObject();
+ $pos=$o->getLabel();
+ break;
+ }
+ switch($mode){
+ // add in Index
+ case 1:
+ if(isset($this->indexArr[$ind][$pos])){
+ $this->indexArr[$ind][$pos][] = $k;
+ }else{
+ $this->indexArr[$ind][$pos][0] = $k;
+ }
+ break;
+ // remove from Index
+ case 0:
+ $subject=$statement->getSubject();
+ $predicate=$statement->getPredicate();
+ $object=$statement->getObject();
+ $k=-1;
+ if(!isset($this->indexArr[$ind][$pos])){
+ return -1;
+ }
+ $num=count($this->indexArr[$ind][$pos]);
+ foreach($this->indexArr[$ind][$pos] as $key => $value){
+ $t=$this->triples[$value];
+ if($this->matchStatement($t,$subject,$predicate,$object)){
+ $k=$value;
+ if($num==1){
+ unset($this->indexArr[$ind][$pos]);
+ }else{
+ unset($this->indexArr[$ind][$pos][$key]);
+ }
+ return $k;
+ }
+ }
+ break;
+ }
+ return $k;
+ }
+
+
+ /**
+ * finds next or previous matching statement.
+ * Returns Position in model or -1 if there is no match.
+ *
+ *
+ * @param String
+ * @param object Subject
+ * @param object Predicate
+ * @param object Object
+ * @param integer
+ * @param integer
+ * @return integer
+ * @access private
+ */
+ function _findMatchIndex($pos,&$s,&$p,&$o,$ind,$off){
+ $match=-1;
+ if (!isset($this->indexArr[$ind][$pos])) {
+ return $match;}
+ foreach($this->indexArr[$ind][$pos] as $key =>$value){
+ $t=$this->triples[$value];
+ if ($this->matchStatement($t,$s,$p,$o)){
+ if($off <= $value){
+ $match= $value;
+ return $match;
+ }
+ }
+ }
+
+ return $match;
+
+ }
+
+
+
+
+} // end: MemModel
+
+
+?>
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/Model.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/Model.php
new file mode 100755
index 00000000..1c086b54
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/Model.php
@@ -0,0 +1,566 @@
+ triples, where P is a uriref, S is either
+ * a uriref or a blank node, and O is either a uriref, a blank node, or a literal.
+ *
+ *
+ * @version $Id: Model.php 551 2007-11-22 19:58:35Z p_frischmuth $
+ * @author Radoslaw Oldakowski
+ * @author Daniel Westphal
+ *
+ * @package model
+ * @access public
+ */
+class Model extends Object
+{
+ /**
+ * Base URI of the Model.
+ * Affects creating of new resources and serialization syntax.
+ *
+ * @var string
+ * @access private
+ */
+ var $baseURI;
+
+ /**
+ * Number of the last assigned bNode.
+ *
+ * @var integer
+ * @access private
+ */
+ var $bNodeCount;
+
+ /**
+ * SparqlParser so we can re-use it
+ * @var Parser
+ */
+ var $queryParser = null;
+
+
+
+ /**
+ * Notice for people who are used to work with older versions of RAP.
+ *
+ * @throws PHPError
+ * @access public
+ */
+ function Model()
+ {
+
+ $errmsg = 'Since RAP 0.6 the class for manipulating memory models has been renamed to MemModel.';
+ $errmsg .= '
Sorry for this inconvenience.
';
+
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+
+
+ /**
+ * Return current baseURI.
+ *
+ * @return string
+ * @access public
+ */
+ function getBaseURI()
+ {
+ return $this->baseURI;
+ }
+
+
+
+ /**
+ * Load a model from a file containing RDF, N3, N-Triples or a xhtml document containing RDF.
+ * This function recognizes the suffix of the filename (.n3 or .rdf) and
+ * calls a suitable parser, if no $type is given as string ("rdf" "n3" "nt");
+ * If the model is not empty, the contents of the file is added to this DbModel.
+ *
+ * @param string $filename
+ * @param string $type
+ * @param boolean $stream
+ * @access public
+ */
+ function load($filename, $type = NULL, $stream=false)
+ {
+ if ((isset($type)) && ($type =='n3') OR ($type =='nt')) {
+ // Import Package Syntax
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_N3);
+ $parser = new N3Parser();
+ }elseif ((isset($type)) && ($type =='rdf')) {
+ // Import Package Syntax
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_RDF);
+ $parser = new RdfParser();
+ }elseif ((isset($type)) && ($type =='grddl')) {
+ // Import Package Syntax
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_GRDDL);
+ $parser = new GRDDLParser();
+ }elseif ((isset($type)) && ($type =='rss')) {
+ // Import Package Syntax
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_RSS);
+ $parser = new RssParser();
+ }else {
+ // create a parser according to the suffix of the filename
+ // if there is no suffix assume the file to be XML/RDF
+ preg_match("/\.([a-zA-Z0-9_]+)$/", $filename, $suffix);
+ if (isset($suffix[1]) && (strtolower($suffix[1]) == 'n3' OR strtolower($suffix[1]) == 'nt')){
+ // Import Package Syntax
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_N3);
+ $parser = new N3Parser();
+ }elseif (isset($suffix[1]) && (strtolower($suffix[1]) == 'htm' OR strtolower($suffix[1]) == 'html' OR strtolower($suffix[1]) == 'xhtml')){
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_GRDDL);
+ $parser = new GRDDLParser();
+ }else{
+ // Import Package Syntax
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_RDF);
+ $parser = new RdfParser();
+ }
+ };
+
+ if (($stream && $type=='rdf')||($stream && $type=='n3')) {
+ $temp=&$parser->generateModel($filename,false,$this);
+ } else{
+ $temp=&$parser->generateModel($filename);
+ }
+ $this->addModel($temp);
+ if($this->getBaseURI()== null)
+ $this->setBaseURI($temp->getBaseURI());
+ }
+
+ /**
+ * This method takes a string conatining data and adds the parsed data to this model.
+ *
+ * @param string $str The string containing the data to be parsed and loaded.
+ * @param type $type The type of the string, currently only 'json' is supported.
+ */
+ function loadFromString($str, $type) {
+
+ switch ($type) {
+ case 'json':
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_JSON);
+ $parser = new JsonParser();
+ break;
+ case 'n3':
+ case 'nt':
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_N3);
+ $parser = new N3Parser();
+ break;
+ case 'rdf':
+ case 'rdfxml':
+ case 'xml':
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_RDF);
+ $parser = new RdfParser();
+ break;
+ case 'grddl':
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_GRDDL);
+ $parser = new GRDDLParser();
+ break;
+ case 'rss':
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_RSS);
+ $parser = new RssParser();
+ break;
+ default:
+ trigger_error('(class: Model; method: loadFromString): type ' . $type . 'is currently not supported',
+ E_USER_ERROR);
+ }
+
+ if ($parser instanceof JsonParser) {
+ $parser->generateModelFromString($str, $this);
+ } else {
+ $parser->generateModel($str, false, $this);
+ }
+ }
+
+ /**
+ * Adds a statement from another model to this model.
+ * If the statement to be added contains a blankNode with an identifier
+ * already existing in this model, a new blankNode is generated.
+ *
+ * @param Object Statement $statement
+ * @access private
+ */
+ function _addStatementFromAnotherModel($statement, &$blankNodes_tmp)
+ {
+ $subject = $statement->getSubject();
+ $object = $statement->getObject();
+
+ if (is_a($subject, "BlankNode")) {
+ $label = $subject->getLabel();
+ if (!array_key_exists($label, $blankNodes_tmp))
+ {
+ if ($this->findFirstMatchingStatement($subject, NULL, NULL)
+ || $this->findFirstMatchingStatement(NULL, NULL, $subject))
+ {
+ $blankNodes_tmp[$label] = new BlankNode($this);
+ $statement->subj = $blankNodes_tmp[$label];
+ } else {
+ $blankNodes_tmp[$label] = $subject;
+ }
+ } else
+ $statement->subj = $blankNodes_tmp[$label];
+ }
+
+ if (is_a($object, "BlankNode")) {
+ $label = $object->getLabel();
+ if (!array_key_exists($label, $blankNodes_tmp))
+ {
+ if ($this->findFirstMatchingStatement($object, NULL, NULL)
+ || $this->findFirstMatchingStatement(NULL, NULL, $object))
+ {
+ $blankNodes_tmp[$label] = new BlankNode($this);
+ $statement->obj = $blankNodes_tmp[$label];
+ } else {
+ $blankNodes_tmp[$label] = $object;
+ }
+ } else
+ $statement->obj = $blankNodes_tmp[$label];
+ }
+ $this->add($statement);
+ }
+
+
+
+ /**
+ * Internal method, that returns a resource URI that is unique for the Model.
+ * URIs are generated using the base_uri of the DbModel, the prefix and a unique number.
+ * If no prefix is defined, the bNode prefix, defined in constants.php, is used.
+ *
+ * @param string $prefix
+ * @return string
+ * @access private
+ */
+ function getUniqueResourceURI($prefix = false)
+ {
+ static $bNodeCount;
+ if(!$bNodeCount)
+ $bNodeCount = 0;
+
+ if(!$prefix)
+ $prefix=BNODE_PREFIX;
+
+ return $prefix.++$bNodeCount;
+ }
+
+
+
+ /**
+ * Returns a ResModel with this model as baseModel. This is the same as
+ * ModelFactory::getResModelForBaseModel($this).
+ *
+ * @return object ResModel
+ * @access public
+ */
+ function & getResModel()
+ {
+ return ModelFactory::getResModelForBaseModel($this);
+ }
+
+
+
+ /**
+ * Returns an OntModel with this model as baseModel.
+ * $vocabulary has to be one of the following constants (currently only one is supported):
+ * RDFS_VOCABULARY to select a RDFS Vocabulary.
+ *
+ * This is the same as ModelFactory::getOntModelForBaseModel($this, $vocabulary).
+ *
+ * @param constant $vocabulary
+ * @return object OntModel
+ * @access public
+ */
+ function & getOntModel($vocabulary)
+ {
+ return ModelFactory::getOntModelForBaseModel($this, $vocabulary);
+ }
+
+
+
+ /**
+ * Searches for triples using find() and tracks forward blank nodes
+ * until the final objects in the retrieved subgraphs are all named resources.
+ * The method calls itself recursivly until the result is complete.
+ * NULL input for subject, predicate or object will match anything.
+ * Inputparameters are ignored for recursivly found statements.
+ * Returns a new MemModel or adds (without checking for duplicates)
+ * the found statements to a given MemModel.
+ * Returns an empty MemModel, if nothing is found.
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * WARNING: This method can be slow with large models.
+ * NOTE: Blank nodes are not renamed, they keep the same nodeIDs
+ * as in the queried model!
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ *
+ * @author Anton Koestlbacher
+ * @param object Node $subject
+ * @param object Node $predicate
+ * @param object Node $object
+ * @param object MemModel $object
+ * @return object MemModel
+ * @access public
+ * @throws PhpError
+ */
+ function findForward($subject, $predicate, $object, &$newModel = NULL)
+ {
+ if (!is_a($newModel, "MemModel"))
+ {
+ $newModel = New MemModel;
+ }
+
+ if (is_a($this, "DbModel"))
+ {
+ $model = $this;
+ $res = $model->find($subject, $predicate, $object);
+ $it = $res->getStatementIterator();
+ }
+ elseif (is_a($this, "MemModel")) {
+ $model = $this;
+ $it = $model->findAsIterator($subject, $predicate, $object);
+ }
+ elseif (is_a($this, "ResModel")) {
+ $model = $this->model;
+ $it = $model->findAsIterator($subject, $predicate, $object);
+ }
+
+ while ($it->hasNext())
+ {
+ $statement = $it->next();
+ $newModel->add($statement);
+ if (is_a($statement->object(),'BlankNode'))
+ {
+ $model->findForward($statement->object(), NULL, NULL, $newModel);
+ }
+ }
+ return $newModel;
+ }
+
+
+
+ /**
+ * Perform an RDQL query on this Model. Should work with all types of models.
+ * This method returns a MemModel containing the result statements.
+ * If $closure is set to TRUE, the result will additionally contain
+ * statements found by the findForward-method for blank nodes.
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * WARNING: If called with $closure = TRUE this method
+ * can be slow with large models.
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ *
+ * @author Anton K�tlbacher
+ * @author code snippets taken from the RAP Netapi by Phil Dawes and Chris Bizer
+ * @access public
+ * @param string $queryString
+ * @param boolean $closure
+ * @return object MemModel
+ *
+ */
+ function & getMemModelByRDQL($queryString, $closure = FALSE)
+ {
+ require_once(RDFAPI_INCLUDE_DIR.PACKAGE_RDQL);
+ $parser = new RdqlParser();
+ $parsedQuery =& $parser->parseQuery($queryString);
+
+ // If there are variables used in the pattern but not
+ // in the select clause, add them to the select clause
+ foreach ($parsedQuery['patterns'] as $n => $pattern)
+ {
+ foreach ($pattern as $key => $val_1)
+ {
+ if ($val_1['value']{0}=='?')
+ {
+ if (!in_array($val_1['value'],$parsedQuery['selectVars']))
+ {
+ array_push($parsedQuery['selectVars'],$val_1['value']);
+ }
+ }
+ }
+ }
+
+ if (is_a($this, "DbModel"))
+ {
+ $engine = new RdqlDbEngine();
+ $model = $this;
+ }
+ elseif (is_a($this, "MemModel"))
+ {
+ $engine = new RdqlMemEngine();
+ $model = $this;
+ }
+ elseif (is_a($this, "ResModel"))
+ {
+ $engine = new RdqlMemEngine();
+ $model = $this->model;
+ }
+
+ $res = $engine->queryModel($model,$parsedQuery,TRUE);
+ $rdqlIter = new RdqlResultIterator($res);
+ $newModel = new MemModel();
+
+ // Build statements from RdqlResultIterator
+ while ($rdqlIter->hasNext()) {
+ $result = $rdqlIter->next();
+ foreach ($parsedQuery['patterns'] as $n => $pattern)
+ {
+ if (substr($pattern['subject']['value'], 0, 1) == '?')
+ {
+ $subj = $result[$pattern['subject']['value']];
+ }
+ else
+ {
+ $subj = new Resource($pattern['subject']['value']);
+ }
+ if (substr($pattern['predicate']['value'], 0, 1) == '?')
+ {
+ $pred = $result[$pattern['predicate']['value']];
+ }
+ else
+ {
+ $pred = new Resource($pattern['predicate']['value']);
+ }
+
+ if (substr($pattern['object']['value'], 0, 1) == '?')
+ {
+ $obj = $result[$pattern['object']['value']];
+ }
+ else
+ {
+ if (isset($pattern['object']['is_literal']))
+ {
+ $obj = new Literal($pattern['object']['value']);
+ $obj->setDatatype($pattern['object']['l_dtype']);
+ $obj->setLanguage($pattern['object']['l_lang']);
+ }
+ else
+ {
+ $obj = new Resource($pattern['object']['value']);
+ }
+ }
+
+ $statement = new Statement($subj,$pred,$obj);
+ $newModel->add($statement);
+
+ // findForward() Statements containing an eventually given blank node
+ // and add them to the result, if closure = true
+ if (is_a($statement->object(),'BlankNode') && $closure == True)
+ {
+ $newModel = $model->findForward($statement->object(),NULL,NULL, $newModel);
+ }
+ if (is_a($statement->subject(),'BlankNode') && $closure == True)
+ {
+ $newModel = $model->findForward($statement->subject(),NULL,NULL, $newModel);
+ }
+ }
+ }
+ return $newModel;
+ }
+
+
+
+ /**
+ * Alias for RDFUtil::visualiseGraph(&$model, $format, $short_prefix)
+ *
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * Note: See RDFUtil for further Information.
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ *
+ * @author Anton K�tlbacher
+ * @param string $format
+ * @param boolean $short_prefix
+ * @return string, binary
+ * @access public
+ * @throws PhpError
+ */
+ function visualize($format = "dot", $short_prefix = TRUE)
+ {
+ return RDFUtil::visualizeGraph($this, $format, $short_prefix);
+ }
+
+
+ /**
+ * Performs a SPARQL query against a model. The model is converted to
+ * an RDF Dataset. The result can be retrived in SPARQL Query Results XML Format or
+ * as an array containing the variables an their bindings.
+ *
+ * @param string $query the sparql query string
+ * @param string $resultform the result form ('xml' for SPARQL Query Results XML Format)
+ * @return string/array
+ */
+ function sparqlQuery($query, $resultform = false)
+ {
+ list($engine, $dataset) = $this->_prepareSparql();
+ return $engine->queryModel(
+ $dataset,
+ $this->_parseSparqlQuery($query),
+ $resultform
+ );
+ }//function sparqlQuery($query,$resultform = false)
+
+
+
+ /**
+ * Prepares a sparql query and returns a prepared statement
+ * that can be executed with data later on.
+ *
+ * @param string $query Sparql query to prepare.
+ * @return SparqlEngine_PreparedStatement prepared statement object
+ */
+ function sparqlPrepare($query)
+ {
+ list($engine, $dataset) = $this->_prepareSparql();
+ return $engine->prepare(
+ $dataset,
+ $this->_parseSparqlQuery($query)
+ );
+ }//function sparqlPrepare($query)
+
+
+
+ /**
+ * Prepares everything for SparqlEngine-usage
+ * Loads the files, creates instances for SparqlEngine and
+ * Dataset...
+ *
+ * @return array First value is the sparql engine, second the dataset
+ */
+ function _prepareSparql()
+ {
+ require_once RDFAPI_INCLUDE_DIR . 'sparql/SparqlEngine.php';
+ require_once RDFAPI_INCLUDE_DIR . 'dataset/DatasetMem.php';
+
+ $dataset = new DatasetMem();
+ $dataset->setDefaultGraph($this);
+
+ return array(
+ SparqlEngine::factory($this),
+ $dataset
+ );
+ }//function _prepareSparql()
+
+
+
+ /**
+ * Parses an query and returns the parsed form.
+ * If the query is not a string but a Query object,
+ * it will just be returned.
+ *
+ * @param $query mixed String or Query object
+ * @return Query query object
+ * @throws Exception If $query is no string and no Query object
+ */
+ function _parseSparqlQuery($query)
+ {
+ if ($this->queryParser === null) {
+ require_once RDFAPI_INCLUDE_DIR . 'sparql/SparqlParser.php';
+ $this->queryParser = new SparqlParser();
+ }
+ return $this->queryParser->parse($query);
+ }//function _parseSparqlQuery($query)
+
+} // end: Model
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/ModelFactory.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/ModelFactory.php
new file mode 100755
index 00000000..b62bfc52
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/ModelFactory.php
@@ -0,0 +1,288 @@
+
+* @author Richard Cyganiak
+*
+*
+* @package model
+* @access public
+**/
+class ModelFactory
+{
+ /**
+ * Returns a MemModel.
+ * You can supply a base URI
+ *
+ * @param string $baseURI
+ * @return object MemModel
+ * @access public
+ */
+ function & getDefaultModel($baseURI = null)
+ {
+ return ModelFactory::getMemModel($baseURI);
+ }
+
+ /**
+ * Returns a NamedGraphSetMem.
+ * You can supply a GraphSet name.
+ *
+ * @param string $graphSetId
+ * @param string $uri
+ * @access public
+ */
+ function & getDatasetMem($graphSetId = null)
+ {
+ require_once RDFAPI_INCLUDE_DIR . 'dataset/DatasetMem.php';
+ $m = new DatasetMem($graphSetId);
+ return $m;
+ }
+
+ /**
+ * Returns a MemModel.
+ * You can supply a base URI
+ *
+ * @param string $baseURI
+ * @return object MemModel
+ * @access public
+ */
+ function & getMemModel($baseURI = null)
+ {
+ require_once RDFAPI_INCLUDE_DIR . 'model/MemModel.php';
+ $m = new MemModel($baseURI);
+ return $m;
+ }
+
+ /**
+ * Returns a DbModel with the database connection
+ * defined in constants.php.
+ * You can supply a base URI. If a model with the given base
+ * URI exists in the DbStore, it'll be opened.
+ * If not, a new model will be created.
+ *
+ * @param string $baseURI
+ * @return object DbModel
+ * @access public
+ */
+ function & getDefaultDbModel($baseURI = null)
+ {
+ $dbStore = ModelFactory::getDbStore();
+ $m = ModelFactory::getDbModel($dbStore,$baseURI);
+ return $m;
+ }
+
+ /**
+ * Returns a new DbModel using the database connection
+ * supplied by $dbStore.
+ * You can supply a base URI. If a model with the given base
+ * URI exists in the DbStore, it'll be opened.
+ * If not, a new model will be created.
+ *
+ * @param object DbStore $dbStore
+ * @param string $baseURI
+ * @return object DbModel
+ * @access public
+ */
+ function & getDbModel($dbStore, $baseURI = null)
+ {
+ if ($dbStore->modelExists($baseURI)) {
+ return $dbStore->getModel($baseURI);
+ }
+
+ return $dbStore->getNewModel($baseURI);
+ }
+
+ /**
+ * Returns a database connection with the given parameters.
+ * Paramters, which are not defined are taken from the constants.php
+ *
+ * @param string $dbDriver
+ * @param string $host
+ * @param string $dbName
+ * @param string $user
+ * @param string $password
+ * @return object DbStore
+ * @access public
+ */
+ function & getDbStore($dbDriver=ADODB_DB_DRIVER, $host=ADODB_DB_HOST, $dbName=ADODB_DB_NAME,
+ $user=ADODB_DB_USER, $password=ADODB_DB_PASSWORD)
+ {
+ $dbs = new DbStore($dbDriver, $host, $dbName,$user, $password);
+ return $dbs;
+ }
+
+ /**
+ * Returns a InfModelF.
+ * (MemModel with forward chaining inference engine)
+ * Configurations can be done in constants.php
+ * You can supply a base URI
+ *
+ * @param string $baseURI
+ * @return object MemModel
+ * @access public
+ */
+ function & getInfModelF($baseURI = null)
+ {
+ require_once RDFAPI_INCLUDE_DIR . 'infModel/InfModelF.php';
+ $mod = new InfModelF($baseURI);
+ return $mod;
+ }
+
+ /**
+ * Returns a InfModelB.
+ * (MemModel with backward chaining inference engine)
+ * Configurations can be done in constants.php
+ * You can supply a base URI
+ *
+ * @param string $baseURI
+ * @return object MemModel
+ * @access public
+ */
+ function & getInfModelB($baseURI = null)
+ {
+ require_once RDFAPI_INCLUDE_DIR . 'infModel/InfModelB.php';
+ $mod = new InfModelB($baseURI);
+ return $mod;
+ }
+
+ /**
+ * Returns a ResModel.
+ * $modelType has to be one of the following constants:
+ * MEMMODEL,DBMODEL,INFMODELF,INFMODELB to create a resmodel with a new
+ * model from defined type.
+ * You can supply a base URI
+ *
+ * @param constant $modelType
+ * @param string $baseURI
+ * @return object ResModel
+ * @access public
+ */
+ function & getResModel($modelType, $baseURI = null)
+ {
+ switch ($modelType) {
+ case DBMODEL:
+ $baseModel = ModelFactory::getDefaultDbModel($baseURI);
+ break;
+
+ case INFMODELF:
+ $baseModel = ModelFactory::getInfModelF($baseURI);
+ break;
+
+ case INFMODELB:
+ $baseModel = ModelFactory::getInfModelB($baseURI);
+ break;
+
+ default:
+ $baseModel = ModelFactory::getMemModel($baseURI);
+ break;
+ }
+ return ModelFactory::getResModelForBaseModel($baseModel);
+ }
+
+ /**
+ * Creates a ResModel that wraps an existing base model.
+ *
+ * @param object Model $baseModel
+ * @return object ResModel
+ * @access public
+ */
+ function &getResModelForBaseModel(&$baseModel) {
+ require_once RDFAPI_INCLUDE_DIR . 'resModel/ResModel.php';
+ $mod = new ResModel($baseModel);
+ return $mod;
+ }
+
+ /**
+ * Returns an OntModel.
+ * $modelType has to be one of the following constants:
+ * MEMMODEL, DBMODEL, INFMODELF, INFMODELB to create a OntModel
+ * with a new model from defined type.
+ * $vocabulary defines the ontology language. Currently only
+ * RDFS_VOCABULARY is supported. You can supply a model base URI.
+ *
+ * @param constant $modelType
+ * @param constant $vocabulary
+ * @param string $baseURI
+ * @return object OntModel
+ * @access public
+ */
+ function & getOntModel($modelType,$vocabulary, $baseURI = null)
+ {
+ switch ($modelType)
+ {
+ case DBMODEL:
+ $baseModel = ModelFactory::getDefaultDbModel($baseURI);
+ break;
+
+ case INFMODELF:
+ $baseModel = ModelFactory::getInfModelF($baseURI);
+ break;
+
+ case INFMODELB:
+ $baseModel = ModelFactory::getInfModelB($baseURI);
+ break;
+
+ default:
+ $baseModel = ModelFactory::getMemModel($baseURI);;
+ }
+
+ $mod = ModelFactory::getOntModelForBaseModel($baseModel, $vocabulary);
+ return $mod;
+ }
+
+ /**
+ * Creates an OntModel that wraps an existing base model.
+ * $vocabulary defines the ontology language. Currently only
+ * RDFS_VOCABULARY is supported.
+ *
+ * @param object Model $baseModel
+ * @param constant $vocabulary
+ * @return object OntModel
+ * @access public
+ */
+ function &getOntModelForBaseModel(&$baseModel, $vocabulary)
+ {
+ require_once RDFAPI_INCLUDE_DIR . 'ontModel/OntModel.php';
+
+ switch ($vocabulary)
+ {
+ case RDFS_VOCABULARY:
+ require_once(RDFAPI_INCLUDE_DIR.'ontModel/'.RDFS_VOCABULARY);
+ $vocab_object = new RdfsVocabulary();
+ break;
+ default:
+ trigger_error("Unknown vocabulary constant '$vocabulary'; only RDFS_VOCABULARY is supported", E_USER_WARNING);
+ $vocab_object = null;
+ break;
+ }
+ $mod = new OntModel($baseModel, $vocab_object);
+ return $mod;
+ }
+
+
+
+ /**
+ * Creates a SparqlClient.
+ *
+ * @param String $server Link to a SPARQL endpoint.
+ * @return SparqlClient the SparqlClient object.
+ * @access public
+ */
+ function & getSparqlClient($server){
+ $cl = new SparqlClient($server);
+ return $cl;
+ }
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/ModelP.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/ModelP.php
new file mode 100755
index 00000000..15a5cf08
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/ModelP.php
@@ -0,0 +1,27 @@
+
+//
+// ----------------------------------------------------------------------------------
+
+// Include Model classes
+require_once( RDFAPI_INCLUDE_DIR . 'model/Node.php' );
+require_once( RDFAPI_INCLUDE_DIR . 'model/Literal.php' );
+require_once( RDFAPI_INCLUDE_DIR . 'model/Resource.php' );
+require_once( RDFAPI_INCLUDE_DIR . 'model/Blanknode.php' );
+require_once( RDFAPI_INCLUDE_DIR . 'model/Statement.php' );
+require_once( RDFAPI_INCLUDE_DIR . 'model/Model.php' );
+require_once( RDFAPI_INCLUDE_DIR . 'model/MemModel.php' );
+require_once( RDFAPI_INCLUDE_DIR . 'model/DbStore.php' );
+require_once( RDFAPI_INCLUDE_DIR . 'util/StatementIterator.php' );
+require_once( RDFAPI_INCLUDE_DIR . 'model/ModelFactory.php' );
+require_once( RDFAPI_INCLUDE_DIR . 'sparql/SparqlClient.php' );
+require_once( RDFAPI_INCLUDE_DIR . 'sparql/ClientQuery.php' );
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/Node.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/Node.php
new file mode 100755
index 00000000..16d11445
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/Node.php
@@ -0,0 +1,25 @@
+
+ * @package model
+ * @abstract
+ *
+ */
+ class Node extends Object {
+ } // end:RDFNode
+
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/Resource.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/Resource.php
new file mode 100755
index 00000000..4a1b4869
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/Resource.php
@@ -0,0 +1,142 @@
+
+ *
+ * @package model
+ * @access public
+ *
+ */
+ class Resource extends Node {
+
+ /**
+ * URIref to the resource
+ * @var string
+ * @access private
+ */
+ var $uri;
+
+
+ /**
+ * Constructor
+ * Takes an URI or a namespace/localname combination
+ *
+ * @param string $namespace_or_uri
+ * @param string $localName
+ * @access public
+ */
+ function Resource($namespace_or_uri , $localName = NULL) {
+ if ($localName == NULL) {
+ $this->uri = $namespace_or_uri;
+ } else {
+ $this->uri = $namespace_or_uri . $localName;
+ }
+ }
+
+
+ /**
+ * Returns the URI of the resource.
+ * @return string
+ * @access public
+ */
+ function getURI() {
+ return $this->uri;
+ }
+
+ /**
+ * Returns the label of the resource, which is the URI of the resource.
+ * @access public
+ * @return string
+ */
+ function getLabel() {
+ return $this->getURI();
+ }
+
+ /**
+ * Returns the namespace of the resource. May return null.
+ * @access public
+ * @return string
+ */
+ function getNamespace() {
+ // Import Package Utility
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_UTILITY);
+
+ return RDFUtil::guessNamespace($this->uri);
+ }
+
+ /**
+ * Returns the local name of the resource.
+ * @access public
+ * @return string
+ */
+ function getLocalName() {
+ // Import Package Utility
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_UTILITY);
+
+ return RDFUtil::guessName($this->uri);
+ }
+
+ /**
+ * Dumps resource.
+ * @access public
+ * @return string
+ */
+ function toString() {
+ return 'Resource("' . $this->uri .'")';
+ }
+
+ /**
+ * Checks if the resource equals another resource.
+ * Two resources are equal, if they have the same URI
+ *
+ * @access public
+ * @param object resource $that
+ * @return boolean
+ */
+ function equals ($that) {
+
+ if ($this == $that) {
+ return true;
+ }
+
+ if (($that == NULL) or !(is_a($that, 'Resource')) or (is_a($that, 'BlankNode'))) {
+ return false;
+ }
+
+ if ($this->getURI() == $that->getURI()) {
+ return true;
+ }
+
+ return false;
+ }
+
+
+
+
+ /**
+ * Doing string magic in PHP5
+ * @return string String representation of this Resource
+ */
+ function __toString()
+ {
+ return $this->toString();
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/Statement.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/Statement.php
new file mode 100755
index 00000000..a7b24627
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/model/Statement.php
@@ -0,0 +1,313 @@
+
+ * @version $Id: Statement.php 268 2006-05-15 05:28:09Z tgauss $
+ * @package model
+ */
+class Statement extends Object {
+
+ /**
+ * Subject of the statement
+ *
+ * @var object resource
+ * @access private
+ */
+ var $subj;
+
+ /**
+ * Predicate of the statement
+ *
+ * @var object resource
+ * @access private
+ */
+ var $pred;
+
+ /**
+ * Object of the statement
+ *
+ * @var object node
+ * @access private
+ */
+ var $obj;
+
+ /**
+ * The parameters to constructor are instances of classes and not just strings
+ *
+ * @param object node $subj
+ * @param object node $pred
+ * @param object node $obj
+ * @throws PhpError
+ */
+ function Statement($subj, $pred, $obj) {
+
+ if (!is_a($subj, 'Resource')) {
+ $errmsg = RDFAPI_ERROR .
+ '(class: Statement; method: new): Resource expected as subject.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+ if (!is_a($pred, 'Resource') || is_a($pred, 'BlankNode')) {
+ $errmsg = RDFAPI_ERROR .
+ '(class: Statement; method: new): Resource expected as predicate, no blank node allowed.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+ if (!(is_a($obj, 'Resource') or is_a($obj, 'Literal'))) {
+ $errmsg = RDFAPI_ERROR .
+ '(class: Statement; method: new): Resource or Literal expected as object.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+
+ $this->pred = $pred;
+ $this->subj = $subj;
+ $this->obj = $obj;
+ }
+
+ /**
+ * Returns the subject of the triple.
+ * @access public
+ * @return object node
+ */
+ function getSubject() {
+ return $this->subj;
+ }
+
+ /**
+ * Returns the predicate of the triple.
+ * @access public
+ * @return object node
+ */
+ function getPredicate() {
+ return $this->pred;
+ }
+
+ /**
+ * Returns the object of the triple.
+ * @access public
+ * @return object node
+ */
+ function getObject() {
+ return $this->obj;
+ }
+
+ /**
+ * Alias for getSubject()
+ * @access public
+ * @return object node
+ */
+ function subject() {
+ return $this->subj;
+ }
+
+ /**
+ * Alias for getPredicate()
+ * @access public
+ * @return object node
+ */
+ function predicate() {
+ return $this->pred;
+ }
+
+ /**
+ * Alias for getObject()
+ * @access public
+ * @return object node
+ */
+ function object() {
+ return $this->obj;
+ }
+ /**
+ * Retruns the hash code of the triple.
+ * @access public
+ * @return string
+ */
+ function hashCode() {
+ return md5($this->subj->getLabel() . $this->pred->getLabel() . $this->obj->getLabel());
+ }
+
+ /**
+ * Dumps the triple.
+ * @access public
+ * @return string
+ */
+
+ function toString() {
+ return 'Triple(' . $this->subj->toString() . ', ' . $this->pred->toString() . ', ' . $this->obj->toString() . ')';
+
+ }
+
+ /**
+ * Returns a toString() serialization of the statements's subject.
+ *
+ * @access public
+ * @return string
+ */
+ function toStringSubject() {
+ return $this->subj->toString();
+ }
+
+ /**
+ * Returns a toString() serialization of the statements's predicate.
+ *
+ * @access public
+ * @return string
+ */
+ function toStringPredicate() {
+ return $this->pred->toString();
+ }
+
+ /**
+ * Reurns a toString() serialization of the statements's object.
+ *
+ * @access public
+ * @return string
+ */
+ function toStringObject() {
+ return $this->obj->toString();
+ }
+
+ /**
+ * Returns the URI or bNode identifier of the statements's subject.
+ *
+ * @access public
+ * @return string
+ */
+ function getLabelSubject() {
+ return $this->subj->getLabel();
+ }
+
+ /**
+ * Returns the URI of the statements's predicate.
+ *
+ * @access public
+ * @return string
+ */
+ function getLabelPredicate() {
+ return $this->pred->getLabel();
+ }
+
+ /**
+ * Reurns the URI, text or bNode identifier of the statements's object.
+ *
+ * @access public
+ * @return string
+ */
+ function getLabelObject() {
+ return $this->obj->getLabel();
+ }
+
+ /**
+ * Checks if two statements are equal.
+ * Two statements are considered to be equal if they have the
+ * same subject, predicate and object. A statement can only be equal
+ * to another statement object.
+ * @access public
+ * @param object statement $that
+ * @return boolean
+ */
+
+ function equals ($that) {
+
+ if ($this == $that) {
+ return true;
+ }
+ if ($that == NULL || !(is_a($that, 'Statement'))) {
+ return false;
+ }
+
+ return
+ $this->subj->equals($that->subject()) &&
+ $this->pred->equals($that->predicate()) &&
+ $this->obj->equals($that->object());
+ }
+
+ /**
+ * Compares two statements and returns integer less than, equal to, or greater than zero.
+ * Can be used for writing sorting function for models or with the PHP function usort().
+ *
+ * @access public
+ * @param object statement &$that
+ * @return boolean
+ */
+
+ function compare(&$that) {
+ return statementsorter($this, $that);
+ // statementsorter function see below
+ }
+
+
+ /**
+ * Reifies a statement.
+ * Returns a new MemModel that is the reification of the statement.
+ * For naming the statement's bNode a Model or bNodeID must be passed to the method.
+ *
+ * @access public
+ * @param mixed &$model_or_bNodeID
+ * @return object model
+ */
+
+ function & reify(&$model_or_bNodeID) {
+
+ if (is_a($model_or_bNodeID, 'MemModel')) {
+ // parameter is model
+ $statementModel = new MemModel($model_or_bNodeID->getBaseURI());
+ $thisStatement = new BlankNode($model_or_bNodeID);
+ } else {
+ // parameter is bNodeID
+ $statementModel = new MemModel();
+ $thisStatement = &$model_or_bNodeID;
+ }
+
+ $RDFstatement = new Resource(RDF_NAMESPACE_URI . RDF_STATEMENT);
+ $RDFtype = new Resource(RDF_NAMESPACE_URI . RDF_TYPE);
+ $RDFsubject = new Resource(RDF_NAMESPACE_URI . RDF_SUBJECT);
+ $RDFpredicate = new Resource(RDF_NAMESPACE_URI . RDF_PREDICATE);
+ $RDFobject = new Resource(RDF_NAMESPACE_URI . RDF_OBJECT);
+
+ $statementModel->add(new Statement($thisStatement, $RDFtype, $RDFstatement));
+ $statementModel->add(new Statement($thisStatement, $RDFsubject, $this->getSubject()));
+ $statementModel->add(new Statement($thisStatement, $RDFpredicate, $this->getPredicate()));
+ $statementModel->add(new Statement($thisStatement, $RDFobject, $this->Object()));
+
+ return $statementModel;
+ }
+
+} // end: Statement
+
+
+/**
+* Comparison function for comparing two statements.
+* statementsorter() is used by the PHP function usort ( array array, callback cmp_function)
+*
+* @access private
+* @param object Statement $a
+* @param object Statement $b
+* @return integer less than, equal to, or greater than zero
+* @throws phpErrpr
+*/
+function statementsorter($a,$b) {
+ //Compare subjects
+ $x=$a->getSubject();
+ $y=$b->getSubject();
+ $r=strcmp($x->getLabel(),$y->getLabel());
+ if ($r!=0) return $r;
+ //Compare predicates
+ $x=$a->getPredicate();
+ $y=$b->getPredicate();
+ $r=strcmp($x->getURI(),$y->getURI());
+ if ($r!=0) return $r;
+ //Final resort, compare objects
+ $x=$a->getObject();
+ $y=$b->getObject();
+ return strcmp($x->toString(),$y->toString());
+}
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/all-wcprops b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/all-wcprops
new file mode 100755
index 00000000..e6f8e819
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/all-wcprops
@@ -0,0 +1,59 @@
+K 25
+svn:wc:ra_dav:version-url
+V 62
+/svnroot/rdfapi-php/!svn/ver/320/trunk/rdfapi-php/api/ontModel
+END
+OWLVocabulary.php
+K 25
+svn:wc:ra_dav:version-url
+V 80
+/svnroot/rdfapi-php/!svn/ver/320/trunk/rdfapi-php/api/ontModel/OWLVocabulary.php
+END
+OntModel.php
+K 25
+svn:wc:ra_dav:version-url
+V 75
+/svnroot/rdfapi-php/!svn/ver/320/trunk/rdfapi-php/api/ontModel/OntModel.php
+END
+OntModelP.php
+K 25
+svn:wc:ra_dav:version-url
+V 76
+/svnroot/rdfapi-php/!svn/ver/320/trunk/rdfapi-php/api/ontModel/OntModelP.php
+END
+OntProperty.php
+K 25
+svn:wc:ra_dav:version-url
+V 78
+/svnroot/rdfapi-php/!svn/ver/320/trunk/rdfapi-php/api/ontModel/OntProperty.php
+END
+OntClass.php
+K 25
+svn:wc:ra_dav:version-url
+V 75
+/svnroot/rdfapi-php/!svn/ver/320/trunk/rdfapi-php/api/ontModel/OntClass.php
+END
+RdfsVocabulary.php
+K 25
+svn:wc:ra_dav:version-url
+V 81
+/svnroot/rdfapi-php/!svn/ver/320/trunk/rdfapi-php/api/ontModel/RdfsVocabulary.php
+END
+Individual.php
+K 25
+svn:wc:ra_dav:version-url
+V 77
+/svnroot/rdfapi-php/!svn/ver/320/trunk/rdfapi-php/api/ontModel/Individual.php
+END
+OntResource.php
+K 25
+svn:wc:ra_dav:version-url
+V 78
+/svnroot/rdfapi-php/!svn/ver/268/trunk/rdfapi-php/api/ontModel/OntResource.php
+END
+OntVocabulary.php
+K 25
+svn:wc:ra_dav:version-url
+V 80
+/svnroot/rdfapi-php/!svn/ver/320/trunk/rdfapi-php/api/ontModel/OntVocabulary.php
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/entries b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/entries
new file mode 100755
index 00000000..50afc937
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/entries
@@ -0,0 +1,145 @@
+8
+
+dir
+556
+https://rdfapi-php.svn.sourceforge.net/svnroot/rdfapi-php/trunk/rdfapi-php/api/ontModel
+https://rdfapi-php.svn.sourceforge.net/svnroot/rdfapi-php
+
+
+
+2006-11-21T09:38:51.000000Z
+320
+tgauss
+
+
+svn:special svn:externals svn:needs-lock
+
+
+
+
+
+
+
+
+
+
+
+b2ee660e-c932-0410-bdee-d8da4d8102f4
+
+OWLVocabulary.php
+file
+
+
+
+
+2008-02-29T14:57:44.944478Z
+1aa171d09b4c8b94c8a7ba91b6308485
+2006-11-21T09:38:51.000000Z
+320
+tgauss
+has-props
+
+OntModel.php
+file
+
+
+
+
+2008-02-29T14:57:44.960099Z
+4ffe80bd79ce8743d44ea9340504ace5
+2006-11-21T09:38:51.000000Z
+320
+tgauss
+has-props
+
+OntModelP.php
+file
+
+
+
+
+2008-02-29T14:57:44.960099Z
+c3d6da8305a6cefb7508123ba7653aaf
+2006-11-21T09:38:51.000000Z
+320
+tgauss
+has-props
+
+OntProperty.php
+file
+
+
+
+
+2008-02-29T14:57:44.975719Z
+d8382a3da93dbe2c74459b04f81ba394
+2006-11-21T09:38:51.000000Z
+320
+tgauss
+has-props
+
+OntClass.php
+file
+
+
+
+
+2008-02-29T14:57:44.975719Z
+8d5625f702080b2f019076977af48091
+2006-11-21T09:38:51.000000Z
+320
+tgauss
+has-props
+
+RdfsVocabulary.php
+file
+
+
+
+
+2008-02-29T14:57:44.991340Z
+0ab4fcefc17f5191a6dd8eb3de8006f9
+2006-11-21T09:38:51.000000Z
+320
+tgauss
+has-props
+
+Individual.php
+file
+
+
+
+
+2008-02-29T14:57:45.006960Z
+bdc7c8bba4d51aaee0a8ad81f2880ba7
+2006-11-21T09:38:51.000000Z
+320
+tgauss
+has-props
+
+OntResource.php
+file
+
+
+
+
+2008-02-29T14:57:45.006960Z
+58899fb5c36b0212ab7e282b8398ef04
+2006-05-15T05:28:09.000000Z
+268
+tgauss
+has-props
+
+OntVocabulary.php
+file
+
+
+
+
+2008-02-29T14:57:45.022581Z
+08eeba057d70b745eb6bf206eb7b6ddb
+2006-11-21T09:38:51.000000Z
+320
+tgauss
+has-props
+
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/format b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/format
new file mode 100755
index 00000000..45a4fb75
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/format
@@ -0,0 +1 @@
+8
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/prop-base/Individual.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/prop-base/Individual.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/prop-base/Individual.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/prop-base/OWLVocabulary.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/prop-base/OWLVocabulary.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/prop-base/OWLVocabulary.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/prop-base/OntClass.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/prop-base/OntClass.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/prop-base/OntClass.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/prop-base/OntModel.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/prop-base/OntModel.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/prop-base/OntModel.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/prop-base/OntModelP.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/prop-base/OntModelP.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/prop-base/OntModelP.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/prop-base/OntProperty.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/prop-base/OntProperty.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/prop-base/OntProperty.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/prop-base/OntResource.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/prop-base/OntResource.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/prop-base/OntResource.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/prop-base/OntVocabulary.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/prop-base/OntVocabulary.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/prop-base/OntVocabulary.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/prop-base/RdfsVocabulary.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/prop-base/RdfsVocabulary.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/prop-base/RdfsVocabulary.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/text-base/Individual.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/text-base/Individual.php.svn-base
new file mode 100755
index 00000000..f12ee60e
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/text-base/Individual.php.svn-base
@@ -0,0 +1,39 @@
+
+*
+*
+* @package ontModel
+* @access public
+**/
+
+class Individual extends OntResource
+{
+
+ /**
+ * Constructor
+ * You can supply a uri
+ *
+ * @param string $uri
+ * @access public
+ */
+ function Individual($uri = null)
+ {
+ parent::OntResource($uri);
+ }
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/text-base/OWLVocabulary.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/text-base/OWLVocabulary.php.svn-base
new file mode 100755
index 00000000..6dd1c4c5
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/text-base/OWLVocabulary.php.svn-base
@@ -0,0 +1,369 @@
+
+*
+*
+* @package ontModel
+* @access public
+**/
+class OWLVocabulary extends OntVocabulary
+{
+
+ /**
+ * Answer the resource that represents the class 'class' in this vocabulary.
+ *
+ * @return object ResResource
+ * @access public
+ */
+ function ONTCLASS()
+ {
+ return new ResResource(OWL_NS.'Class');
+ }
+
+ /**
+ * Answer the predicate that denotes the domain of a property.
+ *
+ * @return object ResProperty
+ * @access public
+ */
+ function DOMAIN()
+ {
+ return new ResProperty(RDF_SCHEMA_URI.RDFS_DOMAIN);
+ }
+
+
+ /**
+ * Answer the predicate that denotes comment annotation on an ontology element.
+ *
+ * @return object ResProperty
+ * @access public
+ */
+ function COMMENT()
+ {
+ return new ResProperty(RDF_SCHEMA_URI.RDFS_COMMENT);
+ }
+
+ /**
+ * Answer the predicate that denotes isDefinedBy annotation on an ontology element
+ *
+ * @return object ResProperty
+ * @access public
+ */
+ function IS_DEFINED_BY()
+ {
+ return new ResProperty(RDF_SCHEMA_URI.RDFS_IS_DEFINED_BY);
+ }
+
+ /**
+ * Answer the predicate that denotes label annotation on an ontology element
+ *
+ * @return object ResProperty
+ * @access public
+ */
+ function LABEL()
+ {
+ return new ResProperty(RDF_SCHEMA_URI.RDFS_LABEL);
+ }
+
+ /**
+ * Answer the predicate that denotes the domain of a property.
+ *
+ * @return object ResProperty
+ * @access public
+ */
+ function RANGE()
+ {
+ return new ResProperty(RDF_SCHEMA_URI.RDFS_RANGE);
+ }
+
+ /**
+ * Answer the predicate that denotes seeAlso annotation on an ontology element
+ *
+ * @return object ResProperty
+ * @access public
+ */
+ function SEE_ALSO()
+ {
+ return new ResProperty(RDF_SCHEMA_URI.RDFS_SEE_ALSO);
+ }
+
+ /**
+ * Answer the predicate that denotes that one class is a sub-class of another.
+ *
+ * @return object ResProperty
+ * @access public
+ */
+ function SUB_CLASS_OF()
+ {
+ return new ResProperty(RDF_SCHEMA_URI.RDFS_SUBCLASSOF);
+ }
+
+ /**
+ * Answer the predicate that denotes that one property is a sub-property of another.
+ *
+ * @return object ResProperty
+ * @access public
+ */
+ function SUB_PROPERTY_OF()
+ {
+ return new ResProperty(RDF_SCHEMA_URI.RDFS_SUBPROPERTYOF);
+ }
+
+
+
+ function ANNOTATION_PROPERTY()
+ {
+ return new ResProperty(OWL_NS . 'AnnotationProperty');
+ }
+
+ function ALL_DIFFERENT()
+ {
+ return new ResProperty(OWL_NS . 'AllDifferent');
+ }
+
+ function ALL_VALUES_FROM()
+ {
+ return new ResProperty(OWL_NS . 'allValuesFrom');
+ }
+
+ function BACKWARD_COMPATIBLE_WITH()
+ {
+ return new ResProperty(OWL_NS . 'backwardCompatibleWith');
+ }
+
+ function CARDINALITY()
+ {
+ return new ResProperty(OWL_NS . 'cardinality');
+ }
+
+ function COMPLEMENT_OF()
+ {
+ return new ResProperty(OWL_NS . 'complementOf');
+ }
+
+ function DATATYPE()
+ {
+ return new ResProperty(OWL_NS . 'Datatype');
+ }
+
+ function DATATYPE_PROPERTY()
+ {
+ return new ResProperty(OWL_NS . 'DatatypeProperty');
+ }
+
+ function DATA_RANGE()
+ {
+ return new ResProperty(OWL_NS . 'DataRange');
+ }
+
+ function DATATYPE_RESTRICTION()
+ {
+ return new ResProperty(OWL_NS . 'DatatypeRestriction');
+ }
+
+ function DEPRECATED_CLASS()
+ {
+ return new ResProperty(OWL_NS . 'DeprecatedClass');
+ }
+
+ function DEPRECATED_PROPERTY()
+ {
+ return new ResProperty(OWL_NS . 'DeprecatedProperty');
+ }
+
+ function DISTINCT_MEMBERS()
+ {
+ return new ResProperty(OWL_NS . 'distinctMembers');
+ }
+
+ function DIFFERENT_FROM()
+ {
+ return new ResProperty(OWL_NS . 'differentFrom');
+ }
+
+ function DISJOINT_WITH()
+ {
+ return new ResProperty(OWL_NS . 'disjointWith');
+ }
+
+ function EQUIVALENT_CLASS()
+ {
+ return new ResProperty(OWL_NS . 'equivalentClass');
+ }
+
+ function EQUIVALENT_PROPERTY()
+ {
+ return new ResProperty(OWL_NS . 'equivalentProperty');
+ }
+
+ function FUNCTIONAL_PROPERTY()
+ {
+ return new ResProperty(OWL_NS . 'FunctionalProperty');
+ }
+
+ function HAS_VALUE()
+ {
+ return new ResProperty(OWL_NS . 'hasValue');
+ }
+
+ function INCOMPATIBLE_WITH()
+ {
+ return new ResProperty(OWL_NS . 'incompatibleWith');
+ }
+
+ function IMPORTS()
+ {
+ return new ResProperty(OWL_NS . 'imports');
+ }
+
+ function INTERSECTION_OF()
+ {
+ return new ResProperty(OWL_NS . 'intersectionOf');
+ }
+
+ function INVERSE_FUNCTIONAL_PROPERTY()
+ {
+ return new ResProperty(OWL_NS . 'InverseFunctionalProperty');
+ }
+
+ function INVERSE_OF()
+ {
+ return new ResProperty(OWL_NS . 'inverseOf');
+ }
+
+ function MAX_CARDINALITY()
+ {
+ return new ResProperty(OWL_NS . 'maxCardinality');
+ }
+
+ function MIN_CARDINALITY()
+ {
+ return new ResProperty(OWL_NS . 'minCardinality');
+ }
+
+ function NOTHING()
+ {
+ return new ResProperty(OWL_NS . 'Nothing');
+ }
+
+ function OBJECT_CLASS()
+ {
+ return new ResProperty(OWL_NS . 'ObjectClass');
+ }
+
+ function OBJECT_PROPERTY()
+ {
+ return new ResProperty(OWL_NS . 'ObjectProperty');
+ }
+
+ function OBJECT_RESTRICTION()
+ {
+ return new ResProperty(OWL_NS . 'ObjectRestriction');
+ }
+
+ function ONE_OF()
+ {
+ return new ResProperty(OWL_NS . 'oneOf');
+ }
+
+ function ON_PROPERTY()
+ {
+ return new ResProperty(OWL_NS . 'onProperty');
+ }
+
+ function ONTOLOGY()
+ {
+ return new ResProperty(OWL_NS . 'Ontology');
+
+ }
+
+ function PRIOR_VERSION()
+ {
+ return new ResProperty(OWL_NS . 'priorVersion');
+ }
+
+ function PROPERTY()
+ {
+ return new ResProperty(OWL_NS . 'Property');
+ }
+
+ function RESTRICTION()
+ {
+ return new ResProperty(OWL_NS . 'Restriction');
+ }
+
+ function SAME_AS()
+ {
+ return new ResProperty(OWL_NS . 'sameAs');
+ }
+
+ function SAME_CLASS_AS()
+ {
+ return new ResProperty(OWL_NS . 'sameClassAs');
+ }
+
+ function SAME_INDIVIDUAL_AS()
+ {
+ return new ResProperty(OWL_NS . 'sameIndividualAs');
+ }
+
+ function SAME_PROPERTY_AS()
+ {
+ return new ResProperty(OWL_NS . 'samePropertyAs');
+ }
+
+ function SOME_VALUES_FROM()
+ {
+ return new ResProperty(OWL_NS . 'someValuesFrom');
+ }
+
+ function SYMMETRIC_PROPERTY()
+ {
+ return new ResProperty(OWL_NS . 'SymmetricProperty');
+ }
+
+ function THING()
+ {
+ return new ResProperty(OWL_NS . 'Thing');
+ }
+
+ function TRANSITIVE_PROPERTY()
+ {
+ return new ResProperty(OWL_NS . 'TransitiveProperty');
+ }
+
+ function UNION_OF()
+ {
+ return new ResProperty(OWL_NS . 'unionOf');
+ }
+
+ function VERSION_INFO()
+ {
+ return new ResProperty(OWL_NS . 'versionInfo');
+ }
+
+ function NAMESPACE()
+ {
+ return OWL_NS;
+ }
+
+ /**
+ * Answer the predicate that denotes the rdf:type property.
+ *
+ * @return object ResProperty
+ * @access public
+ */
+ function TYPE()
+ {
+ return new ResProperty(RDF_NAMESPACE_URI.RDF_TYPE);
+ }
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/text-base/OntClass.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/text-base/OntClass.php.svn-base
new file mode 100755
index 00000000..2be5d196
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/text-base/OntClass.php.svn-base
@@ -0,0 +1,285 @@
+
+*
+*
+* @package ontModel
+* @access public
+**/
+class OntClass extends OntResource
+{
+ /**
+ * Constructor
+ * You can supply a uri
+ *
+ * @param string $uri
+ * @access public
+ */
+ function OntClass($uri = null)
+ {
+ parent::OntResource($uri);
+ }
+
+ /**
+ * Add a sub-class of this class.
+ *
+ * @param object ResResource $resResource
+ * @return boolean
+ * @access public
+ */
+ function addSubClass($resResource)
+ {
+ return $resResource->addProperty($this->vocabulary->SUB_CLASS_OF(),$this);
+ }
+
+ /**
+ * Add a super-class of this class.
+ *
+ * @param object ResResource $resResource
+ * @return boolean
+ * @access public
+ */
+ function addSuperClass($resResource)
+ {
+ return $this->addProperty($this->vocabulary->SUB_CLASS_OF(),$resResource);
+ }
+
+ /**
+ * Answer a class that is the sub-class of this class.
+ * If there is more than one such class, an arbitrary selection is made.
+ *
+ * @return object OntClass or NULL
+ * @access public
+ */
+ function getSubClass()
+ {
+ $statement = $this->model->findFirstMatchingStatement(null,$this->vocabulary->SUB_CLASS_OF(),$this);
+ if ($statement !== null)
+ return $this->model->createOntClass($statement->getLabelSubject());
+
+ return null;
+ }
+
+ /**
+ * Answer a class that is the super-class of this class.
+ * If there is more than one such class, an arbitrary selection is made.
+ *
+ * @return object OntClass or NULL
+ * @access public
+ */
+ function getSuperClass()
+ {
+ return $this->getPropertyValue($this->vocabulary->SUB_CLASS_OF(),'OntClass');
+ }
+
+ /**
+ * Answer true if the given class is a sub-class of this class.
+ * $direct - If true, only search the classes that are directly
+ * adjacent to this class in the class hierarchy.
+ *
+ * @param object ResResource $resResource
+ * @param boolean $direct
+ * @return boolean
+ * @access public
+ */
+ function hasSubclass($resResource, $direct = true)
+ {
+ if ($direct)
+ return $resResource->hasProperty($this->vocabulary->SUB_CLASS_OF(),$this);
+
+ $index=array();
+ return ($this->_getSubAttributeStatementsRec($this,$this->vocabulary->SUB_CLASS_OF(),$index,$resResource) === true);
+ }
+
+ /**
+ * Answer true if the given class is a super-class of this class.
+ * $direct - If true, only search the classes that are directly
+ * adjacent to this class in the class hierarchy.
+ *
+ * @param object ResResource $resResource
+ * @param boolean $direct
+ * @return boolean
+ * @access public
+ */
+ function hasSuperClass($resResource, $direct = true)
+ {
+ if ($direct)
+ return $this->hasProperty($this->vocabulary->SUB_CLASS_OF(),$resResource);
+
+ $index=array();
+ return ($this->_getSuperAttributeStatementsRec($this,$this->vocabulary->SUB_CLASS_OF(),$index,$resResource) === true);
+ }
+
+ /**
+ * Answer an ResIterator over the individuals in the model that have this class
+ * among their types.
+ *
+ * @return object ResIterator
+ * @access public
+ */
+ function listInstances()
+ {
+ /*
+ $statements= $this->model->find(null,$this->vocabulary->TYPE(),$this);
+ $return = array();
+ $returnIndex=array();
+ foreach ($statements as $statement)
+ {
+ $subjectLabel=$statement->getLabelSubject();
+ if (!in_array($subjectLabel,$returnIndex))
+ {
+ $returnIndex[]=$subjectLabel;
+ $return[]=$statement->getSubject();
+ }
+ }
+ return $return;
+ */
+ return new ResIterator(null,$this->vocabulary->TYPE(),$this,'s',$this->model,'Individual');
+
+ }
+
+ /**
+ * Answer an array over the classes that are declared to be sub-classes of this class.
+ * Each element of the array will be an OntClass.
+ * $direct - If true, only search the classes that are directly
+ * adjacent to this class in the class hierarchy.
+ *
+ * @param boolean $direct
+ * @return array
+ * @access public
+ */
+ function listSubClasses($direct = true)
+ {
+ $return = array();
+ if ($direct)
+ {
+ $statements = $this->model->find(null,$this->vocabulary->SUB_CLASS_OF(),$this);
+ } else
+ {
+ $index = array();
+ $statements = $this->_getSubAttributeStatementsRec($this,$this->vocabulary->SUB_CLASS_OF(),$index);
+ }
+
+ $returnIndex=array();
+ foreach ($statements as $statement)
+ {
+ $subjectLabel=$statement->getLabelSubject();
+ if (!in_array($subjectLabel,$returnIndex))
+ {
+ $returnIndex[]=$subjectLabel;
+ $return[]=$this->model->createOntClass($subjectLabel);
+ }
+ }
+ return $return;
+ }
+
+ /**
+ * Answer an array over the classes that are declared to be super-classes of this class.
+ * Each element of the array will be an OntClass.
+ * $direct - If true, only search the classes that are directly
+ * adjacent to this class in the class hierarchy.
+ *
+ * @param boolean $direct
+ * @return array
+ * @access public
+ */
+ function listSuperClasses($direct = true)
+ {
+ $return = array();
+ if ($direct)
+ return $this->listProperty($this->vocabulary->SUB_CLASS_OF(),'OntClass');
+
+ $index=array();
+ $statements = $this->_getSuperAttributeStatementsRec($this,$this->vocabulary->SUB_CLASS_OF(),$index);
+ $returnIndex=array();
+ foreach ($statements as $statement)
+ {
+ $objectLabel=$statement->getLabelObject();
+ if (!in_array($objectLabel,$returnIndex))
+ {
+ $returnIndex[]=$objectLabel;
+ $return[]=$this->model->createOntClass($objectLabel);
+ }
+ }
+ return $return;
+ }
+
+ /**
+ * Remove the given class from the sub-classes of this class.
+ *
+ * @param object ResResource $resResource
+ * @return boolean
+ * @access public
+ */
+ function removeSubClass($resResource)
+ {
+ return $this->model->remove(new Statement($resResource,$this->vocabulary->SUB_CLASS_OF(),$this));
+ }
+
+ /**
+ * Remove the given class from the super-classes of this class.
+ *
+ * @param object ResResource $resResource
+ * @return boolean
+ * @access public
+ */
+ function removeSuperClass($resResource)
+ {
+ return $this->removeProperty($this->vocabulary->SUB_CLASS_OF(),$resResource);
+ }
+
+ /**
+ * Assert that this class is super-class of the given class.
+ * Any existing statements for subClassOf on prop will be removed.
+ *
+ * @param object ResResource $resResource
+ * @access public
+ */
+ function setSubClass($resResource)
+ {
+ foreach ($this->listSubClasses() as $oldRes)
+ {
+ $this->removeSubClass($oldRes);
+ }
+ $this->addSubClass($resResource);
+ }
+
+ /**
+ * Assert that this class is sub-class of the given class.
+ * Any existing statements for subClassOf on prop will be removed.
+ *
+ * @param object ResResource $resResource
+ * @access public
+ */
+ function setSuperClass($resResource)
+ {
+ $this->setPropertyValue($this->vocabulary->SUB_CLASS_OF(),$resResource);
+ }
+
+ /**
+ * Answer a resource that represents an instance of this OntClass and Individual
+ * node in this model.
+ * If a resource with the given uri exists in the model, it will be re-used.
+ * If not, a new one is created in the updateable sub-model of the ontology model.
+ *
+ * @param string $uri
+ * @return object Individual
+ * @access public
+ */
+ function createInstance($uri = null)
+ {
+ $instance = $this->model->createIndividual($uri);
+ $instance->setInstanceRdfType($this);
+ return $instance;
+ }
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/text-base/OntModel.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/text-base/OntModel.php.svn-base
new file mode 100755
index 00000000..8741d5fa
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/text-base/OntModel.php.svn-base
@@ -0,0 +1,169 @@
+
+*
+*
+* @package ontModel
+* @access public
+**/
+class OntModel extends ResModel
+{
+ /**
+ * Holds a reference to the assoiated vocabulary.
+ * @var object
+ * @access private
+ */
+ var $vocabulary;
+
+
+ /**
+ * Constructor.
+ * You have to supply a memmodel/dbmodel/infmodel to save the statements and a vocabulary
+ *
+ * @param object Model $model
+ * @access public
+ */
+ function OntModel(& $model,& $vocabulary)
+ {
+ parent::ResModel($model);
+ $this->vocabulary = & $vocabulary;
+ }
+
+ /**
+ * Answer a resource that represents a class description node in this model.
+ * If a resource with the given uri exists in the model, it will be re-used.
+ * If not, a new one is created in the updateable sub-model of the ontology model.
+ *
+ * @param string $uri
+ * @return object OntClass
+ * @access public
+ */
+ function createOntClass($uri = null)
+ {
+ $class = new OntClass($uri);
+ $class->setAssociatedModel($this);
+ $class->setVocabulary($this->vocabulary);
+ $class->setInstanceRdfType($this->vocabulary->ONTCLASS());
+ return $class;
+ }
+
+ /**
+ * Answer a resource that represents an Individual node in this model.
+ * If a resource with the given uri exists in the model, it will be re-used.
+ * If not, a new one is created in the updateable sub-model of the ontology model.
+ *
+ * @param string $uri
+ * @return object Individual
+ * @access public
+ */
+ function createIndividual($uri = null)
+ {
+ $individual = new Individual($uri);
+ $individual->setAssociatedModel($this);
+ $individual->setVocabulary($this->vocabulary);
+ return $individual;
+ }
+
+ /**
+ * Answer a resource that represents an OntProperty node in this model.
+ * If a resource with the given uri exists in the model, it will be re-used.
+ * If not, a new one is created in the updateable sub-model of the ontology model.
+ *
+ * @param string $uri
+ * @return object OntProperty
+ * @access public
+ */
+ function createOntProperty($uri = null)
+ {
+ $ontProperty = new OntProperty($uri);
+ $ontProperty->setAssociatedModel($this);
+ $ontProperty->setVocabulary($this->vocabulary);
+ $ontProperty->setInstanceRdfType($this->createResource(RDF_NAMESPACE_URI.RDF_PROPERTY));
+ return $ontProperty;
+ }
+
+ /**
+ * Answer an array that ranges over all of the various forms of class
+ * description resource in this model.
+ * Class descriptions include domain/range definitions, named classes and subClass constructs.
+ *
+ * @return array of object ResResource
+ * @access public
+ */
+ function listClasses()
+ {
+ //get all statements, with an rdf:type as property
+ $statements= $this->find(null,$this->vocabulary->TYPE(),null);
+ $return = array();
+ $returnIndex=array();
+ foreach ($statements as $statement)
+ {
+ $objectLabel=$statement->getLabelObject();
+ //if it's about a typed Individual
+ if ($objectLabel!=RDF_SCHEMA_URI.RDFS_CLASS)
+ {
+ if (!in_array($objectLabel,$returnIndex))
+ {
+ $returnIndex[]=$objectLabel;
+ $return[]=$statement->getObject();
+ }
+ } else
+ //if it's a "class1 rdf:type rdf:class" construct
+ {
+ $subjectLabel=$statement->getLabelSubject();
+ if (!in_array($subjectLabel,$returnIndex))
+ {
+ $returnIndex[]=$subjectLabel;
+ $return[]=$statement->getSubject();
+ }
+ }
+ }
+ //find all statements about SubClassConstructs
+ $statements= $this->find(null,$this->vocabulary->SUB_CLASS_OF(),null);
+ foreach ($statements as $statement)
+ {
+ //add the statements object to the result
+ $objectLabel=$statement->getLabelObject();
+ if (!in_array($objectLabel,$returnIndex))
+ {
+ $returnIndex[]=$objectLabel;
+ $return[]=$statement->getObject();
+ }
+ }
+ foreach ($statements as $statement)
+ {
+ //add the statements subject to the result
+ $objectLabel=$statement->getLabelSubject();
+ if (!in_array($objectLabel,$returnIndex))
+ {
+ $returnIndex[]=$objectLabel;
+ $return[]=$statement->getSubject();
+ }
+ }
+ return $return;
+ }
+}
+?>
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/text-base/OntModelP.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/text-base/OntModelP.php.svn-base
new file mode 100755
index 00000000..03883ac3
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/text-base/OntModelP.php.svn-base
@@ -0,0 +1,24 @@
+
+* @package ontModel
+*
+* ----------------------------------------------------------------------------------
+*/
+// Include OntModel classes
+include_once( RDFAPI_INCLUDE_DIR . PACKAGE_RESMODEL);
+require_once( RDFAPI_INCLUDE_DIR . 'ontModel/OntVocabulary.php');
+require_once( RDFAPI_INCLUDE_DIR . 'ontModel/RdfsVocabulary.php');
+require_once( RDFAPI_INCLUDE_DIR . 'ontModel/OntModel.php');
+require_once( RDFAPI_INCLUDE_DIR . 'ontModel/OntResource.php');
+require_once( RDFAPI_INCLUDE_DIR . 'ontModel/OntProperty.php');
+require_once( RDFAPI_INCLUDE_DIR . 'ontModel/OntClass.php');
+require_once( RDFAPI_INCLUDE_DIR . 'ontModel/Individual.php');
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/text-base/OntProperty.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/text-base/OntProperty.php.svn-base
new file mode 100755
index 00000000..38cf309f
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/text-base/OntProperty.php.svn-base
@@ -0,0 +1,390 @@
+
+*
+*
+* @package ontModel
+* @access public
+**/
+
+class OntProperty extends OntResource
+{
+ /**
+ * Constructor.
+ * You can supply a URI.
+ *
+ * @param string $uri
+ * @access public
+ */
+ function OntProperty($uri = null)
+ {
+ parent::OntResource($uri);
+ }
+
+ /**
+ * Add a resource representing the domain of this property.
+ *
+ * @param object ResResource $resResource
+ * @return boolean
+ * @access public
+ */
+ function addDomain($resResource)
+ {
+ return $this->addProperty($this->vocabulary->DOMAIN(),$resResource);
+ }
+
+ /**
+ * Add a resource representing the range of this property.
+ *
+ * @param object ResResource $resResource
+ * @return boolean
+ * @access public
+ */
+ function addRange($resResource)
+ {
+ return $this->addProperty($this->vocabulary->RANGE(),$resResource);
+ }
+
+ /**
+ * Add a sub-property of this property.
+ *
+ * @param object ResProperty $resProperty
+ * @return boolean
+ * @access public
+ */
+ function addSubProperty($resProperty)
+ {
+ return $resProperty->addProperty($this->vocabulary->SUB_PROPERTY_OF(),$this);
+ }
+
+ /**
+ * Add a super-property of this property.
+ *
+ * @param object ResProperty $resProperty
+ * @return boolean
+ * @access public
+ */
+ function addSuperProperty($resProperty)
+ {
+ return $this->addProperty($this->vocabulary->SUB_PROPERTY_OF(),$resProperty);
+ }
+
+ /**
+ * Answer a OntClass that represents the domain class of this property.
+ * If there is more than one such resource, an arbitrary selection is made.
+ *
+ * @return object OntClass
+ * @access public
+ */
+ function getDomain()
+ {
+ return $this->getPropertyValue($this->vocabulary->DOMAIN(),'OntClass');
+ }
+
+ /**
+ * Answer a OntClass that represents the range class of this property.
+ * If there is more than one such resource, an arbitrary selection is made.
+ *
+ * @return object OntClass
+ * @access public
+ */
+ function getRange()
+ {
+ return $this->getPropertyValue($this->vocabulary->RANGE(),'OntClass');
+ }
+
+ /**
+ * Answer a property that is the sub-property of this property.
+ * If there is more than one such property, an arbitrary selection is made.
+ *
+ * @return object OntProperty
+ * @access public
+ */
+ function getSubProperty()
+ {
+ $statement = $this->model->findFirstMatchingStatement(null,$this->vocabulary->SUB_PROPERTY_OF(),$this);
+ if ($statement !== null)
+ return new OntProperty($statement->getLabelSubject());
+
+ return null;
+ }
+
+ /**
+ * Answer a property that is the super-property of this property.
+ * If there is more than one such property, an arbitrary selection is made.
+ *
+ * @return object OntProperty
+ * @access public
+ */
+ function getSuperProperty()
+ {
+ return $this->getPropertyValue($this->vocabulary->SUB_PROPERTY_OF(),'OntProperty');
+ }
+
+ /**
+ * Answer true if the given resource a class specifying the domain of this property.
+ *
+ * @param object ResResource $resResource
+ * @return boolean
+ * @access public
+ */
+ function hasDomain($resResource)
+ {
+ return $this->hasProperty($this->vocabulary->DOMAIN(),$resResource);
+ }
+
+ /**
+ * Answer true if the given resource a class specifying the range of this property.
+ *
+ * @param object ResResource $resResource
+ * @return boolean
+ * @access public
+ */
+ function hasRange($resResource)
+ {
+ return $this->hasProperty($this->vocabulary->RANGE(),$resResource);
+ }
+
+ /**
+ * Answer true if the given property is a sub-property of this property.
+ * If $direct is set to true, only consider the direcly adjacent
+ * properties in the property hierarchy
+ *
+ * @param object ResResource $resProperty
+ * @param boolean $direct
+ * @return boolean
+ * @access public
+ */
+ function hasSubProperty($resProperty, $direct = true)
+ {
+ if ($direct)
+ return $resProperty->hasProperty($this->vocabulary->SUB_PROPERTY_OF(),$this);
+
+ $index=array();
+ return ($this->_getSubAttributeStatementsRec($this,$this->vocabulary->SUB_PROPERTY_OF(),$index,$resProperty) === true);
+ }
+
+ /**
+ * Answer true if the given property is a super-property of this property.
+ * If $direct is set to true, only consider the direcly adjacent
+ * properties in the property hierarchy
+ *
+ * @param object ResResource $resProperty
+ * @param boolean $direct
+ * @return boolean
+ * @access public
+ */
+ function hasSuperProperty($resProperty, $direct = true)
+ {
+ if ($direct)
+ return $this->hasProperty($this->vocabulary->SUB_PROPERTY_OF(),$resProperty);
+
+ $index=array();
+ return ($this->_getSuperAttributeStatementsRec($this,$this->vocabulary->SUB_PROPERTY_OF(),$index,$resProperty) === true);
+ }
+
+ /**
+ * Answer an array of all of the declared domain classes of this property.
+ * Each element of the iterator will be an OntClass.
+ *
+ * @return array of OntClasses
+ * @access public
+ */
+ function listDomain()
+ {
+ return $this->listProperty($this->vocabulary->DOMAIN(),'OntClass');
+ }
+
+ /**
+ * Answer an array of all of the declared range classes of this property.
+ * Each element of the iterator will be an OntClass.
+ *
+ * @return array of OntClasses
+ * @access public
+ */
+ function listRange()
+ {
+ return $this->listProperty($this->vocabulary->RANGE(),'OntClass');
+ }
+
+ /**
+ * Answer an array of all the properties that are declared to be
+ * sub-properties of this property. Each element of the iterator will be an
+ * OntProperty.
+ * If $direct is set to true, only consider the direcly adjacent
+ * properties in the property hierarchy
+ *
+ * @param boolean $direct
+ * @return array of OntProperties
+ * @access public
+ */
+ function listSubProperties($direct = true)
+ {
+ $return = array();
+ if ($direct)
+ {
+ $statements = $this->model->find(null,$this->vocabulary->SUB_PROPERTY_OF(),$this);
+ } else
+ {
+ $index = array();
+ $statements = $this->_getSubAttributeStatementsRec($this,$this->vocabulary->SUB_PROPERTY_OF(),$index);
+ }
+
+ $returnIndex=array();
+ foreach ($statements as $statement)
+ {
+ $objectLabel=$statement->getLabelSubject();
+ if (!in_array($objectLabel,$returnIndex))
+ {
+ $returnIndex[]=$objectLabel;
+ $return[]=new OntProperty($statement->getLabelSubject());
+ }
+ }
+ return $return;
+ }
+
+ /**
+ * Answer an array of all the properties that are declared to be
+ * super-properties of this property. Each element of the iterator will be an
+ * OntProperty.
+ * If $direct is set to true, only consider the direcly adjacent
+ * properties in the property hierarchy
+ *
+ * @param boolean $direct
+ * @return array of OntProperties
+ * @access public
+ */
+ function listSuperProperties($direct = true)
+ {
+ $return = array();
+ if ($direct)
+ return $this->listProperty($this->vocabulary->SUB_PROPERTY_OF(),'OntProperty');
+
+ $index=array();
+ $statements = $this->_getSuperAttributeStatementsRec($this,$this->vocabulary->SUB_PROPERTY_OF(),$index);
+ $returnIndex=array();
+ foreach ($statements as $statement)
+ {
+ $objectLabel=$statement->getLabelObject();
+ if (!in_array($objectLabel,$returnIndex))
+ {
+ $returnIndex[]=$objectLabel;
+ $return[]=new OntProperty($statement->getLabelObject());
+ }
+ }
+ return $return;
+ }
+
+ /**
+ * Remove the given class from the stated domain(s) of this property.
+ *
+ * @param object ResResource $resResource
+ * @return boolean
+ * @access public
+ */
+ function removeDomain($resResource)
+ {
+ return $this->removeProperty($this->vocabulary->DOMAIN(),$resResource);
+ }
+
+ /**
+ * Remove the given class from the stated range(es) of this property.
+ *
+ * @param object ResResource $resResource
+ * @return boolean
+ * @access public
+ */
+ function removeRange($resResource)
+ {
+ return $this->removeProperty($this->vocabulary->RANGE(),$resResource);
+ }
+
+ /**
+ * Remove the given property from the sub-properties of this property.
+ *
+ * @param object ResProperty $resProperty
+ * @return boolean
+ * @access public
+ */
+ function removeSubProperty($resProperty)
+ {
+ return $this->model->remove(new Statement($resProperty,$this->vocabulary->SUB_PROPERTY_OF(),$this));
+ }
+
+ /**
+ * Remove the given property from the super-properties of this property.
+ *
+ * @param object ResProperty $resProperty
+ * @return boolean
+ * @access public
+ */
+ function removeSuperProperty($resProperty)
+ {
+ return $this->removeProperty($this->vocabulary->SUB_PROPERTY_OF(),$resProperty);
+ }
+
+ /**
+ * Assert that the given resource represents the class of individuals
+ * that form the domain of this property. Any existing domain statements
+ * for this property are removed.
+ *
+ * @param object ResResource $resResource
+ * @access public
+ */
+ function setDomain($resResource)
+ {
+ $this->setPropertyValue($this->vocabulary->DOMAIN(),$resResource);
+ }
+
+ /**
+ * Assert that the given resource represents the class of individuals
+ * that form the range of this property. Any existing range statements
+ * for this property are removed.
+ *
+ * @param object ResResource $resResource
+ * @access public
+ */
+ function setRange($resResource)
+ {
+ $this->setPropertyValue($this->vocabulary->RANGE(),$resResource);
+ }
+
+ /**
+ * Assert that this property is super-property of the given property.
+ * Any existing statements for superPropertyOf on prop will be removed.
+ *
+ * @param object ResProperty $resProperty
+ * @access public
+ */
+ function setSubProperty($resProperty)
+ {
+ foreach ($this->listSubProperties() as $oldResProperty)
+ {
+ $this->removeSubProperty($oldResProperty);
+ }
+
+ $this->addSubProperty($resProperty);
+ }
+
+ /**
+ * Assert that this property is sub-property of the given property.
+ * Any existing statements for subPropertyOf on prop will be removed.
+ *
+ * @param object ResProperty $resProperty
+ * @access public
+ */
+ function setSuperProperty($resProperty)
+ {
+ $this->setPropertyValue($this->vocabulary->SUB_PROPERTY_OF(),$resProperty);
+ }
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/text-base/OntResource.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/text-base/OntResource.php.svn-base
new file mode 100755
index 00000000..cc78df3e
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/text-base/OntResource.php.svn-base
@@ -0,0 +1,739 @@
+
+*
+*
+* @package ontModel
+* @access public
+**/
+class OntResource extends ResResource
+{
+ /**
+ * Holds a reference to the assoiated vocabulary
+ * @var object
+ * @access private
+ */
+ var $vocabulary;
+
+ /**
+ * Holds a resResource of the type, which is this ontResource of.
+ * If this value is set, the ontModel will add an additional
+ * statement about this resource and the fiven rdf:type
+ * @var object
+ * @access private
+ */
+ var $rdfType;
+
+
+ /**
+ * Constructor
+ * You can supply a uri
+ *
+ * @param string $uri
+ * @access public
+ */
+ function OntResource($uri = null)
+ {
+ $this->rdfType=false;
+ parent::ResResource($uri);
+ }
+
+ /**
+ * Sets the reference to the assoiated vocabulary
+ *
+ * @param object OntVocabulary $vocabulary
+ * @access public
+ */
+ function setVocabulary(& $vocabulary)
+ {
+ $this->vocabulary = & $vocabulary;
+ }
+
+ /**
+ * Add the given comment to this resource.
+ *
+ * @param object ResLiteral $comment
+ * @return boolean
+ * @access public
+ */
+ function addComment($comment)
+ {
+ return $this->addProperty($this->vocabulary->COMMENT(),$comment);
+ }
+
+ /**
+ * Answer the comment string for this object. If there is more than one such resource, an arbitrary selection is made.
+ *
+ * @return object ResLiteral or NULL
+ * @access public
+ */
+ function getComment()
+ {
+ return $this->getPropertyValue($this->vocabulary->COMMENT());
+ }
+
+ /**
+ * Add a resource that is declared to provide a definition of this resource.
+ *
+ * @param object ResResource $resResource
+ * @return boolean
+ * @access public
+ */
+ function addIsDefinedBy($resResource)
+ {
+ return $this->addProperty($this->vocabulary->IS_DEFINED_BY(),$resResource);
+ }
+
+ /**
+ * Answer a resource that is declared to provide a definition of this resource.
+ * If there is more than one such resource, an arbitrary selection is made.
+ *
+ * @return object ResResource
+ * @access public
+ */
+ function getIsDefinedBy()
+ {
+ return $this->getPropertyValue($this->vocabulary->IS_DEFINED_BY());
+ }
+
+ /**
+ * Add the given Label to this resource
+ *
+ * @param object ResLiteral $resLiteral
+ * @return boolean
+ * @access public
+ */
+ function addLabelProperty($resLiteral)
+ {
+ return $this->addProperty($this->vocabulary->LABEL(),$resLiteral);
+ }
+
+ /**
+ * Answer the label ResLiteral for this object.
+ * If there is more than one such resource, an arbitrary selection is made.
+ *
+ * @param string $uri
+ * @return object ResResource
+ * @access public
+ */
+ function getLabelProperty()
+ {
+ return $this->getPropertyValue($this->vocabulary->LABEL());
+ }
+
+ /**
+ * Add the given class as one of the rdf:type's for this resource.
+ *
+ * @param object ResResource $resResource
+ * @return boolean
+ * @access public
+ */
+ function addRDFType($resResource)
+ {
+ return $this->addProperty($this->vocabulary->TYPE(),$resResource);
+ }
+
+ /**
+ * Answer the rdf:type (ie the class) of this resource.
+ * If there is more than one type for this resource, the return value will
+ * be one of the values, but it is not specified which one
+ * (nor that it will consistently be the same one each time).
+ *
+ * @return object ResResource
+ * @access public
+ */
+ function getRDFType()
+ {
+ return $this->getPropertyValue($this->vocabulary->TYPE());
+ }
+
+ /**
+ * Add a resource that is declared to provided additional
+ * information about the definition of this resource.
+ *
+ * @param object ResResource $resResource
+ * @return boolean
+ * @access public
+ */
+ function addSeeAlso($resResource)
+ {
+ return $this->addProperty($this->vocabulary->SEE_ALSO(),$resResource);
+ }
+
+ /**
+ * Answer a resource that provides additional information about this resource.
+ * If more than one such resource is defined, make an arbitrary choice.
+ *
+ * @return object ResResource
+ * @access public
+ */
+ function getSeeAlso()
+ {
+ return $this->getPropertyValue($this->vocabulary->SEE_ALSO());
+ }
+
+ /**
+ * Answer a view of this resource as a class
+ *
+ * @return object OntClass
+ * @access public
+ */
+ function asClass()
+ {
+ return $this->model->createOntClass($this->uri);
+ }
+
+ /**
+ * Answer a view of this resource as an Individual
+ *
+ * @return object Individual
+ * @access public
+ */
+ function asIndividual()
+ {
+ return $this->model->createIndividual($this->uri);
+ }
+
+ /**
+ * Answer a view of this resource as a property
+ *
+ * @return object OntProperty
+ * @access public
+ */
+ function asOntProperty()
+ {
+ return $this->model->createOntProperty($this->uri);
+ }
+
+ /**
+ * Answer a reference to the ontology language profile that governs the
+ * ontology model to which this ontology resource is attached.
+ *
+ * @param string $uri
+ * @return object OntClass
+ * @access public
+ */
+ function getVocabulary()
+ {
+ return $this->vocabulary ;
+ }
+
+ /**
+ * Answer the value of a given RDF property for this resource as $returnType, or null
+ * if it doesn't have one. If there is more than one RDF statement with
+ * the given property for the current value, it is not defined which of
+ * the values will be returned.
+ * The following return Types are supported: 'OntClass', 'OntProperty', 'Individual', and 'ResResource'
+ * Default is 'ResResource'
+ *
+ * @param object ResResource $property
+ * @param string $returnType
+ * @return object OntClass
+ * @access public
+ */
+ function getPropertyValue($property, $returnType = 'ResResource')
+ {
+ $statement=$this->getProperty($property);
+ if ($statement===null)
+ return null;
+
+ switch ($returnType)
+ {
+ case 'OntClass':
+ return $this->model->createOntClass($statement->getLabelObject());
+ break;
+
+ case 'OntProperty':
+ return $this->model->createOntProperty($statement->getLabelObject());
+ break;
+
+ case 'Individual':
+ return $this->model->createIndividual($statement->getLabelObject());
+ break;
+
+ default:
+ return $statement->getObject();
+ break;
+ }
+ }
+
+ /**
+ * Answer true if this resource has the given comment.
+ *
+ * @param object ResLiteral $resLiteral
+ * @return boolean
+ * @access public
+ */
+ function hasComment($resLiteral)
+ {
+ return $this->hasProperty($this->vocabulary->COMMENT(),$resLiteral);
+ }
+
+ /**
+ * Answer true if this resource has the given label.
+ *
+ * @param object ResLiteral $resLiteral
+ * @return boolean
+ * @access public
+ */
+ function hasLabelProperty($resLiteral)
+ {
+ return $this->hasProperty($this->vocabulary->LABEL(),$resLiteral);
+ }
+
+ /**
+ * Answer true if this resource has the given rdf:type.
+ *
+ * @param object ResResource $ontClass
+ * @return boolean
+ * @access public
+ */
+ function hasRDFType($ontClass)
+ {
+ return $this->hasProperty($this->vocabulary->TYPE(),$ontClass);
+ }
+
+ /**
+ * Answer true if this resource has the given resource as a source
+ * of additional information.
+ *
+ * @param object ResResource $resResource
+ * @return boolean
+ * @access public
+ */
+ function hasSeeAlso($resResource)
+ {
+ return $this->hasProperty($this->vocabulary->SEE_ALSO(),$resResource);
+ }
+
+ /**
+ * Answer true if this resource is defined by the given resource.
+ *
+ * @param object ResResource $resResource
+ * @return boolean
+ * @access public
+ */
+ function isDefinedBy($resResource)
+ {
+ return $this->hasProperty($this->vocabulary->IS_DEFINED_BY(),$resResource);
+ }
+
+ /**
+ * Answer an array of all of the comment literals for this resource.
+ *
+ * @param string $language
+ * @return array
+ * @access public
+ */
+ function listComments($language)
+ {
+ $return=$this->listProperty($this->vocabulary->COMMENT());
+ if ($language === false)
+ return $return;
+
+ foreach ($return as $key => $resLiteral)
+ {
+ if (!is_a($resLiteral,'ResLiteral') || $resLiteral->getLanguage() != $language)
+ unset ($return[$key]);
+ }
+ return $return;
+ }
+
+ /**
+ * Answer an array of all of the resources that are declared to define this resource.
+ *
+ * @return array
+ * @access public
+ */
+ function listIsDefinedBy()
+ {
+ return $this->listProperty($this->vocabulary->IS_DEFINED_BY());
+ }
+
+ /**
+ * Answer an array of all of the label literals for this resource, with the given
+ * language, if $language is set.
+ *
+ * @return array
+ * @access public
+ */
+ function listLabelProperties($language = false)
+ {
+ $return=$this->listProperty($this->vocabulary->LABEL());
+ if ($language === false)
+ return $return;
+
+ foreach ($return as $key => $resLiteral)
+ {
+ if (!is_a($resLiteral,'ResLiteral') || $resLiteral->getLanguage() != $language)
+ unset ($return[$key]);
+ }
+ return $return;
+
+ }
+
+ /**
+ * Answer an array of the RDF classes to which this resource belongs.
+ * If $direct is true, only answer those resources that are direct types of
+ * this resource, not the super-classes of the class etc.
+ *
+ * @param boolean $direct
+ * @return array Array of ResResources
+ * @access public
+ */
+ function listRDFTypes($direct = true)
+ {
+ return $this->listProperty($this->vocabulary->TYPE());
+ }
+
+ /**
+ * Answer an array of all of the resources that are declared to
+ * provide addition information about this resource.
+ *
+ * @return array Array of ResResources
+ * @access public
+ */
+ function listSeeAlso()
+ {
+ return $this->listProperty($this->vocabulary->SEE_ALSO());
+ }
+
+ /**
+ * Answer an array of values of a given RDF property for this resource as $returnType, or null
+ * if it doesn't have one.
+ * The following return Types are supported: 'OntClass', 'OntProperty', 'Individual', and 'ResResource'
+ * Default is 'ResResource'
+ *
+ * @param object ResResource $property
+ * @param string $returnType
+ * @return array of ResResources
+ * @access public
+ */
+ function listProperty($property, $returnType = 'OntResource')
+ {
+ $return=array();
+ $resArray = $this->listProperties($property);
+ foreach ($resArray as $statement)
+ {
+ switch ($returnType)
+ {
+ case 'OntClass':
+ $return[]=$this->model->createOntClass($statement->getLabelObject());
+ break;
+
+ case 'OntProperty':
+ $return[]=$this->model->createOntProperty($statement->getLabelObject());
+ break;
+
+ case 'Individual':
+ $return[]=$this->model->createIndividual($statement->getLabelObject());
+ break;
+
+ default:
+ $return[]=$statement->getObject();
+ break;
+ }
+ }
+ return $return;
+ }
+
+ /**
+ * Remove the statement that the given ResLiteral is a comment on this resource.
+ * Returns true, if a statement was removed
+ *
+ * @param object ResLiteral $resLiteral
+ * @return boolean
+ * @access public
+ */
+ function removeComment($resLiteral)
+ {
+ return $this->removeProperty($this->vocabulary->COMMENT(),$resLiteral);
+ }
+
+ /**
+ * Remove the statement that this resource is defined by the given resource.
+ *
+ * @param object ResResource $resResource
+ * @return boolean
+ * @access public
+ */
+ function removeDefinedBy($resResource)
+ {
+ return $this->removeProperty($this->vocabulary->IS_DEFINED_BY(),$resResource);
+ }
+
+ /**
+ * Remove the statement that the given ResLiteral is a label on this resource.
+ * Returns true, if a statement was removed
+ *
+ * @param object ResLiteral $resLiteral
+ * @return boolean
+ * @access public
+ */
+ function removeLabelProperty($resLiteral)
+ {
+ return $this->removeProperty($this->vocabulary->LABEL(),$resLiteral);
+ }
+
+ /**
+ * Remove the specific property-value pair from this resource.
+ *
+ * @param object ResResource $property
+ * @param object ResResource $value
+ * @return boolean
+ * @access public
+ */
+ function removeProperty($property, $value)
+ {
+ return $this->model->remove(new Statement($this,$property,$value));
+ }
+
+ /**
+ * Remove the statement that this resource is of the given RDF type.
+ *
+ * @param object ResResource $resResource
+ * @return boolean
+ * @access public
+ */
+ function removeRDFType($resResource)
+ {
+ return $this->removeProperty($this->vocabulary->TYPE(),$resResource);
+ }
+
+ /**
+ * Remove the statement indicating the given resource as a source of
+ * additional information about this resource.
+ *
+ * @param object ResResource $resResource
+ * @return boolean
+ * @access public
+ */
+ function removeSeeAlso($resResource)
+ {
+ return $this->removeProperty($this->vocabulary->SEE_ALSO(),$resResource);
+ }
+
+ /**
+ * Assert that the given string is the comment on this resource.
+ * Any existing statements for comment will be removed.
+ *
+ * @param object ResLiteral $resLiteral
+ * @access public
+ */
+ function setComment($resLiteral)
+ {
+ $this->setPropertyValue($this->vocabulary->COMMENT(),$resLiteral);
+ }
+
+ /**
+ * Assert that the given resource provides a source of definitions about this resource.
+ * Any existing statements for isDefinedBy will be removed.
+ *
+ * @param object ResResource $resResource
+ * @access public
+ */
+ function setIsDefinedBy($resResource)
+ {
+ $this->setPropertyValue($this->vocabulary->IS_DEFINED_BY(),$resResource);
+ }
+
+ /**
+ * Assert that the given string is the label on this resource.
+ * Any existing statements for comment will be removed.
+ *
+ * @param object ResLiteral $resLiteral
+ * @access public
+ */
+ function setLabelProperty($resLiteral)
+ {
+ $this->setPropertyValue($this->vocabulary->LABEL(),$resLiteral);
+ }
+
+ /**
+ * Set the value of the given property of this ontology resource to the given value.
+ * Maintains the invariant that there is at most one value of the property for a
+ * given resource, so existing property values are first removed.
+ * To add multiple properties, use addProperty.
+ *
+ * @param object ResResource $property
+ * @param object ResResource $value
+ * @access public
+ */
+ function setPropertyValue($property, $value)
+ {
+ $this->removeAll($property);
+ $this->addProperty($property,$value);
+ }
+
+ /**
+ * Set the RDF type (ie the class) for this resource,
+ * replacing any existing rdf:type property. Any existing statements
+ * for the RDF type will first be removed.
+ *
+ * @param object ResResource $resResource
+ * @access public
+ */
+ function setRDFType($resResource)
+ {
+ $this->setPropertyValue($this->vocabulary->TYPE(),$resResource);
+ }
+
+ /**
+ * Add a resource that is declared to provided additional information
+ * about the definition of this resource
+ *
+ * @param object ResResource $resResource
+ * @access public
+ */
+ function setSeeAlso($resResource)
+ {
+ $this->setPropertyValue($this->vocabulary->SEE_ALSO(),$resResource);
+ }
+
+ /**
+ * Returns an array of ResResources that are recursively connected by $attribute
+ * in superProperty direction.
+ * If $onlyFindThisResResource is set to a ResResource, this function returns boolean
+ * if this distinct resource recursively is connected to the $startResource.
+ *
+ * @param object ResResource $startResource
+ * @param object ResResource $attribute
+ * @param array $attribute
+ * @param object ResResource $onlyFindThisResResource
+ * @return array OR boolean
+ * @access private
+ */
+ function _getSuperAttributeStatementsRec(& $startResource,& $attribute,& $attributeIndex, $onlyFindThisResResource = false)
+ {
+
+ $return = $startResource->listProperties($attribute);
+
+ if ($onlyFindThisResResource)
+ {
+ foreach ($return as $statement)
+ {
+ if ($onlyFindThisResResource->equals($statement->getObject()))
+ return true;
+ }
+ }
+
+ foreach ($return as $statement)
+ {
+ $attributeLabel=$statement->getLabelObject();
+ if (!in_array($attributeLabel,$attributeIndex))
+ {
+ $attributeIndex[]=$attributeLabel;
+ $subReturn = $this->_getSuperAttributeStatementsRec($statement->getObject(), $attribute, $attributeIndex, $onlyFindThisResResource);
+ }
+ }
+ if (isset($subReturn))
+ {
+ if ($subReturn === true)
+ return true;
+ return array_merge($return,$subReturn);
+ }
+
+ return $return;
+ }
+
+ /**
+ * Returns an array of ResResources that are recursively connected by $attribute
+ * in subProperty direction.
+ * If $onlyFindThisResResource is set to a ResResource, this function returns boolean
+ * if this distinct resource recursively is connected to the $startResource.
+ *
+ * @param object ResResource $startResource
+ * @param object ResResource $attribute
+ * @param array $attribute
+ * @param object ResResource $onlyFindThisResResource
+ * @return array OR boolean
+ * @access private
+ */
+ function _getSubAttributeStatementsRec(& $startResource,& $attribute,& $attributeIndex, $onlyFindThisResResource = false)
+ {
+
+ $return = $this->model->find(null,$attribute,$startResource);
+
+ if ($onlyFindThisResResource)
+ {
+ foreach ($return as $statement)
+ {
+ if ($onlyFindThisResResource->equals($statement->getSubject()))
+ return true;
+ }
+ }
+
+ foreach ($return as $statement)
+ {
+ $attributeLabel=$statement->getLabelSubject();
+ if (!in_array($attributeLabel,$attributeIndex))
+ {
+ $attributeIndex[]=$attributeLabel;
+ $subReturn = $this->_getSubAttributeStatementsRec($statement->getSubject(), $attribute, $attributeIndex, $onlyFindThisResResource);
+ }
+ }
+ if (isset($subReturn))
+ {
+ if ($subReturn === true)
+ return true;
+ return array_merge($return,$subReturn);
+ }
+
+ return $return;
+ }
+
+ /**
+ * Add a property to this resource.
+ * A statement with this resource as the subject, p as the predicate and o
+ * as the object is added to the model associated with this resource.
+ * If $this->rdfType is set, an additional statement about it's type
+ * is added.
+ *
+ * @param ResResource $property
+ * @param ResResource/ResLiteral $object
+ * @return object ResResource
+ * @access public
+ */
+ function addProperty($property,$object)
+ {
+ if ($this->rdfType !== false)
+ if (!$this->hasRDFType($this->rdfType))
+ $this->model->add(new Statement($this,$this->vocabulary->TYPE(),$this->rdfType));
+
+ return parent:: addProperty($property,$object);
+ }
+
+ /**
+ * Sets the rdf:type, that this distinct resource is instance of.
+ * If this value is set, the ontModel will add an additional
+ * statement about this resource and the fiven rdf:type
+ *
+ * @param object ResResource $resResource
+ * @access public
+ */
+ function setInstanceRdfType($resResource)
+ {
+ $this->rdfType = $resResource;
+ }
+
+ /**
+ * returns the rdf:type, that this distinct resource is instance of.
+ *
+ * @return object ResResource $resResource
+ * @access public
+ */
+ function getInstanceRdfType()
+ {
+ return $this->rdfType;
+ }
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/text-base/OntVocabulary.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/text-base/OntVocabulary.php.svn-base
new file mode 100755
index 00000000..f6d29a08
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/text-base/OntVocabulary.php.svn-base
@@ -0,0 +1,25 @@
+
+*
+*
+* @package ontModel
+* @access public
+**/
+class OntVocabulary
+{
+
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/text-base/RdfsVocabulary.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/text-base/RdfsVocabulary.php.svn-base
new file mode 100755
index 00000000..310af9bc
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/.svn/text-base/RdfsVocabulary.php.svn-base
@@ -0,0 +1,143 @@
+
+*
+*
+* @package ontModel
+* @access public
+**/
+class RdfsVocabulary extends OntVocabulary
+{
+
+ /**
+ * Answer the resource that represents the class 'class' in this vocabulary.
+ *
+ * @return object ResResource
+ * @access public
+ */
+ function ONTCLASS()
+ {
+ return new ResResource(RDF_SCHEMA_URI.RDFS_CLASS);
+ }
+
+ /**
+ * Answer the predicate that denotes the domain of a property.
+ *
+ * @return object ResProperty
+ * @access public
+ */
+ function DOMAIN()
+ {
+ return new ResProperty(RDF_SCHEMA_URI.RDFS_DOMAIN);
+ }
+
+
+ /**
+ * Answer the predicate that denotes comment annotation on an ontology element.
+ *
+ * @return object ResProperty
+ * @access public
+ */
+ function COMMENT()
+ {
+ return new ResProperty(RDF_SCHEMA_URI.RDFS_COMMENT);
+ }
+
+ /**
+ * Answer the predicate that denotes isDefinedBy annotation on an ontology element
+ *
+ * @return object ResProperty
+ * @access public
+ */
+ function IS_DEFINED_BY()
+ {
+ return new ResProperty(RDF_SCHEMA_URI.RDFS_IS_DEFINED_BY);
+ }
+
+ /**
+ * Answer the predicate that denotes label annotation on an ontology element
+ *
+ * @return object ResProperty
+ * @access public
+ */
+ function LABEL()
+ {
+ return new ResProperty(RDF_SCHEMA_URI.RDFS_LABEL);
+ }
+
+ /**
+ * Answer the predicate that denotes the domain of a property.
+ *
+ * @return object ResProperty
+ * @access public
+ */
+ function RANGE()
+ {
+ return new ResProperty(RDF_SCHEMA_URI.RDFS_RANGE);
+ }
+
+ /**
+ * Answer the predicate that denotes seeAlso annotation on an ontology element
+ *
+ * @return object ResProperty
+ * @access public
+ */
+ function SEE_ALSO()
+ {
+ return new ResProperty(RDF_SCHEMA_URI.RDFS_SEE_ALSO);
+ }
+
+ /**
+ * Answer the predicate that denotes that one class is a sub-class of another.
+ *
+ * @return object ResProperty
+ * @access public
+ */
+ function SUB_CLASS_OF()
+ {
+ return new ResProperty(RDF_SCHEMA_URI.RDFS_SUBCLASSOF);
+ }
+
+ /**
+ * Answer the predicate that denotes that one property is a sub-property of another.
+ *
+ * @return object ResProperty
+ * @access public
+ */
+ function SUB_PROPERTY_OF()
+ {
+ return new ResProperty(RDF_SCHEMA_URI.RDFS_SUBPROPERTYOF);
+ }
+
+ /**
+ * Answer the string that is the namespace prefix for this vocabulary
+ *
+ * @return string
+ * @access public
+ */
+ function NAMESPACE()
+ {
+ return RDF_SCHEMA_URI;
+ }
+
+ /**
+ * Answer the predicate that denotes the rdf:type property.
+ *
+ * @return object ResProperty
+ * @access public
+ */
+ function TYPE()
+ {
+ return new ResProperty(RDF_NAMESPACE_URI.RDF_TYPE);
+ }
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/Individual.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/Individual.php
new file mode 100755
index 00000000..6e5354a5
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/Individual.php
@@ -0,0 +1,39 @@
+
+*
+*
+* @package ontModel
+* @access public
+**/
+
+class Individual extends OntResource
+{
+
+ /**
+ * Constructor
+ * You can supply a uri
+ *
+ * @param string $uri
+ * @access public
+ */
+ function Individual($uri = null)
+ {
+ parent::OntResource($uri);
+ }
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/OWLVocabulary.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/OWLVocabulary.php
new file mode 100755
index 00000000..8a398864
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/OWLVocabulary.php
@@ -0,0 +1,369 @@
+
+*
+*
+* @package ontModel
+* @access public
+**/
+class OWLVocabulary extends OntVocabulary
+{
+
+ /**
+ * Answer the resource that represents the class 'class' in this vocabulary.
+ *
+ * @return object ResResource
+ * @access public
+ */
+ function ONTCLASS()
+ {
+ return new ResResource(OWL_NS.'Class');
+ }
+
+ /**
+ * Answer the predicate that denotes the domain of a property.
+ *
+ * @return object ResProperty
+ * @access public
+ */
+ function DOMAIN()
+ {
+ return new ResProperty(RDF_SCHEMA_URI.RDFS_DOMAIN);
+ }
+
+
+ /**
+ * Answer the predicate that denotes comment annotation on an ontology element.
+ *
+ * @return object ResProperty
+ * @access public
+ */
+ function COMMENT()
+ {
+ return new ResProperty(RDF_SCHEMA_URI.RDFS_COMMENT);
+ }
+
+ /**
+ * Answer the predicate that denotes isDefinedBy annotation on an ontology element
+ *
+ * @return object ResProperty
+ * @access public
+ */
+ function IS_DEFINED_BY()
+ {
+ return new ResProperty(RDF_SCHEMA_URI.RDFS_IS_DEFINED_BY);
+ }
+
+ /**
+ * Answer the predicate that denotes label annotation on an ontology element
+ *
+ * @return object ResProperty
+ * @access public
+ */
+ function LABEL()
+ {
+ return new ResProperty(RDF_SCHEMA_URI.RDFS_LABEL);
+ }
+
+ /**
+ * Answer the predicate that denotes the domain of a property.
+ *
+ * @return object ResProperty
+ * @access public
+ */
+ function RANGE()
+ {
+ return new ResProperty(RDF_SCHEMA_URI.RDFS_RANGE);
+ }
+
+ /**
+ * Answer the predicate that denotes seeAlso annotation on an ontology element
+ *
+ * @return object ResProperty
+ * @access public
+ */
+ function SEE_ALSO()
+ {
+ return new ResProperty(RDF_SCHEMA_URI.RDFS_SEE_ALSO);
+ }
+
+ /**
+ * Answer the predicate that denotes that one class is a sub-class of another.
+ *
+ * @return object ResProperty
+ * @access public
+ */
+ function SUB_CLASS_OF()
+ {
+ return new ResProperty(RDF_SCHEMA_URI.RDFS_SUBCLASSOF);
+ }
+
+ /**
+ * Answer the predicate that denotes that one property is a sub-property of another.
+ *
+ * @return object ResProperty
+ * @access public
+ */
+ function SUB_PROPERTY_OF()
+ {
+ return new ResProperty(RDF_SCHEMA_URI.RDFS_SUBPROPERTYOF);
+ }
+
+
+
+ function ANNOTATION_PROPERTY()
+ {
+ return new ResProperty(OWL_NS . 'AnnotationProperty');
+ }
+
+ function ALL_DIFFERENT()
+ {
+ return new ResProperty(OWL_NS . 'AllDifferent');
+ }
+
+ function ALL_VALUES_FROM()
+ {
+ return new ResProperty(OWL_NS . 'allValuesFrom');
+ }
+
+ function BACKWARD_COMPATIBLE_WITH()
+ {
+ return new ResProperty(OWL_NS . 'backwardCompatibleWith');
+ }
+
+ function CARDINALITY()
+ {
+ return new ResProperty(OWL_NS . 'cardinality');
+ }
+
+ function COMPLEMENT_OF()
+ {
+ return new ResProperty(OWL_NS . 'complementOf');
+ }
+
+ function DATATYPE()
+ {
+ return new ResProperty(OWL_NS . 'Datatype');
+ }
+
+ function DATATYPE_PROPERTY()
+ {
+ return new ResProperty(OWL_NS . 'DatatypeProperty');
+ }
+
+ function DATA_RANGE()
+ {
+ return new ResProperty(OWL_NS . 'DataRange');
+ }
+
+ function DATATYPE_RESTRICTION()
+ {
+ return new ResProperty(OWL_NS . 'DatatypeRestriction');
+ }
+
+ function DEPRECATED_CLASS()
+ {
+ return new ResProperty(OWL_NS . 'DeprecatedClass');
+ }
+
+ function DEPRECATED_PROPERTY()
+ {
+ return new ResProperty(OWL_NS . 'DeprecatedProperty');
+ }
+
+ function DISTINCT_MEMBERS()
+ {
+ return new ResProperty(OWL_NS . 'distinctMembers');
+ }
+
+ function DIFFERENT_FROM()
+ {
+ return new ResProperty(OWL_NS . 'differentFrom');
+ }
+
+ function DISJOINT_WITH()
+ {
+ return new ResProperty(OWL_NS . 'disjointWith');
+ }
+
+ function EQUIVALENT_CLASS()
+ {
+ return new ResProperty(OWL_NS . 'equivalentClass');
+ }
+
+ function EQUIVALENT_PROPERTY()
+ {
+ return new ResProperty(OWL_NS . 'equivalentProperty');
+ }
+
+ function FUNCTIONAL_PROPERTY()
+ {
+ return new ResProperty(OWL_NS . 'FunctionalProperty');
+ }
+
+ function HAS_VALUE()
+ {
+ return new ResProperty(OWL_NS . 'hasValue');
+ }
+
+ function INCOMPATIBLE_WITH()
+ {
+ return new ResProperty(OWL_NS . 'incompatibleWith');
+ }
+
+ function IMPORTS()
+ {
+ return new ResProperty(OWL_NS . 'imports');
+ }
+
+ function INTERSECTION_OF()
+ {
+ return new ResProperty(OWL_NS . 'intersectionOf');
+ }
+
+ function INVERSE_FUNCTIONAL_PROPERTY()
+ {
+ return new ResProperty(OWL_NS . 'InverseFunctionalProperty');
+ }
+
+ function INVERSE_OF()
+ {
+ return new ResProperty(OWL_NS . 'inverseOf');
+ }
+
+ function MAX_CARDINALITY()
+ {
+ return new ResProperty(OWL_NS . 'maxCardinality');
+ }
+
+ function MIN_CARDINALITY()
+ {
+ return new ResProperty(OWL_NS . 'minCardinality');
+ }
+
+ function NOTHING()
+ {
+ return new ResProperty(OWL_NS . 'Nothing');
+ }
+
+ function OBJECT_CLASS()
+ {
+ return new ResProperty(OWL_NS . 'ObjectClass');
+ }
+
+ function OBJECT_PROPERTY()
+ {
+ return new ResProperty(OWL_NS . 'ObjectProperty');
+ }
+
+ function OBJECT_RESTRICTION()
+ {
+ return new ResProperty(OWL_NS . 'ObjectRestriction');
+ }
+
+ function ONE_OF()
+ {
+ return new ResProperty(OWL_NS . 'oneOf');
+ }
+
+ function ON_PROPERTY()
+ {
+ return new ResProperty(OWL_NS . 'onProperty');
+ }
+
+ function ONTOLOGY()
+ {
+ return new ResProperty(OWL_NS . 'Ontology');
+
+ }
+
+ function PRIOR_VERSION()
+ {
+ return new ResProperty(OWL_NS . 'priorVersion');
+ }
+
+ function PROPERTY()
+ {
+ return new ResProperty(OWL_NS . 'Property');
+ }
+
+ function RESTRICTION()
+ {
+ return new ResProperty(OWL_NS . 'Restriction');
+ }
+
+ function SAME_AS()
+ {
+ return new ResProperty(OWL_NS . 'sameAs');
+ }
+
+ function SAME_CLASS_AS()
+ {
+ return new ResProperty(OWL_NS . 'sameClassAs');
+ }
+
+ function SAME_INDIVIDUAL_AS()
+ {
+ return new ResProperty(OWL_NS . 'sameIndividualAs');
+ }
+
+ function SAME_PROPERTY_AS()
+ {
+ return new ResProperty(OWL_NS . 'samePropertyAs');
+ }
+
+ function SOME_VALUES_FROM()
+ {
+ return new ResProperty(OWL_NS . 'someValuesFrom');
+ }
+
+ function SYMMETRIC_PROPERTY()
+ {
+ return new ResProperty(OWL_NS . 'SymmetricProperty');
+ }
+
+ function THING()
+ {
+ return new ResProperty(OWL_NS . 'Thing');
+ }
+
+ function TRANSITIVE_PROPERTY()
+ {
+ return new ResProperty(OWL_NS . 'TransitiveProperty');
+ }
+
+ function UNION_OF()
+ {
+ return new ResProperty(OWL_NS . 'unionOf');
+ }
+
+ function VERSION_INFO()
+ {
+ return new ResProperty(OWL_NS . 'versionInfo');
+ }
+
+ function NAMESPACE()
+ {
+ return OWL_NS;
+ }
+
+ /**
+ * Answer the predicate that denotes the rdf:type property.
+ *
+ * @return object ResProperty
+ * @access public
+ */
+ function TYPE()
+ {
+ return new ResProperty(RDF_NAMESPACE_URI.RDF_TYPE);
+ }
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/OntClass.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/OntClass.php
new file mode 100755
index 00000000..02ec1121
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/OntClass.php
@@ -0,0 +1,285 @@
+
+*
+*
+* @package ontModel
+* @access public
+**/
+class OntClass extends OntResource
+{
+ /**
+ * Constructor
+ * You can supply a uri
+ *
+ * @param string $uri
+ * @access public
+ */
+ function OntClass($uri = null)
+ {
+ parent::OntResource($uri);
+ }
+
+ /**
+ * Add a sub-class of this class.
+ *
+ * @param object ResResource $resResource
+ * @return boolean
+ * @access public
+ */
+ function addSubClass($resResource)
+ {
+ return $resResource->addProperty($this->vocabulary->SUB_CLASS_OF(),$this);
+ }
+
+ /**
+ * Add a super-class of this class.
+ *
+ * @param object ResResource $resResource
+ * @return boolean
+ * @access public
+ */
+ function addSuperClass($resResource)
+ {
+ return $this->addProperty($this->vocabulary->SUB_CLASS_OF(),$resResource);
+ }
+
+ /**
+ * Answer a class that is the sub-class of this class.
+ * If there is more than one such class, an arbitrary selection is made.
+ *
+ * @return object OntClass or NULL
+ * @access public
+ */
+ function getSubClass()
+ {
+ $statement = $this->model->findFirstMatchingStatement(null,$this->vocabulary->SUB_CLASS_OF(),$this);
+ if ($statement !== null)
+ return $this->model->createOntClass($statement->getLabelSubject());
+
+ return null;
+ }
+
+ /**
+ * Answer a class that is the super-class of this class.
+ * If there is more than one such class, an arbitrary selection is made.
+ *
+ * @return object OntClass or NULL
+ * @access public
+ */
+ function getSuperClass()
+ {
+ return $this->getPropertyValue($this->vocabulary->SUB_CLASS_OF(),'OntClass');
+ }
+
+ /**
+ * Answer true if the given class is a sub-class of this class.
+ * $direct - If true, only search the classes that are directly
+ * adjacent to this class in the class hierarchy.
+ *
+ * @param object ResResource $resResource
+ * @param boolean $direct
+ * @return boolean
+ * @access public
+ */
+ function hasSubclass($resResource, $direct = true)
+ {
+ if ($direct)
+ return $resResource->hasProperty($this->vocabulary->SUB_CLASS_OF(),$this);
+
+ $index=array();
+ return ($this->_getSubAttributeStatementsRec($this,$this->vocabulary->SUB_CLASS_OF(),$index,$resResource) === true);
+ }
+
+ /**
+ * Answer true if the given class is a super-class of this class.
+ * $direct - If true, only search the classes that are directly
+ * adjacent to this class in the class hierarchy.
+ *
+ * @param object ResResource $resResource
+ * @param boolean $direct
+ * @return boolean
+ * @access public
+ */
+ function hasSuperClass($resResource, $direct = true)
+ {
+ if ($direct)
+ return $this->hasProperty($this->vocabulary->SUB_CLASS_OF(),$resResource);
+
+ $index=array();
+ return ($this->_getSuperAttributeStatementsRec($this,$this->vocabulary->SUB_CLASS_OF(),$index,$resResource) === true);
+ }
+
+ /**
+ * Answer an ResIterator over the individuals in the model that have this class
+ * among their types.
+ *
+ * @return object ResIterator
+ * @access public
+ */
+ function listInstances()
+ {
+ /*
+ $statements= $this->model->find(null,$this->vocabulary->TYPE(),$this);
+ $return = array();
+ $returnIndex=array();
+ foreach ($statements as $statement)
+ {
+ $subjectLabel=$statement->getLabelSubject();
+ if (!in_array($subjectLabel,$returnIndex))
+ {
+ $returnIndex[]=$subjectLabel;
+ $return[]=$statement->getSubject();
+ }
+ }
+ return $return;
+ */
+ return new ResIterator(null,$this->vocabulary->TYPE(),$this,'s',$this->model,'Individual');
+
+ }
+
+ /**
+ * Answer an array over the classes that are declared to be sub-classes of this class.
+ * Each element of the array will be an OntClass.
+ * $direct - If true, only search the classes that are directly
+ * adjacent to this class in the class hierarchy.
+ *
+ * @param boolean $direct
+ * @return array
+ * @access public
+ */
+ function listSubClasses($direct = true)
+ {
+ $return = array();
+ if ($direct)
+ {
+ $statements = $this->model->find(null,$this->vocabulary->SUB_CLASS_OF(),$this);
+ } else
+ {
+ $index = array();
+ $statements = $this->_getSubAttributeStatementsRec($this,$this->vocabulary->SUB_CLASS_OF(),$index);
+ }
+
+ $returnIndex=array();
+ foreach ($statements as $statement)
+ {
+ $subjectLabel=$statement->getLabelSubject();
+ if (!in_array($subjectLabel,$returnIndex))
+ {
+ $returnIndex[]=$subjectLabel;
+ $return[]=$this->model->createOntClass($subjectLabel);
+ }
+ }
+ return $return;
+ }
+
+ /**
+ * Answer an array over the classes that are declared to be super-classes of this class.
+ * Each element of the array will be an OntClass.
+ * $direct - If true, only search the classes that are directly
+ * adjacent to this class in the class hierarchy.
+ *
+ * @param boolean $direct
+ * @return array
+ * @access public
+ */
+ function listSuperClasses($direct = true)
+ {
+ $return = array();
+ if ($direct)
+ return $this->listProperty($this->vocabulary->SUB_CLASS_OF(),'OntClass');
+
+ $index=array();
+ $statements = $this->_getSuperAttributeStatementsRec($this,$this->vocabulary->SUB_CLASS_OF(),$index);
+ $returnIndex=array();
+ foreach ($statements as $statement)
+ {
+ $objectLabel=$statement->getLabelObject();
+ if (!in_array($objectLabel,$returnIndex))
+ {
+ $returnIndex[]=$objectLabel;
+ $return[]=$this->model->createOntClass($objectLabel);
+ }
+ }
+ return $return;
+ }
+
+ /**
+ * Remove the given class from the sub-classes of this class.
+ *
+ * @param object ResResource $resResource
+ * @return boolean
+ * @access public
+ */
+ function removeSubClass($resResource)
+ {
+ return $this->model->remove(new Statement($resResource,$this->vocabulary->SUB_CLASS_OF(),$this));
+ }
+
+ /**
+ * Remove the given class from the super-classes of this class.
+ *
+ * @param object ResResource $resResource
+ * @return boolean
+ * @access public
+ */
+ function removeSuperClass($resResource)
+ {
+ return $this->removeProperty($this->vocabulary->SUB_CLASS_OF(),$resResource);
+ }
+
+ /**
+ * Assert that this class is super-class of the given class.
+ * Any existing statements for subClassOf on prop will be removed.
+ *
+ * @param object ResResource $resResource
+ * @access public
+ */
+ function setSubClass($resResource)
+ {
+ foreach ($this->listSubClasses() as $oldRes)
+ {
+ $this->removeSubClass($oldRes);
+ }
+ $this->addSubClass($resResource);
+ }
+
+ /**
+ * Assert that this class is sub-class of the given class.
+ * Any existing statements for subClassOf on prop will be removed.
+ *
+ * @param object ResResource $resResource
+ * @access public
+ */
+ function setSuperClass($resResource)
+ {
+ $this->setPropertyValue($this->vocabulary->SUB_CLASS_OF(),$resResource);
+ }
+
+ /**
+ * Answer a resource that represents an instance of this OntClass and Individual
+ * node in this model.
+ * If a resource with the given uri exists in the model, it will be re-used.
+ * If not, a new one is created in the updateable sub-model of the ontology model.
+ *
+ * @param string $uri
+ * @return object Individual
+ * @access public
+ */
+ function createInstance($uri = null)
+ {
+ $instance = $this->model->createIndividual($uri);
+ $instance->setInstanceRdfType($this);
+ return $instance;
+ }
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/OntModel.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/OntModel.php
new file mode 100755
index 00000000..8c1db9c6
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/OntModel.php
@@ -0,0 +1,169 @@
+
+*
+*
+* @package ontModel
+* @access public
+**/
+class OntModel extends ResModel
+{
+ /**
+ * Holds a reference to the assoiated vocabulary.
+ * @var object
+ * @access private
+ */
+ var $vocabulary;
+
+
+ /**
+ * Constructor.
+ * You have to supply a memmodel/dbmodel/infmodel to save the statements and a vocabulary
+ *
+ * @param object Model $model
+ * @access public
+ */
+ function OntModel(& $model,& $vocabulary)
+ {
+ parent::ResModel($model);
+ $this->vocabulary = & $vocabulary;
+ }
+
+ /**
+ * Answer a resource that represents a class description node in this model.
+ * If a resource with the given uri exists in the model, it will be re-used.
+ * If not, a new one is created in the updateable sub-model of the ontology model.
+ *
+ * @param string $uri
+ * @return object OntClass
+ * @access public
+ */
+ function createOntClass($uri = null)
+ {
+ $class = new OntClass($uri);
+ $class->setAssociatedModel($this);
+ $class->setVocabulary($this->vocabulary);
+ $class->setInstanceRdfType($this->vocabulary->ONTCLASS());
+ return $class;
+ }
+
+ /**
+ * Answer a resource that represents an Individual node in this model.
+ * If a resource with the given uri exists in the model, it will be re-used.
+ * If not, a new one is created in the updateable sub-model of the ontology model.
+ *
+ * @param string $uri
+ * @return object Individual
+ * @access public
+ */
+ function createIndividual($uri = null)
+ {
+ $individual = new Individual($uri);
+ $individual->setAssociatedModel($this);
+ $individual->setVocabulary($this->vocabulary);
+ return $individual;
+ }
+
+ /**
+ * Answer a resource that represents an OntProperty node in this model.
+ * If a resource with the given uri exists in the model, it will be re-used.
+ * If not, a new one is created in the updateable sub-model of the ontology model.
+ *
+ * @param string $uri
+ * @return object OntProperty
+ * @access public
+ */
+ function createOntProperty($uri = null)
+ {
+ $ontProperty = new OntProperty($uri);
+ $ontProperty->setAssociatedModel($this);
+ $ontProperty->setVocabulary($this->vocabulary);
+ $ontProperty->setInstanceRdfType($this->createResource(RDF_NAMESPACE_URI.RDF_PROPERTY));
+ return $ontProperty;
+ }
+
+ /**
+ * Answer an array that ranges over all of the various forms of class
+ * description resource in this model.
+ * Class descriptions include domain/range definitions, named classes and subClass constructs.
+ *
+ * @return array of object ResResource
+ * @access public
+ */
+ function listClasses()
+ {
+ //get all statements, with an rdf:type as property
+ $statements= $this->find(null,$this->vocabulary->TYPE(),null);
+ $return = array();
+ $returnIndex=array();
+ foreach ($statements as $statement)
+ {
+ $objectLabel=$statement->getLabelObject();
+ //if it's about a typed Individual
+ if ($objectLabel!=RDF_SCHEMA_URI.RDFS_CLASS)
+ {
+ if (!in_array($objectLabel,$returnIndex))
+ {
+ $returnIndex[]=$objectLabel;
+ $return[]=$statement->getObject();
+ }
+ } else
+ //if it's a "class1 rdf:type rdf:class" construct
+ {
+ $subjectLabel=$statement->getLabelSubject();
+ if (!in_array($subjectLabel,$returnIndex))
+ {
+ $returnIndex[]=$subjectLabel;
+ $return[]=$statement->getSubject();
+ }
+ }
+ }
+ //find all statements about SubClassConstructs
+ $statements= $this->find(null,$this->vocabulary->SUB_CLASS_OF(),null);
+ foreach ($statements as $statement)
+ {
+ //add the statements object to the result
+ $objectLabel=$statement->getLabelObject();
+ if (!in_array($objectLabel,$returnIndex))
+ {
+ $returnIndex[]=$objectLabel;
+ $return[]=$statement->getObject();
+ }
+ }
+ foreach ($statements as $statement)
+ {
+ //add the statements subject to the result
+ $objectLabel=$statement->getLabelSubject();
+ if (!in_array($objectLabel,$returnIndex))
+ {
+ $returnIndex[]=$objectLabel;
+ $return[]=$statement->getSubject();
+ }
+ }
+ return $return;
+ }
+}
+?>
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/OntModelP.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/OntModelP.php
new file mode 100755
index 00000000..8a7a11d9
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/OntModelP.php
@@ -0,0 +1,24 @@
+
+* @package ontModel
+*
+* ----------------------------------------------------------------------------------
+*/
+// Include OntModel classes
+include_once( RDFAPI_INCLUDE_DIR . PACKAGE_RESMODEL);
+require_once( RDFAPI_INCLUDE_DIR . 'ontModel/OntVocabulary.php');
+require_once( RDFAPI_INCLUDE_DIR . 'ontModel/RdfsVocabulary.php');
+require_once( RDFAPI_INCLUDE_DIR . 'ontModel/OntModel.php');
+require_once( RDFAPI_INCLUDE_DIR . 'ontModel/OntResource.php');
+require_once( RDFAPI_INCLUDE_DIR . 'ontModel/OntProperty.php');
+require_once( RDFAPI_INCLUDE_DIR . 'ontModel/OntClass.php');
+require_once( RDFAPI_INCLUDE_DIR . 'ontModel/Individual.php');
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/OntProperty.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/OntProperty.php
new file mode 100755
index 00000000..787a91e8
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/OntProperty.php
@@ -0,0 +1,390 @@
+
+*
+*
+* @package ontModel
+* @access public
+**/
+
+class OntProperty extends OntResource
+{
+ /**
+ * Constructor.
+ * You can supply a URI.
+ *
+ * @param string $uri
+ * @access public
+ */
+ function OntProperty($uri = null)
+ {
+ parent::OntResource($uri);
+ }
+
+ /**
+ * Add a resource representing the domain of this property.
+ *
+ * @param object ResResource $resResource
+ * @return boolean
+ * @access public
+ */
+ function addDomain($resResource)
+ {
+ return $this->addProperty($this->vocabulary->DOMAIN(),$resResource);
+ }
+
+ /**
+ * Add a resource representing the range of this property.
+ *
+ * @param object ResResource $resResource
+ * @return boolean
+ * @access public
+ */
+ function addRange($resResource)
+ {
+ return $this->addProperty($this->vocabulary->RANGE(),$resResource);
+ }
+
+ /**
+ * Add a sub-property of this property.
+ *
+ * @param object ResProperty $resProperty
+ * @return boolean
+ * @access public
+ */
+ function addSubProperty($resProperty)
+ {
+ return $resProperty->addProperty($this->vocabulary->SUB_PROPERTY_OF(),$this);
+ }
+
+ /**
+ * Add a super-property of this property.
+ *
+ * @param object ResProperty $resProperty
+ * @return boolean
+ * @access public
+ */
+ function addSuperProperty($resProperty)
+ {
+ return $this->addProperty($this->vocabulary->SUB_PROPERTY_OF(),$resProperty);
+ }
+
+ /**
+ * Answer a OntClass that represents the domain class of this property.
+ * If there is more than one such resource, an arbitrary selection is made.
+ *
+ * @return object OntClass
+ * @access public
+ */
+ function getDomain()
+ {
+ return $this->getPropertyValue($this->vocabulary->DOMAIN(),'OntClass');
+ }
+
+ /**
+ * Answer a OntClass that represents the range class of this property.
+ * If there is more than one such resource, an arbitrary selection is made.
+ *
+ * @return object OntClass
+ * @access public
+ */
+ function getRange()
+ {
+ return $this->getPropertyValue($this->vocabulary->RANGE(),'OntClass');
+ }
+
+ /**
+ * Answer a property that is the sub-property of this property.
+ * If there is more than one such property, an arbitrary selection is made.
+ *
+ * @return object OntProperty
+ * @access public
+ */
+ function getSubProperty()
+ {
+ $statement = $this->model->findFirstMatchingStatement(null,$this->vocabulary->SUB_PROPERTY_OF(),$this);
+ if ($statement !== null)
+ return new OntProperty($statement->getLabelSubject());
+
+ return null;
+ }
+
+ /**
+ * Answer a property that is the super-property of this property.
+ * If there is more than one such property, an arbitrary selection is made.
+ *
+ * @return object OntProperty
+ * @access public
+ */
+ function getSuperProperty()
+ {
+ return $this->getPropertyValue($this->vocabulary->SUB_PROPERTY_OF(),'OntProperty');
+ }
+
+ /**
+ * Answer true if the given resource a class specifying the domain of this property.
+ *
+ * @param object ResResource $resResource
+ * @return boolean
+ * @access public
+ */
+ function hasDomain($resResource)
+ {
+ return $this->hasProperty($this->vocabulary->DOMAIN(),$resResource);
+ }
+
+ /**
+ * Answer true if the given resource a class specifying the range of this property.
+ *
+ * @param object ResResource $resResource
+ * @return boolean
+ * @access public
+ */
+ function hasRange($resResource)
+ {
+ return $this->hasProperty($this->vocabulary->RANGE(),$resResource);
+ }
+
+ /**
+ * Answer true if the given property is a sub-property of this property.
+ * If $direct is set to true, only consider the direcly adjacent
+ * properties in the property hierarchy
+ *
+ * @param object ResResource $resProperty
+ * @param boolean $direct
+ * @return boolean
+ * @access public
+ */
+ function hasSubProperty($resProperty, $direct = true)
+ {
+ if ($direct)
+ return $resProperty->hasProperty($this->vocabulary->SUB_PROPERTY_OF(),$this);
+
+ $index=array();
+ return ($this->_getSubAttributeStatementsRec($this,$this->vocabulary->SUB_PROPERTY_OF(),$index,$resProperty) === true);
+ }
+
+ /**
+ * Answer true if the given property is a super-property of this property.
+ * If $direct is set to true, only consider the direcly adjacent
+ * properties in the property hierarchy
+ *
+ * @param object ResResource $resProperty
+ * @param boolean $direct
+ * @return boolean
+ * @access public
+ */
+ function hasSuperProperty($resProperty, $direct = true)
+ {
+ if ($direct)
+ return $this->hasProperty($this->vocabulary->SUB_PROPERTY_OF(),$resProperty);
+
+ $index=array();
+ return ($this->_getSuperAttributeStatementsRec($this,$this->vocabulary->SUB_PROPERTY_OF(),$index,$resProperty) === true);
+ }
+
+ /**
+ * Answer an array of all of the declared domain classes of this property.
+ * Each element of the iterator will be an OntClass.
+ *
+ * @return array of OntClasses
+ * @access public
+ */
+ function listDomain()
+ {
+ return $this->listProperty($this->vocabulary->DOMAIN(),'OntClass');
+ }
+
+ /**
+ * Answer an array of all of the declared range classes of this property.
+ * Each element of the iterator will be an OntClass.
+ *
+ * @return array of OntClasses
+ * @access public
+ */
+ function listRange()
+ {
+ return $this->listProperty($this->vocabulary->RANGE(),'OntClass');
+ }
+
+ /**
+ * Answer an array of all the properties that are declared to be
+ * sub-properties of this property. Each element of the iterator will be an
+ * OntProperty.
+ * If $direct is set to true, only consider the direcly adjacent
+ * properties in the property hierarchy
+ *
+ * @param boolean $direct
+ * @return array of OntProperties
+ * @access public
+ */
+ function listSubProperties($direct = true)
+ {
+ $return = array();
+ if ($direct)
+ {
+ $statements = $this->model->find(null,$this->vocabulary->SUB_PROPERTY_OF(),$this);
+ } else
+ {
+ $index = array();
+ $statements = $this->_getSubAttributeStatementsRec($this,$this->vocabulary->SUB_PROPERTY_OF(),$index);
+ }
+
+ $returnIndex=array();
+ foreach ($statements as $statement)
+ {
+ $objectLabel=$statement->getLabelSubject();
+ if (!in_array($objectLabel,$returnIndex))
+ {
+ $returnIndex[]=$objectLabel;
+ $return[]=new OntProperty($statement->getLabelSubject());
+ }
+ }
+ return $return;
+ }
+
+ /**
+ * Answer an array of all the properties that are declared to be
+ * super-properties of this property. Each element of the iterator will be an
+ * OntProperty.
+ * If $direct is set to true, only consider the direcly adjacent
+ * properties in the property hierarchy
+ *
+ * @param boolean $direct
+ * @return array of OntProperties
+ * @access public
+ */
+ function listSuperProperties($direct = true)
+ {
+ $return = array();
+ if ($direct)
+ return $this->listProperty($this->vocabulary->SUB_PROPERTY_OF(),'OntProperty');
+
+ $index=array();
+ $statements = $this->_getSuperAttributeStatementsRec($this,$this->vocabulary->SUB_PROPERTY_OF(),$index);
+ $returnIndex=array();
+ foreach ($statements as $statement)
+ {
+ $objectLabel=$statement->getLabelObject();
+ if (!in_array($objectLabel,$returnIndex))
+ {
+ $returnIndex[]=$objectLabel;
+ $return[]=new OntProperty($statement->getLabelObject());
+ }
+ }
+ return $return;
+ }
+
+ /**
+ * Remove the given class from the stated domain(s) of this property.
+ *
+ * @param object ResResource $resResource
+ * @return boolean
+ * @access public
+ */
+ function removeDomain($resResource)
+ {
+ return $this->removeProperty($this->vocabulary->DOMAIN(),$resResource);
+ }
+
+ /**
+ * Remove the given class from the stated range(es) of this property.
+ *
+ * @param object ResResource $resResource
+ * @return boolean
+ * @access public
+ */
+ function removeRange($resResource)
+ {
+ return $this->removeProperty($this->vocabulary->RANGE(),$resResource);
+ }
+
+ /**
+ * Remove the given property from the sub-properties of this property.
+ *
+ * @param object ResProperty $resProperty
+ * @return boolean
+ * @access public
+ */
+ function removeSubProperty($resProperty)
+ {
+ return $this->model->remove(new Statement($resProperty,$this->vocabulary->SUB_PROPERTY_OF(),$this));
+ }
+
+ /**
+ * Remove the given property from the super-properties of this property.
+ *
+ * @param object ResProperty $resProperty
+ * @return boolean
+ * @access public
+ */
+ function removeSuperProperty($resProperty)
+ {
+ return $this->removeProperty($this->vocabulary->SUB_PROPERTY_OF(),$resProperty);
+ }
+
+ /**
+ * Assert that the given resource represents the class of individuals
+ * that form the domain of this property. Any existing domain statements
+ * for this property are removed.
+ *
+ * @param object ResResource $resResource
+ * @access public
+ */
+ function setDomain($resResource)
+ {
+ $this->setPropertyValue($this->vocabulary->DOMAIN(),$resResource);
+ }
+
+ /**
+ * Assert that the given resource represents the class of individuals
+ * that form the range of this property. Any existing range statements
+ * for this property are removed.
+ *
+ * @param object ResResource $resResource
+ * @access public
+ */
+ function setRange($resResource)
+ {
+ $this->setPropertyValue($this->vocabulary->RANGE(),$resResource);
+ }
+
+ /**
+ * Assert that this property is super-property of the given property.
+ * Any existing statements for superPropertyOf on prop will be removed.
+ *
+ * @param object ResProperty $resProperty
+ * @access public
+ */
+ function setSubProperty($resProperty)
+ {
+ foreach ($this->listSubProperties() as $oldResProperty)
+ {
+ $this->removeSubProperty($oldResProperty);
+ }
+
+ $this->addSubProperty($resProperty);
+ }
+
+ /**
+ * Assert that this property is sub-property of the given property.
+ * Any existing statements for subPropertyOf on prop will be removed.
+ *
+ * @param object ResProperty $resProperty
+ * @access public
+ */
+ function setSuperProperty($resProperty)
+ {
+ $this->setPropertyValue($this->vocabulary->SUB_PROPERTY_OF(),$resProperty);
+ }
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/OntResource.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/OntResource.php
new file mode 100755
index 00000000..c4ee58fd
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/OntResource.php
@@ -0,0 +1,739 @@
+
+*
+*
+* @package ontModel
+* @access public
+**/
+class OntResource extends ResResource
+{
+ /**
+ * Holds a reference to the assoiated vocabulary
+ * @var object
+ * @access private
+ */
+ var $vocabulary;
+
+ /**
+ * Holds a resResource of the type, which is this ontResource of.
+ * If this value is set, the ontModel will add an additional
+ * statement about this resource and the fiven rdf:type
+ * @var object
+ * @access private
+ */
+ var $rdfType;
+
+
+ /**
+ * Constructor
+ * You can supply a uri
+ *
+ * @param string $uri
+ * @access public
+ */
+ function OntResource($uri = null)
+ {
+ $this->rdfType=false;
+ parent::ResResource($uri);
+ }
+
+ /**
+ * Sets the reference to the assoiated vocabulary
+ *
+ * @param object OntVocabulary $vocabulary
+ * @access public
+ */
+ function setVocabulary(& $vocabulary)
+ {
+ $this->vocabulary = & $vocabulary;
+ }
+
+ /**
+ * Add the given comment to this resource.
+ *
+ * @param object ResLiteral $comment
+ * @return boolean
+ * @access public
+ */
+ function addComment($comment)
+ {
+ return $this->addProperty($this->vocabulary->COMMENT(),$comment);
+ }
+
+ /**
+ * Answer the comment string for this object. If there is more than one such resource, an arbitrary selection is made.
+ *
+ * @return object ResLiteral or NULL
+ * @access public
+ */
+ function getComment()
+ {
+ return $this->getPropertyValue($this->vocabulary->COMMENT());
+ }
+
+ /**
+ * Add a resource that is declared to provide a definition of this resource.
+ *
+ * @param object ResResource $resResource
+ * @return boolean
+ * @access public
+ */
+ function addIsDefinedBy($resResource)
+ {
+ return $this->addProperty($this->vocabulary->IS_DEFINED_BY(),$resResource);
+ }
+
+ /**
+ * Answer a resource that is declared to provide a definition of this resource.
+ * If there is more than one such resource, an arbitrary selection is made.
+ *
+ * @return object ResResource
+ * @access public
+ */
+ function getIsDefinedBy()
+ {
+ return $this->getPropertyValue($this->vocabulary->IS_DEFINED_BY());
+ }
+
+ /**
+ * Add the given Label to this resource
+ *
+ * @param object ResLiteral $resLiteral
+ * @return boolean
+ * @access public
+ */
+ function addLabelProperty($resLiteral)
+ {
+ return $this->addProperty($this->vocabulary->LABEL(),$resLiteral);
+ }
+
+ /**
+ * Answer the label ResLiteral for this object.
+ * If there is more than one such resource, an arbitrary selection is made.
+ *
+ * @param string $uri
+ * @return object ResResource
+ * @access public
+ */
+ function getLabelProperty()
+ {
+ return $this->getPropertyValue($this->vocabulary->LABEL());
+ }
+
+ /**
+ * Add the given class as one of the rdf:type's for this resource.
+ *
+ * @param object ResResource $resResource
+ * @return boolean
+ * @access public
+ */
+ function addRDFType($resResource)
+ {
+ return $this->addProperty($this->vocabulary->TYPE(),$resResource);
+ }
+
+ /**
+ * Answer the rdf:type (ie the class) of this resource.
+ * If there is more than one type for this resource, the return value will
+ * be one of the values, but it is not specified which one
+ * (nor that it will consistently be the same one each time).
+ *
+ * @return object ResResource
+ * @access public
+ */
+ function getRDFType()
+ {
+ return $this->getPropertyValue($this->vocabulary->TYPE());
+ }
+
+ /**
+ * Add a resource that is declared to provided additional
+ * information about the definition of this resource.
+ *
+ * @param object ResResource $resResource
+ * @return boolean
+ * @access public
+ */
+ function addSeeAlso($resResource)
+ {
+ return $this->addProperty($this->vocabulary->SEE_ALSO(),$resResource);
+ }
+
+ /**
+ * Answer a resource that provides additional information about this resource.
+ * If more than one such resource is defined, make an arbitrary choice.
+ *
+ * @return object ResResource
+ * @access public
+ */
+ function getSeeAlso()
+ {
+ return $this->getPropertyValue($this->vocabulary->SEE_ALSO());
+ }
+
+ /**
+ * Answer a view of this resource as a class
+ *
+ * @return object OntClass
+ * @access public
+ */
+ function asClass()
+ {
+ return $this->model->createOntClass($this->uri);
+ }
+
+ /**
+ * Answer a view of this resource as an Individual
+ *
+ * @return object Individual
+ * @access public
+ */
+ function asIndividual()
+ {
+ return $this->model->createIndividual($this->uri);
+ }
+
+ /**
+ * Answer a view of this resource as a property
+ *
+ * @return object OntProperty
+ * @access public
+ */
+ function asOntProperty()
+ {
+ return $this->model->createOntProperty($this->uri);
+ }
+
+ /**
+ * Answer a reference to the ontology language profile that governs the
+ * ontology model to which this ontology resource is attached.
+ *
+ * @param string $uri
+ * @return object OntClass
+ * @access public
+ */
+ function getVocabulary()
+ {
+ return $this->vocabulary ;
+ }
+
+ /**
+ * Answer the value of a given RDF property for this resource as $returnType, or null
+ * if it doesn't have one. If there is more than one RDF statement with
+ * the given property for the current value, it is not defined which of
+ * the values will be returned.
+ * The following return Types are supported: 'OntClass', 'OntProperty', 'Individual', and 'ResResource'
+ * Default is 'ResResource'
+ *
+ * @param object ResResource $property
+ * @param string $returnType
+ * @return object OntClass
+ * @access public
+ */
+ function getPropertyValue($property, $returnType = 'ResResource')
+ {
+ $statement=$this->getProperty($property);
+ if ($statement===null)
+ return null;
+
+ switch ($returnType)
+ {
+ case 'OntClass':
+ return $this->model->createOntClass($statement->getLabelObject());
+ break;
+
+ case 'OntProperty':
+ return $this->model->createOntProperty($statement->getLabelObject());
+ break;
+
+ case 'Individual':
+ return $this->model->createIndividual($statement->getLabelObject());
+ break;
+
+ default:
+ return $statement->getObject();
+ break;
+ }
+ }
+
+ /**
+ * Answer true if this resource has the given comment.
+ *
+ * @param object ResLiteral $resLiteral
+ * @return boolean
+ * @access public
+ */
+ function hasComment($resLiteral)
+ {
+ return $this->hasProperty($this->vocabulary->COMMENT(),$resLiteral);
+ }
+
+ /**
+ * Answer true if this resource has the given label.
+ *
+ * @param object ResLiteral $resLiteral
+ * @return boolean
+ * @access public
+ */
+ function hasLabelProperty($resLiteral)
+ {
+ return $this->hasProperty($this->vocabulary->LABEL(),$resLiteral);
+ }
+
+ /**
+ * Answer true if this resource has the given rdf:type.
+ *
+ * @param object ResResource $ontClass
+ * @return boolean
+ * @access public
+ */
+ function hasRDFType($ontClass)
+ {
+ return $this->hasProperty($this->vocabulary->TYPE(),$ontClass);
+ }
+
+ /**
+ * Answer true if this resource has the given resource as a source
+ * of additional information.
+ *
+ * @param object ResResource $resResource
+ * @return boolean
+ * @access public
+ */
+ function hasSeeAlso($resResource)
+ {
+ return $this->hasProperty($this->vocabulary->SEE_ALSO(),$resResource);
+ }
+
+ /**
+ * Answer true if this resource is defined by the given resource.
+ *
+ * @param object ResResource $resResource
+ * @return boolean
+ * @access public
+ */
+ function isDefinedBy($resResource)
+ {
+ return $this->hasProperty($this->vocabulary->IS_DEFINED_BY(),$resResource);
+ }
+
+ /**
+ * Answer an array of all of the comment literals for this resource.
+ *
+ * @param string $language
+ * @return array
+ * @access public
+ */
+ function listComments($language)
+ {
+ $return=$this->listProperty($this->vocabulary->COMMENT());
+ if ($language === false)
+ return $return;
+
+ foreach ($return as $key => $resLiteral)
+ {
+ if (!is_a($resLiteral,'ResLiteral') || $resLiteral->getLanguage() != $language)
+ unset ($return[$key]);
+ }
+ return $return;
+ }
+
+ /**
+ * Answer an array of all of the resources that are declared to define this resource.
+ *
+ * @return array
+ * @access public
+ */
+ function listIsDefinedBy()
+ {
+ return $this->listProperty($this->vocabulary->IS_DEFINED_BY());
+ }
+
+ /**
+ * Answer an array of all of the label literals for this resource, with the given
+ * language, if $language is set.
+ *
+ * @return array
+ * @access public
+ */
+ function listLabelProperties($language = false)
+ {
+ $return=$this->listProperty($this->vocabulary->LABEL());
+ if ($language === false)
+ return $return;
+
+ foreach ($return as $key => $resLiteral)
+ {
+ if (!is_a($resLiteral,'ResLiteral') || $resLiteral->getLanguage() != $language)
+ unset ($return[$key]);
+ }
+ return $return;
+
+ }
+
+ /**
+ * Answer an array of the RDF classes to which this resource belongs.
+ * If $direct is true, only answer those resources that are direct types of
+ * this resource, not the super-classes of the class etc.
+ *
+ * @param boolean $direct
+ * @return array Array of ResResources
+ * @access public
+ */
+ function listRDFTypes($direct = true)
+ {
+ return $this->listProperty($this->vocabulary->TYPE());
+ }
+
+ /**
+ * Answer an array of all of the resources that are declared to
+ * provide addition information about this resource.
+ *
+ * @return array Array of ResResources
+ * @access public
+ */
+ function listSeeAlso()
+ {
+ return $this->listProperty($this->vocabulary->SEE_ALSO());
+ }
+
+ /**
+ * Answer an array of values of a given RDF property for this resource as $returnType, or null
+ * if it doesn't have one.
+ * The following return Types are supported: 'OntClass', 'OntProperty', 'Individual', and 'ResResource'
+ * Default is 'ResResource'
+ *
+ * @param object ResResource $property
+ * @param string $returnType
+ * @return array of ResResources
+ * @access public
+ */
+ function listProperty($property, $returnType = 'OntResource')
+ {
+ $return=array();
+ $resArray = $this->listProperties($property);
+ foreach ($resArray as $statement)
+ {
+ switch ($returnType)
+ {
+ case 'OntClass':
+ $return[]=$this->model->createOntClass($statement->getLabelObject());
+ break;
+
+ case 'OntProperty':
+ $return[]=$this->model->createOntProperty($statement->getLabelObject());
+ break;
+
+ case 'Individual':
+ $return[]=$this->model->createIndividual($statement->getLabelObject());
+ break;
+
+ default:
+ $return[]=$statement->getObject();
+ break;
+ }
+ }
+ return $return;
+ }
+
+ /**
+ * Remove the statement that the given ResLiteral is a comment on this resource.
+ * Returns true, if a statement was removed
+ *
+ * @param object ResLiteral $resLiteral
+ * @return boolean
+ * @access public
+ */
+ function removeComment($resLiteral)
+ {
+ return $this->removeProperty($this->vocabulary->COMMENT(),$resLiteral);
+ }
+
+ /**
+ * Remove the statement that this resource is defined by the given resource.
+ *
+ * @param object ResResource $resResource
+ * @return boolean
+ * @access public
+ */
+ function removeDefinedBy($resResource)
+ {
+ return $this->removeProperty($this->vocabulary->IS_DEFINED_BY(),$resResource);
+ }
+
+ /**
+ * Remove the statement that the given ResLiteral is a label on this resource.
+ * Returns true, if a statement was removed
+ *
+ * @param object ResLiteral $resLiteral
+ * @return boolean
+ * @access public
+ */
+ function removeLabelProperty($resLiteral)
+ {
+ return $this->removeProperty($this->vocabulary->LABEL(),$resLiteral);
+ }
+
+ /**
+ * Remove the specific property-value pair from this resource.
+ *
+ * @param object ResResource $property
+ * @param object ResResource $value
+ * @return boolean
+ * @access public
+ */
+ function removeProperty($property, $value)
+ {
+ return $this->model->remove(new Statement($this,$property,$value));
+ }
+
+ /**
+ * Remove the statement that this resource is of the given RDF type.
+ *
+ * @param object ResResource $resResource
+ * @return boolean
+ * @access public
+ */
+ function removeRDFType($resResource)
+ {
+ return $this->removeProperty($this->vocabulary->TYPE(),$resResource);
+ }
+
+ /**
+ * Remove the statement indicating the given resource as a source of
+ * additional information about this resource.
+ *
+ * @param object ResResource $resResource
+ * @return boolean
+ * @access public
+ */
+ function removeSeeAlso($resResource)
+ {
+ return $this->removeProperty($this->vocabulary->SEE_ALSO(),$resResource);
+ }
+
+ /**
+ * Assert that the given string is the comment on this resource.
+ * Any existing statements for comment will be removed.
+ *
+ * @param object ResLiteral $resLiteral
+ * @access public
+ */
+ function setComment($resLiteral)
+ {
+ $this->setPropertyValue($this->vocabulary->COMMENT(),$resLiteral);
+ }
+
+ /**
+ * Assert that the given resource provides a source of definitions about this resource.
+ * Any existing statements for isDefinedBy will be removed.
+ *
+ * @param object ResResource $resResource
+ * @access public
+ */
+ function setIsDefinedBy($resResource)
+ {
+ $this->setPropertyValue($this->vocabulary->IS_DEFINED_BY(),$resResource);
+ }
+
+ /**
+ * Assert that the given string is the label on this resource.
+ * Any existing statements for comment will be removed.
+ *
+ * @param object ResLiteral $resLiteral
+ * @access public
+ */
+ function setLabelProperty($resLiteral)
+ {
+ $this->setPropertyValue($this->vocabulary->LABEL(),$resLiteral);
+ }
+
+ /**
+ * Set the value of the given property of this ontology resource to the given value.
+ * Maintains the invariant that there is at most one value of the property for a
+ * given resource, so existing property values are first removed.
+ * To add multiple properties, use addProperty.
+ *
+ * @param object ResResource $property
+ * @param object ResResource $value
+ * @access public
+ */
+ function setPropertyValue($property, $value)
+ {
+ $this->removeAll($property);
+ $this->addProperty($property,$value);
+ }
+
+ /**
+ * Set the RDF type (ie the class) for this resource,
+ * replacing any existing rdf:type property. Any existing statements
+ * for the RDF type will first be removed.
+ *
+ * @param object ResResource $resResource
+ * @access public
+ */
+ function setRDFType($resResource)
+ {
+ $this->setPropertyValue($this->vocabulary->TYPE(),$resResource);
+ }
+
+ /**
+ * Add a resource that is declared to provided additional information
+ * about the definition of this resource
+ *
+ * @param object ResResource $resResource
+ * @access public
+ */
+ function setSeeAlso($resResource)
+ {
+ $this->setPropertyValue($this->vocabulary->SEE_ALSO(),$resResource);
+ }
+
+ /**
+ * Returns an array of ResResources that are recursively connected by $attribute
+ * in superProperty direction.
+ * If $onlyFindThisResResource is set to a ResResource, this function returns boolean
+ * if this distinct resource recursively is connected to the $startResource.
+ *
+ * @param object ResResource $startResource
+ * @param object ResResource $attribute
+ * @param array $attribute
+ * @param object ResResource $onlyFindThisResResource
+ * @return array OR boolean
+ * @access private
+ */
+ function _getSuperAttributeStatementsRec(& $startResource,& $attribute,& $attributeIndex, $onlyFindThisResResource = false)
+ {
+
+ $return = $startResource->listProperties($attribute);
+
+ if ($onlyFindThisResResource)
+ {
+ foreach ($return as $statement)
+ {
+ if ($onlyFindThisResResource->equals($statement->getObject()))
+ return true;
+ }
+ }
+
+ foreach ($return as $statement)
+ {
+ $attributeLabel=$statement->getLabelObject();
+ if (!in_array($attributeLabel,$attributeIndex))
+ {
+ $attributeIndex[]=$attributeLabel;
+ $subReturn = $this->_getSuperAttributeStatementsRec($statement->getObject(), $attribute, $attributeIndex, $onlyFindThisResResource);
+ }
+ }
+ if (isset($subReturn))
+ {
+ if ($subReturn === true)
+ return true;
+ return array_merge($return,$subReturn);
+ }
+
+ return $return;
+ }
+
+ /**
+ * Returns an array of ResResources that are recursively connected by $attribute
+ * in subProperty direction.
+ * If $onlyFindThisResResource is set to a ResResource, this function returns boolean
+ * if this distinct resource recursively is connected to the $startResource.
+ *
+ * @param object ResResource $startResource
+ * @param object ResResource $attribute
+ * @param array $attribute
+ * @param object ResResource $onlyFindThisResResource
+ * @return array OR boolean
+ * @access private
+ */
+ function _getSubAttributeStatementsRec(& $startResource,& $attribute,& $attributeIndex, $onlyFindThisResResource = false)
+ {
+
+ $return = $this->model->find(null,$attribute,$startResource);
+
+ if ($onlyFindThisResResource)
+ {
+ foreach ($return as $statement)
+ {
+ if ($onlyFindThisResResource->equals($statement->getSubject()))
+ return true;
+ }
+ }
+
+ foreach ($return as $statement)
+ {
+ $attributeLabel=$statement->getLabelSubject();
+ if (!in_array($attributeLabel,$attributeIndex))
+ {
+ $attributeIndex[]=$attributeLabel;
+ $subReturn = $this->_getSubAttributeStatementsRec($statement->getSubject(), $attribute, $attributeIndex, $onlyFindThisResResource);
+ }
+ }
+ if (isset($subReturn))
+ {
+ if ($subReturn === true)
+ return true;
+ return array_merge($return,$subReturn);
+ }
+
+ return $return;
+ }
+
+ /**
+ * Add a property to this resource.
+ * A statement with this resource as the subject, p as the predicate and o
+ * as the object is added to the model associated with this resource.
+ * If $this->rdfType is set, an additional statement about it's type
+ * is added.
+ *
+ * @param ResResource $property
+ * @param ResResource/ResLiteral $object
+ * @return object ResResource
+ * @access public
+ */
+ function addProperty($property,$object)
+ {
+ if ($this->rdfType !== false)
+ if (!$this->hasRDFType($this->rdfType))
+ $this->model->add(new Statement($this,$this->vocabulary->TYPE(),$this->rdfType));
+
+ return parent:: addProperty($property,$object);
+ }
+
+ /**
+ * Sets the rdf:type, that this distinct resource is instance of.
+ * If this value is set, the ontModel will add an additional
+ * statement about this resource and the fiven rdf:type
+ *
+ * @param object ResResource $resResource
+ * @access public
+ */
+ function setInstanceRdfType($resResource)
+ {
+ $this->rdfType = $resResource;
+ }
+
+ /**
+ * returns the rdf:type, that this distinct resource is instance of.
+ *
+ * @return object ResResource $resResource
+ * @access public
+ */
+ function getInstanceRdfType()
+ {
+ return $this->rdfType;
+ }
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/OntVocabulary.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/OntVocabulary.php
new file mode 100755
index 00000000..22e8ac86
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/OntVocabulary.php
@@ -0,0 +1,25 @@
+
+*
+*
+* @package ontModel
+* @access public
+**/
+class OntVocabulary
+{
+
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/RdfsVocabulary.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/RdfsVocabulary.php
new file mode 100755
index 00000000..b0c4ff3d
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/ontModel/RdfsVocabulary.php
@@ -0,0 +1,143 @@
+
+*
+*
+* @package ontModel
+* @access public
+**/
+class RdfsVocabulary extends OntVocabulary
+{
+
+ /**
+ * Answer the resource that represents the class 'class' in this vocabulary.
+ *
+ * @return object ResResource
+ * @access public
+ */
+ function ONTCLASS()
+ {
+ return new ResResource(RDF_SCHEMA_URI.RDFS_CLASS);
+ }
+
+ /**
+ * Answer the predicate that denotes the domain of a property.
+ *
+ * @return object ResProperty
+ * @access public
+ */
+ function DOMAIN()
+ {
+ return new ResProperty(RDF_SCHEMA_URI.RDFS_DOMAIN);
+ }
+
+
+ /**
+ * Answer the predicate that denotes comment annotation on an ontology element.
+ *
+ * @return object ResProperty
+ * @access public
+ */
+ function COMMENT()
+ {
+ return new ResProperty(RDF_SCHEMA_URI.RDFS_COMMENT);
+ }
+
+ /**
+ * Answer the predicate that denotes isDefinedBy annotation on an ontology element
+ *
+ * @return object ResProperty
+ * @access public
+ */
+ function IS_DEFINED_BY()
+ {
+ return new ResProperty(RDF_SCHEMA_URI.RDFS_IS_DEFINED_BY);
+ }
+
+ /**
+ * Answer the predicate that denotes label annotation on an ontology element
+ *
+ * @return object ResProperty
+ * @access public
+ */
+ function LABEL()
+ {
+ return new ResProperty(RDF_SCHEMA_URI.RDFS_LABEL);
+ }
+
+ /**
+ * Answer the predicate that denotes the domain of a property.
+ *
+ * @return object ResProperty
+ * @access public
+ */
+ function RANGE()
+ {
+ return new ResProperty(RDF_SCHEMA_URI.RDFS_RANGE);
+ }
+
+ /**
+ * Answer the predicate that denotes seeAlso annotation on an ontology element
+ *
+ * @return object ResProperty
+ * @access public
+ */
+ function SEE_ALSO()
+ {
+ return new ResProperty(RDF_SCHEMA_URI.RDFS_SEE_ALSO);
+ }
+
+ /**
+ * Answer the predicate that denotes that one class is a sub-class of another.
+ *
+ * @return object ResProperty
+ * @access public
+ */
+ function SUB_CLASS_OF()
+ {
+ return new ResProperty(RDF_SCHEMA_URI.RDFS_SUBCLASSOF);
+ }
+
+ /**
+ * Answer the predicate that denotes that one property is a sub-property of another.
+ *
+ * @return object ResProperty
+ * @access public
+ */
+ function SUB_PROPERTY_OF()
+ {
+ return new ResProperty(RDF_SCHEMA_URI.RDFS_SUBPROPERTYOF);
+ }
+
+ /**
+ * Answer the string that is the namespace prefix for this vocabulary
+ *
+ * @return string
+ * @access public
+ */
+ function NAMESPACE()
+ {
+ return RDF_SCHEMA_URI;
+ }
+
+ /**
+ * Answer the predicate that denotes the rdf:type property.
+ *
+ * @return object ResProperty
+ * @access public
+ */
+ function TYPE()
+ {
+ return new ResProperty(RDF_NAMESPACE_URI.RDF_TYPE);
+ }
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/all-wcprops b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/all-wcprops
new file mode 100755
index 00000000..d048a41e
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/all-wcprops
@@ -0,0 +1,41 @@
+K 25
+svn:wc:ra_dav:version-url
+V 58
+/svnroot/rdfapi-php/!svn/ver/436/trunk/rdfapi-php/api/rdql
+END
+RdqlResultIterator.php
+K 25
+svn:wc:ra_dav:version-url
+V 81
+/svnroot/rdfapi-php/!svn/ver/268/trunk/rdfapi-php/api/rdql/RdqlResultIterator.php
+END
+RdqlDbEngine.php
+K 25
+svn:wc:ra_dav:version-url
+V 75
+/svnroot/rdfapi-php/!svn/ver/559/trunk/rdfapi-php/api/rdql/RdqlDbEngine.php
+END
+RdqlParser.php
+K 25
+svn:wc:ra_dav:version-url
+V 73
+/svnroot/rdfapi-php/!svn/ver/282/trunk/rdfapi-php/api/rdql/RdqlParser.php
+END
+RDQL.php
+K 25
+svn:wc:ra_dav:version-url
+V 67
+/svnroot/rdfapi-php/!svn/ver/320/trunk/rdfapi-php/api/rdql/RDQL.php
+END
+RdqlMemEngine.php
+K 25
+svn:wc:ra_dav:version-url
+V 76
+/svnroot/rdfapi-php/!svn/ver/268/trunk/rdfapi-php/api/rdql/RdqlMemEngine.php
+END
+RdqlEngine.php
+K 25
+svn:wc:ra_dav:version-url
+V 73
+/svnroot/rdfapi-php/!svn/ver/268/trunk/rdfapi-php/api/rdql/RdqlEngine.php
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/entries b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/entries
new file mode 100755
index 00000000..4c36cd16
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/entries
@@ -0,0 +1,106 @@
+8
+
+dir
+556
+https://rdfapi-php.svn.sourceforge.net/svnroot/rdfapi-php/trunk/rdfapi-php/api/rdql
+https://rdfapi-php.svn.sourceforge.net/svnroot/rdfapi-php
+
+
+
+2007-05-14T14:02:56.000000Z
+436
+cweiske
+
+
+svn:special svn:externals svn:needs-lock
+
+
+
+
+
+
+
+
+
+
+
+b2ee660e-c932-0410-bdee-d8da4d8102f4
+
+RdqlResultIterator.php
+file
+
+
+
+
+2008-02-29T14:57:45.147546Z
+2082617ae1572e2c8743d02da7471197
+2006-05-15T05:28:09.000000Z
+268
+tgauss
+has-props
+
+RdqlDbEngine.php
+file
+559
+
+
+
+2008-02-29T15:21:35.971116Z
+ef48aab131905e1d659302007a72ba23
+2008-02-29T15:21:35.565210Z
+559
+cax
+has-props
+
+RdqlParser.php
+file
+
+
+
+
+2008-02-29T14:57:45.163166Z
+8758bf7cb75eb3d0f34c5663fb818ee3
+2006-06-08T06:25:14.000000Z
+282
+tgauss
+has-props
+
+RDQL.php
+file
+
+
+
+
+2008-02-29T14:57:45.178787Z
+23ff8280200454e7df2c77e474713d57
+2006-11-21T09:38:51.000000Z
+320
+tgauss
+has-props
+
+RdqlMemEngine.php
+file
+
+
+
+
+2008-02-29T14:57:45.178787Z
+bed653582ea03b7e46ffa37e34685114
+2006-05-15T05:28:09.000000Z
+268
+tgauss
+has-props
+
+RdqlEngine.php
+file
+
+
+
+
+2008-02-29T14:57:45.194408Z
+d53f77256d1b05acc670e5af1d7a1773
+2006-05-15T05:28:09.000000Z
+268
+tgauss
+has-props
+
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/format b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/format
new file mode 100755
index 00000000..45a4fb75
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/format
@@ -0,0 +1 @@
+8
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/prop-base/RDQL.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/prop-base/RDQL.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/prop-base/RDQL.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/prop-base/RdqlDbEngine.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/prop-base/RdqlDbEngine.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/prop-base/RdqlDbEngine.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/prop-base/RdqlEngine.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/prop-base/RdqlEngine.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/prop-base/RdqlEngine.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/prop-base/RdqlMemEngine.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/prop-base/RdqlMemEngine.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/prop-base/RdqlMemEngine.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/prop-base/RdqlParser.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/prop-base/RdqlParser.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/prop-base/RdqlParser.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/prop-base/RdqlResultIterator.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/prop-base/RdqlResultIterator.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/prop-base/RdqlResultIterator.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/text-base/RDQL.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/text-base/RDQL.php.svn-base
new file mode 100755
index 00000000..ae136f10
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/text-base/RDQL.php.svn-base
@@ -0,0 +1,17 @@
+
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/text-base/RdqlDbEngine.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/text-base/RdqlDbEngine.php.svn-base
new file mode 100755
index 00000000..f09086fd
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/text-base/RdqlDbEngine.php.svn-base
@@ -0,0 +1,506 @@
+
+ *
+ * @package rdql
+ * @access public
+ */
+
+Class RdqlDbEngine extends RdqlEngine {
+
+
+/**
+ * Parsed query variables and constraints.
+ *
+ * @var array ['selectVars'][] = ?VARNAME
+ * ['sources'][] = URI
+ * ['patterns'][]['subject']['value'] = VARorURI
+ * ['predicate']['value'] = VARorURI
+ * ['object']['value'] = VARorURIorLiterl
+ * ['is_literal'] = boolean
+ * ['l_lang'] = string
+ * ['l_dtype'] = string
+ * ['filters'][]['string'] = string
+ * ['evalFilterStr'] = string
+ * ['reqexEqExprs'][]['var'] = ?VARNAME
+ * ['operator'] = (eq | ne)
+ * ['regex'] = string
+ * ['strEqExprs'][]['var'] = ?VARNAME
+ * ['operator'] = (eq | ne)
+ * ['value'] = string
+ * ['value_type'] = ('variable' | 'URI' | 'Literal')
+ * ['value_lang'] = string
+ * ['value_dtype'] = string
+ * ['numExpr']['vars'][] = ?VARNAME
+ * ( [] stands for an integer index - 0..N )
+ * @access private
+ */
+ var $parsedQuery;
+
+
+/**
+ * When an RDQL query is performed on a DbModel, in first step the engine searches
+ * in database for triples matching the Rdql-WHERE clause. A recordSet is returned.
+ * $rsIndexes maps select and filter variables to their corresponding indexes
+ * in the returned recordSet.
+ *
+ * @var array [?VARNAME]['value'] = integer
+ * ['nType'] = integer
+ * ['l_lang'] = integer
+ * ['l_dtype'] = integer
+ * @access private
+ */
+ var $rsIndexes;
+
+
+ /**
+ * Perform an RDQL Query on the given DbModel.
+ *
+ * @param object DbModel $dbModel
+ * @param array &$parsedQuery (the same format as $this->parsedQuery)
+ * @param boolean $returnNodes
+ * @return array [][?VARNAME] = object Node (if $returnNodes = TRUE)
+ * OR array [][?VARNAME] = string
+ * @access public
+ */
+ function & queryModel(&$dbModel, &$parsedQuery, $returnNodes = TRUE) {
+
+ $this->parsedQuery = &$parsedQuery;
+
+ $sql = $this->generateSql($dbModel->modelID);
+ $recordSet =& $dbModel->dbConn->execute($sql);
+ $queryResult = $this->filterQueryResult($recordSet);
+
+ if ($returnNodes)
+ $ret = $this->toNodes($queryResult);
+ else
+ $ret = $this->toString($queryResult);
+ return $ret;
+ }
+
+
+ /**
+ * Generate an SQL string to query the database for tuples matching all patterns
+ * of $parsedQuery.
+ *
+ * @param integer $modelID
+ * @return string
+ * @access private
+ */
+ function generateSql($modelID) {
+
+ $sql = $this->generateSql_SelectClause();
+ $sql .= $this->generateSql_FromClause();
+ $sql .= $this->generateSql_WhereClause($modelID);
+ return $sql;
+ }
+
+
+/**
+ * Generate SQL SELECT clause.
+ *
+ * @return string
+ * @throws PHPError
+ * @access private
+ */
+ function generateSql_SelectClause() {
+
+ $sql_select = 'SELECT';
+ $index = 0;
+ $this->rsIndexes = array();
+
+ foreach ($this->parsedQuery['selectVars'] as $var)
+ $sql_select .= $this->_generateSql_SelectVar($var, $index);
+
+ if (isset($this->parsedQuery['filters'])) {
+ foreach ($this->parsedQuery['filters'] as $n => $filter) {
+
+ // variables from numeric expressions
+ foreach ($filter['numExprVars'] as $numVar)
+ $sql_select .= $this->_generateSql_SelectVar($numVar, $index);
+
+ // variables from regex equality expressions
+ foreach ($filter['regexEqExprs'] as $regexEqExpr)
+ $sql_select .= $this->_generateSql_SelectVar($regexEqExpr['var'], $index);
+
+ // variables from string equality expressions
+ foreach ($filter['strEqExprs'] as $strEqVar)
+ $sql_select .= $this->_generateSql_SelectVar($strEqVar['var'], $index);
+ }
+ }
+
+ return rtrim($sql_select, " , ");
+ }
+
+
+/**
+ * Generate SQL FROM clause
+ *
+ * @return string
+ * @access private
+ */
+ function generateSql_FromClause() {
+
+ $sql_from = ' FROM';
+ foreach ($this->parsedQuery['patterns'] as $n => $v)
+ $sql_from .= ' statements s' .($n+1) .' , ';
+
+ return rtrim($sql_from, ' , ');
+ }
+
+
+/**
+ * Generate an SQL WHERE clause
+ *
+ * @param integer $modelID
+ * @return string
+ * @access private
+ */
+ function generateSql_WhereClause($modelID) {
+
+ $sql_where = ' WHERE';
+ $count_patterns = count($this->parsedQuery['patterns']);
+ foreach ($this->parsedQuery['patterns'] as $n => $pattern) {
+ $sql_where .= ' s' .($n+1) .'.modelID=' .$modelID .' AND';
+ foreach ($pattern as $key => $val_1)
+ if ($val_1['value'] && $val_1['value']{0}=='?') {
+ $sql_tmp = ' s' .($n+1) .'.' .$key .'=';
+ // find internal bindings
+ switch ($key) {
+ case 'subject':
+ if ($pattern['subject']['value'] == $pattern['predicate']['value'])
+ $sql_where .= $sql_tmp .'s' .($n+1) .'.predicate AND';
+ elseif ($pattern['subject']['value'] == $pattern['object']['value'])
+ $sql_where .= $sql_tmp .'s' .($n+1) .'.object AND';
+ break;
+ case 'predicate':
+ if ($pattern['predicate']['value'] == $pattern['object']['value'])
+ $sql_where .= $sql_tmp .'s' .($n+1) .'.object AND';
+ }
+ // find external bindings
+ for ($i=$n+1; $i<$count_patterns; $i++)
+ foreach ($this->parsedQuery['patterns'][$i] as $key2 => $val_2)
+ if ($val_1['value']==$val_2['value']) {
+ $sql_where .= $sql_tmp .'s' .($i+1) .'.' .$key2 .' AND';
+ break 2;
+ }
+ }else {
+ $sql_where .= ' s' .($n+1) .'.' .$key ."='" .$val_1['value'] ."' AND";
+ if ($key == 'object' && isset($val_1['is_literal'])) {
+ $sql_where .= ' s' .($n+1) .".object_is='l' AND";
+ $sql_where .= ' s' .($n+1) .".l_datatype='" .$val_1['l_dtype'] ."' AND";
+ $sql_where .= ' s' .($n+1) .".l_language='" .$val_1['l_lang'] ."' AND";
+ }
+ }
+ }
+ return rtrim($sql_where, ' AND');
+ }
+
+
+/**
+ * Filter tuples containing variables matching all patterns from the WHERE clause
+ * of an RDQL query. As a result of a database query using ADOdb these tuples
+ * are returned as an ADORecordSet object, which is then passed to this function.
+ *
+ * @param object ADORecordSet &$recordSet
+ * @return array [][?VARNAME]['value'] = string
+ * ['nType'] = string
+ * ['l_lang'] = string
+ * ['l_dtype'] = string
+ * @access private
+ */
+ function filterQueryResult(&$recordSet) {
+ $queryResult=array();
+
+ if (isset($this->parsedQuery['filters'])) {
+
+ while (!$recordSet->EOF) {
+
+ foreach ($this->parsedQuery['filters'] as $filter) {
+
+ $evalFilterStr = $filter['evalFilterStr'];
+
+ // evaluate regex equality expressions of each filter
+ foreach ($filter['regexEqExprs'] as $i => $expr) {
+ preg_match($expr['regex'], $recordSet->fields[$this->rsIndexes[$expr['var']]['value']], $match);
+ $op = substr($expr['operator'], 0,1);
+ if (($op != '!' && !isset($match[0])) || ($op == '!' && isset($match[0])))
+ $evalFilterStr = str_replace("##RegEx_$i##", 'FALSE', $evalFilterStr);
+ else
+ $evalFilterStr = str_replace("##RegEx_$i##", 'TRUE', $evalFilterStr);
+ }
+
+ // evaluate string equality expressions
+ foreach ($filter['strEqExprs'] as $i => $expr) {
+
+ $exprBoolVal = 'FALSE';
+
+ switch ($expr['value_type']) {
+
+ case 'variable':
+ if (($recordSet->fields[$this->rsIndexes[$expr['var']]['value']] ==
+ $recordSet->fields[$this->rsIndexes[$expr['value']]['value']] &&
+ $expr['operator'] == 'eq') ||
+ ($recordSet->fields[$this->rsIndexes[$expr['var']]['value']] !=
+ $recordSet->fields[$this->rsIndexes[$expr['value']]['value']] &&
+ $expr['operator'] == 'ne'))
+
+ $exprBoolVal = 'TRUE';
+ break;
+
+ case 'URI':
+
+ if (isset($this->rsIndexes[$expr['var']]['nType']) &&
+ $recordSet->fields[$this->rsIndexes[$expr['var']]['nType']] == 'l') {
+
+ if ($expr['operator'] == 'ne')
+ $exprBoolVal = 'TRUE';
+ break;
+ }
+
+ if (($recordSet->fields[$this->rsIndexes[$expr['var']]['value']] ==
+ $expr['value'] && $expr['operator'] == 'eq') ||
+ ($recordSet->fields[$this->rsIndexes[$expr['var']]['value']] !=
+ $expr['value'] && $expr['operator'] == 'ne'))
+ $exprBoolVal = 'TRUE';
+ break;
+
+ case 'Literal':
+
+ if (!isset($this->rsIndexes[$expr['var']]['nType']) ||
+ $recordSet->fields[$this->rsIndexes[$expr['var']]['nType']] != 'l') {
+
+ if ($expr['operator'] == 'ne')
+ $exprBoolVal = 'TRUE';
+ break;
+ }
+
+ $filterLiteral= new Literal($expr['value'],$expr['value_lang']);
+ $filterLiteral->setDatatype($expr['value_dtype']);
+
+ $resultLiteral=new Literal($recordSet->fields[$this->rsIndexes[$expr['var']]['value']]);
+ $resultLiteral->setDatatype($recordSet->fields[$this->rsIndexes[$expr['var']]['l_dtype']]);
+ $resultLiteral->setLanguage($recordSet->fields[$this->rsIndexes[$expr['var']]['l_lang']]);
+
+ $equal=$resultLiteral->equals($filterLiteral);
+
+ if (($equal && $expr['operator'] == 'eq') ||
+ (!$equal && $expr['operator'] == 'ne'))
+ $exprBoolVal = 'TRUE';
+ else
+ $exprBoolVal = 'FALSE';
+
+ }
+
+ $evalFilterStr = str_replace("##strEqExpr_$i##", $exprBoolVal, $evalFilterStr);
+ }
+
+ // evaluate numerical expressions
+ foreach ($filter['numExprVars'] as $varName) {
+ $varValue = "'" .$recordSet->fields[$this->rsIndexes[$varName]['value']] ."'";
+ $evalFilterStr = str_replace($varName, $varValue, $evalFilterStr);
+ }
+
+ eval("\$filterBoolVal = $evalFilterStr; \$eval_filter_ok = TRUE;");
+ if (!isset($eval_filter_ok))
+ trigger_error(RDQL_AND_ERR ."'" .htmlspecialchars($filter['string']) ."'", E_USER_ERROR);
+
+ if (!$filterBoolVal) {
+ $recordSet->MoveNext();
+ continue 2;
+ }
+
+ }
+ $queryResult[] = $this->_convertRsRowToQueryResultRow($recordSet->fields);
+ $recordSet->MoveNext();
+ }
+
+ }else
+ while (!$recordSet->EOF) {
+ $queryResult[] = $this->_convertRsRowToQueryResultRow($recordSet->fields);
+ $recordSet->MoveNext();
+ }
+ return $queryResult;
+ }
+
+
+/**
+ * Serialize variable values of $queryResult to string.
+ *
+ * @param array &$queryResult [][?VARNAME]['value'] = string
+ * ['nType'] = string
+ * ['l_lang'] = string
+ * ['l_dtype'] = string
+ * @return array [][?VARNAME] = string
+ * @access private
+ */
+ function toString(&$queryResult) {
+
+ // if a result set is empty return only variable sames
+ if (count($queryResult) == 0) {
+ foreach ($this->parsedQuery['selectVars'] as $selectVar)
+ $res[0][$selectVar] = NULL;
+ return $res;
+ }
+
+ $res = array();
+ foreach ($queryResult as $n => $var)
+ foreach ($var as $varname => $varProperties)
+ if ($varProperties['nType'] == 'r' || $varProperties['nType'] == 'b')
+ $res[$n][$varname] = '<' .$varProperties['value'] .'>';
+ else {
+ $res[$n][$varname] = '"' .$varProperties['value'] .'"';
+ if ($varProperties['l_lang'] != NULL)
+ $res[$n][$varname] .= ' (xml:lang="' .$varProperties['l_lang'] .'")';
+ if ($varProperties['l_dtype'] != NULL)
+ $res[$n][$varname] .= ' (rdf:datatype="' .$varProperties['l_dtype'] .'")';
+ }
+ return $res;
+ }
+
+
+/**
+ * Convert variable values of $queryResult to objects (Node).
+ *
+ * @param array &$queryResult [][?VARNAME]['value'] = string
+ * ['nType'] = string
+ * ['l_lang'] = string
+ * ['l_dtype'] = string
+ * @return array [][?VARNAME] = object Node
+ * @access private
+ */
+ function toNodes(&$queryResult) {
+
+ // if a result set is empty return only variable sames
+ if (count($queryResult) == 0) {
+ foreach ($this->parsedQuery['selectVars'] as $selectVar)
+ $res[0][$selectVar] = NULL;
+ return $res;
+ }
+
+ $res = array();
+ foreach ($queryResult as $n => $var)
+ foreach ($var as $varname => $varProperties)
+ if ($varProperties['nType'] == 'r')
+ $res[$n][$varname] = new Resource($varProperties['value']);
+ elseif ($varProperties['nType'] == 'b')
+ $res[$n][$varname] = new BlankNode($varProperties['value']);
+ else {
+ $res[$n][$varname] = new Literal($varProperties['value'], $varProperties['l_lang']);
+ if ($varProperties['l_dtype'] != NULL)
+ $res[$n][$varname]->setDataType($varProperties['l_dtype']);
+ }
+ return $res;
+ }
+
+
+/**
+ * Generate a piece of an sql select statement for a variable.
+ * Look first if the given variable is defined as a pattern object.
+ * (So you can select the node type, literal lang and dtype)
+ * If not found - look for subjects and select node label and type.
+ * If there is no result either go to predicates.
+ * Predicates are always resources therefore select only the node label.
+ *
+ * @param string $varName
+ * @return string
+ * @access private
+ */
+function _generateSql_SelectVar ($varName, &$index) {
+
+ $sql_select = '';
+
+ if (array_key_exists($varName, $this->rsIndexes))
+ return NULL;
+
+ foreach ($this->parsedQuery['patterns'] as $n => $pattern)
+ if ($varName == $pattern['object']['value']) {
+
+ // select the object label
+ $sql_select .= " s" .++$n .".object as _" .ltrim($varName, "?") ." , ";
+ $this->rsIndexes[$varName]['value'] = $index++;
+ // select the node type
+ $sql_select .= " s" .$n .".object_is , ";
+ $this->rsIndexes[$varName]['nType'] = $index++;
+ // select the object language
+ $sql_select .= " s" .$n .".l_language , ";
+ $this->rsIndexes[$varName]['l_lang'] = $index++;
+ // select the object dtype
+ $sql_select .= " s" .$n .".l_datatype , ";
+ $this->rsIndexes[$varName]['l_dtype'] = $index++;
+
+ return $sql_select;
+ }
+
+ foreach ($this->parsedQuery['patterns'] as $n => $pattern)
+ if ($varName == $pattern['subject']['value']) {
+
+ // select the object label
+ $sql_select .= " s" .++$n .".subject as _" .ltrim($varName, "?") ." , ";
+ $this->rsIndexes[$varName]['value'] = $index++;
+ // select the node type
+ $sql_select .= " s" .$n .".subject_is , ";
+ $this->rsIndexes[$varName]['nType'] = $index++;
+
+ return $sql_select;
+ }
+
+ foreach ($this->parsedQuery['patterns'] as $n => $pattern)
+ if ($varName == $pattern['predicate']['value']) {
+
+ // select the object label
+ $sql_select .= " s" .++$n .".predicate as _" .ltrim($varName, "?") ." , ";
+ $this->rsIndexes[$varName]['value'] = $index++;
+
+ return $sql_select;
+ }
+ }
+
+
+/**
+ * Converts a single row of ADORecordSet->fields array to the format of
+ * $queryResult array using pointers to indexes ($this->rsIndexes) in RecordSet->fields.
+ *
+ * @param array &$record [] = string
+ * @return array [?VARNAME]['value'] = string
+ * ['nType'] = string
+ * ['l_lang'] = string
+ * ['l_dtype'] = string
+ * @access private
+ */
+ function _convertRsRowToQueryResultRow(&$record) {
+
+ // return only select variables (without conditional variables from the AND clause)
+ foreach ($this->parsedQuery['selectVars'] as $selectVar) {
+ $resultRow[$selectVar]['value'] = $record[$this->rsIndexes[$selectVar]['value']];
+ if (isset($this->rsIndexes[$selectVar]['nType']))
+ $resultRow[$selectVar]['nType'] = $record[$this->rsIndexes[$selectVar]['nType']];
+ // is a predicate then
+ else
+ $resultRow[$selectVar]['nType'] = 'r';
+
+ if ($resultRow[$selectVar]['nType'] == 'l') {
+ $resultRow[$selectVar]['l_lang'] = $record[$this->rsIndexes[$selectVar]['l_lang']];
+ $resultRow[$selectVar]['l_dtype'] = $record[$this->rsIndexes[$selectVar]['l_dtype']];
+ }
+ }
+ return $resultRow;
+ }
+
+} // end: Class RdqlDbEngine
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/text-base/RdqlEngine.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/text-base/RdqlEngine.php.svn-base
new file mode 100755
index 00000000..950238ac
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/text-base/RdqlEngine.php.svn-base
@@ -0,0 +1,69 @@
+
+ *
+ * @package rdql
+ * @access public
+ */
+
+Class RdqlEngine extends Object{
+
+
+
+/**
+ * Prints a query result as HTML table.
+ * You can change the colors in the configuration file.
+ *
+ * @param array $queryResult [][?VARNAME] = object Node
+ * @access private
+ */
+ function writeQueryResultAsHtmlTable($queryResult) {
+ // Import Package Utility
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_UTILITY);
+
+ if (current($queryResult[0]) == NULL) {
+ echo 'no match
';
+ return;
+ }
+
+ echo '| No. | ';
+ foreach ($queryResult[0] as $varName => $value)
+ echo "$varName | ";
+ echo '
';
+
+ foreach ($queryResult as $n => $var) {
+
+
+ echo '| ' .($n + 1) .'. | ';
+ foreach ($var as $varName => $value) {
+ echo INDENTATION . INDENTATION . '';
+ echo ' ';
+
+ $lang = NULL;
+ $dtype = NULL;
+ if (is_a($value, 'Literal')) {
+ if ($value->getLanguage() != NULL)
+ $lang = ' (xml:lang="' . $value->getLanguage() . '") ';
+ if ($value->getDatatype() != NULL)
+ $dtype = ' (rdf:datatype="' . $value->getDatatype() . '") ';
+ }
+ echo RDFUtil::getNodeTypeName($value) .$value->getLabel() . $lang . $dtype .' ';
+ }
+ echo ' |
';
+ }
+ echo '
';
+ }
+
+} // end: Class RdqlEngine
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/text-base/RdqlMemEngine.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/text-base/RdqlMemEngine.php.svn-base
new file mode 100755
index 00000000..b3b86201
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/text-base/RdqlMemEngine.php.svn-base
@@ -0,0 +1,555 @@
+
+ *
+ * @package rdql
+ * @access public
+ */
+
+Class RdqlMemEngine extends RdqlEngine {
+
+
+/**
+ * Parsed query variables and constraints.
+ *
+ * @var array ['selectVars'][] = ?VARNAME
+ * ['sources'][] = URI
+ * ['patterns'][]['subject']['value'] = VARorURI
+ * ['predicate']['value'] = VARorURI
+ * ['object']['value'] = VARorURIorLiterl
+ * ['is_literal'] = boolean
+ * ['l_lang'] = string
+ * ['l_dtype'] = string
+ * ['filters'][]['string'] = string
+ * ['evalFilterStr'] = string
+ * ['reqexEqExprs'][]['var'] = ?VARNAME
+ * ['operator'] = (eq | ne)
+ * ['regex'] = string
+ * ['strEqExprs'][]['var'] = ?VARNAME
+ * ['operator'] = (eq | ne)
+ * ['value'] = string
+ * ['value_type'] = ('variable' | 'URI' | 'Literal')
+ * ['value_lang'] = string
+ * ['value_dtype'] = string
+ * ['numExpr']['vars'][] = ?VARNAME
+ * ( [] stands for an integer index - 0..N )
+ * @access private
+ */
+ var $parsedQuery;
+
+
+ /**
+ * Perform an RDQL Query on the given MemModel.
+ *
+ * @param object MemModel &$memModel
+ * @param array &$parsedQuery (the same format as $this->parsedQuery)
+ * @param boolean $returnNodes
+ * @return array [][?VARNAME] = object Node (if $returnNodes = TRUE)
+ * OR array [][?VARNAME] = string
+ *
+ * @access public
+ */
+ function & queryModel(&$memModel, &$parsedQuery, $returnNodes = TRUE) {
+
+ $this->parsedQuery = $parsedQuery;
+
+ // find tuples matching all patterns
+ $res = $this->findTuplesMatchingAllPatterns($memModel);
+
+ // filter tuples
+ if (isset($parsedQuery['filters']))
+ $res = $this->filterTuples($res);
+
+ // select variables to be returned
+ $res = $this->selectVariables($res);
+
+ if(!$returnNodes)
+ return $this->toString($res);
+
+ return $res;
+ }
+
+
+ /**
+ * Find triples matching all patterns of an RDQL query and return an array
+ * with variables from all patterns and their corresponding values.
+ * The variable values returned are instances of object Node.
+ *
+ * @param object MemModel &$memModel
+ * @return array [][?VARNAME] = object Node
+ *
+ * @access private
+ */
+ function findTuplesMatchingAllPatterns(&$memModel) {
+
+ $resultSet = $this->findTuplesMatchingOnePattern($memModel, $this->parsedQuery['patterns'][0]);
+ for ($i=1; $iparsedQuery['patterns']); $i++) {
+ $rs = $this->findTuplesMatchingOnePattern($memModel, $this->parsedQuery['patterns'][$i]);
+ $resultSet = $this->joinTuples($resultSet, $rs);
+ }
+ return $resultSet;
+ }
+
+
+/**
+ * Find tuples matching one pattern and return an array with pattern
+ * variables and their corresponding values (instances of object Node).
+ *
+ * @param object MemModel &$memModel
+ * @param array &$pattern ['subject']['value'] = VARorURI
+ * ['predicate']['value'] = VARorURI
+ * ['object']['value'] = VARorURIorLiterl
+ * ['is_literal'] = boolean
+ * ['l_lang'] = string
+ * ['l_dtype'] = string
+ * @return array [][?VARNAME] = object Node
+ *
+ * @access private
+ */
+ function findTuplesMatchingOnePattern(&$memModel, &$pattern) {
+
+ $resultSet = array();
+ $i = 0;
+ // parameters to be passed to the method findTriplesMatchingPattern
+ foreach ($pattern as $key => $v) {
+ if ($v['value'] && $v['value']{0} == '?') {
+ if ($key == 'object') {
+ $param['object']['is_a'] = 'ANY';
+ $param['object']['string'] = 'ANY';
+ $param['object']['lang'] = NULL;
+ $param['object']['dtype'] = NULL;
+ } else
+ $param[$key] = 'ANY';
+ $var[$i]['key'] = $key;
+ $var[$i++]['val'] = $v['value'];
+ }else
+ if (isset($v['is_literal'])) {
+ $param[$key]['is_a'] = 'Literal';
+ $param[$key]['string'] = $v['value'];
+ $param[$key]['lang'] = $v['l_lang'];
+ $param[$key]['dtype'] = $v['l_dtype'];
+ }else{
+ if ($key == 'object') {
+ $param[$key]['is_a'] = 'Resource';
+ $param[$key]['string'] = $v['value'];
+ $param[$key]['lang'] = NULL;
+ $param[$key]['dtype'] = NULL;
+ }else
+ $param[$key] = $v['value'];
+ }
+ }
+
+ // find pattern internal bindings e.g. (?x, ?z, ?x)
+ $intBindings = NULL;
+ for ($i=0; $i $v)
+ if ($i != $n && $var[$i]['val'] == $v['val'])
+ $intBindings[] = $var[$i]['key'];
+
+ // find triples of the $memModel matching $pattern
+ $resModel = $this->findTriplesMatchingPattern($memModel, $param['subject'],
+ $param['predicate'],
+ $param['object']['is_a'],
+ $param['object']['string'],
+ $param['object']['lang'],
+ $param['object']['dtype'],
+ $intBindings);
+
+ // set values of the pattern variables to be returned
+ if ($pattern['subject']['value']{0} == '?') {
+ $n = 0;
+ foreach ($resModel->triples as $triple)
+ $resultSet[$n++][$pattern['subject']['value']] = $triple->subj;
+ }
+ if ($pattern['predicate']['value']{0} == '?') {
+ $n = 0;
+ foreach ($resModel->triples as $triple)
+ $resultSet[$n++][$pattern['predicate']['value']] = $triple->pred;
+ }
+ if ($pattern['object']['value'] && $pattern['object']['value']{0} == '?') {
+ $n = 0;
+ foreach ($resModel->triples as $triple)
+ $resultSet[$n++][$pattern['object']['value']] = $triple->obj;
+ }
+ return $resultSet;
+ }
+
+
+/**
+ * Search in $memModel for triples matching one pattern from the WHERE clause.
+ * 'ANY' input for $subjLabel..$objLabel, $obj_is will match anything.
+ * NULL input for $objDtype will only match obj->dtype = NULL
+ * NULL input for $objLanguage will match obj->lang = NULL or anything if a
+ * literal is datatyped (except for XMLLiterals and plain literals)
+ * This method also checks internal bindings if provided.
+ *
+ * @param object MemModel $memModel
+ * @param string $subjLabel
+ * @param string $predLabel
+ * @param string $objLabel
+ * @param string $obj_is
+ * @param string $objLanguage
+ * @param string $objDtype
+ * @param array $intBindings [] = string
+ * @return object MemModel
+ * @access private
+ */
+ function findTriplesMatchingPattern(&$memModel, $subjLabel, $predLabel, $obj_is,
+ $objLabel, $objLang, $objDtype, &$intBindings) {
+
+ $res = new MemModel();
+
+ if($memModel->isEmpty())
+ return $res;
+
+ if ($subjLabel=='ANY')
+ {
+ $subj=NULL;
+ } else
+ {
+ $subj=new Resource($subjLabel);
+ };
+ if ($predLabel=='ANY')
+ {
+ $pred=NULL;
+ } else
+ {
+ $pred=new Resource($predLabel);
+ };
+
+ if ($objLabel=='ANY')
+ {
+ $obj=NULL;
+ } else
+ {
+ if ($obj_is == 'Literal')
+ {
+ $obj=new Literal($objLabel);
+ $obj->setDatatype($objDtype);
+ $obj->setLanguage($objLang);
+ } else {
+ $obj=new Resource($objLabel);
+ }
+ };
+
+ $res=$memModel->find($subj,$pred,$obj);
+
+ if ($intBindings)
+ foreach ($res->triples as $triple)
+ {
+ if (!$this->_checkIntBindings($triple, $intBindings))
+ {
+ $res->remove($triple);
+ }
+ }
+
+ return $res;
+}
+
+
+/**
+ * Perform an SQL-like inner join on two resultSets.
+ *
+ * @param array &$finalRes [][?VARNAME] = object Node
+ * @param array &$res [][?VARNAME] = object Node
+ * @return array [][?VARNAME] = object Node
+ *
+ * @access private
+ */
+ function joinTuples(&$finalRes, &$res) {
+
+ if (count($finalRes) == 0 || count($res) == 0)
+ return array();
+
+ // find joint variables and new variables to be added to $finalRes
+ $jointVars = array();
+ $newVars = array();
+ foreach ($res[0] as $varname => $node) {
+ if (array_key_exists($varname, $finalRes[0]))
+ $jointVars[] = $varname;
+ else
+ $newVars[] = $varname;
+ }
+
+ // eliminate rows of $finalRes in which the values of $jointVars do not have
+ // a corresponding row in $res.
+ foreach ($finalRes as $n => $fRes) {
+ foreach ($res as $i => $r) {
+ $ok = TRUE;
+ foreach ($jointVars as $j_varname)
+ if ($r[$j_varname] != $fRes[$j_varname]) {
+ $ok = FALSE;
+ break;
+ }
+ if ($ok)
+ break;
+ }
+ if (!$ok)
+ unset($finalRes[$n]);
+ }
+
+ // join $res and $finalRes
+ $joinedRes = array();
+ foreach ($res as $i => $r) {
+ foreach ($finalRes as $n => $fRes) {
+ $ok = TRUE;
+ foreach ($jointVars as $j_varname)
+ if ($r[$j_varname] != $fRes[$j_varname]) {
+ $ok = FALSE;
+ break;
+ }
+ if ($ok) {
+ $joinedRow = $finalRes[$n];
+ foreach($newVars as $n_varname)
+ $joinedRow[$n_varname] = $r[$n_varname];
+ $joinedRes[] = $joinedRow;
+ }
+ }
+ }
+
+ return $joinedRes;
+ }
+
+
+/**
+ * Filter the result-set of query variables by evaluating each filter from the
+ * AND clause of the RDQL query.
+ *
+ * @param array &$finalRes [][?VARNAME] = object Node
+ * @return array [][?VARNAME] = object Node
+ * @access private
+ */
+ function filterTuples(&$finalRes) {
+
+ foreach ($this->parsedQuery['filters'] as $filter) {
+
+ foreach ($finalRes as $n => $fRes) {
+ $evalFilterStr = $filter['evalFilterStr'];
+
+ // evaluate regex equality expressions of each filter
+ foreach ($filter['regexEqExprs'] as $i => $expr) {
+
+ preg_match($expr['regex'], $fRes[$expr['var']]->getLabel(), $match);
+ $op = substr($expr['operator'], 0,1);
+ if (($op != '!' && !isset($match[0])) || ($op == '!' && isset($match[0])))
+ $evalFilterStr = str_replace("##RegEx_$i##", 'FALSE', $evalFilterStr);
+ else
+ $evalFilterStr = str_replace("##RegEx_$i##", 'TRUE', $evalFilterStr);
+
+ }
+
+ // evaluate string equality expressions
+ foreach ($filter['strEqExprs'] as $i => $expr) {
+
+ $exprBoolVal = 'FALSE';
+
+ switch ($expr['value_type']) {
+
+ case 'variable':
+ if (($fRes[$expr['var']] == $fRes[$expr['value']] && $expr['operator'] == 'eq') ||
+ ($fRes[$expr['var']] != $fRes[$expr['value']] && $expr['operator'] == 'ne'))
+ $exprBoolVal = 'TRUE';
+ break;
+
+ case 'URI':
+
+ if (is_a($fRes[$expr['var']], 'Literal')) {
+ if ($expr['operator'] == 'ne')
+ $exprBoolVal = 'TRUE';
+ break;
+ }
+
+ if (($fRes[$expr['var']]->getLabel() == $expr['value'] && $expr['operator'] == 'eq') ||
+ ($fRes[$expr['var']]->getLabel() != $expr['value'] && $expr['operator'] == 'ne'))
+ $exprBoolVal = 'TRUE';
+ break;
+
+ case 'Literal':
+
+ if (!is_a($fRes[$expr['var']], 'Literal')) {
+ if ($expr['operator'] == 'ne')
+ $exprBoolVal = 'TRUE';
+ break;
+ }
+
+ $filterLiteral= new Literal($expr['value'],$expr['value_lang']);
+ $filterLiteral->setDatatype($expr['value_dtype']);
+
+ $equal=$fRes[$expr['var']]->equals($filterLiteral);
+/* if ($fRes[$expr['var']]->getLabel() == $expr['value'] &&
+ $fRes[$expr['var']]->getDatatype() == $expr['value_dtype']) {
+
+ $equal = TRUE;
+
+ // Lang tags only differentiate literals in rdf:XMLLiterals and plain literals.
+ // Therefore if a literal is datatyped ignore the language tag.
+ if ((($expr['value_dtype'] == NULL) ||
+ ($expr['value_dtype'] == 'http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral') ||
+ ($expr['value_dtype'] == 'http://www.w3.org/2001/XMLSchema#string')) &&
+ (($fRes[$expr['var']]->getLanguage() != $expr['value_lang'])))
+
+ $equal = FALSE;
+ }else
+ $equal = FALSE;
+ */
+ if (($equal && $expr['operator'] == 'eq') ||
+ (!$equal && $expr['operator'] == 'ne'))
+ $exprBoolVal = 'TRUE';
+ else
+ $exprBoolVal = 'FALSE';
+
+ }
+ $evalFilterStr = str_replace("##strEqExpr_$i##", $exprBoolVal, $evalFilterStr);
+ }
+
+ // evaluate numerical expressions
+ foreach ($filter['numExprVars'] as $varName) {
+ $varValue = "'" .$fRes[$varName]->getLabel() ."'";
+ $evalFilterStr = str_replace($varName, $varValue, $evalFilterStr);
+ }
+
+ eval("\$filterBoolVal = $evalFilterStr; \$eval_filter_ok = TRUE;");
+ if (!isset($eval_filter_ok))
+ trigger_error(RDQL_AND_ERR ."'" .htmlspecialchars($filter['string']) ."'", E_USER_ERROR);
+
+ if (!$filterBoolVal)
+ unset($finalRes[$n]);
+ }
+ }
+
+ return $finalRes;
+ }
+
+
+/**
+ * Remove all conditional variables from the result-set and leave only variables
+ * specified in the SELECT clause of the RDQL query.
+ *
+ * @param array &$finalRes [][?VARNAME] = object Node
+ * @return array [][?VARNAME] = object Node
+ * @access private
+ */
+ function selectVariables(&$finalRes) {
+
+ // if nothing has been found return only one row of $finalRes
+ // with select variables having empty values
+ if (count($finalRes) == 0) {
+ foreach ($this->parsedQuery['selectVars'] as $selectVar)
+ $finalRes[0][$selectVar] = NULL;
+ return $finalRes;
+ }
+
+ // return only selectVars in the same order as given in the RDQL query
+ // and reindex $finalRes.
+ $n = 0;
+ foreach($finalRes as $key => $val) {
+ foreach ($this->parsedQuery['selectVars'] as $selectVar)
+ $resultSet[$n][$selectVar] = $val[$selectVar];
+ unset($finalRes[$key]);
+ ++$n;
+ }
+
+ return $resultSet;
+ }
+
+
+/**
+ * Convert the variable values of $finalRes from objects to their string serialization.
+ *
+ * @param array &$finalRes [][?VARNAME] = object Node
+ * @return array [][?VARNAME] = string
+ * @access private
+ */
+ function toString(&$finalRes) {
+
+ foreach ($finalRes as $n => $tuple)
+ foreach ($tuple as $varname => $node) {
+ if (is_a($node, 'Resource'))
+ $res[$n][$varname] = '<' .$node->getLabel() .'>';
+ elseif (is_a($node, 'Literal')) {
+ $res[$n][$varname] = '"' .$node->getLabel() .'"';
+ if ($node->getLanguage())
+ $res[$n][$varname] .= ' (xml:lang="' .$node->getLanguage() .'")';
+ if ($node->getDatatype())
+ $res[$n][$varname] .= ' (rdf:datatype="' .$node->getDatatype() .'")';
+ }else
+ $res[$n][$varname] = $node;
+ }
+ return $res;
+ }
+
+
+/**
+ * Check if the given triple meets pattern internal bindings
+ * e.g. (?x, ?z, ?x) ==> statement subject must be identical with the statement object
+ *
+ * @param object statement &$triple
+ * @param array &$intBindings [] = string
+ * @return boolean
+ * @access private
+ */
+ function _checkIntBindings (&$triple, &$intBindings) {
+
+ if (in_array('subject', $intBindings)) {
+ if (in_array('predicate', $intBindings))
+ if ($triple->subj != $triple->pred)
+ return FALSE;
+ if (in_array('object', $intBindings)) {
+ if (is_a($triple->obj, 'Literal'))
+ return FALSE;
+ elseif ($triple->subj != $triple->obj)
+ return FALSE;
+ }
+ return TRUE;
+ }
+ if (in_array('predicate', $intBindings)) {
+ if (is_a($triple->obj, 'Literal'))
+ return FALSE;
+ elseif ($triple->pred != $triple->obj)
+ return FALSE;
+ return TRUE;
+ }
+ }
+
+
+/**
+ * Check if the lang and dtype of the passed object Literal are equal $lang and $dtype
+ * !!! Language only differentiates literals in rdf:XMLLiterals and plain literals (xsd:string).
+ * !!! Therefore if a literal is datatyped ignore the language.
+ *
+ * @param object Literal $literal
+ * @param string $dtype1
+ * @param string $dtype2
+ * @return boolean
+ * @access private
+ */
+ function _equalsLangDtype ($literal, $lang, $dtype) {
+
+ if ($dtype == $literal->getDatatype()) {
+ if (($dtype == NULL ||
+ $dtype == 'http://www.w3.org/2001/XMLSchema#string' ||
+ $dtype == 'http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral') &&
+ ($lang != $literal->getLanguage()))
+ return FALSE;
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+
+} // end: Class RdqlMemEngine
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/text-base/RdqlParser.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/text-base/RdqlParser.php.svn-base
new file mode 100755
index 00000000..3403966a
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/text-base/RdqlParser.php.svn-base
@@ -0,0 +1,1063 @@
+
+ *
+ * @package rdql
+ * @access public
+ */
+
+
+Class RdqlParser extends Object{
+
+/**
+ * Parsed query variables and constraints.
+ * { } are only used within the parser class and are not returned as parsed query.
+ * ( [] stands for an integer index - 0..N )
+ *
+ * @var array ['selectVars'][] = ?VARNAME
+ * ['sources'][]{['value']} = URI | QName
+ * {['is_qname'] = boolean}
+ * ['patterns'][]['subject']['value'] = VARorURI
+ * {['is_qname'] = boolean}
+ * ['predicate']['value'] = VARorURI
+ * {['is_qname'] = boolean}
+ * ['object']['value'] = VARorURIorLiterl
+ * {['is_qname'] = boolean}
+ * ['is_literal'] = boolean
+ * ['l_lang'] = string
+ * ['l_dtype'] = string
+ * {['l_dtype_is_qname'] = boolean}
+ * ['filters'][]['string'] = string
+ * ['evalFilterStr'] = string
+ * ['reqexEqExprs'][]['var'] = ?VARNAME
+ * ['operator'] = (eq | ne)
+ * ['regex'] = string
+ * ['strEqExprs'][]['var'] = ?VARNAME
+ * ['operator'] = (eq | ne)
+ * ['value'] = string
+ * ['value_type'] = ('variable' | 'URI' | 'QName' | 'Literal')
+ * ['value_lang'] = string
+ * ['value_dtype'] = string
+ * {['value_dtype_is_qname'] = boolean}
+ * ['numExpr']['vars'][] = ?VARNAME
+ * {['ns'][PREFIX] = NAMESPACE}
+ * @access private
+ */
+ var $parsedQuery;
+
+
+/**
+ * Query string divided into a sequence of tokens.
+ * A token is either: ' ' or "\n" or "\r" or "\t" or ',' or '(' or ')'
+ * or a string containing any characters except from the above.
+ *
+ * @var array
+ * @access private
+ */
+ var $tokens;
+
+
+/**
+ * Parse the given RDQL query string and return an array with query variables and constraints.
+ *
+ * @param string $queryString
+ * @return array $this->parsedQuery
+ * @access public
+ */
+ function & parseQuery($queryString) {
+
+ $cleanQueryString = $this->removeComments($queryString);
+ $this->tokenize($cleanQueryString);
+ $this->startParsing();
+ if ($this->parsedQuery['selectVars'][0] == '*')
+ $this->parsedQuery['selectVars'] = $this->findAllQueryVariables();
+ else
+ $this->_checkSelectVars();
+ $this->replaceNamespacePrefixes();
+
+ return $this->parsedQuery;
+ }
+
+
+/**
+ * Remove comments from the passed query string.
+ *
+ * @param string $query
+ * @return string
+ * @throws PHPError
+ * @access private
+ */
+ function removeComments($query) {
+
+ $last = strlen($query)-1;
+ $query .= ' ';
+ $clean = '';
+ for ($i=0; $i<=$last; $i++) {
+ // don't search for comments inside a 'literal'@lang^^dtype or "literal"@lang^^dtype
+ if ($query{$i} == "'" || $query{$i} == '"') {
+ $quotMark = $query{$i};
+ do
+ $clean .= $query{$i++};
+ while($i < $last && $query{$i} != $quotMark);
+ $clean .= $query{$i};
+ // language
+ if ($query{$i+1} == '@') {
+ do{
+ if ($query{$i+1} == '^' && $query{$i+2} == '^')
+ break;
+ $clean .= $query{++$i};
+ }while ($i < $last && $query{$i} != ' ' && $query{$i} != "\t"
+ && $query{$i} != "\n" && $query{$i} != "\r");
+ }
+ // datatype
+ if ($query{$i+1} == '^' && $query{$i+2} == '^') {
+ do
+ $clean .= $query{++$i};
+ while ($i < $last && $query{$i} != ' ' && $query{$i} != "\t"
+ && $query{$i} != "\n" && $query{$i} != "\r" );
+ }
+ // don't search for comments inside an either
+ }elseif ($query{$i} == '<') {
+ do{
+ $clean .= $query{$i++};
+ }while($i < $last && $query{$i} != '>');
+ $clean .= $query{$i};
+ }elseif ($query{$i} == '/') {
+ // clear: // comment
+ if ($i < $last && $query{$i+1} == '/') {
+ while($i < $last && $query{$i} != "\n" && $query{$i} != "\r")
+ ++$i;
+ $clean .= ' ';
+ // clear: /*comment*/
+ }elseif ($i < $last-2 && $query{$i+1} == '*') {
+ $i += 2;
+ while($i < $last && ($query{$i} != '*' || $query{$i+1} != '/'))
+ ++$i;
+ if ($i >= $last && ($query{$last-1} != '*' || $query{$last} != '/'))
+ trigger_error(RDQL_SYN_ERR .": unterminated comment - '*/' missing", E_USER_ERROR);
+ ++$i;
+ }else
+ $clean .= $query{$i};
+ }else
+ $clean .= $query{$i};
+ }
+ return $clean;
+ }
+
+
+/**
+ * Divide the query string into tokens.
+ * A token is either: ' ' or "\n" or "\r" or '\t' or ',' or '(' or ')'
+ * or a string containing any character except from the above.
+ *
+ * @param string $queryString
+ * @access private
+ */
+ function tokenize($queryString) {
+
+ $queryString = trim($queryString, " \r\n\t");
+ $specialChars = array (" ", "\t", "\r", "\n", ",", "(", ")");
+ $len = strlen($queryString);
+ $this->tokens[0]='';
+ $n = 0;
+
+ for ($i=0; $i<$len; ++$i) {
+ if (!in_array($queryString{$i}, $specialChars))
+ $this->tokens[$n] .= $queryString{$i};
+ else {
+ if ($this->tokens[$n] != '')
+ ++$n;
+ $this->tokens[$n] = $queryString{$i};
+ $this->tokens[++$n] = '';
+ }
+ }
+ }
+
+
+/**
+ * Start parsing of the tokenized query string.
+ *
+ * @access private
+ */
+ function startParsing() {
+
+ $this->parseSelect();
+ }
+
+
+/**
+ * Parse the SELECT clause of an Rdql query.
+ * When the parsing of the SELECT clause is finished, this method will call
+ * a suitable method to parse the subsequent clause.
+ *
+ * @throws PhpError
+ * @access private
+ */
+ function parseSelect() {
+
+ $this->_clearWhiteSpaces();
+
+ // Check if the queryString contains a "SELECT" token
+ if (strcasecmp('SELECT', current($this->tokens)))
+ trigger_error(RDQL_SEL_ERR ."'" .current($this->tokens)
+ ."' - SELECT keyword expected", E_USER_ERROR);
+ unset($this->tokens[key($this->tokens)]);
+ $this->_clearWhiteSpaces();
+
+ // Parse SELECT *
+ if (current($this->tokens) == '*') {
+ unset($this->tokens[key($this->tokens)]);
+ $this->parsedQuery['selectVars'][0] = '*';
+ $this->_clearWhiteSpaces();
+ if (strcasecmp('FROM', current($this->tokens))
+ && strcasecmp('SOURCE', current($this->tokens))
+ && strcasecmp('WHERE', current($this->tokens)))
+ trigger_error(RDQL_SYN_ERR .": '" .htmlspecialchars(current($this->tokens))
+ ."' - SOURCE or WHERE clause expected", E_USER_ERROR);
+ }
+
+ // Parse SELECT ?Var (, ?Var)*
+ $commaExpected = FALSE;
+ $comma = FALSE;
+ while (current($this->tokens) != NULL) {
+ $k = key($this->tokens);
+ $token = $this->tokens[$k];
+
+ switch ($token) {
+ case ',': if (!$commaExpected)
+ trigger_error(RDQL_SEL_ERR ." ',' - unexpected comma", E_USER_ERROR);
+ $comma = TRUE;
+ $commaExpected = FALSE;
+ break;
+ case '(':
+ case ')': trigger_error(RDQL_SEL_ERR ." '$token' - illegal input", E_USER_ERROR);
+ break;
+ default :
+ if (!strcasecmp('FROM', $token) || !strcasecmp('SOURCE', $token)) {
+ if ($comma)
+ trigger_error(RDQL_SEL_ERR ." ',' - unexpected comma", E_USER_ERROR);
+ unset($this->tokens[$k]);
+ return $this->parseFrom();
+ }elseif (!strcasecmp('WHERE', $token) && !$comma) {
+ if ($comma)
+ trigger_error(RDQL_SEL_ERR ." ',' - unexpected comma", E_USER_ERROR);
+ unset($this->tokens[$k]);
+ return $this->parseWhere();
+ }
+ if ($token{0} == '?') {
+ $this->parsedQuery['selectVars'][] = $this->_validateVar($token, RDQL_SEL_ERR);
+ $commaExpected = TRUE;
+ $comma = FALSE;
+ }else
+ trigger_error(RDQL_SEL_ERR ." '$token' - '?' missing", E_USER_ERROR);
+ }
+ unset($this->tokens[$k]);
+ $this->_clearWhiteSpaces();
+ }
+ trigger_error(RDQL_SYN_ERR . ': WHERE clause missing', E_USER_ERROR);
+ }
+
+
+/**
+ * Parse the FROM/SOURCES clause of an Rdql query
+ * When the parsing of this clause is finished, parseWhere() will be called.
+ *
+ * @throws PhpError
+ * @access private
+ */
+ function parseFrom() {
+
+ $comma = FALSE;
+ $commaExpected = FALSE;
+ $i = -1;
+ while (current($this->tokens) != NULL) {
+
+ $this->_clearWhiteSpaces();
+ if (!strcasecmp('WHERE', current($this->tokens)) && count($this->parsedQuery['sources']) != 0) {
+ if ($comma)
+ trigger_error(RDQL_SEL_ERR ." ',' - unexpected comma", E_USER_ERROR);
+ unset($this->tokens[key($this->tokens)]);
+ return $this->parseWhere();
+ }
+ if (current($this->tokens) == ',') {
+ if ($commaExpected) {
+ $comma = TRUE;
+ $commaExpected = FALSE;
+ unset($this->tokens[key($this->tokens)]);
+ }else
+ trigger_error(RDQL_SRC_ERR ."',' - unecpected comma", E_USER_ERROR);
+ }else{
+ $token = current($this->tokens);
+ $this->parsedQuery['sources'][++$i]['value'] = $this->_validateURI($token, RDQL_SRC_ERR);
+ if ($token{0} != '<')
+ $this->parsedQuery['sources'][$i]['is_qname'] = TRUE;
+ $commaExpected = TRUE;
+ $comma = FALSE;
+ }
+ }
+ trigger_error(RDQL_SYN_ERR .': WHERE clause missing', E_USER_ERROR);
+ }
+
+
+/**'
+ * Parse the WHERE clause of an Rdql query.
+ * When the parsing of the WHERE clause is finished, this method will call
+ * a suitable method to parse the subsequent clause if provided.
+ *
+ * @throws PhpError
+ * @access private
+ */
+ function parseWhere() {
+
+ $comma = FALSE;
+ $commaExpected = FALSE;
+ $i=0;
+
+ do {
+ $this->_clearWhiteSpaces();
+ if (!strcasecmp('AND', current($this->tokens))
+ && count($this->parsedQuery['patterns']) != 0){
+ if ($comma)
+ trigger_error(RDQL_WHR_ERR ." ',' - unexpected comma", E_USER_ERROR);
+ unset($this->tokens[key($this->tokens)]);
+ return $this->parseAnd();
+ }elseif (!strcasecmp('USING', current($this->tokens))
+ && count($this->parsedQuery['patterns']) != 0) {
+ if ($comma)
+ trigger_error(RDQL_WHR_ERR ." ',' - unexpected comma", E_USER_ERROR);
+ unset($this->tokens[key($this->tokens)]);
+ return $this->parseUsing();
+ }
+
+ if (current($this->tokens) == ',') {
+ $comma = TRUE;
+ $this->_checkComma($commaExpected, RDQL_WHR_ERR);
+
+ }else{
+
+ if (current($this->tokens) != '(')
+ trigger_error(RDQL_WHR_ERR ."'" .current($this->tokens)
+ ."' - '(' expected", E_USER_ERROR);
+ unset($this->tokens[key($this->tokens)]);
+ $this->_clearWhiteSpaces();
+
+ $this->parsedQuery['patterns'][$i]['subject'] = $this->_validateVarUri(current($this->tokens));
+ $this->_checkComma(TRUE, RDQL_WHR_ERR);
+ $this->parsedQuery['patterns'][$i]['predicate'] = $this->_validateVarUri(current($this->tokens));
+ $this->_checkComma(TRUE, RDQL_WHR_ERR);
+ $this->parsedQuery['patterns'][$i++]['object'] = $this->_validateVarUriLiteral(current($this->tokens));
+ $this->_clearWhiteSpaces();
+
+ if (current($this->tokens) != ')')
+ trigger_error(RDQL_WHR_ERR ."'" .current($this->tokens) ."' - ')' expected", E_USER_ERROR);
+ unset($this->tokens[key($this->tokens)]);
+ $this->_clearWhiteSpaces();
+ $commaExpected = TRUE;
+ $comma = FALSE;
+ }
+ }while(current($this->tokens) != NULL);
+
+ if ($comma)
+ trigger_error(RDQL_WHR_ERR ." ',' - unexpected comma", E_USER_ERROR);
+ }
+
+
+/**
+ * Parse the AND clause of an Rdql query
+ *
+ * @throws PhpError
+ * @access private
+ * @todo clear comments
+ */
+ function parseAnd() {
+
+ $this->_clearWhiteSpaces();
+ $n = 0;
+ $filterStr = '';
+
+ while(current($this->tokens) != NULL) {
+ $k = key($this->tokens);
+ $token = $this->tokens[$k];
+
+ if (!strcasecmp('USING', $token)) {
+ $this->parseFilter($n, $filterStr);
+ unset($this->tokens[$k]);
+ return $this->parseUsing();
+ }elseif ($token == ',') {
+ $this->parseFilter($n, $filterStr);
+ $filterStr = '';
+ $token = '';
+ ++$n;
+ }
+ $filterStr .= $token;
+ unset($this->tokens[$k]);
+ }
+ $this->parseFilter($n, $filterStr);
+ }
+
+
+/**
+ * Parse the USING clause of an Rdql query
+ *
+ * @throws PhpError
+ * @access private
+ */
+ function parseUsing() {
+
+ $commaExpected = FALSE;
+ $comma = FALSE;
+
+ do {
+ $this->_clearWhiteSpaces();
+ if (current($this->tokens) == ',') {
+ $comma = TRUE;
+ $this->_checkComma($commaExpected, RDQL_USG_ERR);
+ }else{
+ $prefix = $this->_validatePrefix(current($this->tokens));
+ $this->_clearWhiteSpaces();
+
+ if (strcasecmp('FOR', current($this->tokens)))
+ trigger_error(RDQL_USG_ERR ." keyword: 'FOR' missing in the namespace declaration: '", E_USER_ERROR);
+ unset($this->tokens[key($this->tokens)]);
+ $this->_clearWhiteSpaces();
+
+ $this->parsedQuery['ns'][$prefix] = $this->_validateUri(current($this->tokens), RDQL_USG_ERR);
+ $this->_clearWhiteSpaces();
+ $commaExpected = TRUE;
+ $comma = FALSE;
+ }
+ }while(current($this->tokens) != NULL);
+
+ if ($comma)
+ trigger_error(RDQL_WHR_ERR ." ',' - unexpected comma", E_USER_ERROR);
+ }
+
+
+/**
+ * Check if a filter from the AND clause contains an equal number of '(' and ')'
+ * and parse filter expressions.
+ *
+ * @param integer $n
+ * @param string $filter
+ * @throws PHPError
+ * @access private
+ */
+ function parseFilter($n, $filter) {
+
+ if ($filter == NULL)
+ trigger_error(RDQL_AND_ERR ." ',' - unexpected comma", E_USER_ERROR);
+ $paren = substr_count($filter, '(') - substr_count($filter, ')');
+ if ($paren != 0) {
+ if ($paren > 0)
+ $errorMsg = "'" .htmlspecialchars($filter) ."' - ')' missing ";
+ elseif ($paren < 0)
+ $errorMsg = "'" .htmlspecialchars($filter) ."' - too many ')' ";
+ trigger_error(RDQL_AND_ERR .$errorMsg, E_USER_ERROR);
+ }
+
+ $this->parsedQuery['filters'][$n] = $this->parseExpressions($filter);
+ }
+
+
+/**
+ * Parse expressions inside the passed filter:
+ * 1) regex equality expressions: ?var [~~ | =~ | !~ ] REG_EX
+ * 2a) string equality expressions: ?var [eq | ne] "literal"@lang^^dtype.
+ * 2b) string equality expressions: ?var [eq | ne] or ?var [eq | ne] prefix:local_name
+ * 3) numerical expressions: e.q. (?var1 - ?var2)*4 >= 20
+ *
+ * In cases 1-2 parse each expression of the given filter into an array of variables.
+ * For each parsed expression put a place holder (e.g. ##RegEx_1##) into the filterStr.
+ * The RDQLengine will then replace each place holder with the outcomming boolean value
+ * of the corresponding expression.
+ * The remaining filterStr contains only numerical expressions and place holders.
+ *
+ * @param string $filteStr
+ * @return array ['string'] = string
+ * ['evalFilterStr'] = string
+ * ['reqexEqExprs'][]['var'] = ?VARNAME
+ * ['operator'] = (eq | ne)
+ * ['regex'] = string
+ * ['strEqExprs'][]['var'] = ?VARNAME
+ * ['operator'] = (eq | ne)
+ * ['value'] = string
+ * ['value_type'] = ('variable' | 'URI' | 'QName'| 'Literal')
+ * ['value_lang'] = string
+ * ['value_dtype'] = string
+ * ['value_dtype_is_qname'] = boolean
+ * ['numExpr']['vars'][] = ?VARNAME
+ * @access private
+ */
+ function parseExpressions($filterStr) {
+
+ $parsedFilter['string'] = $filterStr;
+ $parsedFilter['regexEqExprs'] = array();
+ $parsedFilter['strEqExprs'] = array();
+ $parsedFilter['numExprVars'] = array();
+
+ // parse regex string equality expressions, e.g. ?x ~~ !//foo.com/r!i
+ $reg_ex = "/(\?[a-zA-Z0-9_]+)\s+([~!=]~)\s+(['|\"])?([^\s'\"]+)(['|\"])?/";
+ preg_match_all($reg_ex, $filterStr, $eqExprs);
+ foreach ($eqExprs[0] as $i => $eqExpr) {
+ $this->_checkRegExQuotation($filterStr, $eqExprs[3][$i], $eqExprs[5][$i]);
+ $parsedFilter['regexEqExprs'][$i]['var'] = $this->_isDefined($eqExprs[1][$i]);
+ $parsedFilter['regexEqExprs'][$i]['operator'] = $eqExprs[2][$i];
+ $parsedFilter['regexEqExprs'][$i]['regex'] = $eqExprs[4][$i];
+
+ $filterStr = str_replace($eqExpr, " ##RegEx_$i## ", $filterStr);
+ }
+
+ // parse ?var [eq | ne] "literal"@lang^^dtype
+ $reg_ex = "/(\?[a-zA-Z0-9_]+)\s+(eq|ne)\s+(\'[^\']*\'|\"[^\"]*\")";
+ $reg_ex .= "(@[a-zA-Z]+)?(\^{2}\S+:?\S+)?/i";
+ preg_match_all($reg_ex, $filterStr, $eqExprs);
+ foreach ($eqExprs[0] as $i => $eqExpr) {
+ $parsedFilter['strEqExprs'][$i]['var'] = $this->_isDefined($eqExprs[1][$i]);#
+ $parsedFilter['strEqExprs'][$i]['operator'] = strtolower($eqExprs[2][$i]);
+ $parsedFilter['strEqExprs'][$i]['value'] = trim($eqExprs[3][$i],"'\"");
+ $parsedFilter['strEqExprs'][$i]['value_type'] = 'Literal';
+ $parsedFilter['strEqExprs'][$i]['value_lang'] = substr($eqExprs[4][$i], 1);
+ $dtype = substr($eqExprs[5][$i], 2);
+ if ($dtype) {
+ $parsedFilter['strEqExprs'][$i]['value_dtype'] = $this->_validateUri($dtype, RDQL_AND_ERR);
+ if ($dtype{0} != '<')
+ $parsedFilter['strEqExprs'][$i]['value_dtype_is_qname'] = TRUE;
+ }else
+ $parsedFilter['strEqExprs'][$i]['value_dtype'] = '';
+
+ $filterStr = str_replace($eqExprs[0][$i], " ##strEqExpr_$i## ", $filterStr);
+ }
+
+ // parse ?var [eq | ne] ?var
+ $ii = count($parsedFilter['strEqExprs']);
+ $reg_ex = "/(\?[a-zA-Z0-9_]+)\s+(eq|ne)\s+(\?[a-zA-Z0-9_]+)/i";
+ preg_match_all($reg_ex, $filterStr, $eqExprs);
+ foreach ($eqExprs[0] as $i => $eqExpr) {
+ $parsedFilter['strEqExprs'][$ii]['var'] = $this->_isDefined($eqExprs[1][$i]);
+ $parsedFilter['strEqExprs'][$ii]['operator'] = strtolower($eqExprs[2][$i]);
+ $parsedFilter['strEqExprs'][$ii]['value'] = $this->_isDefined($eqExprs[3][$i]);
+ $parsedFilter['strEqExprs'][$ii]['value_type'] = 'variable';
+
+ $filterStr = str_replace($eqExprs[0][$i], " ##strEqExpr_$ii## ", $filterStr);
+ $ii++;
+ }
+
+ // parse ?var [eq | ne] or ?var [eq | ne] prefix:local_name
+ $reg_ex = "/(\?[a-zA-Z0-9_]+)\s+(eq|ne)\s+((<\S+>)|(\S+:\S*))/i";
+ preg_match_all($reg_ex, $filterStr, $eqExprs);
+ foreach ($eqExprs[0] as $i => $eqExpr) {
+ $parsedFilter['strEqExprs'][$ii]['var'] = $this->_isDefined($eqExprs[1][$i]);
+ $parsedFilter['strEqExprs'][$ii]['operator'] = strtolower($eqExprs[2][$i]);
+ if ($eqExprs[4][$i]) {
+ $parsedFilter['strEqExprs'][$ii]['value'] = trim($eqExprs[4][$i], "<>");
+ $parsedFilter['strEqExprs'][$ii]['value_type'] = 'URI';
+ }else if($eqExprs[5][$i]){
+ $this->_validateQName($eqExprs[5][$i], RDQL_AND_ERR);
+ $parsedFilter['strEqExprs'][$ii]['value'] = $eqExprs[5][$i];
+ $parsedFilter['strEqExprs'][$ii]['value_type'] = 'QName';
+ }
+
+ $filterStr = str_replace($eqExprs[0][$i], " ##strEqExpr_$ii## ", $filterStr);
+ $ii++;
+ }
+
+ $parsedFilter['evalFilterStr'] = $filterStr;
+
+ // all that is left are numerical expressions and place holders for the above expressions
+ preg_match_all("/\?[a-zA-Z0-9_]+/", $filterStr, $vars);
+ foreach ($vars[0] as $var) {
+ $parsedFilter['numExprVars'][] = $this->_isDefined($var);
+ }
+
+ return $parsedFilter;
+ }
+
+
+/**
+ * Find all query variables used in the WHERE clause.
+ *
+ * @return array [] = ?VARNAME
+ * @access private
+ */
+ function findAllQueryVariables() {
+
+ $vars = array();
+ foreach ($this->parsedQuery['patterns'] as $pattern) {
+ $count = 0;
+ foreach ($pattern as $v) {
+ if ($v['value'] && $v['value']{0} == '?') {
+ ++$count;
+ if (!in_array($v['value'], $vars))
+ $vars[] = $v['value'];
+ }
+ }
+ if (!$count)
+ trigger_error(RDQL_WHR_ERR .'pattern contains no variables', E_USER_ERROR);
+ }
+
+ return $vars;
+ }
+
+
+/**
+ * Replace all namespace prefixes in the pattern and constraint clause of an rdql query
+ * with the namespaces declared in the USING clause and default namespaces.
+ *
+ * @access private
+ */
+ function replaceNamespacePrefixes() {
+
+ global $default_prefixes;
+
+ if (!isset($this->parsedQuery['ns']))
+ $this->parsedQuery['ns'] = array();
+
+ // add default namespaces
+ // if in an rdql query a reserved prefix (e.g. rdf: rdfs:) is used
+ // it will be overridden by the default namespace defined in constants.php
+ $this->parsedQuery['ns'] = array_merge($this->parsedQuery['ns'], $default_prefixes);
+
+ // replace namespace prefixes in the FROM clause
+ if (isset($this->parsedQuery['sources']))
+ foreach ($this->parsedQuery['sources'] as $n => $source) {
+ if (isset($source['is_qname']))
+ $this->parsedQuery['sources'][$n] = $this->_replaceNamespacePrefix($source['value'], RDQL_SRC_ERR);
+ else {
+ foreach ($this->parsedQuery['ns'] as $prefix => $uri)
+ $source['value'] = eregi_replace("$prefix:", $uri, $source['value']);
+ $this->parsedQuery['sources'][$n] = $source['value'];
+ }
+
+ }
+
+ // replace namespace prefixes in the where clause
+ foreach ($this->parsedQuery['patterns'] as $n => $pattern) {
+ foreach ($pattern as $key => $v)
+ if ($v['value'] && $v['value']{0} != '?') {
+ if (isset($v['is_qname'])) {
+ $this->parsedQuery['patterns'][$n][$key]['value']
+ = $this->_replaceNamespacePrefix($v['value'], RDQL_WHR_ERR);
+ unset($this->parsedQuery['patterns'][$n][$key]['is_qname']);
+ } else { // is quoted URI (== ) or Literal
+ if (isset($this->parsedQuery['patterns'][$n][$key]['is_literal'])) {
+ if (isset($this->parsedQuery['patterns'][$n][$key]['l_dtype_is_qname'])) {
+ $this->parsedQuery['patterns'][$n][$key]['l_dtype']
+ = $this->_replaceNamespacePrefix($v['l_dtype'], RDQL_WHR_ERR);
+ unset($this->parsedQuery['patterns'][$n][$key]['l_dtype_is_qname']);
+ }else {
+ foreach ($this->parsedQuery['ns'] as $prefix => $uri)
+ $this->parsedQuery['patterns'][$n][$key]['l_dtype']
+ = eregi_replace("$prefix:", $uri, $this->parsedQuery['patterns'][$n][$key]['l_dtype']);
+ }
+ }else {
+ foreach ($this->parsedQuery['ns'] as $prefix => $uri)
+ $this->parsedQuery['patterns'][$n][$key]['value']
+ = eregi_replace("$prefix:", $uri, $this->parsedQuery['patterns'][$n][$key]['value']);
+ }
+ }
+ }
+ }
+
+ // replace prefixes in the constraint clause
+ if (isset($this->parsedQuery['filters']))
+ foreach ($this->parsedQuery['filters'] as $n => $filter)
+ foreach ($filter['strEqExprs'] as $i => $expr) {
+ if ($expr['value_type'] == 'QName') {
+ $this->parsedQuery['filters'][$n]['strEqExprs'][$i]['value']
+ = $this->_replaceNamespacePrefix($expr['value'], RDQL_AND_ERR);
+ $this->parsedQuery['filters'][$n]['strEqExprs'][$i]['value_type'] = 'URI';
+ }
+ if ($expr['value_type'] == 'URI')
+ foreach ($this->parsedQuery['ns'] as $prefix => $uri)
+ $this->parsedQuery['filters'][$n]['strEqExprs'][$i]['value']
+ = eregi_replace("$prefix:", $uri,
+ $this->parsedQuery['filters'][$n]['strEqExprs'][$i]['value']);
+ elseif ($expr['value_type'] == 'Literal') {
+ if (isset($expr['value_dtype_is_qname'])) {
+ $this->parsedQuery['filters'][$n]['strEqExprs'][$i]['value_dtype']
+ = $this->_replaceNamespacePrefix($expr['value_dtype'], RDQL_AND_ERR);
+ unset($this->parsedQuery['filters'][$n]['strEqExprs'][$i]['value_dtype_is_qname']);
+ } else {
+ foreach ($this->parsedQuery['ns'] as $prefix => $uri)
+ $this->parsedQuery['filters'][$n]['strEqExprs'][$i]['value_dtype']
+ = eregi_replace("$prefix:", $uri,
+ $this->parsedQuery['filters'][$n]['strEqExprs'][$i]['value_dtype']);
+ }
+ }
+ }
+
+ unset($this->parsedQuery['ns']);
+ }
+
+
+// =============================================================================
+// *************************** helper functions ********************************
+// =============================================================================
+
+
+/**
+ * Remove whitespace-tokens from the array $this->tokens
+ *
+ * @access private
+ */
+ function _clearWhiteSpaces() {
+
+ while (current($this->tokens) == ' ' ||
+ current($this->tokens) == "\n" ||
+ current($this->tokens) == "\t" ||
+ current($this->tokens) == "\r")
+
+ unset($this->tokens[key($this->tokens)]);
+ }
+
+
+/**
+ * Check if the query string of the given clause contains an undesired ','.
+ * If a comma was correctly placed then remove it and clear all whitespaces.
+ *
+ * @param string $commaExpected
+ * @param string $clause_error
+ * @throws PHPError
+ * @access private
+ */
+ function _checkComma($commaExpected, $clause_error) {
+
+ $this->_clearWhiteSpaces();
+ if (current($this->tokens) == ',') {
+ if (!$commaExpected)
+ trigger_error($clause_error ."',' - unexpected comma", E_USER_ERROR);
+ else {
+ unset($this->tokens[key($this->tokens)]);
+ $this->_checkComma(FALSE, $clause_error);
+ }
+ }
+ }
+
+
+/**
+ * Check if the given token is either a variable (?var) or the first token of an URI ().
+ * In case of an URI this function returns the whole URI string.
+ *
+ * @param string $token
+ * @return array ['value'] = string
+ * @throws PHPError
+ * @access private
+ */
+ function _validateVarUri($token) {
+
+ if ($token{0} == '?') {
+ $token_res['value'] = $this->_validateVar($token, RDQL_WHR_ERR);
+ } else {
+ $token_res['value'] = $this->_validateUri($token, RDQL_WHR_ERR);
+ if ($token{0} != '<')
+ $token_res['is_qname'] = TRUE;
+ }
+ return $token_res;
+ }
+
+
+/**
+ * Check if the given token is either a variable (?var) or the first token
+ * of either an URI () or a literal ("Literal").
+ * In case of a literal return an array with literal properties (value, language, datatype).
+ * In case of a variable or an URI return only ['value'] = string.
+ *
+ * @param string $token
+ * @return array ['value'] = string
+ * ['is_qname'] = boolean
+ * ['is_literal'] = boolean
+ * ['l_lang'] = string
+ * ['l_dtype'] = string
+ * @throws PHPError
+ * @access private
+ */
+ function _validateVarUriLiteral($token) {
+
+ if ($token{0} == '?')
+ $statement_object['value'] = $this->_validateVar($token, RDQL_WHR_ERR);
+ elseif ($token{0} == "'" || $token{0} == '"')
+ $statement_object = $this->_validateLiteral($token);
+ elseif ($token{0} == '<')
+ $statement_object['value'] = $this->_validateUri($token, RDQL_WHR_ERR);
+ elseif (ereg(':', $token)) {
+ $statement_object['value'] = $this->_validateUri($token, RDQL_WHR_ERR);
+ $statement_object['is_qname'] = TRUE;
+ }else
+ trigger_error(RDQL_WHR_ERR ." '$token' - ?Variable, <URI>, QName, or \"LITERAL\" expected", E_USER_ERROR);
+ return $statement_object;
+ }
+
+
+/**
+ * Check if the given token is a valid variable name (?var).
+ *
+ * @param string $token
+ * @param string $clause_error
+ * @return string
+ * @throws PHPError
+ * @access private
+ */
+ function _validateVar($token, $clause_error) {
+
+ preg_match("/\?[a-zA-Z0-9_]+/", $token, $match);
+ if (!isset($match[0]) || $match[0] != $token)
+ trigger_error($clause_error ."'" .htmlspecialchars($token)
+ ."' - variable name contains illegal characters", E_USER_ERROR);
+ unset($this->tokens[key($this->tokens)]);
+ return $token;
+ }
+
+
+/**
+ * Check if $token is the first token of a valid URI () and return the whole URI string
+ *
+ * @param string $token
+ * @param string $clause_error
+ * @return string
+ * @throws PHPError
+ * @access private
+ */
+ function _validateUri($token, $clause_error) {
+
+ if ($token{0} != '<') {
+ if (strpos($token, ':') && $this->_validateQName($token, $clause_error)) {
+ unset($this->tokens[key($this->tokens)]);
+ return rtrim($token, ':');
+ }
+ $errmsg = $clause_error .'\'' .htmlspecialchars($token) .'\' ';
+ if ($clause_error == RDQL_WHR_ERR)
+ $errmsg .= "- ?Variable or <URI> or QName expected";
+ else
+ $errmsg .= "- <URI> or QName expected";
+ trigger_error($errmsg, E_USER_ERROR);
+ }else{
+ $token_res = $token;
+ while($token{strlen($token)-1} != '>' && $token != NULL) {
+ if ($token == '(' || $token == ')' || $token == ',' ||
+ $token == ' ' || $token == "\n" || $token == "\r") {
+ trigger_error($clause_error .'\'' .htmlspecialchars($token_res)
+ ."' - illegal input: '$token' - '>' missing", E_USER_ERROR);
+ }
+ unset($this->tokens[key($this->tokens)]);
+ $token = current($this->tokens);
+ $token_res .= $token;
+ }
+ if ($token == NULL)
+ trigger_error($clause_error .'\'' .htmlspecialchars($token_res) ."' - '>' missing", E_USER_ERROR);
+ unset($this->tokens[key($this->tokens)]);
+ return trim($token_res, '<>');
+ }
+ }
+
+
+/**
+ * Check if $token is the first token of a valid literal ("LITERAL") and
+ * return an array with literal properties (value, language, datatype).
+ *
+ * @param string $token
+ * @return array ['value'] = string
+ * ['is_literal'] = boolean
+ * ['l_lang'] = string
+ * ['l_dtype'] = string
+ * ['l_dtype_is_qname'] = boolean
+ * @throws PHPError
+ * @access private
+ */
+ function _validateLiteral($token) {
+
+ $quotation_mark = $token{0};
+ $statement_object = array ('value' => '',
+ 'is_literal' => TRUE,
+ 'l_lang' => '',
+ 'l_dtype' => '');
+ $this->tokens[key($this->tokens)] = substr($token,1);
+
+ $return = FALSE;
+ foreach ($this->tokens as $k => $token) {
+
+ if ($token != NULL && $token{strlen($token)-1} == $quotation_mark) {
+ $token = rtrim($token, $quotation_mark);
+ $return = TRUE;
+
+ // parse @language(^^datatype)?
+ }elseif (strpos($token, $quotation_mark .'@') || substr($token, 0, 2) == $quotation_mark .'@') {
+ $lang = substr($token, strpos($token, $quotation_mark .'@')+2);
+ if (strpos($lang, '^^') || substr($lang, 0,2) == '^^') {
+ $dtype = substr($lang, strpos($lang, '^^')+2);
+ if (!$dtype)
+ trigger_error(RDQL_WHR_ERR .$quotation_mark .$statement_object['value']
+ .$token ." - datatype expected" ,E_USER_ERROR);
+
+ $statement_object['l_dtype'] = $this->_validateUri($dtype, RDQL_WHR_ERR);
+ if ($dtype{0} != '<')
+ $statement_object['l_dtype_is_qname'] = TRUE;
+
+ $lang = substr($lang, 0, strpos($lang, '^^'));
+ }
+ if (!$lang)
+ trigger_error(RDQL_WHR_ERR .$quotation_mark .$statement_object['value']
+ .$token ." - language expected" ,E_USER_ERROR);
+ $statement_object['l_lang'] = $lang;
+ $token = substr($token, 0, strpos($token, $quotation_mark .'@'));
+ $return = TRUE;
+
+ // parse ^^datatype
+ }elseif (strpos($token, $quotation_mark .'^^') || substr($token, 0, 3) == $quotation_mark .'^^') {
+ $dtype = substr($token, strpos($token, $quotation_mark .'^^')+3);
+ if (!$dtype)
+ trigger_error(RDQL_WHR_ERR .$quotation_mark .$statement_object['value']
+ .$token ." - datatype expected" ,E_USER_ERROR);
+
+ $statement_object['l_dtype'] = $this->_validateUri($dtype, RDQL_WHR_ERR);
+ if ($dtype{0} != '<')
+ $statement_object['l_dtype_is_qname'] = TRUE;
+
+ $token = substr($token, 0, strpos($token, $quotation_mark .'^^'));
+ $return = TRUE;
+ }elseif (strpos($token, $quotation_mark))
+ trigger_error(RDQL_WHR_ERR ."'$token' - illegal input", E_USER_ERROR);
+ $statement_object['value'] .= $token;
+ unset($this->tokens[$k]);
+ if ($return)
+ return $statement_object;
+ }
+ trigger_error(RDQL_WHR_ERR ."quotation end mark: $quotation_mark missing", E_USER_ERROR);
+ }
+
+
+/**
+ * Check if the given token is a valid QName.
+ *
+ * @param string $token
+ * @param string $clause_error
+ * @return boolean
+ * @throws PHPError
+ * @access private
+ */
+function _validateQName($token, $clause_error) {
+
+ $parts = explode(':', $token);
+ if (count($parts) > 2)
+ trigger_error($clause_error ."illegal QName: '$token'", E_USER_ERROR);
+ if (!$this->_validateNCName($parts[0]))
+ trigger_error($clause_error ."illegal prefix in QName: '$token'", E_USER_ERROR);
+ if ($parts[1] && !$this->_validateNCName($parts[1]))
+ trigger_error($clause_error ."illegal local part in QName: '$token'", E_USER_ERROR);
+
+ return TRUE;
+}
+
+
+/**
+ * Check if the given token is a valid NCName.
+ *
+ * @param string $token
+ * @return boolean
+ * @access private
+ */
+function _validateNCName($token) {
+
+ preg_match("/[a-zA-Z_]+[a-zA-Z_0-9.\-]*/", $token, $match);
+ if (isset($match[0]) && $match[0] == $token)
+ return TRUE;
+ return FALSE;
+}
+
+
+/**
+ * Check if the given token is a valid namespace prefix.
+ *
+ * @param string $token
+ * @return string
+ * @throws PHPError
+ * @access private
+ */
+ function _validatePrefix($token) {
+
+ if (!$this->_validateNCName($token))
+ trigger_error(RDQL_USG_ERR ."'" .htmlspecialchars($token)
+ ."' - illegal input, namespace prefix expected", E_USER_ERROR);
+ unset($this->tokens[key($this->tokens)]);
+ return $token;
+ }
+
+/**
+ * Replace a prefix in a given QName and return a full URI.
+ *
+ * @param string $qName
+ * @param string $clasue_error
+ * @return string
+ * @throws PHPError
+ * @access private
+ */
+ function _replaceNamespacePrefix($qName, $clause_error) {
+
+ $qName_parts = explode(':', $qName);
+ if (!array_key_exists($qName_parts[0], $this->parsedQuery['ns']))
+ trigger_error($clause_error .'undefined prefix: \'' .$qName_parts[0] .'\' in: \'' .$qName .'\'', E_USER_ERROR);
+ return $this->parsedQuery['ns'][$qName_parts[0]] .$qName_parts[1];
+ }
+
+
+/**
+ * Check if all variables from the SELECT clause are defined in the WHERE clause
+ *
+ * @access private
+ */
+ function _checkSelectVars() {
+
+ foreach ($this->parsedQuery['selectVars'] as $var)
+ $this->_isDefined($var);
+ }
+
+
+/**
+ * Check if the given variable is defined in the WHERE clause.
+ *
+ * @param $var string
+ * @return string
+ * @throws PHPError
+ * @access private
+ */
+ function _isDefined($var) {
+
+ $allQueryVars = $this->findAllQueryVariables();
+
+ if (!in_array($var, $allQueryVars))
+ trigger_error(RDQL_SYN_ERR .": '$var' - variable must be defined in the WHERE clause", E_USER_ERROR);
+ return $var;
+ }
+
+
+/**
+ * Throw an error if the regular expression from the AND clause is not quoted.
+ *
+ * @param string $filterString
+ * @param string $lQuotMark
+ * @param string $rQuotMark
+ * @throws PHPError
+ * @access private
+ */
+ function _checkRegExQuotation($filterString, $lQuotMark, $rQuotMark) {
+
+ if (!$lQuotMark)
+ trigger_error(RDQL_AND_ERR ."'$filterString' - regular expressions must be quoted", E_USER_ERROR);
+
+ if ($lQuotMark != $rQuotMark)
+ trigger_error(RDQL_AND_ERR ."'$filterString' - quotation end mark in the regular expression missing", E_USER_ERROR);
+ }
+
+} // end: Class RdqlParser
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/text-base/RdqlResultIterator.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/text-base/RdqlResultIterator.php.svn-base
new file mode 100755
index 00000000..f8ca8856
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/.svn/text-base/RdqlResultIterator.php.svn-base
@@ -0,0 +1,193 @@
+, Chris Bizer
+ *
+ * @package rdql
+ * @access public
+ *
+ */
+ class RdqlResultIterator extends Object {
+
+ /**
+ * Reference to the Rdql result
+ * @var array RdqlResult
+ * @access private
+ */
+ var $RdqlResult;
+
+ /**
+ * Current position
+ * RdqlResultIterator does not use the build in PHP array iterator,
+ * so you can use serveral iterators on a single Rdql result.
+ * @var integer
+ * @access private
+ */
+ var $position;
+
+
+ /**
+ * Constructor
+ *
+ * @param object RdqlResult
+ * @access public
+ */
+ function RdqlResultIterator(&$RdqlResult) {
+
+ $noResult = TRUE;
+ foreach($RdqlResult[0] as $value)
+ if ($value != NULL) {
+ $noResult = FALSE;
+ break;
+ }
+
+ if($noResult)
+ $this->RdqlResult = NULL;
+ else
+ $this->RdqlResult = $RdqlResult;
+
+ $this->position = -1;
+ }
+
+ /**
+ * Returns the labels of the result as array.
+ * @return array of strings with the result labels OR null if there are no results.
+ * @access public
+ */
+ function getResultLabels() {
+ if(count($this->RdqlResult)>0) {
+ return array_keys($this->RdqlResult[0]);
+ } else return null;
+ }
+
+ /**
+ * Returns the number of results.
+ * @return integer
+ * @access public
+ */
+ function countResults() {
+
+ return count($this->RdqlResult);
+
+ }
+ /**
+ * Returns TRUE if there are more results.
+ * @return boolean
+ * @access public
+ */
+ function hasNext() {
+ if ($this->position < count($this->RdqlResult) - 1 ) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ }
+
+ /**
+ * Returns TRUE if the first result has not been reached.
+ * @return boolean
+ * @access public
+ */
+ function hasPrevious() {
+ if ($this->position > 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ } }
+
+ /**
+ * Returns the next result array.
+ * @param integer $element
+ * @return result array OR single result if $element was specified OR NULL if there is no next result.
+ * @access public
+ */
+ function next($element = null) {
+ if ($this->position < count($this->RdqlResult) - 1) {
+ $this->position++;
+ if ($element) {return $this->RdqlResult[$this->position][$element];}
+ else return $this->RdqlResult[$this->position];
+ } else {
+ return NULL;
+ }
+ }
+
+ /**
+ * Returns the previous result.
+ * @param integer $element
+ * @return result array OR single result if $element was specified OR NULL if there is no next result.
+ * @access public
+ */
+ function previous($element = null) {
+ if ($this->position > 0) {
+ $this->position--;
+ if ($element) {return $this->RdqlResult[$this->position][$element];}
+ else return $this->RdqlResult[$this->position];
+ } else {
+ return NULL;
+ }
+ }
+
+ /**
+ * Returns the current result.
+ * @param integer $element
+ * @return result array OR single result if $element was specified OR NULL if there is no next result.
+ * @access public
+ */
+ function current($element = null) {
+ if (($this->position >= 0) && ($this->position < count($this->RdqlResult))) {
+ if ($element) {return $this->RdqlResult[$this->position][$element];}
+ else return $this->RdqlResult[$this->position];
+ } else {
+ return NULL;
+ }
+ }
+
+ /**
+ * Moves the pointer to the first result.
+ * @return void
+ * @access public
+ */
+ function moveFirst() {
+ $this->position = 0;
+ }
+
+ /**
+ * Moves the pointer to the last result.
+ * @return void
+ * @access public
+ */
+ function moveLast() {
+ $this->position = count($this->RdqlResult) - 1;
+ }
+
+ /**
+ * Moves the pointer to a specific result.
+ * If you set an off-bounds value, next(), previous() and current() will return NULL
+ * @return void
+ * @access public
+ */
+ function moveTo($position) {
+ $this->position = $position;
+ }
+
+ /**
+ * Returns the current position of the iterator.
+ * @return integer
+ * @access public
+ */
+ function getCurrentPosition() {
+ return $this->position;
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/RDQL.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/RDQL.php
new file mode 100755
index 00000000..2761ca62
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/RDQL.php
@@ -0,0 +1,17 @@
+
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/RdqlDbEngine.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/RdqlDbEngine.php
new file mode 100755
index 00000000..5e1899d6
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/RdqlDbEngine.php
@@ -0,0 +1,506 @@
+
+ *
+ * @package rdql
+ * @access public
+ */
+
+Class RdqlDbEngine extends RdqlEngine {
+
+
+/**
+ * Parsed query variables and constraints.
+ *
+ * @var array ['selectVars'][] = ?VARNAME
+ * ['sources'][] = URI
+ * ['patterns'][]['subject']['value'] = VARorURI
+ * ['predicate']['value'] = VARorURI
+ * ['object']['value'] = VARorURIorLiterl
+ * ['is_literal'] = boolean
+ * ['l_lang'] = string
+ * ['l_dtype'] = string
+ * ['filters'][]['string'] = string
+ * ['evalFilterStr'] = string
+ * ['reqexEqExprs'][]['var'] = ?VARNAME
+ * ['operator'] = (eq | ne)
+ * ['regex'] = string
+ * ['strEqExprs'][]['var'] = ?VARNAME
+ * ['operator'] = (eq | ne)
+ * ['value'] = string
+ * ['value_type'] = ('variable' | 'URI' | 'Literal')
+ * ['value_lang'] = string
+ * ['value_dtype'] = string
+ * ['numExpr']['vars'][] = ?VARNAME
+ * ( [] stands for an integer index - 0..N )
+ * @access private
+ */
+ var $parsedQuery;
+
+
+/**
+ * When an RDQL query is performed on a DbModel, in first step the engine searches
+ * in database for triples matching the Rdql-WHERE clause. A recordSet is returned.
+ * $rsIndexes maps select and filter variables to their corresponding indexes
+ * in the returned recordSet.
+ *
+ * @var array [?VARNAME]['value'] = integer
+ * ['nType'] = integer
+ * ['l_lang'] = integer
+ * ['l_dtype'] = integer
+ * @access private
+ */
+ var $rsIndexes;
+
+
+ /**
+ * Perform an RDQL Query on the given DbModel.
+ *
+ * @param object DbModel $dbModel
+ * @param array &$parsedQuery (the same format as $this->parsedQuery)
+ * @param boolean $returnNodes
+ * @return array [][?VARNAME] = object Node (if $returnNodes = TRUE)
+ * OR array [][?VARNAME] = string
+ * @access public
+ */
+ function & queryModel(&$dbModel, &$parsedQuery, $returnNodes = TRUE) {
+
+ $this->parsedQuery = &$parsedQuery;
+
+ $sql = $this->generateSql($dbModel->modelID);
+ $recordSet =& $dbModel->dbConn->execute($sql);
+ $queryResult = $this->filterQueryResult($recordSet);
+
+ if ($returnNodes)
+ $ret = $this->toNodes($queryResult);
+ else
+ $ret = $this->toString($queryResult);
+ return $ret;
+ }
+
+
+ /**
+ * Generate an SQL string to query the database for tuples matching all patterns
+ * of $parsedQuery.
+ *
+ * @param integer $modelID
+ * @return string
+ * @access private
+ */
+ function generateSql($modelID) {
+
+ $sql = $this->generateSql_SelectClause();
+ $sql .= $this->generateSql_FromClause();
+ $sql .= $this->generateSql_WhereClause($modelID);
+ return $sql;
+ }
+
+
+/**
+ * Generate SQL SELECT clause.
+ *
+ * @return string
+ * @throws PHPError
+ * @access private
+ */
+ function generateSql_SelectClause() {
+
+ $sql_select = 'SELECT';
+ $index = 0;
+ $this->rsIndexes = array();
+
+ foreach ($this->parsedQuery['selectVars'] as $var)
+ $sql_select .= $this->_generateSql_SelectVar($var, $index);
+
+ if (isset($this->parsedQuery['filters'])) {
+ foreach ($this->parsedQuery['filters'] as $n => $filter) {
+
+ // variables from numeric expressions
+ foreach ($filter['numExprVars'] as $numVar)
+ $sql_select .= $this->_generateSql_SelectVar($numVar, $index);
+
+ // variables from regex equality expressions
+ foreach ($filter['regexEqExprs'] as $regexEqExpr)
+ $sql_select .= $this->_generateSql_SelectVar($regexEqExpr['var'], $index);
+
+ // variables from string equality expressions
+ foreach ($filter['strEqExprs'] as $strEqVar)
+ $sql_select .= $this->_generateSql_SelectVar($strEqVar['var'], $index);
+ }
+ }
+
+ return rtrim($sql_select, " , ");
+ }
+
+
+/**
+ * Generate SQL FROM clause
+ *
+ * @return string
+ * @access private
+ */
+ function generateSql_FromClause() {
+
+ $sql_from = ' FROM';
+ foreach ($this->parsedQuery['patterns'] as $n => $v)
+ $sql_from .= ' statements s' .($n+1) .' , ';
+
+ return rtrim($sql_from, ' , ');
+ }
+
+
+/**
+ * Generate an SQL WHERE clause
+ *
+ * @param integer $modelID
+ * @return string
+ * @access private
+ */
+ function generateSql_WhereClause($modelID) {
+
+ $sql_where = ' WHERE';
+ $count_patterns = count($this->parsedQuery['patterns']);
+ foreach ($this->parsedQuery['patterns'] as $n => $pattern) {
+ $sql_where .= ' s' .($n+1) .'.modelID=' .$modelID .' AND';
+ foreach ($pattern as $key => $val_1)
+ if ($val_1['value'] && $val_1['value']{0}=='?') {
+ $sql_tmp = ' s' .($n+1) .'.' .$key .'=';
+ // find internal bindings
+ switch ($key) {
+ case 'subject':
+ if ($pattern['subject']['value'] == $pattern['predicate']['value'])
+ $sql_where .= $sql_tmp .'s' .($n+1) .'.predicate AND';
+ elseif ($pattern['subject']['value'] == $pattern['object']['value'])
+ $sql_where .= $sql_tmp .'s' .($n+1) .'.object AND';
+ break;
+ case 'predicate':
+ if ($pattern['predicate']['value'] == $pattern['object']['value'])
+ $sql_where .= $sql_tmp .'s' .($n+1) .'.object AND';
+ }
+ // find external bindings
+ for ($i=$n+1; $i<$count_patterns; $i++)
+ foreach ($this->parsedQuery['patterns'][$i] as $key2 => $val_2)
+ if ($val_1['value']==$val_2['value']) {
+ $sql_where .= $sql_tmp .'s' .($i+1) .'.' .$key2 .' AND';
+ break 2;
+ }
+ }else {
+ $sql_where .= ' s' .($n+1) .'.' .$key ."='" .$val_1['value'] ."' AND";
+ if ($key == 'object' && isset($val_1['is_literal'])) {
+ $sql_where .= ' s' .($n+1) .".object_is='l' AND";
+ $sql_where .= ' s' .($n+1) .".l_datatype='" .$val_1['l_dtype'] ."' AND";
+ $sql_where .= ' s' .($n+1) .".l_language='" .$val_1['l_lang'] ."' AND";
+ }
+ }
+ }
+ return rtrim($sql_where, ' AND');
+ }
+
+
+/**
+ * Filter tuples containing variables matching all patterns from the WHERE clause
+ * of an RDQL query. As a result of a database query using ADOdb these tuples
+ * are returned as an ADORecordSet object, which is then passed to this function.
+ *
+ * @param object ADORecordSet &$recordSet
+ * @return array [][?VARNAME]['value'] = string
+ * ['nType'] = string
+ * ['l_lang'] = string
+ * ['l_dtype'] = string
+ * @access private
+ */
+ function filterQueryResult(&$recordSet) {
+ $queryResult=array();
+
+ if (isset($this->parsedQuery['filters'])) {
+
+ while (!$recordSet->EOF) {
+
+ foreach ($this->parsedQuery['filters'] as $filter) {
+
+ $evalFilterStr = $filter['evalFilterStr'];
+
+ // evaluate regex equality expressions of each filter
+ foreach ($filter['regexEqExprs'] as $i => $expr) {
+ preg_match($expr['regex'], $recordSet->fields[$this->rsIndexes[$expr['var']]['value']], $match);
+ $op = substr($expr['operator'], 0,1);
+ if (($op != '!' && !isset($match[0])) || ($op == '!' && isset($match[0])))
+ $evalFilterStr = str_replace("##RegEx_$i##", 'FALSE', $evalFilterStr);
+ else
+ $evalFilterStr = str_replace("##RegEx_$i##", 'TRUE', $evalFilterStr);
+ }
+
+ // evaluate string equality expressions
+ foreach ($filter['strEqExprs'] as $i => $expr) {
+
+ $exprBoolVal = 'FALSE';
+
+ switch ($expr['value_type']) {
+
+ case 'variable':
+ if (($recordSet->fields[$this->rsIndexes[$expr['var']]['value']] ==
+ $recordSet->fields[$this->rsIndexes[$expr['value']]['value']] &&
+ $expr['operator'] == 'eq') ||
+ ($recordSet->fields[$this->rsIndexes[$expr['var']]['value']] !=
+ $recordSet->fields[$this->rsIndexes[$expr['value']]['value']] &&
+ $expr['operator'] == 'ne'))
+
+ $exprBoolVal = 'TRUE';
+ break;
+
+ case 'URI':
+
+ if (isset($this->rsIndexes[$expr['var']]['nType']) &&
+ $recordSet->fields[$this->rsIndexes[$expr['var']]['nType']] == 'l') {
+
+ if ($expr['operator'] == 'ne')
+ $exprBoolVal = 'TRUE';
+ break;
+ }
+
+ if (($recordSet->fields[$this->rsIndexes[$expr['var']]['value']] ==
+ $expr['value'] && $expr['operator'] == 'eq') ||
+ ($recordSet->fields[$this->rsIndexes[$expr['var']]['value']] !=
+ $expr['value'] && $expr['operator'] == 'ne'))
+ $exprBoolVal = 'TRUE';
+ break;
+
+ case 'Literal':
+
+ if (!isset($this->rsIndexes[$expr['var']]['nType']) ||
+ $recordSet->fields[$this->rsIndexes[$expr['var']]['nType']] != 'l') {
+
+ if ($expr['operator'] == 'ne')
+ $exprBoolVal = 'TRUE';
+ break;
+ }
+
+ $filterLiteral= new Literal($expr['value'],$expr['value_lang']);
+ $filterLiteral->setDatatype($expr['value_dtype']);
+
+ $resultLiteral=new Literal($recordSet->fields[$this->rsIndexes[$expr['var']]['value']]);
+ $resultLiteral->setDatatype($recordSet->fields[$this->rsIndexes[$expr['var']]['l_dtype']]);
+ $resultLiteral->setLanguage($recordSet->fields[$this->rsIndexes[$expr['var']]['l_lang']]);
+
+ $equal=$resultLiteral->equals($filterLiteral);
+
+ if (($equal && $expr['operator'] == 'eq') ||
+ (!$equal && $expr['operator'] == 'ne'))
+ $exprBoolVal = 'TRUE';
+ else
+ $exprBoolVal = 'FALSE';
+
+ }
+
+ $evalFilterStr = str_replace("##strEqExpr_$i##", $exprBoolVal, $evalFilterStr);
+ }
+
+ // evaluate numerical expressions
+ foreach ($filter['numExprVars'] as $varName) {
+ $varValue = "'" .$recordSet->fields[$this->rsIndexes[$varName]['value']] ."'";
+ $evalFilterStr = str_replace($varName, $varValue, $evalFilterStr);
+ }
+
+ eval("\$filterBoolVal = $evalFilterStr; \$eval_filter_ok = TRUE;");
+ if (!isset($eval_filter_ok))
+ trigger_error(RDQL_AND_ERR ."'" .htmlspecialchars($filter['string']) ."'", E_USER_ERROR);
+
+ if (!$filterBoolVal) {
+ $recordSet->MoveNext();
+ continue 2;
+ }
+
+ }
+ $queryResult[] = $this->_convertRsRowToQueryResultRow($recordSet->fields);
+ $recordSet->MoveNext();
+ }
+
+ }else
+ while (!$recordSet->EOF) {
+ $queryResult[] = $this->_convertRsRowToQueryResultRow($recordSet->fields);
+ $recordSet->MoveNext();
+ }
+ return $queryResult;
+ }
+
+
+/**
+ * Serialize variable values of $queryResult to string.
+ *
+ * @param array &$queryResult [][?VARNAME]['value'] = string
+ * ['nType'] = string
+ * ['l_lang'] = string
+ * ['l_dtype'] = string
+ * @return array [][?VARNAME] = string
+ * @access private
+ */
+ function toString(&$queryResult) {
+
+ // if a result set is empty return only variable sames
+ if (count($queryResult) == 0) {
+ foreach ($this->parsedQuery['selectVars'] as $selectVar)
+ $res[0][$selectVar] = NULL;
+ return $res;
+ }
+
+ $res = array();
+ foreach ($queryResult as $n => $var)
+ foreach ($var as $varname => $varProperties)
+ if ($varProperties['nType'] == 'r' || $varProperties['nType'] == 'b')
+ $res[$n][$varname] = '<' .$varProperties['value'] .'>';
+ else {
+ $res[$n][$varname] = '"' .$varProperties['value'] .'"';
+ if ($varProperties['l_lang'] != NULL)
+ $res[$n][$varname] .= ' (xml:lang="' .$varProperties['l_lang'] .'")';
+ if ($varProperties['l_dtype'] != NULL)
+ $res[$n][$varname] .= ' (rdf:datatype="' .$varProperties['l_dtype'] .'")';
+ }
+ return $res;
+ }
+
+
+/**
+ * Convert variable values of $queryResult to objects (Node).
+ *
+ * @param array &$queryResult [][?VARNAME]['value'] = string
+ * ['nType'] = string
+ * ['l_lang'] = string
+ * ['l_dtype'] = string
+ * @return array [][?VARNAME] = object Node
+ * @access private
+ */
+ function toNodes(&$queryResult) {
+
+ // if a result set is empty return only variable sames
+ if (count($queryResult) == 0) {
+ foreach ($this->parsedQuery['selectVars'] as $selectVar)
+ $res[0][$selectVar] = NULL;
+ return $res;
+ }
+
+ $res = array();
+ foreach ($queryResult as $n => $var)
+ foreach ($var as $varname => $varProperties)
+ if ($varProperties['nType'] == 'r')
+ $res[$n][$varname] = new Resource($varProperties['value']);
+ elseif ($varProperties['nType'] == 'b')
+ $res[$n][$varname] = new BlankNode($varProperties['value']);
+ else {
+ $res[$n][$varname] = new Literal($varProperties['value'], $varProperties['l_lang']);
+ if ($varProperties['l_dtype'] != NULL)
+ $res[$n][$varname]->setDataType($varProperties['l_dtype']);
+ }
+ return $res;
+ }
+
+
+/**
+ * Generate a piece of an sql select statement for a variable.
+ * Look first if the given variable is defined as a pattern object.
+ * (So you can select the node type, literal lang and dtype)
+ * If not found - look for subjects and select node label and type.
+ * If there is no result either go to predicates.
+ * Predicates are always resources therefore select only the node label.
+ *
+ * @param string $varName
+ * @return string
+ * @access private
+ */
+function _generateSql_SelectVar ($varName, &$index) {
+
+ $sql_select = '';
+
+ if (array_key_exists($varName, $this->rsIndexes))
+ return NULL;
+
+ foreach ($this->parsedQuery['patterns'] as $n => $pattern)
+ if ($varName == $pattern['object']['value']) {
+
+ // select the object label
+ $sql_select .= " s" .++$n .".object as _" .ltrim($varName, "?") ." , ";
+ $this->rsIndexes[$varName]['value'] = $index++;
+ // select the node type
+ $sql_select .= " s" .$n .".object_is , ";
+ $this->rsIndexes[$varName]['nType'] = $index++;
+ // select the object language
+ $sql_select .= " s" .$n .".l_language , ";
+ $this->rsIndexes[$varName]['l_lang'] = $index++;
+ // select the object dtype
+ $sql_select .= " s" .$n .".l_datatype , ";
+ $this->rsIndexes[$varName]['l_dtype'] = $index++;
+
+ return $sql_select;
+ }
+
+ foreach ($this->parsedQuery['patterns'] as $n => $pattern)
+ if ($varName == $pattern['subject']['value']) {
+
+ // select the object label
+ $sql_select .= " s" .++$n .".subject as _" .ltrim($varName, "?") ." , ";
+ $this->rsIndexes[$varName]['value'] = $index++;
+ // select the node type
+ $sql_select .= " s" .$n .".subject_is , ";
+ $this->rsIndexes[$varName]['nType'] = $index++;
+
+ return $sql_select;
+ }
+
+ foreach ($this->parsedQuery['patterns'] as $n => $pattern)
+ if ($varName == $pattern['predicate']['value']) {
+
+ // select the object label
+ $sql_select .= " s" .++$n .".predicate as _" .ltrim($varName, "?") ." , ";
+ $this->rsIndexes[$varName]['value'] = $index++;
+
+ return $sql_select;
+ }
+ }
+
+
+/**
+ * Converts a single row of ADORecordSet->fields array to the format of
+ * $queryResult array using pointers to indexes ($this->rsIndexes) in RecordSet->fields.
+ *
+ * @param array &$record [] = string
+ * @return array [?VARNAME]['value'] = string
+ * ['nType'] = string
+ * ['l_lang'] = string
+ * ['l_dtype'] = string
+ * @access private
+ */
+ function _convertRsRowToQueryResultRow(&$record) {
+
+ // return only select variables (without conditional variables from the AND clause)
+ foreach ($this->parsedQuery['selectVars'] as $selectVar) {
+ $resultRow[$selectVar]['value'] = $record[$this->rsIndexes[$selectVar]['value']];
+ if (isset($this->rsIndexes[$selectVar]['nType']))
+ $resultRow[$selectVar]['nType'] = $record[$this->rsIndexes[$selectVar]['nType']];
+ // is a predicate then
+ else
+ $resultRow[$selectVar]['nType'] = 'r';
+
+ if ($resultRow[$selectVar]['nType'] == 'l') {
+ $resultRow[$selectVar]['l_lang'] = $record[$this->rsIndexes[$selectVar]['l_lang']];
+ $resultRow[$selectVar]['l_dtype'] = $record[$this->rsIndexes[$selectVar]['l_dtype']];
+ }
+ }
+ return $resultRow;
+ }
+
+} // end: Class RdqlDbEngine
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/RdqlEngine.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/RdqlEngine.php
new file mode 100755
index 00000000..117228cf
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/RdqlEngine.php
@@ -0,0 +1,69 @@
+
+ *
+ * @package rdql
+ * @access public
+ */
+
+Class RdqlEngine extends Object{
+
+
+
+/**
+ * Prints a query result as HTML table.
+ * You can change the colors in the configuration file.
+ *
+ * @param array $queryResult [][?VARNAME] = object Node
+ * @access private
+ */
+ function writeQueryResultAsHtmlTable($queryResult) {
+ // Import Package Utility
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_UTILITY);
+
+ if (current($queryResult[0]) == NULL) {
+ echo 'no match
';
+ return;
+ }
+
+ echo '| No. | ';
+ foreach ($queryResult[0] as $varName => $value)
+ echo "$varName | ";
+ echo '
';
+
+ foreach ($queryResult as $n => $var) {
+
+
+ echo '| ' .($n + 1) .'. | ';
+ foreach ($var as $varName => $value) {
+ echo INDENTATION . INDENTATION . '';
+ echo ' ';
+
+ $lang = NULL;
+ $dtype = NULL;
+ if (is_a($value, 'Literal')) {
+ if ($value->getLanguage() != NULL)
+ $lang = ' (xml:lang="' . $value->getLanguage() . '") ';
+ if ($value->getDatatype() != NULL)
+ $dtype = ' (rdf:datatype="' . $value->getDatatype() . '") ';
+ }
+ echo RDFUtil::getNodeTypeName($value) .$value->getLabel() . $lang . $dtype .' ';
+ }
+ echo ' |
';
+ }
+ echo '
';
+ }
+
+} // end: Class RdqlEngine
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/RdqlMemEngine.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/RdqlMemEngine.php
new file mode 100755
index 00000000..bcaa02e4
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/RdqlMemEngine.php
@@ -0,0 +1,555 @@
+
+ *
+ * @package rdql
+ * @access public
+ */
+
+Class RdqlMemEngine extends RdqlEngine {
+
+
+/**
+ * Parsed query variables and constraints.
+ *
+ * @var array ['selectVars'][] = ?VARNAME
+ * ['sources'][] = URI
+ * ['patterns'][]['subject']['value'] = VARorURI
+ * ['predicate']['value'] = VARorURI
+ * ['object']['value'] = VARorURIorLiterl
+ * ['is_literal'] = boolean
+ * ['l_lang'] = string
+ * ['l_dtype'] = string
+ * ['filters'][]['string'] = string
+ * ['evalFilterStr'] = string
+ * ['reqexEqExprs'][]['var'] = ?VARNAME
+ * ['operator'] = (eq | ne)
+ * ['regex'] = string
+ * ['strEqExprs'][]['var'] = ?VARNAME
+ * ['operator'] = (eq | ne)
+ * ['value'] = string
+ * ['value_type'] = ('variable' | 'URI' | 'Literal')
+ * ['value_lang'] = string
+ * ['value_dtype'] = string
+ * ['numExpr']['vars'][] = ?VARNAME
+ * ( [] stands for an integer index - 0..N )
+ * @access private
+ */
+ var $parsedQuery;
+
+
+ /**
+ * Perform an RDQL Query on the given MemModel.
+ *
+ * @param object MemModel &$memModel
+ * @param array &$parsedQuery (the same format as $this->parsedQuery)
+ * @param boolean $returnNodes
+ * @return array [][?VARNAME] = object Node (if $returnNodes = TRUE)
+ * OR array [][?VARNAME] = string
+ *
+ * @access public
+ */
+ function & queryModel(&$memModel, &$parsedQuery, $returnNodes = TRUE) {
+
+ $this->parsedQuery = $parsedQuery;
+
+ // find tuples matching all patterns
+ $res = $this->findTuplesMatchingAllPatterns($memModel);
+
+ // filter tuples
+ if (isset($parsedQuery['filters']))
+ $res = $this->filterTuples($res);
+
+ // select variables to be returned
+ $res = $this->selectVariables($res);
+
+ if(!$returnNodes)
+ return $this->toString($res);
+
+ return $res;
+ }
+
+
+ /**
+ * Find triples matching all patterns of an RDQL query and return an array
+ * with variables from all patterns and their corresponding values.
+ * The variable values returned are instances of object Node.
+ *
+ * @param object MemModel &$memModel
+ * @return array [][?VARNAME] = object Node
+ *
+ * @access private
+ */
+ function findTuplesMatchingAllPatterns(&$memModel) {
+
+ $resultSet = $this->findTuplesMatchingOnePattern($memModel, $this->parsedQuery['patterns'][0]);
+ for ($i=1; $iparsedQuery['patterns']); $i++) {
+ $rs = $this->findTuplesMatchingOnePattern($memModel, $this->parsedQuery['patterns'][$i]);
+ $resultSet = $this->joinTuples($resultSet, $rs);
+ }
+ return $resultSet;
+ }
+
+
+/**
+ * Find tuples matching one pattern and return an array with pattern
+ * variables and their corresponding values (instances of object Node).
+ *
+ * @param object MemModel &$memModel
+ * @param array &$pattern ['subject']['value'] = VARorURI
+ * ['predicate']['value'] = VARorURI
+ * ['object']['value'] = VARorURIorLiterl
+ * ['is_literal'] = boolean
+ * ['l_lang'] = string
+ * ['l_dtype'] = string
+ * @return array [][?VARNAME] = object Node
+ *
+ * @access private
+ */
+ function findTuplesMatchingOnePattern(&$memModel, &$pattern) {
+
+ $resultSet = array();
+ $i = 0;
+ // parameters to be passed to the method findTriplesMatchingPattern
+ foreach ($pattern as $key => $v) {
+ if ($v['value'] && $v['value']{0} == '?') {
+ if ($key == 'object') {
+ $param['object']['is_a'] = 'ANY';
+ $param['object']['string'] = 'ANY';
+ $param['object']['lang'] = NULL;
+ $param['object']['dtype'] = NULL;
+ } else
+ $param[$key] = 'ANY';
+ $var[$i]['key'] = $key;
+ $var[$i++]['val'] = $v['value'];
+ }else
+ if (isset($v['is_literal'])) {
+ $param[$key]['is_a'] = 'Literal';
+ $param[$key]['string'] = $v['value'];
+ $param[$key]['lang'] = $v['l_lang'];
+ $param[$key]['dtype'] = $v['l_dtype'];
+ }else{
+ if ($key == 'object') {
+ $param[$key]['is_a'] = 'Resource';
+ $param[$key]['string'] = $v['value'];
+ $param[$key]['lang'] = NULL;
+ $param[$key]['dtype'] = NULL;
+ }else
+ $param[$key] = $v['value'];
+ }
+ }
+
+ // find pattern internal bindings e.g. (?x, ?z, ?x)
+ $intBindings = NULL;
+ for ($i=0; $i $v)
+ if ($i != $n && $var[$i]['val'] == $v['val'])
+ $intBindings[] = $var[$i]['key'];
+
+ // find triples of the $memModel matching $pattern
+ $resModel = $this->findTriplesMatchingPattern($memModel, $param['subject'],
+ $param['predicate'],
+ $param['object']['is_a'],
+ $param['object']['string'],
+ $param['object']['lang'],
+ $param['object']['dtype'],
+ $intBindings);
+
+ // set values of the pattern variables to be returned
+ if ($pattern['subject']['value']{0} == '?') {
+ $n = 0;
+ foreach ($resModel->triples as $triple)
+ $resultSet[$n++][$pattern['subject']['value']] = $triple->subj;
+ }
+ if ($pattern['predicate']['value']{0} == '?') {
+ $n = 0;
+ foreach ($resModel->triples as $triple)
+ $resultSet[$n++][$pattern['predicate']['value']] = $triple->pred;
+ }
+ if ($pattern['object']['value'] && $pattern['object']['value']{0} == '?') {
+ $n = 0;
+ foreach ($resModel->triples as $triple)
+ $resultSet[$n++][$pattern['object']['value']] = $triple->obj;
+ }
+ return $resultSet;
+ }
+
+
+/**
+ * Search in $memModel for triples matching one pattern from the WHERE clause.
+ * 'ANY' input for $subjLabel..$objLabel, $obj_is will match anything.
+ * NULL input for $objDtype will only match obj->dtype = NULL
+ * NULL input for $objLanguage will match obj->lang = NULL or anything if a
+ * literal is datatyped (except for XMLLiterals and plain literals)
+ * This method also checks internal bindings if provided.
+ *
+ * @param object MemModel $memModel
+ * @param string $subjLabel
+ * @param string $predLabel
+ * @param string $objLabel
+ * @param string $obj_is
+ * @param string $objLanguage
+ * @param string $objDtype
+ * @param array $intBindings [] = string
+ * @return object MemModel
+ * @access private
+ */
+ function findTriplesMatchingPattern(&$memModel, $subjLabel, $predLabel, $obj_is,
+ $objLabel, $objLang, $objDtype, &$intBindings) {
+
+ $res = new MemModel();
+
+ if($memModel->isEmpty())
+ return $res;
+
+ if ($subjLabel=='ANY')
+ {
+ $subj=NULL;
+ } else
+ {
+ $subj=new Resource($subjLabel);
+ };
+ if ($predLabel=='ANY')
+ {
+ $pred=NULL;
+ } else
+ {
+ $pred=new Resource($predLabel);
+ };
+
+ if ($objLabel=='ANY')
+ {
+ $obj=NULL;
+ } else
+ {
+ if ($obj_is == 'Literal')
+ {
+ $obj=new Literal($objLabel);
+ $obj->setDatatype($objDtype);
+ $obj->setLanguage($objLang);
+ } else {
+ $obj=new Resource($objLabel);
+ }
+ };
+
+ $res=$memModel->find($subj,$pred,$obj);
+
+ if ($intBindings)
+ foreach ($res->triples as $triple)
+ {
+ if (!$this->_checkIntBindings($triple, $intBindings))
+ {
+ $res->remove($triple);
+ }
+ }
+
+ return $res;
+}
+
+
+/**
+ * Perform an SQL-like inner join on two resultSets.
+ *
+ * @param array &$finalRes [][?VARNAME] = object Node
+ * @param array &$res [][?VARNAME] = object Node
+ * @return array [][?VARNAME] = object Node
+ *
+ * @access private
+ */
+ function joinTuples(&$finalRes, &$res) {
+
+ if (count($finalRes) == 0 || count($res) == 0)
+ return array();
+
+ // find joint variables and new variables to be added to $finalRes
+ $jointVars = array();
+ $newVars = array();
+ foreach ($res[0] as $varname => $node) {
+ if (array_key_exists($varname, $finalRes[0]))
+ $jointVars[] = $varname;
+ else
+ $newVars[] = $varname;
+ }
+
+ // eliminate rows of $finalRes in which the values of $jointVars do not have
+ // a corresponding row in $res.
+ foreach ($finalRes as $n => $fRes) {
+ foreach ($res as $i => $r) {
+ $ok = TRUE;
+ foreach ($jointVars as $j_varname)
+ if ($r[$j_varname] != $fRes[$j_varname]) {
+ $ok = FALSE;
+ break;
+ }
+ if ($ok)
+ break;
+ }
+ if (!$ok)
+ unset($finalRes[$n]);
+ }
+
+ // join $res and $finalRes
+ $joinedRes = array();
+ foreach ($res as $i => $r) {
+ foreach ($finalRes as $n => $fRes) {
+ $ok = TRUE;
+ foreach ($jointVars as $j_varname)
+ if ($r[$j_varname] != $fRes[$j_varname]) {
+ $ok = FALSE;
+ break;
+ }
+ if ($ok) {
+ $joinedRow = $finalRes[$n];
+ foreach($newVars as $n_varname)
+ $joinedRow[$n_varname] = $r[$n_varname];
+ $joinedRes[] = $joinedRow;
+ }
+ }
+ }
+
+ return $joinedRes;
+ }
+
+
+/**
+ * Filter the result-set of query variables by evaluating each filter from the
+ * AND clause of the RDQL query.
+ *
+ * @param array &$finalRes [][?VARNAME] = object Node
+ * @return array [][?VARNAME] = object Node
+ * @access private
+ */
+ function filterTuples(&$finalRes) {
+
+ foreach ($this->parsedQuery['filters'] as $filter) {
+
+ foreach ($finalRes as $n => $fRes) {
+ $evalFilterStr = $filter['evalFilterStr'];
+
+ // evaluate regex equality expressions of each filter
+ foreach ($filter['regexEqExprs'] as $i => $expr) {
+
+ preg_match($expr['regex'], $fRes[$expr['var']]->getLabel(), $match);
+ $op = substr($expr['operator'], 0,1);
+ if (($op != '!' && !isset($match[0])) || ($op == '!' && isset($match[0])))
+ $evalFilterStr = str_replace("##RegEx_$i##", 'FALSE', $evalFilterStr);
+ else
+ $evalFilterStr = str_replace("##RegEx_$i##", 'TRUE', $evalFilterStr);
+
+ }
+
+ // evaluate string equality expressions
+ foreach ($filter['strEqExprs'] as $i => $expr) {
+
+ $exprBoolVal = 'FALSE';
+
+ switch ($expr['value_type']) {
+
+ case 'variable':
+ if (($fRes[$expr['var']] == $fRes[$expr['value']] && $expr['operator'] == 'eq') ||
+ ($fRes[$expr['var']] != $fRes[$expr['value']] && $expr['operator'] == 'ne'))
+ $exprBoolVal = 'TRUE';
+ break;
+
+ case 'URI':
+
+ if (is_a($fRes[$expr['var']], 'Literal')) {
+ if ($expr['operator'] == 'ne')
+ $exprBoolVal = 'TRUE';
+ break;
+ }
+
+ if (($fRes[$expr['var']]->getLabel() == $expr['value'] && $expr['operator'] == 'eq') ||
+ ($fRes[$expr['var']]->getLabel() != $expr['value'] && $expr['operator'] == 'ne'))
+ $exprBoolVal = 'TRUE';
+ break;
+
+ case 'Literal':
+
+ if (!is_a($fRes[$expr['var']], 'Literal')) {
+ if ($expr['operator'] == 'ne')
+ $exprBoolVal = 'TRUE';
+ break;
+ }
+
+ $filterLiteral= new Literal($expr['value'],$expr['value_lang']);
+ $filterLiteral->setDatatype($expr['value_dtype']);
+
+ $equal=$fRes[$expr['var']]->equals($filterLiteral);
+/* if ($fRes[$expr['var']]->getLabel() == $expr['value'] &&
+ $fRes[$expr['var']]->getDatatype() == $expr['value_dtype']) {
+
+ $equal = TRUE;
+
+ // Lang tags only differentiate literals in rdf:XMLLiterals and plain literals.
+ // Therefore if a literal is datatyped ignore the language tag.
+ if ((($expr['value_dtype'] == NULL) ||
+ ($expr['value_dtype'] == 'http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral') ||
+ ($expr['value_dtype'] == 'http://www.w3.org/2001/XMLSchema#string')) &&
+ (($fRes[$expr['var']]->getLanguage() != $expr['value_lang'])))
+
+ $equal = FALSE;
+ }else
+ $equal = FALSE;
+ */
+ if (($equal && $expr['operator'] == 'eq') ||
+ (!$equal && $expr['operator'] == 'ne'))
+ $exprBoolVal = 'TRUE';
+ else
+ $exprBoolVal = 'FALSE';
+
+ }
+ $evalFilterStr = str_replace("##strEqExpr_$i##", $exprBoolVal, $evalFilterStr);
+ }
+
+ // evaluate numerical expressions
+ foreach ($filter['numExprVars'] as $varName) {
+ $varValue = "'" .$fRes[$varName]->getLabel() ."'";
+ $evalFilterStr = str_replace($varName, $varValue, $evalFilterStr);
+ }
+
+ eval("\$filterBoolVal = $evalFilterStr; \$eval_filter_ok = TRUE;");
+ if (!isset($eval_filter_ok))
+ trigger_error(RDQL_AND_ERR ."'" .htmlspecialchars($filter['string']) ."'", E_USER_ERROR);
+
+ if (!$filterBoolVal)
+ unset($finalRes[$n]);
+ }
+ }
+
+ return $finalRes;
+ }
+
+
+/**
+ * Remove all conditional variables from the result-set and leave only variables
+ * specified in the SELECT clause of the RDQL query.
+ *
+ * @param array &$finalRes [][?VARNAME] = object Node
+ * @return array [][?VARNAME] = object Node
+ * @access private
+ */
+ function selectVariables(&$finalRes) {
+
+ // if nothing has been found return only one row of $finalRes
+ // with select variables having empty values
+ if (count($finalRes) == 0) {
+ foreach ($this->parsedQuery['selectVars'] as $selectVar)
+ $finalRes[0][$selectVar] = NULL;
+ return $finalRes;
+ }
+
+ // return only selectVars in the same order as given in the RDQL query
+ // and reindex $finalRes.
+ $n = 0;
+ foreach($finalRes as $key => $val) {
+ foreach ($this->parsedQuery['selectVars'] as $selectVar)
+ $resultSet[$n][$selectVar] = $val[$selectVar];
+ unset($finalRes[$key]);
+ ++$n;
+ }
+
+ return $resultSet;
+ }
+
+
+/**
+ * Convert the variable values of $finalRes from objects to their string serialization.
+ *
+ * @param array &$finalRes [][?VARNAME] = object Node
+ * @return array [][?VARNAME] = string
+ * @access private
+ */
+ function toString(&$finalRes) {
+
+ foreach ($finalRes as $n => $tuple)
+ foreach ($tuple as $varname => $node) {
+ if (is_a($node, 'Resource'))
+ $res[$n][$varname] = '<' .$node->getLabel() .'>';
+ elseif (is_a($node, 'Literal')) {
+ $res[$n][$varname] = '"' .$node->getLabel() .'"';
+ if ($node->getLanguage())
+ $res[$n][$varname] .= ' (xml:lang="' .$node->getLanguage() .'")';
+ if ($node->getDatatype())
+ $res[$n][$varname] .= ' (rdf:datatype="' .$node->getDatatype() .'")';
+ }else
+ $res[$n][$varname] = $node;
+ }
+ return $res;
+ }
+
+
+/**
+ * Check if the given triple meets pattern internal bindings
+ * e.g. (?x, ?z, ?x) ==> statement subject must be identical with the statement object
+ *
+ * @param object statement &$triple
+ * @param array &$intBindings [] = string
+ * @return boolean
+ * @access private
+ */
+ function _checkIntBindings (&$triple, &$intBindings) {
+
+ if (in_array('subject', $intBindings)) {
+ if (in_array('predicate', $intBindings))
+ if ($triple->subj != $triple->pred)
+ return FALSE;
+ if (in_array('object', $intBindings)) {
+ if (is_a($triple->obj, 'Literal'))
+ return FALSE;
+ elseif ($triple->subj != $triple->obj)
+ return FALSE;
+ }
+ return TRUE;
+ }
+ if (in_array('predicate', $intBindings)) {
+ if (is_a($triple->obj, 'Literal'))
+ return FALSE;
+ elseif ($triple->pred != $triple->obj)
+ return FALSE;
+ return TRUE;
+ }
+ }
+
+
+/**
+ * Check if the lang and dtype of the passed object Literal are equal $lang and $dtype
+ * !!! Language only differentiates literals in rdf:XMLLiterals and plain literals (xsd:string).
+ * !!! Therefore if a literal is datatyped ignore the language.
+ *
+ * @param object Literal $literal
+ * @param string $dtype1
+ * @param string $dtype2
+ * @return boolean
+ * @access private
+ */
+ function _equalsLangDtype ($literal, $lang, $dtype) {
+
+ if ($dtype == $literal->getDatatype()) {
+ if (($dtype == NULL ||
+ $dtype == 'http://www.w3.org/2001/XMLSchema#string' ||
+ $dtype == 'http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral') &&
+ ($lang != $literal->getLanguage()))
+ return FALSE;
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+
+} // end: Class RdqlMemEngine
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/RdqlParser.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/RdqlParser.php
new file mode 100755
index 00000000..34c0fa56
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/RdqlParser.php
@@ -0,0 +1,1063 @@
+
+ *
+ * @package rdql
+ * @access public
+ */
+
+
+Class RdqlParser extends Object{
+
+/**
+ * Parsed query variables and constraints.
+ * { } are only used within the parser class and are not returned as parsed query.
+ * ( [] stands for an integer index - 0..N )
+ *
+ * @var array ['selectVars'][] = ?VARNAME
+ * ['sources'][]{['value']} = URI | QName
+ * {['is_qname'] = boolean}
+ * ['patterns'][]['subject']['value'] = VARorURI
+ * {['is_qname'] = boolean}
+ * ['predicate']['value'] = VARorURI
+ * {['is_qname'] = boolean}
+ * ['object']['value'] = VARorURIorLiterl
+ * {['is_qname'] = boolean}
+ * ['is_literal'] = boolean
+ * ['l_lang'] = string
+ * ['l_dtype'] = string
+ * {['l_dtype_is_qname'] = boolean}
+ * ['filters'][]['string'] = string
+ * ['evalFilterStr'] = string
+ * ['reqexEqExprs'][]['var'] = ?VARNAME
+ * ['operator'] = (eq | ne)
+ * ['regex'] = string
+ * ['strEqExprs'][]['var'] = ?VARNAME
+ * ['operator'] = (eq | ne)
+ * ['value'] = string
+ * ['value_type'] = ('variable' | 'URI' | 'QName' | 'Literal')
+ * ['value_lang'] = string
+ * ['value_dtype'] = string
+ * {['value_dtype_is_qname'] = boolean}
+ * ['numExpr']['vars'][] = ?VARNAME
+ * {['ns'][PREFIX] = NAMESPACE}
+ * @access private
+ */
+ var $parsedQuery;
+
+
+/**
+ * Query string divided into a sequence of tokens.
+ * A token is either: ' ' or "\n" or "\r" or "\t" or ',' or '(' or ')'
+ * or a string containing any characters except from the above.
+ *
+ * @var array
+ * @access private
+ */
+ var $tokens;
+
+
+/**
+ * Parse the given RDQL query string and return an array with query variables and constraints.
+ *
+ * @param string $queryString
+ * @return array $this->parsedQuery
+ * @access public
+ */
+ function & parseQuery($queryString) {
+
+ $cleanQueryString = $this->removeComments($queryString);
+ $this->tokenize($cleanQueryString);
+ $this->startParsing();
+ if ($this->parsedQuery['selectVars'][0] == '*')
+ $this->parsedQuery['selectVars'] = $this->findAllQueryVariables();
+ else
+ $this->_checkSelectVars();
+ $this->replaceNamespacePrefixes();
+
+ return $this->parsedQuery;
+ }
+
+
+/**
+ * Remove comments from the passed query string.
+ *
+ * @param string $query
+ * @return string
+ * @throws PHPError
+ * @access private
+ */
+ function removeComments($query) {
+
+ $last = strlen($query)-1;
+ $query .= ' ';
+ $clean = '';
+ for ($i=0; $i<=$last; $i++) {
+ // don't search for comments inside a 'literal'@lang^^dtype or "literal"@lang^^dtype
+ if ($query{$i} == "'" || $query{$i} == '"') {
+ $quotMark = $query{$i};
+ do
+ $clean .= $query{$i++};
+ while($i < $last && $query{$i} != $quotMark);
+ $clean .= $query{$i};
+ // language
+ if ($query{$i+1} == '@') {
+ do{
+ if ($query{$i+1} == '^' && $query{$i+2} == '^')
+ break;
+ $clean .= $query{++$i};
+ }while ($i < $last && $query{$i} != ' ' && $query{$i} != "\t"
+ && $query{$i} != "\n" && $query{$i} != "\r");
+ }
+ // datatype
+ if ($query{$i+1} == '^' && $query{$i+2} == '^') {
+ do
+ $clean .= $query{++$i};
+ while ($i < $last && $query{$i} != ' ' && $query{$i} != "\t"
+ && $query{$i} != "\n" && $query{$i} != "\r" );
+ }
+ // don't search for comments inside an either
+ }elseif ($query{$i} == '<') {
+ do{
+ $clean .= $query{$i++};
+ }while($i < $last && $query{$i} != '>');
+ $clean .= $query{$i};
+ }elseif ($query{$i} == '/') {
+ // clear: // comment
+ if ($i < $last && $query{$i+1} == '/') {
+ while($i < $last && $query{$i} != "\n" && $query{$i} != "\r")
+ ++$i;
+ $clean .= ' ';
+ // clear: /*comment*/
+ }elseif ($i < $last-2 && $query{$i+1} == '*') {
+ $i += 2;
+ while($i < $last && ($query{$i} != '*' || $query{$i+1} != '/'))
+ ++$i;
+ if ($i >= $last && ($query{$last-1} != '*' || $query{$last} != '/'))
+ trigger_error(RDQL_SYN_ERR .": unterminated comment - '*/' missing", E_USER_ERROR);
+ ++$i;
+ }else
+ $clean .= $query{$i};
+ }else
+ $clean .= $query{$i};
+ }
+ return $clean;
+ }
+
+
+/**
+ * Divide the query string into tokens.
+ * A token is either: ' ' or "\n" or "\r" or '\t' or ',' or '(' or ')'
+ * or a string containing any character except from the above.
+ *
+ * @param string $queryString
+ * @access private
+ */
+ function tokenize($queryString) {
+
+ $queryString = trim($queryString, " \r\n\t");
+ $specialChars = array (" ", "\t", "\r", "\n", ",", "(", ")");
+ $len = strlen($queryString);
+ $this->tokens[0]='';
+ $n = 0;
+
+ for ($i=0; $i<$len; ++$i) {
+ if (!in_array($queryString{$i}, $specialChars))
+ $this->tokens[$n] .= $queryString{$i};
+ else {
+ if ($this->tokens[$n] != '')
+ ++$n;
+ $this->tokens[$n] = $queryString{$i};
+ $this->tokens[++$n] = '';
+ }
+ }
+ }
+
+
+/**
+ * Start parsing of the tokenized query string.
+ *
+ * @access private
+ */
+ function startParsing() {
+
+ $this->parseSelect();
+ }
+
+
+/**
+ * Parse the SELECT clause of an Rdql query.
+ * When the parsing of the SELECT clause is finished, this method will call
+ * a suitable method to parse the subsequent clause.
+ *
+ * @throws PhpError
+ * @access private
+ */
+ function parseSelect() {
+
+ $this->_clearWhiteSpaces();
+
+ // Check if the queryString contains a "SELECT" token
+ if (strcasecmp('SELECT', current($this->tokens)))
+ trigger_error(RDQL_SEL_ERR ."'" .current($this->tokens)
+ ."' - SELECT keyword expected", E_USER_ERROR);
+ unset($this->tokens[key($this->tokens)]);
+ $this->_clearWhiteSpaces();
+
+ // Parse SELECT *
+ if (current($this->tokens) == '*') {
+ unset($this->tokens[key($this->tokens)]);
+ $this->parsedQuery['selectVars'][0] = '*';
+ $this->_clearWhiteSpaces();
+ if (strcasecmp('FROM', current($this->tokens))
+ && strcasecmp('SOURCE', current($this->tokens))
+ && strcasecmp('WHERE', current($this->tokens)))
+ trigger_error(RDQL_SYN_ERR .": '" .htmlspecialchars(current($this->tokens))
+ ."' - SOURCE or WHERE clause expected", E_USER_ERROR);
+ }
+
+ // Parse SELECT ?Var (, ?Var)*
+ $commaExpected = FALSE;
+ $comma = FALSE;
+ while (current($this->tokens) != NULL) {
+ $k = key($this->tokens);
+ $token = $this->tokens[$k];
+
+ switch ($token) {
+ case ',': if (!$commaExpected)
+ trigger_error(RDQL_SEL_ERR ." ',' - unexpected comma", E_USER_ERROR);
+ $comma = TRUE;
+ $commaExpected = FALSE;
+ break;
+ case '(':
+ case ')': trigger_error(RDQL_SEL_ERR ." '$token' - illegal input", E_USER_ERROR);
+ break;
+ default :
+ if (!strcasecmp('FROM', $token) || !strcasecmp('SOURCE', $token)) {
+ if ($comma)
+ trigger_error(RDQL_SEL_ERR ." ',' - unexpected comma", E_USER_ERROR);
+ unset($this->tokens[$k]);
+ return $this->parseFrom();
+ }elseif (!strcasecmp('WHERE', $token) && !$comma) {
+ if ($comma)
+ trigger_error(RDQL_SEL_ERR ." ',' - unexpected comma", E_USER_ERROR);
+ unset($this->tokens[$k]);
+ return $this->parseWhere();
+ }
+ if ($token{0} == '?') {
+ $this->parsedQuery['selectVars'][] = $this->_validateVar($token, RDQL_SEL_ERR);
+ $commaExpected = TRUE;
+ $comma = FALSE;
+ }else
+ trigger_error(RDQL_SEL_ERR ." '$token' - '?' missing", E_USER_ERROR);
+ }
+ unset($this->tokens[$k]);
+ $this->_clearWhiteSpaces();
+ }
+ trigger_error(RDQL_SYN_ERR . ': WHERE clause missing', E_USER_ERROR);
+ }
+
+
+/**
+ * Parse the FROM/SOURCES clause of an Rdql query
+ * When the parsing of this clause is finished, parseWhere() will be called.
+ *
+ * @throws PhpError
+ * @access private
+ */
+ function parseFrom() {
+
+ $comma = FALSE;
+ $commaExpected = FALSE;
+ $i = -1;
+ while (current($this->tokens) != NULL) {
+
+ $this->_clearWhiteSpaces();
+ if (!strcasecmp('WHERE', current($this->tokens)) && count($this->parsedQuery['sources']) != 0) {
+ if ($comma)
+ trigger_error(RDQL_SEL_ERR ." ',' - unexpected comma", E_USER_ERROR);
+ unset($this->tokens[key($this->tokens)]);
+ return $this->parseWhere();
+ }
+ if (current($this->tokens) == ',') {
+ if ($commaExpected) {
+ $comma = TRUE;
+ $commaExpected = FALSE;
+ unset($this->tokens[key($this->tokens)]);
+ }else
+ trigger_error(RDQL_SRC_ERR ."',' - unecpected comma", E_USER_ERROR);
+ }else{
+ $token = current($this->tokens);
+ $this->parsedQuery['sources'][++$i]['value'] = $this->_validateURI($token, RDQL_SRC_ERR);
+ if ($token{0} != '<')
+ $this->parsedQuery['sources'][$i]['is_qname'] = TRUE;
+ $commaExpected = TRUE;
+ $comma = FALSE;
+ }
+ }
+ trigger_error(RDQL_SYN_ERR .': WHERE clause missing', E_USER_ERROR);
+ }
+
+
+/**'
+ * Parse the WHERE clause of an Rdql query.
+ * When the parsing of the WHERE clause is finished, this method will call
+ * a suitable method to parse the subsequent clause if provided.
+ *
+ * @throws PhpError
+ * @access private
+ */
+ function parseWhere() {
+
+ $comma = FALSE;
+ $commaExpected = FALSE;
+ $i=0;
+
+ do {
+ $this->_clearWhiteSpaces();
+ if (!strcasecmp('AND', current($this->tokens))
+ && count($this->parsedQuery['patterns']) != 0){
+ if ($comma)
+ trigger_error(RDQL_WHR_ERR ." ',' - unexpected comma", E_USER_ERROR);
+ unset($this->tokens[key($this->tokens)]);
+ return $this->parseAnd();
+ }elseif (!strcasecmp('USING', current($this->tokens))
+ && count($this->parsedQuery['patterns']) != 0) {
+ if ($comma)
+ trigger_error(RDQL_WHR_ERR ." ',' - unexpected comma", E_USER_ERROR);
+ unset($this->tokens[key($this->tokens)]);
+ return $this->parseUsing();
+ }
+
+ if (current($this->tokens) == ',') {
+ $comma = TRUE;
+ $this->_checkComma($commaExpected, RDQL_WHR_ERR);
+
+ }else{
+
+ if (current($this->tokens) != '(')
+ trigger_error(RDQL_WHR_ERR ."'" .current($this->tokens)
+ ."' - '(' expected", E_USER_ERROR);
+ unset($this->tokens[key($this->tokens)]);
+ $this->_clearWhiteSpaces();
+
+ $this->parsedQuery['patterns'][$i]['subject'] = $this->_validateVarUri(current($this->tokens));
+ $this->_checkComma(TRUE, RDQL_WHR_ERR);
+ $this->parsedQuery['patterns'][$i]['predicate'] = $this->_validateVarUri(current($this->tokens));
+ $this->_checkComma(TRUE, RDQL_WHR_ERR);
+ $this->parsedQuery['patterns'][$i++]['object'] = $this->_validateVarUriLiteral(current($this->tokens));
+ $this->_clearWhiteSpaces();
+
+ if (current($this->tokens) != ')')
+ trigger_error(RDQL_WHR_ERR ."'" .current($this->tokens) ."' - ')' expected", E_USER_ERROR);
+ unset($this->tokens[key($this->tokens)]);
+ $this->_clearWhiteSpaces();
+ $commaExpected = TRUE;
+ $comma = FALSE;
+ }
+ }while(current($this->tokens) != NULL);
+
+ if ($comma)
+ trigger_error(RDQL_WHR_ERR ." ',' - unexpected comma", E_USER_ERROR);
+ }
+
+
+/**
+ * Parse the AND clause of an Rdql query
+ *
+ * @throws PhpError
+ * @access private
+ * @todo clear comments
+ */
+ function parseAnd() {
+
+ $this->_clearWhiteSpaces();
+ $n = 0;
+ $filterStr = '';
+
+ while(current($this->tokens) != NULL) {
+ $k = key($this->tokens);
+ $token = $this->tokens[$k];
+
+ if (!strcasecmp('USING', $token)) {
+ $this->parseFilter($n, $filterStr);
+ unset($this->tokens[$k]);
+ return $this->parseUsing();
+ }elseif ($token == ',') {
+ $this->parseFilter($n, $filterStr);
+ $filterStr = '';
+ $token = '';
+ ++$n;
+ }
+ $filterStr .= $token;
+ unset($this->tokens[$k]);
+ }
+ $this->parseFilter($n, $filterStr);
+ }
+
+
+/**
+ * Parse the USING clause of an Rdql query
+ *
+ * @throws PhpError
+ * @access private
+ */
+ function parseUsing() {
+
+ $commaExpected = FALSE;
+ $comma = FALSE;
+
+ do {
+ $this->_clearWhiteSpaces();
+ if (current($this->tokens) == ',') {
+ $comma = TRUE;
+ $this->_checkComma($commaExpected, RDQL_USG_ERR);
+ }else{
+ $prefix = $this->_validatePrefix(current($this->tokens));
+ $this->_clearWhiteSpaces();
+
+ if (strcasecmp('FOR', current($this->tokens)))
+ trigger_error(RDQL_USG_ERR ." keyword: 'FOR' missing in the namespace declaration: '", E_USER_ERROR);
+ unset($this->tokens[key($this->tokens)]);
+ $this->_clearWhiteSpaces();
+
+ $this->parsedQuery['ns'][$prefix] = $this->_validateUri(current($this->tokens), RDQL_USG_ERR);
+ $this->_clearWhiteSpaces();
+ $commaExpected = TRUE;
+ $comma = FALSE;
+ }
+ }while(current($this->tokens) != NULL);
+
+ if ($comma)
+ trigger_error(RDQL_WHR_ERR ." ',' - unexpected comma", E_USER_ERROR);
+ }
+
+
+/**
+ * Check if a filter from the AND clause contains an equal number of '(' and ')'
+ * and parse filter expressions.
+ *
+ * @param integer $n
+ * @param string $filter
+ * @throws PHPError
+ * @access private
+ */
+ function parseFilter($n, $filter) {
+
+ if ($filter == NULL)
+ trigger_error(RDQL_AND_ERR ." ',' - unexpected comma", E_USER_ERROR);
+ $paren = substr_count($filter, '(') - substr_count($filter, ')');
+ if ($paren != 0) {
+ if ($paren > 0)
+ $errorMsg = "'" .htmlspecialchars($filter) ."' - ')' missing ";
+ elseif ($paren < 0)
+ $errorMsg = "'" .htmlspecialchars($filter) ."' - too many ')' ";
+ trigger_error(RDQL_AND_ERR .$errorMsg, E_USER_ERROR);
+ }
+
+ $this->parsedQuery['filters'][$n] = $this->parseExpressions($filter);
+ }
+
+
+/**
+ * Parse expressions inside the passed filter:
+ * 1) regex equality expressions: ?var [~~ | =~ | !~ ] REG_EX
+ * 2a) string equality expressions: ?var [eq | ne] "literal"@lang^^dtype.
+ * 2b) string equality expressions: ?var [eq | ne] or ?var [eq | ne] prefix:local_name
+ * 3) numerical expressions: e.q. (?var1 - ?var2)*4 >= 20
+ *
+ * In cases 1-2 parse each expression of the given filter into an array of variables.
+ * For each parsed expression put a place holder (e.g. ##RegEx_1##) into the filterStr.
+ * The RDQLengine will then replace each place holder with the outcomming boolean value
+ * of the corresponding expression.
+ * The remaining filterStr contains only numerical expressions and place holders.
+ *
+ * @param string $filteStr
+ * @return array ['string'] = string
+ * ['evalFilterStr'] = string
+ * ['reqexEqExprs'][]['var'] = ?VARNAME
+ * ['operator'] = (eq | ne)
+ * ['regex'] = string
+ * ['strEqExprs'][]['var'] = ?VARNAME
+ * ['operator'] = (eq | ne)
+ * ['value'] = string
+ * ['value_type'] = ('variable' | 'URI' | 'QName'| 'Literal')
+ * ['value_lang'] = string
+ * ['value_dtype'] = string
+ * ['value_dtype_is_qname'] = boolean
+ * ['numExpr']['vars'][] = ?VARNAME
+ * @access private
+ */
+ function parseExpressions($filterStr) {
+
+ $parsedFilter['string'] = $filterStr;
+ $parsedFilter['regexEqExprs'] = array();
+ $parsedFilter['strEqExprs'] = array();
+ $parsedFilter['numExprVars'] = array();
+
+ // parse regex string equality expressions, e.g. ?x ~~ !//foo.com/r!i
+ $reg_ex = "/(\?[a-zA-Z0-9_]+)\s+([~!=]~)\s+(['|\"])?([^\s'\"]+)(['|\"])?/";
+ preg_match_all($reg_ex, $filterStr, $eqExprs);
+ foreach ($eqExprs[0] as $i => $eqExpr) {
+ $this->_checkRegExQuotation($filterStr, $eqExprs[3][$i], $eqExprs[5][$i]);
+ $parsedFilter['regexEqExprs'][$i]['var'] = $this->_isDefined($eqExprs[1][$i]);
+ $parsedFilter['regexEqExprs'][$i]['operator'] = $eqExprs[2][$i];
+ $parsedFilter['regexEqExprs'][$i]['regex'] = $eqExprs[4][$i];
+
+ $filterStr = str_replace($eqExpr, " ##RegEx_$i## ", $filterStr);
+ }
+
+ // parse ?var [eq | ne] "literal"@lang^^dtype
+ $reg_ex = "/(\?[a-zA-Z0-9_]+)\s+(eq|ne)\s+(\'[^\']*\'|\"[^\"]*\")";
+ $reg_ex .= "(@[a-zA-Z]+)?(\^{2}\S+:?\S+)?/i";
+ preg_match_all($reg_ex, $filterStr, $eqExprs);
+ foreach ($eqExprs[0] as $i => $eqExpr) {
+ $parsedFilter['strEqExprs'][$i]['var'] = $this->_isDefined($eqExprs[1][$i]);#
+ $parsedFilter['strEqExprs'][$i]['operator'] = strtolower($eqExprs[2][$i]);
+ $parsedFilter['strEqExprs'][$i]['value'] = trim($eqExprs[3][$i],"'\"");
+ $parsedFilter['strEqExprs'][$i]['value_type'] = 'Literal';
+ $parsedFilter['strEqExprs'][$i]['value_lang'] = substr($eqExprs[4][$i], 1);
+ $dtype = substr($eqExprs[5][$i], 2);
+ if ($dtype) {
+ $parsedFilter['strEqExprs'][$i]['value_dtype'] = $this->_validateUri($dtype, RDQL_AND_ERR);
+ if ($dtype{0} != '<')
+ $parsedFilter['strEqExprs'][$i]['value_dtype_is_qname'] = TRUE;
+ }else
+ $parsedFilter['strEqExprs'][$i]['value_dtype'] = '';
+
+ $filterStr = str_replace($eqExprs[0][$i], " ##strEqExpr_$i## ", $filterStr);
+ }
+
+ // parse ?var [eq | ne] ?var
+ $ii = count($parsedFilter['strEqExprs']);
+ $reg_ex = "/(\?[a-zA-Z0-9_]+)\s+(eq|ne)\s+(\?[a-zA-Z0-9_]+)/i";
+ preg_match_all($reg_ex, $filterStr, $eqExprs);
+ foreach ($eqExprs[0] as $i => $eqExpr) {
+ $parsedFilter['strEqExprs'][$ii]['var'] = $this->_isDefined($eqExprs[1][$i]);
+ $parsedFilter['strEqExprs'][$ii]['operator'] = strtolower($eqExprs[2][$i]);
+ $parsedFilter['strEqExprs'][$ii]['value'] = $this->_isDefined($eqExprs[3][$i]);
+ $parsedFilter['strEqExprs'][$ii]['value_type'] = 'variable';
+
+ $filterStr = str_replace($eqExprs[0][$i], " ##strEqExpr_$ii## ", $filterStr);
+ $ii++;
+ }
+
+ // parse ?var [eq | ne] or ?var [eq | ne] prefix:local_name
+ $reg_ex = "/(\?[a-zA-Z0-9_]+)\s+(eq|ne)\s+((<\S+>)|(\S+:\S*))/i";
+ preg_match_all($reg_ex, $filterStr, $eqExprs);
+ foreach ($eqExprs[0] as $i => $eqExpr) {
+ $parsedFilter['strEqExprs'][$ii]['var'] = $this->_isDefined($eqExprs[1][$i]);
+ $parsedFilter['strEqExprs'][$ii]['operator'] = strtolower($eqExprs[2][$i]);
+ if ($eqExprs[4][$i]) {
+ $parsedFilter['strEqExprs'][$ii]['value'] = trim($eqExprs[4][$i], "<>");
+ $parsedFilter['strEqExprs'][$ii]['value_type'] = 'URI';
+ }else if($eqExprs[5][$i]){
+ $this->_validateQName($eqExprs[5][$i], RDQL_AND_ERR);
+ $parsedFilter['strEqExprs'][$ii]['value'] = $eqExprs[5][$i];
+ $parsedFilter['strEqExprs'][$ii]['value_type'] = 'QName';
+ }
+
+ $filterStr = str_replace($eqExprs[0][$i], " ##strEqExpr_$ii## ", $filterStr);
+ $ii++;
+ }
+
+ $parsedFilter['evalFilterStr'] = $filterStr;
+
+ // all that is left are numerical expressions and place holders for the above expressions
+ preg_match_all("/\?[a-zA-Z0-9_]+/", $filterStr, $vars);
+ foreach ($vars[0] as $var) {
+ $parsedFilter['numExprVars'][] = $this->_isDefined($var);
+ }
+
+ return $parsedFilter;
+ }
+
+
+/**
+ * Find all query variables used in the WHERE clause.
+ *
+ * @return array [] = ?VARNAME
+ * @access private
+ */
+ function findAllQueryVariables() {
+
+ $vars = array();
+ foreach ($this->parsedQuery['patterns'] as $pattern) {
+ $count = 0;
+ foreach ($pattern as $v) {
+ if ($v['value'] && $v['value']{0} == '?') {
+ ++$count;
+ if (!in_array($v['value'], $vars))
+ $vars[] = $v['value'];
+ }
+ }
+ if (!$count)
+ trigger_error(RDQL_WHR_ERR .'pattern contains no variables', E_USER_ERROR);
+ }
+
+ return $vars;
+ }
+
+
+/**
+ * Replace all namespace prefixes in the pattern and constraint clause of an rdql query
+ * with the namespaces declared in the USING clause and default namespaces.
+ *
+ * @access private
+ */
+ function replaceNamespacePrefixes() {
+
+ global $default_prefixes;
+
+ if (!isset($this->parsedQuery['ns']))
+ $this->parsedQuery['ns'] = array();
+
+ // add default namespaces
+ // if in an rdql query a reserved prefix (e.g. rdf: rdfs:) is used
+ // it will be overridden by the default namespace defined in constants.php
+ $this->parsedQuery['ns'] = array_merge($this->parsedQuery['ns'], $default_prefixes);
+
+ // replace namespace prefixes in the FROM clause
+ if (isset($this->parsedQuery['sources']))
+ foreach ($this->parsedQuery['sources'] as $n => $source) {
+ if (isset($source['is_qname']))
+ $this->parsedQuery['sources'][$n] = $this->_replaceNamespacePrefix($source['value'], RDQL_SRC_ERR);
+ else {
+ foreach ($this->parsedQuery['ns'] as $prefix => $uri)
+ $source['value'] = eregi_replace("$prefix:", $uri, $source['value']);
+ $this->parsedQuery['sources'][$n] = $source['value'];
+ }
+
+ }
+
+ // replace namespace prefixes in the where clause
+ foreach ($this->parsedQuery['patterns'] as $n => $pattern) {
+ foreach ($pattern as $key => $v)
+ if ($v['value'] && $v['value']{0} != '?') {
+ if (isset($v['is_qname'])) {
+ $this->parsedQuery['patterns'][$n][$key]['value']
+ = $this->_replaceNamespacePrefix($v['value'], RDQL_WHR_ERR);
+ unset($this->parsedQuery['patterns'][$n][$key]['is_qname']);
+ } else { // is quoted URI (== ) or Literal
+ if (isset($this->parsedQuery['patterns'][$n][$key]['is_literal'])) {
+ if (isset($this->parsedQuery['patterns'][$n][$key]['l_dtype_is_qname'])) {
+ $this->parsedQuery['patterns'][$n][$key]['l_dtype']
+ = $this->_replaceNamespacePrefix($v['l_dtype'], RDQL_WHR_ERR);
+ unset($this->parsedQuery['patterns'][$n][$key]['l_dtype_is_qname']);
+ }else {
+ foreach ($this->parsedQuery['ns'] as $prefix => $uri)
+ $this->parsedQuery['patterns'][$n][$key]['l_dtype']
+ = eregi_replace("$prefix:", $uri, $this->parsedQuery['patterns'][$n][$key]['l_dtype']);
+ }
+ }else {
+ foreach ($this->parsedQuery['ns'] as $prefix => $uri)
+ $this->parsedQuery['patterns'][$n][$key]['value']
+ = eregi_replace("$prefix:", $uri, $this->parsedQuery['patterns'][$n][$key]['value']);
+ }
+ }
+ }
+ }
+
+ // replace prefixes in the constraint clause
+ if (isset($this->parsedQuery['filters']))
+ foreach ($this->parsedQuery['filters'] as $n => $filter)
+ foreach ($filter['strEqExprs'] as $i => $expr) {
+ if ($expr['value_type'] == 'QName') {
+ $this->parsedQuery['filters'][$n]['strEqExprs'][$i]['value']
+ = $this->_replaceNamespacePrefix($expr['value'], RDQL_AND_ERR);
+ $this->parsedQuery['filters'][$n]['strEqExprs'][$i]['value_type'] = 'URI';
+ }
+ if ($expr['value_type'] == 'URI')
+ foreach ($this->parsedQuery['ns'] as $prefix => $uri)
+ $this->parsedQuery['filters'][$n]['strEqExprs'][$i]['value']
+ = eregi_replace("$prefix:", $uri,
+ $this->parsedQuery['filters'][$n]['strEqExprs'][$i]['value']);
+ elseif ($expr['value_type'] == 'Literal') {
+ if (isset($expr['value_dtype_is_qname'])) {
+ $this->parsedQuery['filters'][$n]['strEqExprs'][$i]['value_dtype']
+ = $this->_replaceNamespacePrefix($expr['value_dtype'], RDQL_AND_ERR);
+ unset($this->parsedQuery['filters'][$n]['strEqExprs'][$i]['value_dtype_is_qname']);
+ } else {
+ foreach ($this->parsedQuery['ns'] as $prefix => $uri)
+ $this->parsedQuery['filters'][$n]['strEqExprs'][$i]['value_dtype']
+ = eregi_replace("$prefix:", $uri,
+ $this->parsedQuery['filters'][$n]['strEqExprs'][$i]['value_dtype']);
+ }
+ }
+ }
+
+ unset($this->parsedQuery['ns']);
+ }
+
+
+// =============================================================================
+// *************************** helper functions ********************************
+// =============================================================================
+
+
+/**
+ * Remove whitespace-tokens from the array $this->tokens
+ *
+ * @access private
+ */
+ function _clearWhiteSpaces() {
+
+ while (current($this->tokens) == ' ' ||
+ current($this->tokens) == "\n" ||
+ current($this->tokens) == "\t" ||
+ current($this->tokens) == "\r")
+
+ unset($this->tokens[key($this->tokens)]);
+ }
+
+
+/**
+ * Check if the query string of the given clause contains an undesired ','.
+ * If a comma was correctly placed then remove it and clear all whitespaces.
+ *
+ * @param string $commaExpected
+ * @param string $clause_error
+ * @throws PHPError
+ * @access private
+ */
+ function _checkComma($commaExpected, $clause_error) {
+
+ $this->_clearWhiteSpaces();
+ if (current($this->tokens) == ',') {
+ if (!$commaExpected)
+ trigger_error($clause_error ."',' - unexpected comma", E_USER_ERROR);
+ else {
+ unset($this->tokens[key($this->tokens)]);
+ $this->_checkComma(FALSE, $clause_error);
+ }
+ }
+ }
+
+
+/**
+ * Check if the given token is either a variable (?var) or the first token of an URI ().
+ * In case of an URI this function returns the whole URI string.
+ *
+ * @param string $token
+ * @return array ['value'] = string
+ * @throws PHPError
+ * @access private
+ */
+ function _validateVarUri($token) {
+
+ if ($token{0} == '?') {
+ $token_res['value'] = $this->_validateVar($token, RDQL_WHR_ERR);
+ } else {
+ $token_res['value'] = $this->_validateUri($token, RDQL_WHR_ERR);
+ if ($token{0} != '<')
+ $token_res['is_qname'] = TRUE;
+ }
+ return $token_res;
+ }
+
+
+/**
+ * Check if the given token is either a variable (?var) or the first token
+ * of either an URI () or a literal ("Literal").
+ * In case of a literal return an array with literal properties (value, language, datatype).
+ * In case of a variable or an URI return only ['value'] = string.
+ *
+ * @param string $token
+ * @return array ['value'] = string
+ * ['is_qname'] = boolean
+ * ['is_literal'] = boolean
+ * ['l_lang'] = string
+ * ['l_dtype'] = string
+ * @throws PHPError
+ * @access private
+ */
+ function _validateVarUriLiteral($token) {
+
+ if ($token{0} == '?')
+ $statement_object['value'] = $this->_validateVar($token, RDQL_WHR_ERR);
+ elseif ($token{0} == "'" || $token{0} == '"')
+ $statement_object = $this->_validateLiteral($token);
+ elseif ($token{0} == '<')
+ $statement_object['value'] = $this->_validateUri($token, RDQL_WHR_ERR);
+ elseif (ereg(':', $token)) {
+ $statement_object['value'] = $this->_validateUri($token, RDQL_WHR_ERR);
+ $statement_object['is_qname'] = TRUE;
+ }else
+ trigger_error(RDQL_WHR_ERR ." '$token' - ?Variable, <URI>, QName, or \"LITERAL\" expected", E_USER_ERROR);
+ return $statement_object;
+ }
+
+
+/**
+ * Check if the given token is a valid variable name (?var).
+ *
+ * @param string $token
+ * @param string $clause_error
+ * @return string
+ * @throws PHPError
+ * @access private
+ */
+ function _validateVar($token, $clause_error) {
+
+ preg_match("/\?[a-zA-Z0-9_]+/", $token, $match);
+ if (!isset($match[0]) || $match[0] != $token)
+ trigger_error($clause_error ."'" .htmlspecialchars($token)
+ ."' - variable name contains illegal characters", E_USER_ERROR);
+ unset($this->tokens[key($this->tokens)]);
+ return $token;
+ }
+
+
+/**
+ * Check if $token is the first token of a valid URI () and return the whole URI string
+ *
+ * @param string $token
+ * @param string $clause_error
+ * @return string
+ * @throws PHPError
+ * @access private
+ */
+ function _validateUri($token, $clause_error) {
+
+ if ($token{0} != '<') {
+ if (strpos($token, ':') && $this->_validateQName($token, $clause_error)) {
+ unset($this->tokens[key($this->tokens)]);
+ return rtrim($token, ':');
+ }
+ $errmsg = $clause_error .'\'' .htmlspecialchars($token) .'\' ';
+ if ($clause_error == RDQL_WHR_ERR)
+ $errmsg .= "- ?Variable or <URI> or QName expected";
+ else
+ $errmsg .= "- <URI> or QName expected";
+ trigger_error($errmsg, E_USER_ERROR);
+ }else{
+ $token_res = $token;
+ while($token{strlen($token)-1} != '>' && $token != NULL) {
+ if ($token == '(' || $token == ')' || $token == ',' ||
+ $token == ' ' || $token == "\n" || $token == "\r") {
+ trigger_error($clause_error .'\'' .htmlspecialchars($token_res)
+ ."' - illegal input: '$token' - '>' missing", E_USER_ERROR);
+ }
+ unset($this->tokens[key($this->tokens)]);
+ $token = current($this->tokens);
+ $token_res .= $token;
+ }
+ if ($token == NULL)
+ trigger_error($clause_error .'\'' .htmlspecialchars($token_res) ."' - '>' missing", E_USER_ERROR);
+ unset($this->tokens[key($this->tokens)]);
+ return trim($token_res, '<>');
+ }
+ }
+
+
+/**
+ * Check if $token is the first token of a valid literal ("LITERAL") and
+ * return an array with literal properties (value, language, datatype).
+ *
+ * @param string $token
+ * @return array ['value'] = string
+ * ['is_literal'] = boolean
+ * ['l_lang'] = string
+ * ['l_dtype'] = string
+ * ['l_dtype_is_qname'] = boolean
+ * @throws PHPError
+ * @access private
+ */
+ function _validateLiteral($token) {
+
+ $quotation_mark = $token{0};
+ $statement_object = array ('value' => '',
+ 'is_literal' => TRUE,
+ 'l_lang' => '',
+ 'l_dtype' => '');
+ $this->tokens[key($this->tokens)] = substr($token,1);
+
+ $return = FALSE;
+ foreach ($this->tokens as $k => $token) {
+
+ if ($token != NULL && $token{strlen($token)-1} == $quotation_mark) {
+ $token = rtrim($token, $quotation_mark);
+ $return = TRUE;
+
+ // parse @language(^^datatype)?
+ }elseif (strpos($token, $quotation_mark .'@') || substr($token, 0, 2) == $quotation_mark .'@') {
+ $lang = substr($token, strpos($token, $quotation_mark .'@')+2);
+ if (strpos($lang, '^^') || substr($lang, 0,2) == '^^') {
+ $dtype = substr($lang, strpos($lang, '^^')+2);
+ if (!$dtype)
+ trigger_error(RDQL_WHR_ERR .$quotation_mark .$statement_object['value']
+ .$token ." - datatype expected" ,E_USER_ERROR);
+
+ $statement_object['l_dtype'] = $this->_validateUri($dtype, RDQL_WHR_ERR);
+ if ($dtype{0} != '<')
+ $statement_object['l_dtype_is_qname'] = TRUE;
+
+ $lang = substr($lang, 0, strpos($lang, '^^'));
+ }
+ if (!$lang)
+ trigger_error(RDQL_WHR_ERR .$quotation_mark .$statement_object['value']
+ .$token ." - language expected" ,E_USER_ERROR);
+ $statement_object['l_lang'] = $lang;
+ $token = substr($token, 0, strpos($token, $quotation_mark .'@'));
+ $return = TRUE;
+
+ // parse ^^datatype
+ }elseif (strpos($token, $quotation_mark .'^^') || substr($token, 0, 3) == $quotation_mark .'^^') {
+ $dtype = substr($token, strpos($token, $quotation_mark .'^^')+3);
+ if (!$dtype)
+ trigger_error(RDQL_WHR_ERR .$quotation_mark .$statement_object['value']
+ .$token ." - datatype expected" ,E_USER_ERROR);
+
+ $statement_object['l_dtype'] = $this->_validateUri($dtype, RDQL_WHR_ERR);
+ if ($dtype{0} != '<')
+ $statement_object['l_dtype_is_qname'] = TRUE;
+
+ $token = substr($token, 0, strpos($token, $quotation_mark .'^^'));
+ $return = TRUE;
+ }elseif (strpos($token, $quotation_mark))
+ trigger_error(RDQL_WHR_ERR ."'$token' - illegal input", E_USER_ERROR);
+ $statement_object['value'] .= $token;
+ unset($this->tokens[$k]);
+ if ($return)
+ return $statement_object;
+ }
+ trigger_error(RDQL_WHR_ERR ."quotation end mark: $quotation_mark missing", E_USER_ERROR);
+ }
+
+
+/**
+ * Check if the given token is a valid QName.
+ *
+ * @param string $token
+ * @param string $clause_error
+ * @return boolean
+ * @throws PHPError
+ * @access private
+ */
+function _validateQName($token, $clause_error) {
+
+ $parts = explode(':', $token);
+ if (count($parts) > 2)
+ trigger_error($clause_error ."illegal QName: '$token'", E_USER_ERROR);
+ if (!$this->_validateNCName($parts[0]))
+ trigger_error($clause_error ."illegal prefix in QName: '$token'", E_USER_ERROR);
+ if ($parts[1] && !$this->_validateNCName($parts[1]))
+ trigger_error($clause_error ."illegal local part in QName: '$token'", E_USER_ERROR);
+
+ return TRUE;
+}
+
+
+/**
+ * Check if the given token is a valid NCName.
+ *
+ * @param string $token
+ * @return boolean
+ * @access private
+ */
+function _validateNCName($token) {
+
+ preg_match("/[a-zA-Z_]+[a-zA-Z_0-9.\-]*/", $token, $match);
+ if (isset($match[0]) && $match[0] == $token)
+ return TRUE;
+ return FALSE;
+}
+
+
+/**
+ * Check if the given token is a valid namespace prefix.
+ *
+ * @param string $token
+ * @return string
+ * @throws PHPError
+ * @access private
+ */
+ function _validatePrefix($token) {
+
+ if (!$this->_validateNCName($token))
+ trigger_error(RDQL_USG_ERR ."'" .htmlspecialchars($token)
+ ."' - illegal input, namespace prefix expected", E_USER_ERROR);
+ unset($this->tokens[key($this->tokens)]);
+ return $token;
+ }
+
+/**
+ * Replace a prefix in a given QName and return a full URI.
+ *
+ * @param string $qName
+ * @param string $clasue_error
+ * @return string
+ * @throws PHPError
+ * @access private
+ */
+ function _replaceNamespacePrefix($qName, $clause_error) {
+
+ $qName_parts = explode(':', $qName);
+ if (!array_key_exists($qName_parts[0], $this->parsedQuery['ns']))
+ trigger_error($clause_error .'undefined prefix: \'' .$qName_parts[0] .'\' in: \'' .$qName .'\'', E_USER_ERROR);
+ return $this->parsedQuery['ns'][$qName_parts[0]] .$qName_parts[1];
+ }
+
+
+/**
+ * Check if all variables from the SELECT clause are defined in the WHERE clause
+ *
+ * @access private
+ */
+ function _checkSelectVars() {
+
+ foreach ($this->parsedQuery['selectVars'] as $var)
+ $this->_isDefined($var);
+ }
+
+
+/**
+ * Check if the given variable is defined in the WHERE clause.
+ *
+ * @param $var string
+ * @return string
+ * @throws PHPError
+ * @access private
+ */
+ function _isDefined($var) {
+
+ $allQueryVars = $this->findAllQueryVariables();
+
+ if (!in_array($var, $allQueryVars))
+ trigger_error(RDQL_SYN_ERR .": '$var' - variable must be defined in the WHERE clause", E_USER_ERROR);
+ return $var;
+ }
+
+
+/**
+ * Throw an error if the regular expression from the AND clause is not quoted.
+ *
+ * @param string $filterString
+ * @param string $lQuotMark
+ * @param string $rQuotMark
+ * @throws PHPError
+ * @access private
+ */
+ function _checkRegExQuotation($filterString, $lQuotMark, $rQuotMark) {
+
+ if (!$lQuotMark)
+ trigger_error(RDQL_AND_ERR ."'$filterString' - regular expressions must be quoted", E_USER_ERROR);
+
+ if ($lQuotMark != $rQuotMark)
+ trigger_error(RDQL_AND_ERR ."'$filterString' - quotation end mark in the regular expression missing", E_USER_ERROR);
+ }
+
+} // end: Class RdqlParser
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/RdqlResultIterator.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/RdqlResultIterator.php
new file mode 100755
index 00000000..8a662e12
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/rdql/RdqlResultIterator.php
@@ -0,0 +1,193 @@
+, Chris Bizer
+ *
+ * @package rdql
+ * @access public
+ *
+ */
+ class RdqlResultIterator extends Object {
+
+ /**
+ * Reference to the Rdql result
+ * @var array RdqlResult
+ * @access private
+ */
+ var $RdqlResult;
+
+ /**
+ * Current position
+ * RdqlResultIterator does not use the build in PHP array iterator,
+ * so you can use serveral iterators on a single Rdql result.
+ * @var integer
+ * @access private
+ */
+ var $position;
+
+
+ /**
+ * Constructor
+ *
+ * @param object RdqlResult
+ * @access public
+ */
+ function RdqlResultIterator(&$RdqlResult) {
+
+ $noResult = TRUE;
+ foreach($RdqlResult[0] as $value)
+ if ($value != NULL) {
+ $noResult = FALSE;
+ break;
+ }
+
+ if($noResult)
+ $this->RdqlResult = NULL;
+ else
+ $this->RdqlResult = $RdqlResult;
+
+ $this->position = -1;
+ }
+
+ /**
+ * Returns the labels of the result as array.
+ * @return array of strings with the result labels OR null if there are no results.
+ * @access public
+ */
+ function getResultLabels() {
+ if(count($this->RdqlResult)>0) {
+ return array_keys($this->RdqlResult[0]);
+ } else return null;
+ }
+
+ /**
+ * Returns the number of results.
+ * @return integer
+ * @access public
+ */
+ function countResults() {
+
+ return count($this->RdqlResult);
+
+ }
+ /**
+ * Returns TRUE if there are more results.
+ * @return boolean
+ * @access public
+ */
+ function hasNext() {
+ if ($this->position < count($this->RdqlResult) - 1 ) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ }
+
+ /**
+ * Returns TRUE if the first result has not been reached.
+ * @return boolean
+ * @access public
+ */
+ function hasPrevious() {
+ if ($this->position > 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ } }
+
+ /**
+ * Returns the next result array.
+ * @param integer $element
+ * @return result array OR single result if $element was specified OR NULL if there is no next result.
+ * @access public
+ */
+ function next($element = null) {
+ if ($this->position < count($this->RdqlResult) - 1) {
+ $this->position++;
+ if ($element) {return $this->RdqlResult[$this->position][$element];}
+ else return $this->RdqlResult[$this->position];
+ } else {
+ return NULL;
+ }
+ }
+
+ /**
+ * Returns the previous result.
+ * @param integer $element
+ * @return result array OR single result if $element was specified OR NULL if there is no next result.
+ * @access public
+ */
+ function previous($element = null) {
+ if ($this->position > 0) {
+ $this->position--;
+ if ($element) {return $this->RdqlResult[$this->position][$element];}
+ else return $this->RdqlResult[$this->position];
+ } else {
+ return NULL;
+ }
+ }
+
+ /**
+ * Returns the current result.
+ * @param integer $element
+ * @return result array OR single result if $element was specified OR NULL if there is no next result.
+ * @access public
+ */
+ function current($element = null) {
+ if (($this->position >= 0) && ($this->position < count($this->RdqlResult))) {
+ if ($element) {return $this->RdqlResult[$this->position][$element];}
+ else return $this->RdqlResult[$this->position];
+ } else {
+ return NULL;
+ }
+ }
+
+ /**
+ * Moves the pointer to the first result.
+ * @return void
+ * @access public
+ */
+ function moveFirst() {
+ $this->position = 0;
+ }
+
+ /**
+ * Moves the pointer to the last result.
+ * @return void
+ * @access public
+ */
+ function moveLast() {
+ $this->position = count($this->RdqlResult) - 1;
+ }
+
+ /**
+ * Moves the pointer to a specific result.
+ * If you set an off-bounds value, next(), previous() and current() will return NULL
+ * @return void
+ * @access public
+ */
+ function moveTo($position) {
+ $this->position = $position;
+ }
+
+ /**
+ * Returns the current position of the iterator.
+ * @return integer
+ * @access public
+ */
+ function getCurrentPosition() {
+ return $this->position;
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/all-wcprops b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/all-wcprops
new file mode 100755
index 00000000..cc5b3f60
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/all-wcprops
@@ -0,0 +1,71 @@
+K 25
+svn:wc:ra_dav:version-url
+V 62
+/svnroot/rdfapi-php/!svn/ver/522/trunk/rdfapi-php/api/resModel
+END
+ResAlt.php
+K 25
+svn:wc:ra_dav:version-url
+V 73
+/svnroot/rdfapi-php/!svn/ver/320/trunk/rdfapi-php/api/resModel/ResAlt.php
+END
+ResModel.php
+K 25
+svn:wc:ra_dav:version-url
+V 75
+/svnroot/rdfapi-php/!svn/ver/562/trunk/rdfapi-php/api/resModel/ResModel.php
+END
+ResModelP.php
+K 25
+svn:wc:ra_dav:version-url
+V 76
+/svnroot/rdfapi-php/!svn/ver/320/trunk/rdfapi-php/api/resModel/ResModelP.php
+END
+ResContainer.php
+K 25
+svn:wc:ra_dav:version-url
+V 79
+/svnroot/rdfapi-php/!svn/ver/320/trunk/rdfapi-php/api/resModel/ResContainer.php
+END
+ResProperty.php
+K 25
+svn:wc:ra_dav:version-url
+V 78
+/svnroot/rdfapi-php/!svn/ver/320/trunk/rdfapi-php/api/resModel/ResProperty.php
+END
+ResResource.php
+K 25
+svn:wc:ra_dav:version-url
+V 78
+/svnroot/rdfapi-php/!svn/ver/320/trunk/rdfapi-php/api/resModel/ResResource.php
+END
+ResSeq.php
+K 25
+svn:wc:ra_dav:version-url
+V 73
+/svnroot/rdfapi-php/!svn/ver/320/trunk/rdfapi-php/api/resModel/ResSeq.php
+END
+ResBag.php
+K 25
+svn:wc:ra_dav:version-url
+V 73
+/svnroot/rdfapi-php/!svn/ver/320/trunk/rdfapi-php/api/resModel/ResBag.php
+END
+ResIterator.php
+K 25
+svn:wc:ra_dav:version-url
+V 78
+/svnroot/rdfapi-php/!svn/ver/522/trunk/rdfapi-php/api/resModel/ResIterator.php
+END
+ResList.php
+K 25
+svn:wc:ra_dav:version-url
+V 74
+/svnroot/rdfapi-php/!svn/ver/320/trunk/rdfapi-php/api/resModel/ResList.php
+END
+ResLiteral.php
+K 25
+svn:wc:ra_dav:version-url
+V 77
+/svnroot/rdfapi-php/!svn/ver/320/trunk/rdfapi-php/api/resModel/ResLiteral.php
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/entries b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/entries
new file mode 100755
index 00000000..41c13a43
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/entries
@@ -0,0 +1,171 @@
+8
+
+dir
+556
+https://rdfapi-php.svn.sourceforge.net/svnroot/rdfapi-php/trunk/rdfapi-php/api/resModel
+https://rdfapi-php.svn.sourceforge.net/svnroot/rdfapi-php
+
+
+
+2007-08-14T09:22:22.680195Z
+522
+cweiske
+
+
+svn:special svn:externals svn:needs-lock
+
+
+
+
+
+
+
+
+
+
+
+b2ee660e-c932-0410-bdee-d8da4d8102f4
+
+ResAlt.php
+file
+
+
+
+
+2008-02-29T14:57:48.787146Z
+e8801d9e4af46f7486692045db0f3caf
+2006-11-21T09:38:51.000000Z
+320
+tgauss
+has-props
+
+ResModel.php
+file
+562
+
+
+
+2008-02-29T15:30:18.380615Z
+6b8ab5cac9f16867ea0a8febd2a735c5
+2008-02-29T15:30:18.223618Z
+562
+cax
+has-props
+
+ResModelP.php
+file
+
+
+
+
+2008-02-29T14:57:48.802766Z
+29b5e81c2303064f2003c4e8655ae527
+2006-11-21T09:38:51.000000Z
+320
+tgauss
+has-props
+
+ResContainer.php
+file
+
+
+
+
+2008-02-29T14:57:48.802766Z
+553a34d72326fefa13710a3736ac5436
+2006-11-21T09:38:51.000000Z
+320
+tgauss
+has-props
+
+ResProperty.php
+file
+
+
+
+
+2008-02-29T14:57:48.818387Z
+46856026754e0f2963d8b7e16851b683
+2006-11-21T09:38:51.000000Z
+320
+tgauss
+has-props
+
+ResResource.php
+file
+
+
+
+
+2008-02-29T14:57:48.818387Z
+8bed519062c9cb629c21521e4261623b
+2006-11-21T09:38:51.000000Z
+320
+tgauss
+has-props
+
+ResSeq.php
+file
+
+
+
+
+2008-02-29T14:57:48.834007Z
+11abc64933d31c26ec1baf469e4eb1a5
+2006-11-21T09:38:51.000000Z
+320
+tgauss
+has-props
+
+ResBag.php
+file
+
+
+
+
+2008-02-29T14:57:48.834007Z
+12a922eb46b8c463b3871348a29bdc51
+2006-11-21T09:38:51.000000Z
+320
+tgauss
+has-props
+
+ResIterator.php
+file
+
+
+
+
+2008-02-29T14:57:48.849628Z
+cc4dfa5b25a4806cf60d40b10cedec7b
+2007-08-14T09:22:22.680195Z
+522
+cweiske
+has-props
+
+ResList.php
+file
+
+
+
+
+2008-02-29T14:57:48.849628Z
+ea5928a8f2ba8bbefb7d38bd4182aa1a
+2006-11-21T09:38:51.000000Z
+320
+tgauss
+has-props
+
+ResLiteral.php
+file
+
+
+
+
+2008-02-29T14:57:48.865249Z
+b0ce56aa73ea6d64d7e87b407bbe3739
+2006-11-21T09:38:51.000000Z
+320
+tgauss
+has-props
+
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/format b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/format
new file mode 100755
index 00000000..45a4fb75
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/format
@@ -0,0 +1 @@
+8
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/prop-base/ResAlt.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/prop-base/ResAlt.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/prop-base/ResAlt.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/prop-base/ResBag.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/prop-base/ResBag.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/prop-base/ResBag.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/prop-base/ResContainer.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/prop-base/ResContainer.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/prop-base/ResContainer.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/prop-base/ResIterator.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/prop-base/ResIterator.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/prop-base/ResIterator.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/prop-base/ResList.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/prop-base/ResList.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/prop-base/ResList.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/prop-base/ResLiteral.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/prop-base/ResLiteral.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/prop-base/ResLiteral.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/prop-base/ResModel.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/prop-base/ResModel.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/prop-base/ResModel.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/prop-base/ResModelP.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/prop-base/ResModelP.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/prop-base/ResModelP.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/prop-base/ResProperty.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/prop-base/ResProperty.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/prop-base/ResProperty.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/prop-base/ResResource.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/prop-base/ResResource.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/prop-base/ResResource.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/prop-base/ResSeq.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/prop-base/ResSeq.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/prop-base/ResSeq.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/text-base/ResAlt.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/text-base/ResAlt.php.svn-base
new file mode 100755
index 00000000..9f6859bd
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/text-base/ResAlt.php.svn-base
@@ -0,0 +1,78 @@
+
+*
+* @package resModel
+* @access public
+**/
+class ResAlt extends ResContainer
+{
+
+ /**
+ * Constructor
+ * You can supply a URI
+ *
+ * @param string $uri
+ * @access public
+ */
+ function ResAlt($uri = null)
+ {
+ parent::ResContainer($uri);
+ $this->containerType=new ResResource(RDF_NAMESPACE_URI.RDF_ALT);
+ }
+
+ /**
+ * Return the default value for this resource
+ *
+ * @return object ResResource/ResLiteral
+ * @access public
+ */
+ function getDefault()
+ {
+ //get the first memeber
+ $statements=$this->listProperties($this->_getMembershipPropertyWithIndex(1));
+ if(isset($statements[0]))
+ {
+ //return the value
+ return $statements[0]->getObject();
+ } else
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Set the default value of this container.
+ *
+ * @param object ResResource/ResLiteral $object
+ * @access public
+ */
+ function setDefault($object)
+ {
+ //remember the old default value
+ $oldDefaultObject=$this->getDefault();
+ //if there wasn't a default value before
+ if($oldDefaultObject === null)
+ {
+ //add the new value
+ $this->addProperty($this->_getMembershipPropertyWithIndex(1),$object);
+ } else
+ {
+ //remove the old value
+ $this->removeAll($this->_getMembershipPropertyWithIndex(1));
+ //set the new value
+ $this->addProperty($this->_getMembershipPropertyWithIndex(1),$object);
+ //add the old default value at the end
+ $this->add($oldDefaultObject);
+ }
+ }
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/text-base/ResBag.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/text-base/ResBag.php.svn-base
new file mode 100755
index 00000000..563d2e2c
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/text-base/ResBag.php.svn-base
@@ -0,0 +1,32 @@
+
+*
+* @package resModel
+* @access public
+**/
+class ResBag extends ResContainer
+{
+
+ /**
+ * Constructor
+ * You can supply a URI
+ *
+ * @param string $uri
+ * @access public
+ */
+ function ResBag($uri = null)
+ {
+ parent::ResContainer($uri);
+ $this->containerType=new ResResource(RDF_NAMESPACE_URI.RDF_BAG);
+ }
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/text-base/ResContainer.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/text-base/ResContainer.php.svn-base
new file mode 100755
index 00000000..e46f41f0
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/text-base/ResContainer.php.svn-base
@@ -0,0 +1,219 @@
+
+*
+* @package resModel
+* @access public
+**/
+
+class ResContainer extends ResResource
+{
+ /**
+ * Holds a ResResource of this container type rdf:Seq, rdf:Alt, or rdf:Bag
+ * @var ResResource
+ * @access private
+ */
+ var $containerType;
+
+
+ /**
+ * Constructor
+ * You can supply a URI
+ *
+ * @param string $uri
+ * @access public
+ */
+ function ResContainer($uri = null)
+ {
+ parent::ResResource($uri);
+ }
+
+ /**
+ * Add a new value to a container.
+ * The new value is added as the last element of the container.
+ *
+ * @param object ResResource/ResLiteral $object
+ * @access public
+ */
+ function add($object)
+ {
+ //type this container, if it isn't already typed
+ if(!$this->hasProperty(new ResResource(RDF_NAMESPACE_URI.RDF_TYPE)))
+ $this->addProperty(new ResResource(RDF_NAMESPACE_URI.RDF_TYPE),$this->containerType);
+ //get the current size
+ $actualSize=$this->size();
+ //add the object to the last position
+ $this->addProperty(new ResResource(RDF_NAMESPACE_URI.'_'.($actualSize+1)),$object);
+ }
+
+ /**
+ * Determine whether the container contains a value
+ *
+ * @param obejct ResResource/ResLiteral $resResource
+ * @return boolean
+ * @access public
+ */
+ function contains($resResource)
+ {
+ //get all container's properties
+ foreach ($this->listProperties() as $statement)
+ {
+ //if the property matches a container membership property
+ if ($this->_predicateLabelMatchesMembershipProperty($statement->getLabelPredicate()))
+ {
+ //check, if it's the value, we're looking for.
+ if ($resResource->equals($statement->getObject()))
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns true, if this resource is a container from type rdf:Alt
+ *
+ * @return boolean
+ * @access public
+ */
+ function isAlt()
+ {
+ return ($this->containerType->getURI()==RDF_NAMESPACE_URI.RDF_ALT);
+ }
+
+ /**
+ * Returns true, if this resource is a container from type rdf:Bag
+ *
+ * @return boolean
+ * @access public
+ */
+ function isBag()
+ {
+ return ($this->containerType->getURI()==RDF_NAMESPACE_URI.RDF_BAG);
+ }
+
+ /**
+ * Returns true, if this resource is a container from type rdf:Seq
+ *
+ * @return boolean
+ * @access public
+ */
+ function isSeq()
+ {
+ return ($this->containerType->getURI()==RDF_NAMESPACE_URI.RDF_SEQ);
+ }
+
+ /**
+ * Get an array of all resources that are values of this container
+ *
+ * @return array
+ * @access public
+ */
+ function getMembers()
+ {
+ $return=array();
+ foreach ($this->listProperties() as $statement)
+ {
+ $predicateLabel=$statement->getLabelPredicate();
+ if ($this->_predicateLabelMatchesMembershipProperty($predicateLabel))
+ {
+ $return[$this->_getMemberIndexNrFromMembershipPropertyLabel($predicateLabel)] = $statement->getObject();
+ }
+ }
+ return $return;
+ }
+
+ /**
+ * Remove a value from the container.
+ *
+ * Once removed, the values in the container with a higher ordinal value are renumbered.
+ * The renumbering algorithm depends on the type of container.
+ *
+ * @param obejct ResResource/ResLiteral $resResource
+ * @access public
+ */
+ function remove($object)
+ {
+ $deleteFromIndex=array();
+ //get all container members
+ $memberIndex=$this->getMembers();
+
+ //check each container member if it equals the resoure to be removed
+ foreach ($memberIndex as $key => $value)
+ {
+ //save the statements positio in the container
+ if($object->equals($value))
+ $deleteFromIndex[]=$key;
+ }
+
+ //delete all found container members
+ foreach ($deleteFromIndex as $index)
+ {
+ $this->removeAll($this->_getMembershipPropertyWithIndex($index));
+
+ //renumber all members with higher ordinal numbers than the deleted one
+ for ($i = $index;$i < count($memberIndex); $i++)
+ {
+ $this->removeAll($this->_getMembershipPropertyWithIndex($i+1));
+ $this->addProperty($this->_getMembershipPropertyWithIndex($i),$memberIndex[$i+1]);
+ }
+ }
+
+ }
+
+ /**
+ * Returns the number values in the container.
+ *
+ * @return integer
+ * @access public
+ */
+ function size()
+ {
+ return count($this->getMembers());
+ }
+
+ /**
+ * Checks, if a predicate label fits a container membership property rdf:_n
+ *
+ * @param string $predicateLabel
+ * @return boolean
+ * @access private
+ */
+ function _predicateLabelMatchesMembershipProperty($predicateLabel)
+ {
+ return substr($predicateLabel,0,strlen(RDF_NAMESPACE_URI.'_')) == RDF_NAMESPACE_URI.'_';
+ }
+
+ /**
+ * Get the ordinal number from a membership property rdf:_n
+ *
+ * @param string $predicateLabel
+ * @return integer
+ * @access private
+ */
+ function _getMemberIndexNrFromMembershipPropertyLabel($predicateLabel)
+ {
+ return (int)substr($predicateLabel,strlen(RDF_NAMESPACE_URI.'_'));
+ }
+
+ /**
+ * Get a membership property rdf:_n with index $int
+ *
+ * @param intger $int
+ * @return string
+ * @access private
+ */
+ function _getMembershipPropertyWithIndex($int)
+ {
+ return new ResResource(RDF_NAMESPACE_URI.'_'.$int);
+ }
+}
+?>
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/text-base/ResIterator.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/text-base/ResIterator.php.svn-base
new file mode 100755
index 00000000..b43bf2cd
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/text-base/ResIterator.php.svn-base
@@ -0,0 +1,298 @@
+listInstances();
+* for ($it->rewind(); $it->valid(); $it->next())
+* {
+* $currentResource=$it->current();
+* };
+*
+*
+* @version $Id$
+* @author Daniel Westphal
+*
+*
+* @package resModel
+* @access public
+**/
+class ResIterator
+{
+ /**
+ * Holds a reference to the assoiated ResModel / OntModel
+ * @var object Model
+ * @access private
+ */
+ var $associatedModel;
+
+ /**
+ * The current position
+ * @var integer
+ * @access private
+ */
+ var $key;
+
+ /**
+ * If the current resource is valid
+ * @var boolean
+ * @access private
+ */
+ var $valid;
+
+ /**
+ * The current resource
+ * @var obejct ResResource
+ * @access private
+ */
+ var $currentResource;
+
+ /**
+ * The subject to search for.
+ * @var object ResResource
+ * @access private
+ */
+ var $searchSubject;
+
+ /**
+ * The predicate to search for.
+ * @var object ResResource
+ * @access private
+ */
+ var $searchPredicate;
+
+ /**
+ * The object to search for.
+ * @var object ResResource
+ * @access private
+ */
+ var $searchObject;
+
+ /**
+ * If the resource, we're intrested in is the subject (s), predicate(p),
+ * or object (o) of the found statements
+ *
+ * @var string
+ * @access private
+ */
+ var $getSPO;
+
+ /**
+ * Defines the type of resource, we'd like to receive.
+ *
+ * @var string
+ * @access private
+ */
+ var $returnType;
+
+ /**
+ * If set, each resource will first be checked, if it's
+ * language fits.
+ *
+ * @var string
+ * @access private
+ */
+ var $findLiteralWithLang;
+
+
+ /**
+ * Constructor.
+ *
+ * $subject, $predicate, and $object are used like inf find().
+ * $getSPO supports the strings 's', 'p', and 'o' to return
+ * either the subject, predicate, or object of the result statements.
+ * $returnType supports the strings 'ResProperty', 'ResLiteral',
+ * 'OntProperty', 'OntClass', and 'Individual' and returns the resources
+ * as the matching type.
+ *
+ * @param object ResResource $subject
+ * @param object ResResource $predicate
+ * @param object ResResource $object
+ * @param string $getSPO
+ * @param object ResModel $associatedModel
+ * @param string $returnType
+ * @access public
+ */
+ function ResIterator($subject,$predicate,$object,$getSPO,& $associatedModel,$returnType = false)
+ {
+ $this->searchSubject =& $subject;
+ $this->searchPredicate =& $predicate;
+ $this->searchObject =& $object;
+ $this->getSPO = $getSPO;
+ $this->returnType = $returnType;
+ $this->associatedModel =& $associatedModel;
+ $this->findLiteralWithLang = false;
+ }
+
+ /**
+ * Resets iterator list to start
+ *
+ * @access public
+ */
+ function rewind()
+ {
+ $this->key = -1;
+ $this->next();
+ }
+
+ /**
+ * Says if there are additional items left in the list
+ *
+ * @return boolean
+ * @access public
+ */
+ function valid()
+ {
+ return $this->valid;
+ }
+
+ /**
+ * Moves Iterator to the next item in the list
+ *
+ * @access public
+ */
+ function next()
+ {
+ $this->key++;
+ $this->valid=($this->_getNextResource());
+ }
+
+ /**
+ * Returns the current item
+ *
+ * @return mixed
+ * @access public
+ */
+ function current()
+ {
+ return $this->currentResource;
+ }
+
+ /**
+ * Returns the next Resource (subject, predicate,
+ * or object of the next matching statement).
+ *
+ * @return object resResource
+ * @access private
+ */
+ function _getNextResource()
+ {
+ if ($this->findLiteralWithLang)
+ {
+ do
+ {
+ $nextStatement = $this->associatedModel->findFirstMatchingStatement($this->searchSubject,$this->searchPredicate,$this->searchObject,$this->key);
+ if ($nextStatement === null)
+ return false;
+
+ $object = $nextStatement->getObject();
+ if ($object->getLanguage() != $this->findLiteralWithLang)
+ {
+ $hasCorrectLanguage=false;
+ $this->key++;
+ } else
+ {
+ $hasCorrectLanguage=true;
+ }
+
+ } while (!$hasCorrectLanguage);
+ } else
+ {
+ $nextStatement = $this->associatedModel->findFirstMatchingStatement($this->searchSubject,$this->searchPredicate,$this->searchObject,$this->key);
+ }
+ if ($nextStatement === null)
+ return false;
+
+ switch ($this->getSPO)
+ {
+ case 's':
+ $this->currentResource = $this->_getResourceAs($nextStatement->getSubject());
+ break;
+
+ case 'p':
+ $this->currentResource = $this->_getResourceAs($nextStatement->getPredicate());
+ break;
+
+ case 'o':
+ $this->currentResource = $this->_getResourceAs($nextStatement->getObject());
+ break;
+ }
+ return (true);
+ }
+
+ /**
+ * Returns the key of the current item
+ *
+ * @return integer
+ * @access public
+ */
+ function key()
+ {
+ return $this->key;
+ }
+
+ /**
+ * Sets that only Literals with the matching
+ * language should be returned
+ *
+ * @param string
+ * @access public
+ */
+ function setFindLiteralWithLang($language)
+ {
+ $this->findLiteralWithLang = $language;
+ }
+
+ /**
+ * Returns the $resource as an instance of the type
+ * specified in $this->returnType.
+ *
+ * @param object ResResource
+ * @return object ResResource
+ * @access private
+ */
+ function _getResourceAs($resource)
+ {
+ if ($this->findLiteralWithLang && $resource->getLanguage() != $this->findLiteralWithLang)
+ $this->_getNextResource();
+
+ if($this->returnType)
+ switch ($this->returnType) {
+
+ case 'ResProperty':
+ return $this->associatedModel->createProperty($resource->getLabel());
+ break;
+
+ case 'ResLiteral':
+ $newLiteral = $this->associatedModel->createLiteral($resource->getLabel(),$resource->getLanguage());
+ $newLiteral->setDatatype($resource->getDatatype());
+ return $newLiteral;
+ break;
+
+ case 'OntProperty':
+
+ return $this->associatedModel->createOntProperty($resource->getLabel());
+ break;
+
+ case 'OntClass':
+ return $this->associatedModel->createOntClass($resource->getLabel());
+ break;
+
+ case 'Individual':
+ return $this->associatedModel->createIndividual($resource->getLabel());
+ break;
+ }
+ return $resource;
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/text-base/ResList.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/text-base/ResList.php.svn-base
new file mode 100755
index 00000000..3265470a
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/text-base/ResList.php.svn-base
@@ -0,0 +1,635 @@
+
+
+*
+* @package resModel
+* @access public
+*/
+class ResList extends ResResource
+{
+ /**
+ * Holds a ResResource with the uri rdf:rest
+ * @var ResResource
+ * @access private
+ */
+ var $rdfRestResource;
+
+ /**
+ * Holds a ResResource with the uri rdf:first
+ * @var ResResource
+ * @access private
+ */
+ var $rdfFirstResource;
+
+ /**
+ * Holds a ResResource with the uri rdf:nil
+ * @var ResResource
+ * @access private
+ */
+ var $rdfNilResource;
+
+
+ /**
+ * Constructor
+ * You can supply a URI
+ *
+ * @param string $uri
+ * @access public
+ */
+ function ResList($uri = null)
+ {
+ //call the parent's constructor
+ parent::ResResource($uri);
+ //initialize vars
+ $this->rdfRestResource = new ResResource(RDF_NAMESPACE_URI.RDF_REST);
+ $this->rdfFirstResource = new ResResource(RDF_NAMESPACE_URI.RDF_FIRST);
+ $this->rdfNilResource = new ResResource(RDF_NAMESPACE_URI.RDF_NIL);
+ }
+
+ /**
+ * Returns the value of the list element at the specified position or null.
+ *
+ * @param integer $position
+ * @return ResResource
+ * @access public
+ */
+ function get($position)
+ {
+ //init
+ $listElement=$this;
+ //walk through the list until the position in the list is reached
+ for ($i=0;$i<$position;$i++)
+ {
+ $listElement=$this->_getRestElement($listElement);
+ if($listElement===null)
+ return null;
+ }
+ //return the associated value
+ return $this->_getValue($listElement);
+ }
+
+ /**
+ * Add the given value to the end of the list.
+ * it is only defined if this is not the empty list.
+ *
+ * @param object ResResource $resource
+ * @return boolean
+ * @access public
+ */
+ function add($resource)
+ {
+ //return false if this list is the empty list
+ if($this->uri==RDF_NAMESPACE_URI.RDF_NIL)
+ return false;
+
+ //if this is the first value
+ if ($this->isEmpty())
+ {
+ $newLastElement =& $this;
+ } else
+ //if there are other values in the list
+ {
+ //get the last list element
+ $lastElement=$this->_getListElement();
+ //remove the rdf:rest property
+ $lastElement->removeAll($this->rdfRestResource);
+ //create a new list element
+ $newLastElement=$this->model->createResource();
+ //concatenate the new list element with the list
+ $lastElement->addProperty($this->rdfRestResource,$newLastElement);
+ }
+ //add the value
+ $newLastElement->addProperty($this->rdfFirstResource,$resource);
+ //ad the rdf:nil property to the last list element
+ $newLastElement->addProperty($this->rdfRestResource,$this->rdfNilResource);
+
+ return true;
+ }
+
+ /**
+ * Update the head of the list to have the given value,
+ * and return the previous value.
+ *
+ * @param object ResResource $value
+ * @return ResResource
+ * @access public
+ */
+ //todo: error handling, when empty list
+ function setHead($value)
+ {
+ //save the old value
+ $oldValue=$this->getHead();
+ //remove the old value
+ $this->removeAll($this->rdfFirstResource);
+ //add the new value
+ $this->addProperty($this->rdfFirstResource,$value);
+
+ //return the old value
+ return $oldValue;
+ }
+
+ /**
+ * Get the value that is associated with the head of the list.
+ *
+ * @return ResResource
+ * @access public
+ */
+ //todo: error handling, falls empty list
+ function getHead()
+ {
+ return $this->_getValue($this);
+ }
+
+ /**
+ * Remove the head of the list. The tail of the list
+ * remains in the model. Note that no changes are made to
+ * list cells that point to this list cell as their tail.
+ *
+ * @return ResList
+ * @access public
+ */
+ function removeHead()
+ {
+ //get the second list element
+ $rest=$this->_getRestElement($this);
+ //remove the first element
+ $this->removeAll($this->rdfFirstResource);
+ $this->removeAll($this->rdfRestResource);
+ //change this Resource URI to that of the second list element
+ //thus makin it the fist element
+ $this->uri=$rest->getURI();
+
+ //return the new list
+ return $this;
+ }
+
+ /**
+ * Get the Position of the first occurrence of the given value in the list,
+ * or -1 if the value is not in the list.
+ * You can supply an offset to search for values. (First element has offset 0)
+ * Default is 0
+ *
+ * @param object ResResource $resource
+ * @param integer $offset
+ * @return integer
+ * @access public
+ */
+ function indexOf($resource, $offset = 0)
+ {
+ //init
+ $element=$this;
+ $actualIndex=0;
+
+ //walk through the list until the value is found and the position is higher than
+ //the offset
+ while ($actualIndex < $offset || !$resource->equals($this->_getValue($element)))
+ {
+ //get next list element
+ $element=$this->_getRestElement($element);
+ $actualIndex++;
+
+ //if the end of the list is reached and the value isn't found
+ if ($element===null)
+ return null;
+ }
+ //return the index value
+ return $actualIndex;
+ }
+
+ /**
+ * Replace the value at the i'th position in the list with the given value
+ *
+ * @param integer $index
+ * @param object ResResource $resource
+ * @return object ResResource
+ * @access public
+ */
+ function replace($index, $resource)
+ {
+ //get the list element at the $index position
+ $listElement=$this->_getListElement($index);
+ //get the old value
+ $oldValue=$this->_getValue($listElement);
+ //remove the old value
+ $listElement->removeAll($this->rdfFirstResource);
+ //add the new value
+ $listElement->addProperty($this->rdfFirstResource,$resource);
+ //return the old value
+ return $oldValue;
+ }
+
+ /**
+ * Answer true if the given node appears as the value of a value
+ * of any of the cells of this list.
+ *
+ * @param object ResResource $value
+ * @return boolean
+ * @access public
+ */
+ function contains($value)
+ {
+ //return true, if a position was found.
+ $result=$this->indexOf($value);
+ return ($result!==null);
+ }
+
+ /**
+ * Get the list that is the tail of this list.
+ *
+ * @return object ResList
+ * @access public
+ */
+ function getTail()
+ {
+ //get the second list element
+ $nextListElement= $this->_getRestElement($this);
+ //return the second element as new list
+ return $this->model->createList($nextListElement->getURI());
+ }
+
+ /**
+ * Remove all of the components of this list from the model.
+ * Note that this is operation is only removing the list cells
+ * themselves, not the resources referenced by the list -
+ * unless being the object of an rdf:first statement is the
+ * only mention of that resource in the model.
+ *
+ * @return boolean
+ * @access public
+ */
+ function removeList()
+ {
+ $element=$this;
+
+ while ($element!==null)
+ {
+ $nextElement=$this->_getRestElement($element);
+
+ $element->removeAll($this->rdfFirstResource);
+ $element->removeAll($this->rdfRestResource);
+
+ if (($nextElement !== null) && ($nextElement->getURI()!==RDF_NAMESPACE_URI.RDF_NIL))
+ {
+ $element=$nextElement;
+ } else
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns true, if this list is empty
+ *
+ * @param object Statement $statement
+ * @return integer
+ * @access public
+ */
+ function isEmpty()
+ {
+ return !$this->hasProperty($this->rdfFirstResource);
+ }
+
+ /**
+ * Get all values in the list as an array of ResResources
+ *
+ * @return array
+ * @access public
+ */
+ function getContentInArray()
+ {
+ $result=array();
+ $element=$this;
+
+ while ($element!==null)
+ {
+ //add the value of the current element to the result if is set.
+ $value=$this->_getValue($element);
+ if ($value!==null)
+ $result[]=$value;
+
+ //walk through the list until it's end
+ $nextElement=$this->_getRestElement($element);
+ if (($nextElement !== null) && ($nextElement->getURI()!==RDF_NAMESPACE_URI.RDF_NIL))
+ {
+ $element=$nextElement;
+ } else
+ {
+ break;
+ }
+ }
+ //return the result
+ return $result;
+ }
+
+ /**
+ * Change the tail of this list to point to the given list, so that this list
+ * becomes the list of the concatenation of the elements of
+ * both lists. This is a side-effecting operation on this list;
+ * for a non side-effecting alternative, see append.
+ *
+ *
+ * @param object ResList $ResList
+ * @access public
+ */
+ function concatenate($ResList)
+ {
+ //get the last list element
+ $lastElement=$this->_getListElement();
+ //remove the old tail (rdf:nil)
+ $lastElement->removeAll($this->rdfRestResource);
+ //add the $ResList as new tail
+ $lastElement->addProperty($this->rdfRestResource,$ResList);
+ }
+
+ /**
+ * Answer a new list that is formed by adding each element of
+ * this list to the head of the given list. This is a non
+ * side-effecting operation on either this list or the given
+ * list, but generates a copy of this list. For a more storage
+ * efficient alternative, see concatenate
+ *
+ * @param object ResList $ResList
+ * @return object ResList
+ * @access public
+ */
+ function append($resList)
+ {
+ //get a copy of this list
+ $newList=$this->copy();
+
+ //add all values from the $resList to the new list
+ foreach ($resList->getContentInArray() as $value)
+ {
+ $newList->add($value);
+ }
+ //return the new list
+ return $newList;
+ }
+
+ /**
+ * Answer a list that contains all of the elements of this
+ * list in the same order, but is a duplicate copy in the
+ * underlying model.
+ *
+ * @return object ResList
+ * @access public
+ */
+ function copy()
+ {
+ //create a new list in the model
+ $newList=$this->model->createList();
+ //add all values from this list to the new list
+ foreach ($this->getContentInArray() as $value)
+ {
+ $newList->add($value);
+ }
+ //return the new list
+ return $newList;
+ }
+
+ /**
+ * Return a reference to a new list cell whose head is value
+ * and whose tail is this list.
+ *
+ * @param object ResResource $value
+ * @return object ResList
+ * @access public
+ */
+ function cons($value)
+ {
+ //create a new list
+ $newList=$this->model->createList();
+ //add the new value
+ $newList->add($value);
+ //set this list as the tail of the new list
+ $newList->setTail($this);
+
+ //return the new list
+ return $newList;
+ }
+
+ /**
+ * Update the list cell at the front of the list to have the
+ * given list as tail. The old tail is returned, and remains
+ * in the model.
+ *
+ * @param object ResList $resList
+ * @return object Reslist
+ * @access public
+ */
+ function setTail($resList)
+ {
+ //save the old tail
+ $oldTail=$this->getTail();
+ //remove the old tail
+ $this->removeAll($this->rdfRestResource);
+ //add the $resList as new Tail
+ $this->addProperty($this->rdfRestResource,$resList);
+
+ //return the old tail
+ return $oldTail;
+ }
+
+ /**
+ * Answer true if this list has the same elements in the
+ * same order as the given list. Note that the standard equals
+ * test just tests for equality of two given list cells.
+ * While such a test is sufficient for many purposes, this
+ * test provides a broader equality definition, but is
+ * correspondingly more expensive to test.
+ *
+ * @param object ResList $resList
+ * @return boolean
+ * @access public
+ */
+ function sameListAs($resList)
+ {
+ //init
+ $indexPos=0;
+ do
+ {
+ //get the values for both lists at the actual position
+ $thisValue=$this->get($indexPos);
+ $thatValue=$resList->get($indexPos);
+ //if the values aren't equal, return false
+ if (($thisValue !== null) && !$thisValue->equals($thatValue))
+ return false;
+
+ $indexPos++;
+ //walk until this list reaches a null value (end)
+ } while ($thisValue!==null);
+
+ //if the other list has a null value at this position too, return true
+ //else return false
+ return ($thatValue===null);
+ }
+
+ /**
+ * Remove the given value from this list.
+ * If value does not occur in the list, no action is taken. Since removing the
+ * head of the list will invalidate the list head cell, in
+ * general the list must return the list that results from
+ * this operation. However, in many cases the return value
+ * will be the same as the object that this method is invoked
+ * on.
+ *
+ * @param object ResResource $value
+ * @return object ResList
+ * @access public
+ */
+ function remove($value)
+ {
+ //if the value is the value of the first list element(head)
+ //call the remove head position and return the new head
+ if ($value->equals($this->_getValue($this)))
+ return $this->removeHead();
+
+ $element=$this;
+ do
+ {
+ $newElement=$this->_getRestElement($element);
+
+ //if the value equals the value of the current list element
+ if ($newElement !== null && $value->equals($this->_getValue($newElement)))
+ {
+ //remove the link to the list element to be removed
+ $element->removeAll($this->rdfRestResource);
+ //add a link to the list element AFTER the element to be deleted
+ $element->addProperty($this->rdfRestResource,$this->_getRestElement($newElement));
+ //remove the list element with values
+ $newElement->removeAll($this->rdfFirstResource);
+ $newElement->removeAll($this->rdfRestResource);
+ //return this ResList
+ return $this;
+ }
+ $element=$newElement;
+ } while ($element!==null);
+ //return this list
+ return $this;
+ }
+
+ /**
+ * Answer true if the list is well-formed, by checking that each
+ * node is correctly typed, and has a head and tail pointer from
+ * the correct vocabulary
+ *
+ * @return boolean
+ * @access public
+ */
+ function isValid()
+ {
+ $element=$this;
+ if ($this->_getValue($this)=== null && $this->_getRestElement($this) === null)
+ return true;
+ do
+ {
+ //return true if the last element is a rdf:nil
+ if ($element->getURI() == RDF_NAMESPACE_URI.RDF_NIL)
+ return true;
+ //return false, if the current element has no associated value
+ if ($this->_getValue($element) === null)
+ return false;
+
+ $element=$this->_getRestElement($element);
+ } while ($element !== null);
+ //return false, if the current element has no rdf:rest property
+ return false;
+ }
+
+ /**
+ * Get the associated rdf:rest Resource from the suplied ResList element
+ *
+ * @param object ResList $listElement
+ * @return object ResList
+ * @access private
+ */
+ function _getRestElement($listElement)
+ {
+ //get the rdf:rest property
+ $statement= $this->model->getProperty($listElement,$this->rdfRestResource);
+ //return null, if this property isn't set
+ if ($statement === null)
+ return null;
+
+ //return the value of the rdf:rest property
+ return $statement->getObject();
+ }
+
+ /**
+ * Returns the list element at the $index position.
+ *
+ * If to $index is suplied, the last list element will be returned
+
+ * @param integer $index
+ * @return object ResResource
+ * @access private
+ */
+ function _getListElement($index = null)
+ {
+ $element=$this;
+ $actualIndex=0;
+
+ while ($element!=null)
+ {
+ //return the current element if index matches the current index
+ if ($actualIndex === $index)
+ return $element;
+
+ //return the current element if it the last one
+ if ($element->hasProperty($this->rdfRestResource,$this->rdfNilResource))
+ return $element;
+
+ $nextElement=$this->_getRestElement($element);
+
+ if ($nextElement!==null)
+ {
+ $element=$nextElement;
+ $actualIndex++;
+ } else
+ {
+ break;
+ }
+ }
+ return $element;
+ }
+
+ /**
+ * Get the value associated to the $listResource by the rdf:first property
+ *
+ * @param object ResList $listResource
+ * @return object ResResource
+ * @access private
+ */
+ function _getValue($listResource)
+ {
+ //Return the value of the rdf:first property or null, if it isn't set
+ $statement=$this->model->getProperty($listResource,$this->rdfFirstResource);
+ if ($statement===null)
+ return null;
+
+ return $statement->getObject();
+ }
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/text-base/ResLiteral.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/text-base/ResLiteral.php.svn-base
new file mode 100755
index 00000000..5e1c2a30
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/text-base/ResLiteral.php.svn-base
@@ -0,0 +1,65 @@
+
+
+*
+* @package resModel
+* @access public
+**/
+
+class ResLiteral extends Literal
+{
+ /**
+ * Holds a reference to the associated model
+ * @var ResModel
+ * @access private
+ */
+ var $model;
+
+
+ /**
+ * Constructor
+ * You have to supply a string.
+ *
+ * @param string $str label of the literal
+ * @param string $language optional language identifier
+ */
+ function ResLiteral($str,$language = null)
+ {
+ parent::Literal($str,$language);
+
+ }
+
+ /**
+ * Sets the reference to the assocoated model.
+ *
+ * @param object model $model
+ * @access public
+ */
+ function setAssociatedModel(& $model)
+ {
+ $this->model=& $model;
+ }
+
+ /**
+ * Get the reference to the assocoated model.
+ *
+ * @return object model $model
+ * @access public
+ */
+ function & getAssociatedModel()
+ {
+ return $this->model;
+ }
+
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/text-base/ResModel.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/text-base/ResModel.php.svn-base
new file mode 100755
index 00000000..20db06cc
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/text-base/ResModel.php.svn-base
@@ -0,0 +1,876 @@
+
+*
+*
+* @package resModel
+* @access public
+**/
+
+class ResModel
+{
+
+ /**
+ * Holds a reference to the assoiated memmodel/dbmodel/infmodel
+ * @var ResResource
+ * @access private
+ */
+ var $model;
+
+
+ /**
+ * Constructor
+ * You have to supply a memmodel/dbmodel/infmodel to save the statements.
+ *
+ * @param object model $model
+ * @access public
+ */
+ function ResModel(& $model)
+ {
+ if (!is_a($model,'Model'))
+ trigger_error(RDFAPI_ERROR . '(class: ResourceLayer; method: ResourceLayer):
+ $model has to be object of class Model', E_USER_ERROR);
+
+ $this->model =& $model;
+ }
+
+ /**
+ * Create a new resource associated with this model.
+ * If the uri string isn't set, this creates a bnode.
+ * Otherwise it creates a URI node.
+ * A URI resource is .equals() to any other URI Resource with the same URI
+ * (even in a different model - be warned).
+ *
+ * This method may return an existing Resource with the correct URI and model,
+ * or it may construct a fresh one, as it sees fit.
+ *
+ * Operations on the result Resource may change this model.
+ *
+ * @param string $uri
+ * @return object ResResource
+ * @access public
+ */
+ function createResource($uri = null)
+ {
+ $resResource = new ResResource($uri);
+ //associate the resource with this model, and get a unique identifier
+ //if it is bnode.
+ $resResource->setAssociatedModel($this);
+
+ return $resResource;
+ }
+
+ /**
+ * Create a new Property associated with this model.
+ * This method may return an existing property with the correct URI and model,
+ * or it may construct a fresh one, as it sees fit.
+ *
+ * Subsequent operations on the returned property may modify this model.
+ *
+ *
+ * @param string $uri
+ * @return object ResProperty
+ * @access public
+ */
+ function createProperty($uri = null)
+ {
+ $resProperty = new ResProperty($uri);
+ $resProperty->setAssociatedModel($this);
+
+ return $resProperty;
+ }
+
+ /**
+ * Create an untyped literal from a String value with a specified language.
+ *
+ * If you want to type this literal, you have to set a datatype before
+ * adding it to the model.
+ *
+ *
+ * @param string $label
+ * @param string $languageTag
+ * @return object ResLiteral
+ * @access public
+ */
+ function createLiteral($label,$languageTag = null)
+ {
+ $resLiteral = new ResLiteral($label,$languageTag);
+ $resLiteral->setAssociatedModel($this);
+
+ return $resLiteral;
+ }
+
+ /**
+ * General method to search for triples.
+ * NULL input for any parameter will match anything.
+ * Example: $result = $m->find( NULL, NULL, $node );
+ * Finds all Statements with $node as object.
+ * Returns an array of statements with ResResources.
+ *
+ * @param object ResResource $subject
+ * @param object ResResource $predicate
+ * @param object ResResource $object
+ * @return array
+ * @access public
+ * @throws PhpError
+ */
+ function find($subject,$predicate, $object)
+ {
+ $result=array();
+ //convert ResResources to Resources and Blanknodes
+ $resmodel=$this->model->find( $this->_resNode2Node($subject),
+ $this->_resNode2Node($predicate),
+ $this->_resNode2Node($object)
+ );
+ //convert Resources, Blanknodes to ResResources
+ foreach ($resmodel->triples as $statement)
+ {
+ $result[]=new Statement($this->_node2ResNode($statement->getSubject()),
+ $this->_node2ResNode($statement->getPredicate(),true),
+ $this->_node2ResNode($statement->getObject())
+ );
+ };
+ return $result;
+
+ }
+
+ /**
+ * Searches for triples and returns the first matching statement.
+ * NULL input for any parameter will match anything.
+ * Example: $result = $m->findFirstMatchingStatement( NULL, NULL, $node );
+ * Returns the first statement with ResResources of the Model where the object equals $node.
+ * Returns an NULL if nothing is found.
+ * You can define an offset to search.
+ *
+ * @param object Node $subject
+ * @param object Node $predicate
+ * @param object Node $object
+ * @param integer $offset
+ * @return object Statement
+ * @access public
+ */
+ function findFirstMatchingStatement($subject,$predicate,$object,$offset = 0)
+ {
+
+ $statement = $this->model->findFirstMatchingStatement( $this->_resNode2Node($subject),
+ $this->_resNode2Node($predicate),
+ $this->_resNode2Node($object),
+ $offset
+ );
+ if ($statement!==null)
+ {
+ return new Statement( $this->_node2ResNode($statement->getSubject()),
+ $this->_node2ResNode($statement->getPredicate(),true),
+ $this->_node2ResNode($statement->getObject())
+ );
+ } else
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Adds a new triple to the Model without checking if the statement is already in the Model.
+ * So if you want a duplicate free Model use the addWithoutDuplicates() function (which is slower then add())
+ * Expects a statements with ResResources(ResLiterals)
+ *
+ * @param object Statement $statement
+ * @access public
+ * @throws PhpError
+ */
+ function add($statement)
+ {
+ return $this->model->add(new Statement( $this->_resNode2Node($statement->getSubject()),
+ $this->_resNode2Node($statement->getPredicate()),
+ $this->_resNode2Node($statement->getObject()))
+ );
+ }
+ /**
+ * Checks if a new statement is already in the Model and adds the statement, if it is not in the Model.
+ * addWithoutDuplicates() is significantly slower then add().
+ * Retruns TRUE if the statement is added.
+ * FALSE otherwise.
+ * Expects a statements with ResResources(ResLiterals)
+ *
+ * @param object Statement $statement
+ * @return boolean
+ * @access public
+ * @throws PhpError
+ */
+ function addWithoutDuplicates($statement)
+ {
+ return $this->model->addWithoutDuplicates(new Statement($this->_resNode2Node($statement->getSubject()),
+ $this->_resNode2Node($statement->getPredicate()),
+ $this->_resNode2Node($statement->getObject()))
+ );
+ }
+
+ /**
+ * Tests if the Model contains the given statement.
+ * TRUE if the statement belongs to the model;
+ * FALSE otherwise.
+ * Expects a statement of ResResources(ResLiterals)
+ *
+ * @param object Statement $statement
+ * @return boolean
+ * @access public
+ */
+ function contains(& $statement)
+ {
+
+ return $this->model->contains(new Statement($this->_resNode2Node($statement->getSubject()),
+ $this->_resNode2Node($statement->getPredicate()),
+ $this->_resNode2Node($statement->getObject()))
+ );
+ }
+
+ /**
+ * Determine if all of the statements in a model are also contained in this model.
+ * True if all of the statements in $model are also contained in this model and false otherwise.
+ *
+ * @param object Model &$model
+ * @return boolean
+ * @access public
+ */
+ function containsAll(& $model)
+ {
+ if (is_a($model,'ResModel'))
+ return $this->model->containsAll($model->getModel());
+
+ return $this->model->containsAll($model);
+ }
+
+ /**
+ * Determine if any of the statements in a model are also contained in this model.
+ * True if any of the statements in $model are also contained in this model and false otherwise.
+ *
+ * @param object Model &$model
+ * @return boolean
+ * @access public
+ */
+ function containsAny(& $model)
+ {
+ if (is_a($model,'ResModel'))
+ return $this->model->containsAny($model->getModel());
+ return $this->model->containsAny($model);
+ }
+
+ /**
+ * Determine if the node (ResResource / ResLiteral) $node appears in any statement of this model.
+ *
+ * @param object Node &$node
+ * @return boolean
+ * @access public
+ */
+ function containsResource(& $node)
+ {
+ if ($this->findFirstMatchingStatement($node,null,null) === null)
+ if ($this->findFirstMatchingStatement(null,$node,null) === null)
+ if ($this->findFirstMatchingStatement(null,null,$node) === null)
+ return false;
+
+ return true;
+ }
+
+ /**
+ * Create a literal from a String value with the $dtype Datatype
+ * An existing literal of the right value may be returned, or a fresh one created.
+ *
+ * @param string $value
+ * @param string $dtype
+ * @return object ResLiteral
+ * @access public
+ */
+ function createTypedLiteral($value,$dtype)
+ {
+ $resLiteral = new ResLiteral($value);
+ $resLiteral->setDatatype($dtype);
+ $resLiteral->setAssociatedModel($this);
+
+ return $resLiteral;
+ }
+
+ /**
+ * Checks if two models are equal.
+ * Two models are equal if and only if the two RDF graphs they represent are isomorphic.
+ *
+ * Warning: This method doesn't work correct with models where the same blank node has different
+ * identifiers in the two models. We will correct this in a future version.
+ *
+ * @access public
+ * @param object model &$that
+ * @throws phpErrpr
+ * @return boolean
+ */
+ function equals(& $that)
+ {
+ if (is_a($that,'ResModel'))
+ return $this->model->equals($that->getModel());
+ return $this->model->equals($that);
+ }
+
+ /**
+ * Returns a new model that is the subtraction of another model from this model.
+ *
+ * @param object Model $model
+ * @return object MemModel
+ * @access public
+ * @throws phpErrpr
+ */
+ function subtract($model)
+ {
+ if (is_a($model,'ResModel'))
+ return $this->model->subtract($model->getModel());
+ return $this->model->subtract($model);
+ }
+
+ /**
+ * Answer a statement find(s, p, null) with ResResources(ResLiterals) from this model.
+ * If none exist, return null; if several exist, pick one arbitrarily.
+ *
+ * @param object ResResource $subject
+ * @param object ResResource $property
+ * @return object Statement
+ * @access public
+ * @throws phpErrpr
+ */
+ function getProperty($subject,$property)
+ {
+
+ $statement= $this->model->findFirstMatchingStatement( $this->_resNode2Node($subject),
+ $this->_resNode2Node($property),
+ null
+ );
+ if ($statement === null)
+ return null;
+
+ return new Statement($this->_node2ResNode($statement->getSubject()),
+ $this->_node2ResNode($statement->getPredicate(),true),
+ $this->_node2ResNode($statement->getObject())
+ );
+
+ }
+
+ /**
+ * Checks if MemModel is empty
+ *
+ * @return boolean
+ * @access public
+ */
+ function isEmpty()
+ {
+ return $this->model->isEmpty();
+ }
+
+ /**
+ * Returns a ResIterator with all objects in a model.
+ *
+ * @return object ResIterator
+ * @access public
+ * @throws phpErrpr
+ */
+ function listObjects()
+ {
+ return $this->listObjectsOfProperty(null);
+ }
+
+ /**
+ * Returns a ResIterator with all objects with a given property and property value.
+ *
+ * @param object ResResource $property
+ * @param object ResResource $value
+ * @return object ResIterator
+ * @access public
+ */
+ function listObjectsOfProperty($property, $value = null)
+ {
+ return new ResIterator(null,$property,$value,'o',$this);
+ }
+
+
+ /**
+ * Returns a ResIterator with all subjects in a model.
+ *
+ * @return object ResIterator
+ * @access public
+ * @throws phpErrpr
+ */
+ function listSubjects()
+ {
+ return $this->listSubjectsWithProperty(null);
+ }
+
+ /**
+ * Returns a ResIterator with all subjects with a given property and property value.
+ *
+ * @param object ResResource $property
+ * @param object ResResource $value
+ * @return object ResIterator
+ * @access public
+ * @throws phpErrpr
+ */
+ function listSubjectsWithProperty($property,$value = null)
+ {
+ return new ResIterator(null,$property,$value,'s',$this);
+ }
+
+ /**
+ * Removes the statement of ResResources(ResTriples) from the MemModel.
+ * TRUE if the statement is removed.
+ * FALSE otherwise.
+ *
+ * @param object Statement $statement
+ * @return boolean
+ * @access public
+ * @throws PhpError
+ */
+ function remove($statement)
+ {
+ return $this->model->remove(new Statement( $this->_resNode2Node($statement->getSubject()),
+ $this->_resNode2Node($statement->getPredicate()),
+ $this->_resNode2Node($statement->getObject())
+ ));
+ }
+
+ /**
+ * Number of statements in the MemModel
+ *
+ * @return integer
+ * @access public
+ */
+ function size()
+ {
+ return $this->model->size();
+ }
+
+ /**
+ * Returns a new Model that is the set-union of the model with another model.
+ * Duplicate statements are removed. If you want to allow duplicates, use addModel() which is much faster.
+ *
+ * The result of taking the set-union of two or more RDF graphs (i.e. sets of triples)
+ * is another graph, which we will call the merge of the graphs.
+ * Each of the original graphs is a subgraph of the merged graph. Notice that when forming
+ * a merged graph, two occurrences of a given uriref or literal as nodes in two different
+ * graphs become a single node in the union graph (since by definition they are the same
+ * uriref or literal) but blank nodes are not 'merged' in this way; and arcs are of course
+ * never merged. In particular, this means that every blank node in a merged graph can be
+ * identified as coming from one particular graph in the original set of graphs.
+ *
+ * Notice that one does not, in general, obtain the merge of a set of graphs by concatenating
+ * their corresponding N-triples documents and constructing the graph described by the merged
+ * document, since if some of the documents use the same node identifiers, the merged document
+ * will describe a graph in which some of the blank nodes have been 'accidentally' merged.
+ * To merge Ntriples documents it is necessary to check if the same nodeID is used in two or
+ * more documents, and to replace it with a distinct nodeID in each of them, before merging the
+ * documents. (Not implemented yet !!!!!!!!!!!)
+ *
+ * @param object Model $model
+ * @return object MemModel
+ * @access public
+ * @throws phpErrpr
+ *
+ */
+ function & unite(& $model)
+ {
+ if (is_a($model,'ResModel'))
+ return $this->model->unite($model->getModel());
+ return $this->model->unite($model);
+ }
+
+ /**
+ * Adds another model to this MemModel.
+ * Duplicate statements are not removed.
+ * If you don't want duplicates, use unite().
+ * If any statement of the model to be added to this model contains a blankNode
+ * with an identifier already existing in this model, a new blankNode is generated.
+ *
+ * @param object Model $model
+ * @access public
+ * @throws phpErrpr
+ *
+ */
+ function addModel(&$model)
+ {
+ if (is_a($model,'ResModel'))
+ return $this->model->addModel($model->getModel());
+ return $this->model->addModel($model);
+ }
+
+ /**
+ * Create a new RDF Container from type rdf:Alt
+ * This method may return an existing container with the correct URI and model,
+ * or it may construct a fresh one, as it sees fit.
+ *
+ * Subsequent operations on the returned Container may modify this model.
+ *
+ *
+ * @param string $uri
+ * @return object ResProperty
+ * @access public
+ */
+ function createAlt($uri = null)
+ {
+ $resAlt = new ResAlt($uri);
+ $resAlt->setAssociatedModel($this);
+
+ return $resAlt;
+ }
+
+ /**
+ * Create a new RDF Container from type rdf:Bag
+ * This method may return an existing container with the correct URI and model,
+ * or it may construct a fresh one, as it sees fit.
+ *
+ * Subsequent operations on the returned Container may modify this model.
+ *
+ *
+ * @param string $uri
+ * @return object ResProperty
+ * @access public
+ */
+ function createBag($uri = null)
+ {
+ $resBag = new ResBag($uri);
+ $resBag->setAssociatedModel($this);
+
+ return $resBag;
+ }
+
+ /**
+ * Create a new RDF Container from type rdf:Seq
+ * This method may return an existing container with the correct URI and model,
+ * or it may construct a fresh one, as it sees fit.
+ *
+ * Subsequent operations on the returned Container may modify this model.
+ *
+ *
+ * @param string $uri
+ * @return object ResProperty
+ * @access public
+ */
+ function createSeq($uri = null)
+ {
+ $resSeq = new ResSeq($uri);
+ $resSeq->setAssociatedModel($this);
+
+ return $resSeq;
+ }
+
+ /**
+ * Create a new RDF Collection from type rdf:List
+ * This method may return an existing container with the correct URI and model,
+ * or it may construct a fresh one, as it sees fit.
+ *
+ * Subsequent operations on the returned Container may modify this model.
+ *
+ *
+ * @param string $uri
+ * @return object ResProperty
+ * @access public
+ */
+ function createList($uri = null)
+ {
+ $resList = new ResList($uri);
+ $resList->setAssociatedModel($this);
+
+ return $resList;
+ }
+
+ /**
+ * Returns a reference to the underlying model (Mem/DB/InfModel) that contains the statements
+ *
+ *
+ * @return object Model
+ * @access public
+ */
+ function & getModel()
+ {
+ return $this->model;
+ }
+
+
+ /**
+ * Internal method, that returns a resource URI that is unique for the Model.
+ * URIs are generated using the base_uri of the Model, the prefix and a unique number.
+ * If no prefix is defined, the bNode prefix, defined in constants.php, is used.
+ *
+ * @param string $prefix
+ * @return string
+ * @access private
+ */
+ function getUniqueResourceURI($bnodePrefix)
+ {
+ return $this->model->getUniqueResourceURI($bnodePrefix);
+ }
+
+ /**
+ * Load a model from a file containing RDF, N3 or N-Triples.
+ * This function recognizes the suffix of the filename (.n3 or .rdf) and
+ * calls a suitable parser, if no $type is given as string ("rdf" "n3" "nt");
+ * If the model is not empty, the contents of the file is added to this DbModel.
+ *
+ * @param string $filename
+ * @param string $type
+ * @param boolean $stream
+ * @access public
+ */
+ function load($filename, $type = NULL, $stream=false)
+ {
+ $this->model->load($filename, $type, $stream);
+ }
+
+ /**
+ * Return current baseURI.
+ *
+ * @return string
+ * @access public
+ */
+ function getBaseURI()
+ {
+ return $this->model->getBaseURI();
+ }
+
+ /**
+ * Saves the RDF,N3 or N-Triple serialization of the MemModel to a file.
+ * You can decide to which format the model should be serialized by using a
+ * corresponding suffix-string as $type parameter. If no $type parameter
+ * is placed this method will serialize the model to XML/RDF format.
+ * Returns FALSE if the MemModel couldn't be saved to the file.
+ *
+ * @access public
+ * @param string $filename
+ * @param string $type
+ * @throws PhpError
+ * @return boolean
+ */
+ function saveAs($filename, $type ='rdf')
+ {
+ return $this->model->saveAs($filename, $type ='rdf');
+ }
+
+ /**
+ * Writes the RDF serialization of the MemModel as HTML table.
+ *
+ * @access public
+ */
+ function writeAsHTMLTable()
+ {
+ $this->model->writeAsHtmlTable();
+ }
+
+ /**
+ * Returns a new model containing all the statements which are in both this model and another.
+ *
+ * @param object Model $model
+ * @return object MemModel
+ * @access public
+ * @throws phpErrpr
+ */
+ function & intersect(& $model)
+ {
+ if (is_a($model,'ResModel'))
+ return $this->model->intersect($model->getModel());
+ return $this->model->intersect($model);
+ }
+
+ /**
+ * converts a Resource,Blanknode,Literal into a ResResource, ResProperty, or ResLiteral
+ *
+ * @param object Node $node
+ * @param boolean $isProperty
+ * @return object ResResource / ResProperty / ResLiteral
+ * @access private
+ * @throws phpErrpr
+ */
+ function _node2ResNode($node, $isProperty = false)
+ {
+ if (is_a($node,'Literal'))
+ {
+ $return= new ResLiteral($node->getLabel(),$node->getLanguage());
+ $return->setDatatype($node->getDatatype());
+ $return->setAssociatedModel($this);
+
+ return $return;
+ }
+ if (is_a($node,'Resource'))
+ {
+ if ($isProperty)
+ {
+ $res= new ResProperty($node->getLabel());
+ } else
+ {
+ $res= new ResResource($node->getLabel());
+ }
+ $res->setAssociatedModel($this);
+ if (is_a($node,'Blanknode'))
+ $res->setIsAnon(true);
+
+ return $res;
+ }
+ }
+
+ /**
+ * converts a ResResource, ResProperty, or ResLiteral into a Resource, Blanknode, or Literal
+ *
+ * @param object ResNode $resNode
+ * @return object Node
+ * @access private
+ * @throws phpErrpr
+ */
+ function _resNode2Node($resNode)
+ {
+ if (is_a($resNode,'ResResource'))
+ {
+ if ($resNode->getIsAnon())
+ {
+ $return=new BlankNode($resNode->getURI());
+ } else
+ {
+ $return=new Resource($resNode->getURI());
+ }
+ return $return;
+ }
+
+ if (is_a($resNode,'ResLiteral'))
+ {
+ $literal=new Literal($resNode->getLabel(),$resNode->getLanguage());
+ if ($resNode->getDatatype() != null)
+ $literal->setDatatype($resNode->getDatatype());
+ return $literal;
+ }
+ }
+
+ /**
+ * Set a base URI for the MemModel.
+ * Affects creating of new resources and serialization syntax.
+ * If the URI doesn't end with # : or /, then a # is added to the URI.
+ * @param string $uri
+ * @access public
+ */
+ function setBaseURI($uri)
+ {
+ $this->model->setBaseURI($uri);
+ }
+
+ /**
+ * Writes the RDF serialization of the MemModel as HTML table.
+ *
+ * @access public
+ * @return string
+ */
+ function writeRdfToString()
+ {
+ return $this->model->writeRdfToString();
+ }
+
+ /**
+ * Perform an RDQL query on this MemModel.
+ * This method returns an associative array of variable bindings.
+ * The values of the query variables can either be RAP's objects (instances of Node)
+ * if $returnNodes set to TRUE, or their string serialization.
+ *
+ * @access public
+ * @param string $queryString
+ * @param boolean $returnNodes
+ * @return array [][?VARNAME] = object Node (if $returnNodes = TRUE)
+ * OR array [][?VARNAME] = string
+ *
+ */
+ function & rdqlQuery($queryString, $returnNodes = TRUE)
+ {
+ $ret = $this->model->rdqlQuery($queryString, $returnNodes);
+ return $ret;
+ }
+
+ /**
+ * Perform an RDQL query on this MemModel.
+ * This method returns an RdqlResultIterator of variable bindings.
+ * The values of the query variables can either be RAP's objects (instances of Node)
+ * if $returnNodes set to TRUE, or their string serialization.
+ *
+ * @access public
+ * @param string $queryString
+ * @param boolean $returnNodes
+ * @return object RdqlResultIterator = with values as object Node (if $returnNodes = TRUE)
+ * OR object RdqlResultIterator = with values as strings if (if $returnNodes = FALSE)
+ *
+ */
+ function rdqlQueryAsIterator($queryString, $returnNodes = TRUE)
+ {
+ return $this->model->rdqlQueryAsIterator($queryString, $returnNodes);
+ }
+
+
+ /**
+ * Returns the models namespaces.
+ *
+ * @author Tobias Gauß
+ * @access public
+ * @return Array
+ */
+ function getParsedNamespaces(){
+ return $this->model->getParsedNamespaces();
+ }
+
+
+
+ /**
+ * Adds the namespaces to the model. This method is called by
+ * the parser. !!!! addParsedNamespaces() not overwrites manual
+ * added namespaces in the model !!!!
+ *
+ * @author Tobias Gauß
+ * @access public
+ * @param Array $newNs
+ */
+ function addParsedNamespaces($newNs){
+ $this->model->addParsedNamespaces($newNs);
+ }
+
+
+ /**
+ * Adds a namespace and prefix to the model.
+ *
+ * @author Tobias Gauß
+ * @access public
+ * @param String $prefix, String $nmsp
+ */
+ function addNamespace($prefix, $namespace){
+ $this->model->addNamespace($prefix, $namespace);
+ }
+
+ /**
+ * removes a single namespace from the model
+ *
+ * @author Tobias Gauß
+ * @access public
+ * @param String $nmsp
+ */
+ function removeNamespace($nmsp){
+ return $this->model->removeNamespace($nmsp);
+ }
+
+
+
+
+
+
+}
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/text-base/ResModelP.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/text-base/ResModelP.php.svn-base
new file mode 100755
index 00000000..91a7a0d9
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/text-base/ResModelP.php.svn-base
@@ -0,0 +1,24 @@
+
+//
+// ----------------------------------------------------------------------------------
+
+// Include ResModel classes
+require_once( RDFAPI_INCLUDE_DIR . 'resModel/ResModel.php');
+require_once( RDFAPI_INCLUDE_DIR . 'resModel/ResResource.php');
+require_once( RDFAPI_INCLUDE_DIR . 'resModel/ResContainer.php');
+require_once( RDFAPI_INCLUDE_DIR . 'resModel/ResAlt.php');
+require_once( RDFAPI_INCLUDE_DIR . 'resModel/ResBag.php');
+require_once( RDFAPI_INCLUDE_DIR . 'resModel/ResLiteral.php');
+require_once( RDFAPI_INCLUDE_DIR . 'resModel/ResProperty.php');
+require_once( RDFAPI_INCLUDE_DIR . 'resModel/ResSeq.php');
+require_once( RDFAPI_INCLUDE_DIR . 'resModel/ResIterator.php');
+require_once( RDFAPI_INCLUDE_DIR . 'resModel/ResList.php');
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/text-base/ResProperty.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/text-base/ResProperty.php.svn-base
new file mode 100755
index 00000000..188ad745
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/text-base/ResProperty.php.svn-base
@@ -0,0 +1,32 @@
+
+*
+*
+* @package resModel
+* @access public
+**/
+class ResProperty extends ResResource
+{
+
+ /**
+ * Constructor
+ * You can supply a URI
+ *
+ * @param string $uri
+ * @access public
+ */
+ function ResProperty($uri)
+ {
+ parent::ResResource($uri);
+ }
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/text-base/ResResource.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/text-base/ResResource.php.svn-base
new file mode 100755
index 00000000..54b38ef7
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/text-base/ResResource.php.svn-base
@@ -0,0 +1,212 @@
+
+*
+*
+* @package resModel
+* @access public
+**/
+class ResResource extends Resource
+{
+ /**
+ * Holds a reference to the associated model
+ * @var ResModel
+ * @access private
+ */
+ var $model;
+
+ /**
+ * Is true, if this resource is an anonymous node.
+ * @var boolean
+ * @access private
+ */
+ var $isAnon;
+
+
+ /**
+ * Constructor
+ * You can supply a uri
+ *
+ * @param string $uri
+ * @access public
+ */
+ function ResResource($uri)
+ {
+ parent::Resource($uri);
+ $this->isAnon = ($uri === null);
+ }
+
+ /**
+ * Sets the reference to the assocoated model.
+ *
+ * @param object Model $model
+ * @access public
+ */
+ function setAssociatedModel(& $model)
+ {
+ $this->model=& $model;
+ if ($this->isAnon)
+ $this->uri=$this->model->getUniqueResourceURI(BNODE_PREFIX);
+ }
+
+ /**
+ * Get the reference to the assocoated model.
+ *
+ * @return object Model $model
+ * @access public
+ */
+ function getAssociatedModel()
+ {
+ return $this->model;
+ }
+
+ /**
+ * Sets the URI of this resource
+ *
+ * @param string $uri
+ * @access public
+ */
+ function setURI($uri)
+ {
+ $this->uri = $uri;
+ }
+
+ /**
+ * Add a property to this resource.
+ * A statement with this resource as the subject, p as the predicate and o
+ * as the object is added to the model associated with this resource.
+ *
+ * @param ResResource $property
+ * @param ResResource/ResLiteral $object
+ * @return object ResResource
+ * @access public
+ */
+ function addProperty($property,$object)
+ {
+ $this->model->add(new Statement($this,$property,$object));
+
+ return $this;
+ }
+
+ /**
+ * List all the values with the property p as statements in an array.
+ *
+ * @param ResResource $property
+ * @return ResIterator
+ * @access public
+ */
+ function listProperties($property = null)
+ {
+ return $this->model->find($this,$property,null);
+ }
+
+ /**
+ * Answer some statement (this, p, O) in the associated model.
+ * If there are several such statements, any one of them may be returned.
+ * If no such statements exist, null is returned.
+ *
+ * @param ResResource $property
+ * @return object ResResource
+ * @access public
+ */
+ function getProperty($property)
+ {
+ return $this->model->getProperty($this,$property);
+ }
+
+ /**
+ * Determine whether this resource has any values for a given property.
+ *
+ * @param ResResource $property
+ * @param ResResource $value
+ * @return object ResResource
+ * @access public
+ */
+ function hasProperty($property, $value = null)
+ {
+ $ret= $this->model->findFirstMatchingStatement($this,$property,$value);
+
+ return ($ret!==null);
+ }
+
+ /**
+ * Determine whether this resource is an anonymous resource
+ *
+ * @return boolean
+ * @access public
+ */
+ function getIsAnon()
+ {
+ return $this->isAnon;
+ }
+
+ /**
+ * Set whether this resource is an anonymous resource
+ *
+ * @param boolean
+ * @access public
+ */
+ function setIsAnon($isAnon)
+ {
+ $this->isAnon=$isAnon;
+ }
+
+ /**
+ * Checks if the resource equals another resource.
+ * Two resources are equal, if they have the same URI
+ *
+ * @access public
+ * @param object resource $that
+ * @return boolean
+ */
+ function equals ($that)
+ {
+ if (is_a($that,'ResLiteral'))
+ return $that->equals($this);
+
+ return ($that!==null && ($this->getURI() == $that->getURI()));
+ }
+
+ /**
+ * Delete all the statements with predicate p for this resource from
+ * its associated model.
+ *
+ * @access public
+ * @param object resource $property
+ * @return object ResResource
+ */
+ function removeAll($property = null)
+ {
+ foreach ($this->model->find($this,$property,null) as $statement)
+ {
+ $this->model->remove($statement);
+ }
+ return $this;
+ }
+
+ /**
+ * Delete all the properties for this resource from the associated model.
+ *
+ * @access public
+ * @return object ResResource
+ */
+ function removeProperties()
+ {
+ $this->removeAll();
+ return $this;
+ }
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/text-base/ResSeq.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/text-base/ResSeq.php.svn-base
new file mode 100755
index 00000000..a16bb582
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/.svn/text-base/ResSeq.php.svn-base
@@ -0,0 +1,153 @@
+
+*
+* @package resModel
+* @access public
+**/
+class ResSeq extends ResContainer
+{
+
+ /**
+ * Constructor
+ * You can supply a URI
+ *
+ * @param string $uri
+ * @access public
+ */
+ function ResSeq($uri = null)
+ {
+ parent::ResContainer($uri);
+ $this->containerType=new ResResource(RDF_NAMESPACE_URI.RDF_SEQ);
+ }
+
+ /**
+ * Insert a new member into the sequence at the specified position.
+ * The existing member at that position, and all others with higher indexes,
+ * have their index increased by one.
+ *
+ * @param integer $index
+ * @param object ResResource/ResLiteral $resResource
+ * @return boolean
+ * @access public
+ */
+ function addAtIndex($index, $object)
+ {
+ //get a members index
+ $memberIndex= $this->getMembers();
+
+ //type this container, if it isn't already typed
+ if(!$this->hasProperty(new ResResource(RDF_NAMESPACE_URI.RDF_TYPE)))
+ $this->addProperty(new ResResource(RDF_NAMESPACE_URI.RDF_TYPE),$this->containerType);
+
+ //renumber all higher members
+ for ($i = count($memberIndex);$i >= $index ; $i--)
+ {
+ $this->removeAll($this->_getMembershipPropertyWithIndex($i));
+ $this->addProperty($this->_getMembershipPropertyWithIndex($i+1),$memberIndex[$i]);
+ }
+ //remove the old value at this position
+ $this->removeAll($this->_getMembershipPropertyWithIndex($index));
+ //add the new value
+ $this->addProperty($this->_getMembershipPropertyWithIndex($index),$object);
+
+ return $this;
+ }
+
+ /**
+ * Get the member at a given index
+ *
+ * @param integer $index
+ * @return object ResResource/ResLiteral
+ * @access public
+ */
+ function getMember($index)
+ {
+ $result=$this->listProperties($this->_getMembershipPropertyWithIndex($index));
+ if (isset($result[0]))
+ {
+ return $result[0];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Return the index of a given member of the sequence.
+ * If the same value appears more than once in the sequence, it is undefined
+ * which of the indexes will be returned.
+ * If the member is not found in this sequence, a value of 0 is returned.
+ *
+ * @param object ResResource/ResLiteral $object
+ * @return integer
+ * @access public
+ */
+ function indexOf($object)
+ {
+ //check all members, until $object is found
+ foreach ($this->listProperties() as $statement)
+ {
+ $predicateLabel=$statement->getLabelPredicate();
+ if ($this->_predicateLabelMatchesMembershipProperty($predicateLabel))
+ {
+ if($object->equals($statement->getObject()))
+ //analyze the container membership property and return the index
+ return $this->_getMemberIndexNrFromMembershipPropertyLabel($predicateLabel);
+ }
+ }
+ //return 0 if $object wasn't found
+ return 0;
+ }
+
+ /**
+ * Remove the member at the specified index.
+ * All other members with a higher index will have their index reduced by one.
+ *
+ * @param integer $index
+ * @access public
+ */
+ function removeAtIndex($index)
+ {
+ $memberIndex= $this->getMembers();
+
+
+ $this->removeAll($this->_getMembershipPropertyWithIndex($index));
+
+ for ($i = $index;$i < count($memberIndex); $i++)
+ {
+ $this->removeAll($this->_getMembershipPropertyWithIndex($i+1));
+ $this->addProperty($this->_getMembershipPropertyWithIndex($i),$memberIndex[$i+1]);
+ }
+ return $this;
+ }
+
+ /**
+ * Set the value at a given index in the sequence.
+ *
+ * If the index is not in the range of the sequence, false is returned
+ *
+ * @param integer $index
+ * @return boolean
+ * @access public
+ */
+ function set($index, $object)
+ {
+ if (!$this->hasProperty($this->_getMembershipPropertyWithIndex($index)))
+ return false;
+
+ $this->removeAll($this->_getMembershipPropertyWithIndex($index));
+ $this->addProperty($this->_getMembershipPropertyWithIndex($index),$object);
+ return true;
+ }
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/ResAlt.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/ResAlt.php
new file mode 100755
index 00000000..f4fed7c0
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/ResAlt.php
@@ -0,0 +1,78 @@
+
+*
+* @package resModel
+* @access public
+**/
+class ResAlt extends ResContainer
+{
+
+ /**
+ * Constructor
+ * You can supply a URI
+ *
+ * @param string $uri
+ * @access public
+ */
+ function ResAlt($uri = null)
+ {
+ parent::ResContainer($uri);
+ $this->containerType=new ResResource(RDF_NAMESPACE_URI.RDF_ALT);
+ }
+
+ /**
+ * Return the default value for this resource
+ *
+ * @return object ResResource/ResLiteral
+ * @access public
+ */
+ function getDefault()
+ {
+ //get the first memeber
+ $statements=$this->listProperties($this->_getMembershipPropertyWithIndex(1));
+ if(isset($statements[0]))
+ {
+ //return the value
+ return $statements[0]->getObject();
+ } else
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Set the default value of this container.
+ *
+ * @param object ResResource/ResLiteral $object
+ * @access public
+ */
+ function setDefault($object)
+ {
+ //remember the old default value
+ $oldDefaultObject=$this->getDefault();
+ //if there wasn't a default value before
+ if($oldDefaultObject === null)
+ {
+ //add the new value
+ $this->addProperty($this->_getMembershipPropertyWithIndex(1),$object);
+ } else
+ {
+ //remove the old value
+ $this->removeAll($this->_getMembershipPropertyWithIndex(1));
+ //set the new value
+ $this->addProperty($this->_getMembershipPropertyWithIndex(1),$object);
+ //add the old default value at the end
+ $this->add($oldDefaultObject);
+ }
+ }
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/ResBag.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/ResBag.php
new file mode 100755
index 00000000..98fa662a
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/ResBag.php
@@ -0,0 +1,32 @@
+
+*
+* @package resModel
+* @access public
+**/
+class ResBag extends ResContainer
+{
+
+ /**
+ * Constructor
+ * You can supply a URI
+ *
+ * @param string $uri
+ * @access public
+ */
+ function ResBag($uri = null)
+ {
+ parent::ResContainer($uri);
+ $this->containerType=new ResResource(RDF_NAMESPACE_URI.RDF_BAG);
+ }
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/ResContainer.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/ResContainer.php
new file mode 100755
index 00000000..18c253f0
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/ResContainer.php
@@ -0,0 +1,219 @@
+
+*
+* @package resModel
+* @access public
+**/
+
+class ResContainer extends ResResource
+{
+ /**
+ * Holds a ResResource of this container type rdf:Seq, rdf:Alt, or rdf:Bag
+ * @var ResResource
+ * @access private
+ */
+ var $containerType;
+
+
+ /**
+ * Constructor
+ * You can supply a URI
+ *
+ * @param string $uri
+ * @access public
+ */
+ function ResContainer($uri = null)
+ {
+ parent::ResResource($uri);
+ }
+
+ /**
+ * Add a new value to a container.
+ * The new value is added as the last element of the container.
+ *
+ * @param object ResResource/ResLiteral $object
+ * @access public
+ */
+ function add($object)
+ {
+ //type this container, if it isn't already typed
+ if(!$this->hasProperty(new ResResource(RDF_NAMESPACE_URI.RDF_TYPE)))
+ $this->addProperty(new ResResource(RDF_NAMESPACE_URI.RDF_TYPE),$this->containerType);
+ //get the current size
+ $actualSize=$this->size();
+ //add the object to the last position
+ $this->addProperty(new ResResource(RDF_NAMESPACE_URI.'_'.($actualSize+1)),$object);
+ }
+
+ /**
+ * Determine whether the container contains a value
+ *
+ * @param obejct ResResource/ResLiteral $resResource
+ * @return boolean
+ * @access public
+ */
+ function contains($resResource)
+ {
+ //get all container's properties
+ foreach ($this->listProperties() as $statement)
+ {
+ //if the property matches a container membership property
+ if ($this->_predicateLabelMatchesMembershipProperty($statement->getLabelPredicate()))
+ {
+ //check, if it's the value, we're looking for.
+ if ($resResource->equals($statement->getObject()))
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns true, if this resource is a container from type rdf:Alt
+ *
+ * @return boolean
+ * @access public
+ */
+ function isAlt()
+ {
+ return ($this->containerType->getURI()==RDF_NAMESPACE_URI.RDF_ALT);
+ }
+
+ /**
+ * Returns true, if this resource is a container from type rdf:Bag
+ *
+ * @return boolean
+ * @access public
+ */
+ function isBag()
+ {
+ return ($this->containerType->getURI()==RDF_NAMESPACE_URI.RDF_BAG);
+ }
+
+ /**
+ * Returns true, if this resource is a container from type rdf:Seq
+ *
+ * @return boolean
+ * @access public
+ */
+ function isSeq()
+ {
+ return ($this->containerType->getURI()==RDF_NAMESPACE_URI.RDF_SEQ);
+ }
+
+ /**
+ * Get an array of all resources that are values of this container
+ *
+ * @return array
+ * @access public
+ */
+ function getMembers()
+ {
+ $return=array();
+ foreach ($this->listProperties() as $statement)
+ {
+ $predicateLabel=$statement->getLabelPredicate();
+ if ($this->_predicateLabelMatchesMembershipProperty($predicateLabel))
+ {
+ $return[$this->_getMemberIndexNrFromMembershipPropertyLabel($predicateLabel)] = $statement->getObject();
+ }
+ }
+ return $return;
+ }
+
+ /**
+ * Remove a value from the container.
+ *
+ * Once removed, the values in the container with a higher ordinal value are renumbered.
+ * The renumbering algorithm depends on the type of container.
+ *
+ * @param obejct ResResource/ResLiteral $resResource
+ * @access public
+ */
+ function remove($object)
+ {
+ $deleteFromIndex=array();
+ //get all container members
+ $memberIndex=$this->getMembers();
+
+ //check each container member if it equals the resoure to be removed
+ foreach ($memberIndex as $key => $value)
+ {
+ //save the statements positio in the container
+ if($object->equals($value))
+ $deleteFromIndex[]=$key;
+ }
+
+ //delete all found container members
+ foreach ($deleteFromIndex as $index)
+ {
+ $this->removeAll($this->_getMembershipPropertyWithIndex($index));
+
+ //renumber all members with higher ordinal numbers than the deleted one
+ for ($i = $index;$i < count($memberIndex); $i++)
+ {
+ $this->removeAll($this->_getMembershipPropertyWithIndex($i+1));
+ $this->addProperty($this->_getMembershipPropertyWithIndex($i),$memberIndex[$i+1]);
+ }
+ }
+
+ }
+
+ /**
+ * Returns the number values in the container.
+ *
+ * @return integer
+ * @access public
+ */
+ function size()
+ {
+ return count($this->getMembers());
+ }
+
+ /**
+ * Checks, if a predicate label fits a container membership property rdf:_n
+ *
+ * @param string $predicateLabel
+ * @return boolean
+ * @access private
+ */
+ function _predicateLabelMatchesMembershipProperty($predicateLabel)
+ {
+ return substr($predicateLabel,0,strlen(RDF_NAMESPACE_URI.'_')) == RDF_NAMESPACE_URI.'_';
+ }
+
+ /**
+ * Get the ordinal number from a membership property rdf:_n
+ *
+ * @param string $predicateLabel
+ * @return integer
+ * @access private
+ */
+ function _getMemberIndexNrFromMembershipPropertyLabel($predicateLabel)
+ {
+ return (int)substr($predicateLabel,strlen(RDF_NAMESPACE_URI.'_'));
+ }
+
+ /**
+ * Get a membership property rdf:_n with index $int
+ *
+ * @param intger $int
+ * @return string
+ * @access private
+ */
+ function _getMembershipPropertyWithIndex($int)
+ {
+ return new ResResource(RDF_NAMESPACE_URI.'_'.$int);
+ }
+}
+?>
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/ResIterator.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/ResIterator.php
new file mode 100755
index 00000000..3395dfe2
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/ResIterator.php
@@ -0,0 +1,298 @@
+listInstances();
+* for ($it->rewind(); $it->valid(); $it->next())
+* {
+* $currentResource=$it->current();
+* };
+*
+*
+* @version $Id: ResIterator.php 522 2007-08-14 09:22:22Z cweiske $
+* @author Daniel Westphal
+*
+*
+* @package resModel
+* @access public
+**/
+class ResIterator
+{
+ /**
+ * Holds a reference to the assoiated ResModel / OntModel
+ * @var object Model
+ * @access private
+ */
+ var $associatedModel;
+
+ /**
+ * The current position
+ * @var integer
+ * @access private
+ */
+ var $key;
+
+ /**
+ * If the current resource is valid
+ * @var boolean
+ * @access private
+ */
+ var $valid;
+
+ /**
+ * The current resource
+ * @var obejct ResResource
+ * @access private
+ */
+ var $currentResource;
+
+ /**
+ * The subject to search for.
+ * @var object ResResource
+ * @access private
+ */
+ var $searchSubject;
+
+ /**
+ * The predicate to search for.
+ * @var object ResResource
+ * @access private
+ */
+ var $searchPredicate;
+
+ /**
+ * The object to search for.
+ * @var object ResResource
+ * @access private
+ */
+ var $searchObject;
+
+ /**
+ * If the resource, we're intrested in is the subject (s), predicate(p),
+ * or object (o) of the found statements
+ *
+ * @var string
+ * @access private
+ */
+ var $getSPO;
+
+ /**
+ * Defines the type of resource, we'd like to receive.
+ *
+ * @var string
+ * @access private
+ */
+ var $returnType;
+
+ /**
+ * If set, each resource will first be checked, if it's
+ * language fits.
+ *
+ * @var string
+ * @access private
+ */
+ var $findLiteralWithLang;
+
+
+ /**
+ * Constructor.
+ *
+ * $subject, $predicate, and $object are used like inf find().
+ * $getSPO supports the strings 's', 'p', and 'o' to return
+ * either the subject, predicate, or object of the result statements.
+ * $returnType supports the strings 'ResProperty', 'ResLiteral',
+ * 'OntProperty', 'OntClass', and 'Individual' and returns the resources
+ * as the matching type.
+ *
+ * @param object ResResource $subject
+ * @param object ResResource $predicate
+ * @param object ResResource $object
+ * @param string $getSPO
+ * @param object ResModel $associatedModel
+ * @param string $returnType
+ * @access public
+ */
+ function ResIterator($subject,$predicate,$object,$getSPO,& $associatedModel,$returnType = false)
+ {
+ $this->searchSubject =& $subject;
+ $this->searchPredicate =& $predicate;
+ $this->searchObject =& $object;
+ $this->getSPO = $getSPO;
+ $this->returnType = $returnType;
+ $this->associatedModel =& $associatedModel;
+ $this->findLiteralWithLang = false;
+ }
+
+ /**
+ * Resets iterator list to start
+ *
+ * @access public
+ */
+ function rewind()
+ {
+ $this->key = -1;
+ $this->next();
+ }
+
+ /**
+ * Says if there are additional items left in the list
+ *
+ * @return boolean
+ * @access public
+ */
+ function valid()
+ {
+ return $this->valid;
+ }
+
+ /**
+ * Moves Iterator to the next item in the list
+ *
+ * @access public
+ */
+ function next()
+ {
+ $this->key++;
+ $this->valid=($this->_getNextResource());
+ }
+
+ /**
+ * Returns the current item
+ *
+ * @return mixed
+ * @access public
+ */
+ function current()
+ {
+ return $this->currentResource;
+ }
+
+ /**
+ * Returns the next Resource (subject, predicate,
+ * or object of the next matching statement).
+ *
+ * @return object resResource
+ * @access private
+ */
+ function _getNextResource()
+ {
+ if ($this->findLiteralWithLang)
+ {
+ do
+ {
+ $nextStatement = $this->associatedModel->findFirstMatchingStatement($this->searchSubject,$this->searchPredicate,$this->searchObject,$this->key);
+ if ($nextStatement === null)
+ return false;
+
+ $object = $nextStatement->getObject();
+ if ($object->getLanguage() != $this->findLiteralWithLang)
+ {
+ $hasCorrectLanguage=false;
+ $this->key++;
+ } else
+ {
+ $hasCorrectLanguage=true;
+ }
+
+ } while (!$hasCorrectLanguage);
+ } else
+ {
+ $nextStatement = $this->associatedModel->findFirstMatchingStatement($this->searchSubject,$this->searchPredicate,$this->searchObject,$this->key);
+ }
+ if ($nextStatement === null)
+ return false;
+
+ switch ($this->getSPO)
+ {
+ case 's':
+ $this->currentResource = $this->_getResourceAs($nextStatement->getSubject());
+ break;
+
+ case 'p':
+ $this->currentResource = $this->_getResourceAs($nextStatement->getPredicate());
+ break;
+
+ case 'o':
+ $this->currentResource = $this->_getResourceAs($nextStatement->getObject());
+ break;
+ }
+ return (true);
+ }
+
+ /**
+ * Returns the key of the current item
+ *
+ * @return integer
+ * @access public
+ */
+ function key()
+ {
+ return $this->key;
+ }
+
+ /**
+ * Sets that only Literals with the matching
+ * language should be returned
+ *
+ * @param string
+ * @access public
+ */
+ function setFindLiteralWithLang($language)
+ {
+ $this->findLiteralWithLang = $language;
+ }
+
+ /**
+ * Returns the $resource as an instance of the type
+ * specified in $this->returnType.
+ *
+ * @param object ResResource
+ * @return object ResResource
+ * @access private
+ */
+ function _getResourceAs($resource)
+ {
+ if ($this->findLiteralWithLang && $resource->getLanguage() != $this->findLiteralWithLang)
+ $this->_getNextResource();
+
+ if($this->returnType)
+ switch ($this->returnType) {
+
+ case 'ResProperty':
+ return $this->associatedModel->createProperty($resource->getLabel());
+ break;
+
+ case 'ResLiteral':
+ $newLiteral = $this->associatedModel->createLiteral($resource->getLabel(),$resource->getLanguage());
+ $newLiteral->setDatatype($resource->getDatatype());
+ return $newLiteral;
+ break;
+
+ case 'OntProperty':
+
+ return $this->associatedModel->createOntProperty($resource->getLabel());
+ break;
+
+ case 'OntClass':
+ return $this->associatedModel->createOntClass($resource->getLabel());
+ break;
+
+ case 'Individual':
+ return $this->associatedModel->createIndividual($resource->getLabel());
+ break;
+ }
+ return $resource;
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/ResList.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/ResList.php
new file mode 100755
index 00000000..feeb96f6
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/ResList.php
@@ -0,0 +1,635 @@
+
+
+*
+* @package resModel
+* @access public
+*/
+class ResList extends ResResource
+{
+ /**
+ * Holds a ResResource with the uri rdf:rest
+ * @var ResResource
+ * @access private
+ */
+ var $rdfRestResource;
+
+ /**
+ * Holds a ResResource with the uri rdf:first
+ * @var ResResource
+ * @access private
+ */
+ var $rdfFirstResource;
+
+ /**
+ * Holds a ResResource with the uri rdf:nil
+ * @var ResResource
+ * @access private
+ */
+ var $rdfNilResource;
+
+
+ /**
+ * Constructor
+ * You can supply a URI
+ *
+ * @param string $uri
+ * @access public
+ */
+ function ResList($uri = null)
+ {
+ //call the parent's constructor
+ parent::ResResource($uri);
+ //initialize vars
+ $this->rdfRestResource = new ResResource(RDF_NAMESPACE_URI.RDF_REST);
+ $this->rdfFirstResource = new ResResource(RDF_NAMESPACE_URI.RDF_FIRST);
+ $this->rdfNilResource = new ResResource(RDF_NAMESPACE_URI.RDF_NIL);
+ }
+
+ /**
+ * Returns the value of the list element at the specified position or null.
+ *
+ * @param integer $position
+ * @return ResResource
+ * @access public
+ */
+ function get($position)
+ {
+ //init
+ $listElement=$this;
+ //walk through the list until the position in the list is reached
+ for ($i=0;$i<$position;$i++)
+ {
+ $listElement=$this->_getRestElement($listElement);
+ if($listElement===null)
+ return null;
+ }
+ //return the associated value
+ return $this->_getValue($listElement);
+ }
+
+ /**
+ * Add the given value to the end of the list.
+ * it is only defined if this is not the empty list.
+ *
+ * @param object ResResource $resource
+ * @return boolean
+ * @access public
+ */
+ function add($resource)
+ {
+ //return false if this list is the empty list
+ if($this->uri==RDF_NAMESPACE_URI.RDF_NIL)
+ return false;
+
+ //if this is the first value
+ if ($this->isEmpty())
+ {
+ $newLastElement =& $this;
+ } else
+ //if there are other values in the list
+ {
+ //get the last list element
+ $lastElement=$this->_getListElement();
+ //remove the rdf:rest property
+ $lastElement->removeAll($this->rdfRestResource);
+ //create a new list element
+ $newLastElement=$this->model->createResource();
+ //concatenate the new list element with the list
+ $lastElement->addProperty($this->rdfRestResource,$newLastElement);
+ }
+ //add the value
+ $newLastElement->addProperty($this->rdfFirstResource,$resource);
+ //ad the rdf:nil property to the last list element
+ $newLastElement->addProperty($this->rdfRestResource,$this->rdfNilResource);
+
+ return true;
+ }
+
+ /**
+ * Update the head of the list to have the given value,
+ * and return the previous value.
+ *
+ * @param object ResResource $value
+ * @return ResResource
+ * @access public
+ */
+ //todo: error handling, when empty list
+ function setHead($value)
+ {
+ //save the old value
+ $oldValue=$this->getHead();
+ //remove the old value
+ $this->removeAll($this->rdfFirstResource);
+ //add the new value
+ $this->addProperty($this->rdfFirstResource,$value);
+
+ //return the old value
+ return $oldValue;
+ }
+
+ /**
+ * Get the value that is associated with the head of the list.
+ *
+ * @return ResResource
+ * @access public
+ */
+ //todo: error handling, falls empty list
+ function getHead()
+ {
+ return $this->_getValue($this);
+ }
+
+ /**
+ * Remove the head of the list. The tail of the list
+ * remains in the model. Note that no changes are made to
+ * list cells that point to this list cell as their tail.
+ *
+ * @return ResList
+ * @access public
+ */
+ function removeHead()
+ {
+ //get the second list element
+ $rest=$this->_getRestElement($this);
+ //remove the first element
+ $this->removeAll($this->rdfFirstResource);
+ $this->removeAll($this->rdfRestResource);
+ //change this Resource URI to that of the second list element
+ //thus makin it the fist element
+ $this->uri=$rest->getURI();
+
+ //return the new list
+ return $this;
+ }
+
+ /**
+ * Get the Position of the first occurrence of the given value in the list,
+ * or -1 if the value is not in the list.
+ * You can supply an offset to search for values. (First element has offset 0)
+ * Default is 0
+ *
+ * @param object ResResource $resource
+ * @param integer $offset
+ * @return integer
+ * @access public
+ */
+ function indexOf($resource, $offset = 0)
+ {
+ //init
+ $element=$this;
+ $actualIndex=0;
+
+ //walk through the list until the value is found and the position is higher than
+ //the offset
+ while ($actualIndex < $offset || !$resource->equals($this->_getValue($element)))
+ {
+ //get next list element
+ $element=$this->_getRestElement($element);
+ $actualIndex++;
+
+ //if the end of the list is reached and the value isn't found
+ if ($element===null)
+ return null;
+ }
+ //return the index value
+ return $actualIndex;
+ }
+
+ /**
+ * Replace the value at the i'th position in the list with the given value
+ *
+ * @param integer $index
+ * @param object ResResource $resource
+ * @return object ResResource
+ * @access public
+ */
+ function replace($index, $resource)
+ {
+ //get the list element at the $index position
+ $listElement=$this->_getListElement($index);
+ //get the old value
+ $oldValue=$this->_getValue($listElement);
+ //remove the old value
+ $listElement->removeAll($this->rdfFirstResource);
+ //add the new value
+ $listElement->addProperty($this->rdfFirstResource,$resource);
+ //return the old value
+ return $oldValue;
+ }
+
+ /**
+ * Answer true if the given node appears as the value of a value
+ * of any of the cells of this list.
+ *
+ * @param object ResResource $value
+ * @return boolean
+ * @access public
+ */
+ function contains($value)
+ {
+ //return true, if a position was found.
+ $result=$this->indexOf($value);
+ return ($result!==null);
+ }
+
+ /**
+ * Get the list that is the tail of this list.
+ *
+ * @return object ResList
+ * @access public
+ */
+ function getTail()
+ {
+ //get the second list element
+ $nextListElement= $this->_getRestElement($this);
+ //return the second element as new list
+ return $this->model->createList($nextListElement->getURI());
+ }
+
+ /**
+ * Remove all of the components of this list from the model.
+ * Note that this is operation is only removing the list cells
+ * themselves, not the resources referenced by the list -
+ * unless being the object of an rdf:first statement is the
+ * only mention of that resource in the model.
+ *
+ * @return boolean
+ * @access public
+ */
+ function removeList()
+ {
+ $element=$this;
+
+ while ($element!==null)
+ {
+ $nextElement=$this->_getRestElement($element);
+
+ $element->removeAll($this->rdfFirstResource);
+ $element->removeAll($this->rdfRestResource);
+
+ if (($nextElement !== null) && ($nextElement->getURI()!==RDF_NAMESPACE_URI.RDF_NIL))
+ {
+ $element=$nextElement;
+ } else
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns true, if this list is empty
+ *
+ * @param object Statement $statement
+ * @return integer
+ * @access public
+ */
+ function isEmpty()
+ {
+ return !$this->hasProperty($this->rdfFirstResource);
+ }
+
+ /**
+ * Get all values in the list as an array of ResResources
+ *
+ * @return array
+ * @access public
+ */
+ function getContentInArray()
+ {
+ $result=array();
+ $element=$this;
+
+ while ($element!==null)
+ {
+ //add the value of the current element to the result if is set.
+ $value=$this->_getValue($element);
+ if ($value!==null)
+ $result[]=$value;
+
+ //walk through the list until it's end
+ $nextElement=$this->_getRestElement($element);
+ if (($nextElement !== null) && ($nextElement->getURI()!==RDF_NAMESPACE_URI.RDF_NIL))
+ {
+ $element=$nextElement;
+ } else
+ {
+ break;
+ }
+ }
+ //return the result
+ return $result;
+ }
+
+ /**
+ * Change the tail of this list to point to the given list, so that this list
+ * becomes the list of the concatenation of the elements of
+ * both lists. This is a side-effecting operation on this list;
+ * for a non side-effecting alternative, see append.
+ *
+ *
+ * @param object ResList $ResList
+ * @access public
+ */
+ function concatenate($ResList)
+ {
+ //get the last list element
+ $lastElement=$this->_getListElement();
+ //remove the old tail (rdf:nil)
+ $lastElement->removeAll($this->rdfRestResource);
+ //add the $ResList as new tail
+ $lastElement->addProperty($this->rdfRestResource,$ResList);
+ }
+
+ /**
+ * Answer a new list that is formed by adding each element of
+ * this list to the head of the given list. This is a non
+ * side-effecting operation on either this list or the given
+ * list, but generates a copy of this list. For a more storage
+ * efficient alternative, see concatenate
+ *
+ * @param object ResList $ResList
+ * @return object ResList
+ * @access public
+ */
+ function append($resList)
+ {
+ //get a copy of this list
+ $newList=$this->copy();
+
+ //add all values from the $resList to the new list
+ foreach ($resList->getContentInArray() as $value)
+ {
+ $newList->add($value);
+ }
+ //return the new list
+ return $newList;
+ }
+
+ /**
+ * Answer a list that contains all of the elements of this
+ * list in the same order, but is a duplicate copy in the
+ * underlying model.
+ *
+ * @return object ResList
+ * @access public
+ */
+ function copy()
+ {
+ //create a new list in the model
+ $newList=$this->model->createList();
+ //add all values from this list to the new list
+ foreach ($this->getContentInArray() as $value)
+ {
+ $newList->add($value);
+ }
+ //return the new list
+ return $newList;
+ }
+
+ /**
+ * Return a reference to a new list cell whose head is value
+ * and whose tail is this list.
+ *
+ * @param object ResResource $value
+ * @return object ResList
+ * @access public
+ */
+ function cons($value)
+ {
+ //create a new list
+ $newList=$this->model->createList();
+ //add the new value
+ $newList->add($value);
+ //set this list as the tail of the new list
+ $newList->setTail($this);
+
+ //return the new list
+ return $newList;
+ }
+
+ /**
+ * Update the list cell at the front of the list to have the
+ * given list as tail. The old tail is returned, and remains
+ * in the model.
+ *
+ * @param object ResList $resList
+ * @return object Reslist
+ * @access public
+ */
+ function setTail($resList)
+ {
+ //save the old tail
+ $oldTail=$this->getTail();
+ //remove the old tail
+ $this->removeAll($this->rdfRestResource);
+ //add the $resList as new Tail
+ $this->addProperty($this->rdfRestResource,$resList);
+
+ //return the old tail
+ return $oldTail;
+ }
+
+ /**
+ * Answer true if this list has the same elements in the
+ * same order as the given list. Note that the standard equals
+ * test just tests for equality of two given list cells.
+ * While such a test is sufficient for many purposes, this
+ * test provides a broader equality definition, but is
+ * correspondingly more expensive to test.
+ *
+ * @param object ResList $resList
+ * @return boolean
+ * @access public
+ */
+ function sameListAs($resList)
+ {
+ //init
+ $indexPos=0;
+ do
+ {
+ //get the values for both lists at the actual position
+ $thisValue=$this->get($indexPos);
+ $thatValue=$resList->get($indexPos);
+ //if the values aren't equal, return false
+ if (($thisValue !== null) && !$thisValue->equals($thatValue))
+ return false;
+
+ $indexPos++;
+ //walk until this list reaches a null value (end)
+ } while ($thisValue!==null);
+
+ //if the other list has a null value at this position too, return true
+ //else return false
+ return ($thatValue===null);
+ }
+
+ /**
+ * Remove the given value from this list.
+ * If value does not occur in the list, no action is taken. Since removing the
+ * head of the list will invalidate the list head cell, in
+ * general the list must return the list that results from
+ * this operation. However, in many cases the return value
+ * will be the same as the object that this method is invoked
+ * on.
+ *
+ * @param object ResResource $value
+ * @return object ResList
+ * @access public
+ */
+ function remove($value)
+ {
+ //if the value is the value of the first list element(head)
+ //call the remove head position and return the new head
+ if ($value->equals($this->_getValue($this)))
+ return $this->removeHead();
+
+ $element=$this;
+ do
+ {
+ $newElement=$this->_getRestElement($element);
+
+ //if the value equals the value of the current list element
+ if ($newElement !== null && $value->equals($this->_getValue($newElement)))
+ {
+ //remove the link to the list element to be removed
+ $element->removeAll($this->rdfRestResource);
+ //add a link to the list element AFTER the element to be deleted
+ $element->addProperty($this->rdfRestResource,$this->_getRestElement($newElement));
+ //remove the list element with values
+ $newElement->removeAll($this->rdfFirstResource);
+ $newElement->removeAll($this->rdfRestResource);
+ //return this ResList
+ return $this;
+ }
+ $element=$newElement;
+ } while ($element!==null);
+ //return this list
+ return $this;
+ }
+
+ /**
+ * Answer true if the list is well-formed, by checking that each
+ * node is correctly typed, and has a head and tail pointer from
+ * the correct vocabulary
+ *
+ * @return boolean
+ * @access public
+ */
+ function isValid()
+ {
+ $element=$this;
+ if ($this->_getValue($this)=== null && $this->_getRestElement($this) === null)
+ return true;
+ do
+ {
+ //return true if the last element is a rdf:nil
+ if ($element->getURI() == RDF_NAMESPACE_URI.RDF_NIL)
+ return true;
+ //return false, if the current element has no associated value
+ if ($this->_getValue($element) === null)
+ return false;
+
+ $element=$this->_getRestElement($element);
+ } while ($element !== null);
+ //return false, if the current element has no rdf:rest property
+ return false;
+ }
+
+ /**
+ * Get the associated rdf:rest Resource from the suplied ResList element
+ *
+ * @param object ResList $listElement
+ * @return object ResList
+ * @access private
+ */
+ function _getRestElement($listElement)
+ {
+ //get the rdf:rest property
+ $statement= $this->model->getProperty($listElement,$this->rdfRestResource);
+ //return null, if this property isn't set
+ if ($statement === null)
+ return null;
+
+ //return the value of the rdf:rest property
+ return $statement->getObject();
+ }
+
+ /**
+ * Returns the list element at the $index position.
+ *
+ * If to $index is suplied, the last list element will be returned
+
+ * @param integer $index
+ * @return object ResResource
+ * @access private
+ */
+ function _getListElement($index = null)
+ {
+ $element=$this;
+ $actualIndex=0;
+
+ while ($element!=null)
+ {
+ //return the current element if index matches the current index
+ if ($actualIndex === $index)
+ return $element;
+
+ //return the current element if it the last one
+ if ($element->hasProperty($this->rdfRestResource,$this->rdfNilResource))
+ return $element;
+
+ $nextElement=$this->_getRestElement($element);
+
+ if ($nextElement!==null)
+ {
+ $element=$nextElement;
+ $actualIndex++;
+ } else
+ {
+ break;
+ }
+ }
+ return $element;
+ }
+
+ /**
+ * Get the value associated to the $listResource by the rdf:first property
+ *
+ * @param object ResList $listResource
+ * @return object ResResource
+ * @access private
+ */
+ function _getValue($listResource)
+ {
+ //Return the value of the rdf:first property or null, if it isn't set
+ $statement=$this->model->getProperty($listResource,$this->rdfFirstResource);
+ if ($statement===null)
+ return null;
+
+ return $statement->getObject();
+ }
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/ResLiteral.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/ResLiteral.php
new file mode 100755
index 00000000..2c059e8a
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/ResLiteral.php
@@ -0,0 +1,65 @@
+
+
+*
+* @package resModel
+* @access public
+**/
+
+class ResLiteral extends Literal
+{
+ /**
+ * Holds a reference to the associated model
+ * @var ResModel
+ * @access private
+ */
+ var $model;
+
+
+ /**
+ * Constructor
+ * You have to supply a string.
+ *
+ * @param string $str label of the literal
+ * @param string $language optional language identifier
+ */
+ function ResLiteral($str,$language = null)
+ {
+ parent::Literal($str,$language);
+
+ }
+
+ /**
+ * Sets the reference to the assocoated model.
+ *
+ * @param object model $model
+ * @access public
+ */
+ function setAssociatedModel(& $model)
+ {
+ $this->model=& $model;
+ }
+
+ /**
+ * Get the reference to the assocoated model.
+ *
+ * @return object model $model
+ * @access public
+ */
+ function & getAssociatedModel()
+ {
+ return $this->model;
+ }
+
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/ResModel.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/ResModel.php
new file mode 100755
index 00000000..0aa16b43
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/ResModel.php
@@ -0,0 +1,876 @@
+
+*
+*
+* @package resModel
+* @access public
+**/
+
+class ResModel
+{
+
+ /**
+ * Holds a reference to the assoiated memmodel/dbmodel/infmodel
+ * @var ResResource
+ * @access private
+ */
+ var $model;
+
+
+ /**
+ * Constructor
+ * You have to supply a memmodel/dbmodel/infmodel to save the statements.
+ *
+ * @param object model $model
+ * @access public
+ */
+ function ResModel(& $model)
+ {
+ if (!is_a($model,'Model'))
+ trigger_error(RDFAPI_ERROR . '(class: ResourceLayer; method: ResourceLayer):
+ $model has to be object of class Model', E_USER_ERROR);
+
+ $this->model =& $model;
+ }
+
+ /**
+ * Create a new resource associated with this model.
+ * If the uri string isn't set, this creates a bnode.
+ * Otherwise it creates a URI node.
+ * A URI resource is .equals() to any other URI Resource with the same URI
+ * (even in a different model - be warned).
+ *
+ * This method may return an existing Resource with the correct URI and model,
+ * or it may construct a fresh one, as it sees fit.
+ *
+ * Operations on the result Resource may change this model.
+ *
+ * @param string $uri
+ * @return object ResResource
+ * @access public
+ */
+ function createResource($uri = null)
+ {
+ $resResource = new ResResource($uri);
+ //associate the resource with this model, and get a unique identifier
+ //if it is bnode.
+ $resResource->setAssociatedModel($this);
+
+ return $resResource;
+ }
+
+ /**
+ * Create a new Property associated with this model.
+ * This method may return an existing property with the correct URI and model,
+ * or it may construct a fresh one, as it sees fit.
+ *
+ * Subsequent operations on the returned property may modify this model.
+ *
+ *
+ * @param string $uri
+ * @return object ResProperty
+ * @access public
+ */
+ function createProperty($uri = null)
+ {
+ $resProperty = new ResProperty($uri);
+ $resProperty->setAssociatedModel($this);
+
+ return $resProperty;
+ }
+
+ /**
+ * Create an untyped literal from a String value with a specified language.
+ *
+ * If you want to type this literal, you have to set a datatype before
+ * adding it to the model.
+ *
+ *
+ * @param string $label
+ * @param string $languageTag
+ * @return object ResLiteral
+ * @access public
+ */
+ function createLiteral($label,$languageTag = null)
+ {
+ $resLiteral = new ResLiteral($label,$languageTag);
+ $resLiteral->setAssociatedModel($this);
+
+ return $resLiteral;
+ }
+
+ /**
+ * General method to search for triples.
+ * NULL input for any parameter will match anything.
+ * Example: $result = $m->find( NULL, NULL, $node );
+ * Finds all Statements with $node as object.
+ * Returns an array of statements with ResResources.
+ *
+ * @param object ResResource $subject
+ * @param object ResResource $predicate
+ * @param object ResResource $object
+ * @return array
+ * @access public
+ * @throws PhpError
+ */
+ function find($subject,$predicate, $object)
+ {
+ $result=array();
+ //convert ResResources to Resources and Blanknodes
+ $resmodel=$this->model->find( $this->_resNode2Node($subject),
+ $this->_resNode2Node($predicate),
+ $this->_resNode2Node($object)
+ );
+ //convert Resources, Blanknodes to ResResources
+ foreach ($resmodel->triples as $statement)
+ {
+ $result[]=new Statement($this->_node2ResNode($statement->getSubject()),
+ $this->_node2ResNode($statement->getPredicate(),true),
+ $this->_node2ResNode($statement->getObject())
+ );
+ };
+ return $result;
+
+ }
+
+ /**
+ * Searches for triples and returns the first matching statement.
+ * NULL input for any parameter will match anything.
+ * Example: $result = $m->findFirstMatchingStatement( NULL, NULL, $node );
+ * Returns the first statement with ResResources of the Model where the object equals $node.
+ * Returns an NULL if nothing is found.
+ * You can define an offset to search.
+ *
+ * @param object Node $subject
+ * @param object Node $predicate
+ * @param object Node $object
+ * @param integer $offset
+ * @return object Statement
+ * @access public
+ */
+ function findFirstMatchingStatement($subject,$predicate,$object,$offset = 0)
+ {
+
+ $statement = $this->model->findFirstMatchingStatement( $this->_resNode2Node($subject),
+ $this->_resNode2Node($predicate),
+ $this->_resNode2Node($object),
+ $offset
+ );
+ if ($statement!==null)
+ {
+ return new Statement( $this->_node2ResNode($statement->getSubject()),
+ $this->_node2ResNode($statement->getPredicate(),true),
+ $this->_node2ResNode($statement->getObject())
+ );
+ } else
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Adds a new triple to the Model without checking if the statement is already in the Model.
+ * So if you want a duplicate free Model use the addWithoutDuplicates() function (which is slower then add())
+ * Expects a statements with ResResources(ResLiterals)
+ *
+ * @param object Statement $statement
+ * @access public
+ * @throws PhpError
+ */
+ function add($statement)
+ {
+ return $this->model->add(new Statement( $this->_resNode2Node($statement->getSubject()),
+ $this->_resNode2Node($statement->getPredicate()),
+ $this->_resNode2Node($statement->getObject()))
+ );
+ }
+ /**
+ * Checks if a new statement is already in the Model and adds the statement, if it is not in the Model.
+ * addWithoutDuplicates() is significantly slower then add().
+ * Retruns TRUE if the statement is added.
+ * FALSE otherwise.
+ * Expects a statements with ResResources(ResLiterals)
+ *
+ * @param object Statement $statement
+ * @return boolean
+ * @access public
+ * @throws PhpError
+ */
+ function addWithoutDuplicates($statement)
+ {
+ return $this->model->addWithoutDuplicates(new Statement($this->_resNode2Node($statement->getSubject()),
+ $this->_resNode2Node($statement->getPredicate()),
+ $this->_resNode2Node($statement->getObject()))
+ );
+ }
+
+ /**
+ * Tests if the Model contains the given statement.
+ * TRUE if the statement belongs to the model;
+ * FALSE otherwise.
+ * Expects a statement of ResResources(ResLiterals)
+ *
+ * @param object Statement $statement
+ * @return boolean
+ * @access public
+ */
+ function contains(& $statement)
+ {
+
+ return $this->model->contains(new Statement($this->_resNode2Node($statement->getSubject()),
+ $this->_resNode2Node($statement->getPredicate()),
+ $this->_resNode2Node($statement->getObject()))
+ );
+ }
+
+ /**
+ * Determine if all of the statements in a model are also contained in this model.
+ * True if all of the statements in $model are also contained in this model and false otherwise.
+ *
+ * @param object Model &$model
+ * @return boolean
+ * @access public
+ */
+ function containsAll(& $model)
+ {
+ if (is_a($model,'ResModel'))
+ return $this->model->containsAll($model->getModel());
+
+ return $this->model->containsAll($model);
+ }
+
+ /**
+ * Determine if any of the statements in a model are also contained in this model.
+ * True if any of the statements in $model are also contained in this model and false otherwise.
+ *
+ * @param object Model &$model
+ * @return boolean
+ * @access public
+ */
+ function containsAny(& $model)
+ {
+ if (is_a($model,'ResModel'))
+ return $this->model->containsAny($model->getModel());
+ return $this->model->containsAny($model);
+ }
+
+ /**
+ * Determine if the node (ResResource / ResLiteral) $node appears in any statement of this model.
+ *
+ * @param object Node &$node
+ * @return boolean
+ * @access public
+ */
+ function containsResource(& $node)
+ {
+ if ($this->findFirstMatchingStatement($node,null,null) === null)
+ if ($this->findFirstMatchingStatement(null,$node,null) === null)
+ if ($this->findFirstMatchingStatement(null,null,$node) === null)
+ return false;
+
+ return true;
+ }
+
+ /**
+ * Create a literal from a String value with the $dtype Datatype
+ * An existing literal of the right value may be returned, or a fresh one created.
+ *
+ * @param string $value
+ * @param string $dtype
+ * @return object ResLiteral
+ * @access public
+ */
+ function createTypedLiteral($value,$dtype)
+ {
+ $resLiteral = new ResLiteral($value);
+ $resLiteral->setDatatype($dtype);
+ $resLiteral->setAssociatedModel($this);
+
+ return $resLiteral;
+ }
+
+ /**
+ * Checks if two models are equal.
+ * Two models are equal if and only if the two RDF graphs they represent are isomorphic.
+ *
+ * Warning: This method doesn't work correct with models where the same blank node has different
+ * identifiers in the two models. We will correct this in a future version.
+ *
+ * @access public
+ * @param object model &$that
+ * @throws phpErrpr
+ * @return boolean
+ */
+ function equals(& $that)
+ {
+ if (is_a($that,'ResModel'))
+ return $this->model->equals($that->getModel());
+ return $this->model->equals($that);
+ }
+
+ /**
+ * Returns a new model that is the subtraction of another model from this model.
+ *
+ * @param object Model $model
+ * @return object MemModel
+ * @access public
+ * @throws phpErrpr
+ */
+ function subtract($model)
+ {
+ if (is_a($model,'ResModel'))
+ return $this->model->subtract($model->getModel());
+ return $this->model->subtract($model);
+ }
+
+ /**
+ * Answer a statement find(s, p, null) with ResResources(ResLiterals) from this model.
+ * If none exist, return null; if several exist, pick one arbitrarily.
+ *
+ * @param object ResResource $subject
+ * @param object ResResource $property
+ * @return object Statement
+ * @access public
+ * @throws phpErrpr
+ */
+ function getProperty($subject,$property)
+ {
+
+ $statement= $this->model->findFirstMatchingStatement( $this->_resNode2Node($subject),
+ $this->_resNode2Node($property),
+ null
+ );
+ if ($statement === null)
+ return null;
+
+ return new Statement($this->_node2ResNode($statement->getSubject()),
+ $this->_node2ResNode($statement->getPredicate(),true),
+ $this->_node2ResNode($statement->getObject())
+ );
+
+ }
+
+ /**
+ * Checks if MemModel is empty
+ *
+ * @return boolean
+ * @access public
+ */
+ function isEmpty()
+ {
+ return $this->model->isEmpty();
+ }
+
+ /**
+ * Returns a ResIterator with all objects in a model.
+ *
+ * @return object ResIterator
+ * @access public
+ * @throws phpErrpr
+ */
+ function listObjects()
+ {
+ return $this->listObjectsOfProperty(null);
+ }
+
+ /**
+ * Returns a ResIterator with all objects with a given property and property value.
+ *
+ * @param object ResResource $property
+ * @param object ResResource $value
+ * @return object ResIterator
+ * @access public
+ */
+ function listObjectsOfProperty($property, $value = null)
+ {
+ return new ResIterator(null,$property,$value,'o',$this);
+ }
+
+
+ /**
+ * Returns a ResIterator with all subjects in a model.
+ *
+ * @return object ResIterator
+ * @access public
+ * @throws phpErrpr
+ */
+ function listSubjects()
+ {
+ return $this->listSubjectsWithProperty(null);
+ }
+
+ /**
+ * Returns a ResIterator with all subjects with a given property and property value.
+ *
+ * @param object ResResource $property
+ * @param object ResResource $value
+ * @return object ResIterator
+ * @access public
+ * @throws phpErrpr
+ */
+ function listSubjectsWithProperty($property,$value = null)
+ {
+ return new ResIterator(null,$property,$value,'s',$this);
+ }
+
+ /**
+ * Removes the statement of ResResources(ResTriples) from the MemModel.
+ * TRUE if the statement is removed.
+ * FALSE otherwise.
+ *
+ * @param object Statement $statement
+ * @return boolean
+ * @access public
+ * @throws PhpError
+ */
+ function remove($statement)
+ {
+ return $this->model->remove(new Statement( $this->_resNode2Node($statement->getSubject()),
+ $this->_resNode2Node($statement->getPredicate()),
+ $this->_resNode2Node($statement->getObject())
+ ));
+ }
+
+ /**
+ * Number of statements in the MemModel
+ *
+ * @return integer
+ * @access public
+ */
+ function size()
+ {
+ return $this->model->size();
+ }
+
+ /**
+ * Returns a new Model that is the set-union of the model with another model.
+ * Duplicate statements are removed. If you want to allow duplicates, use addModel() which is much faster.
+ *
+ * The result of taking the set-union of two or more RDF graphs (i.e. sets of triples)
+ * is another graph, which we will call the merge of the graphs.
+ * Each of the original graphs is a subgraph of the merged graph. Notice that when forming
+ * a merged graph, two occurrences of a given uriref or literal as nodes in two different
+ * graphs become a single node in the union graph (since by definition they are the same
+ * uriref or literal) but blank nodes are not 'merged' in this way; and arcs are of course
+ * never merged. In particular, this means that every blank node in a merged graph can be
+ * identified as coming from one particular graph in the original set of graphs.
+ *
+ * Notice that one does not, in general, obtain the merge of a set of graphs by concatenating
+ * their corresponding N-triples documents and constructing the graph described by the merged
+ * document, since if some of the documents use the same node identifiers, the merged document
+ * will describe a graph in which some of the blank nodes have been 'accidentally' merged.
+ * To merge Ntriples documents it is necessary to check if the same nodeID is used in two or
+ * more documents, and to replace it with a distinct nodeID in each of them, before merging the
+ * documents. (Not implemented yet !!!!!!!!!!!)
+ *
+ * @param object Model $model
+ * @return object MemModel
+ * @access public
+ * @throws phpErrpr
+ *
+ */
+ function & unite(& $model)
+ {
+ if (is_a($model,'ResModel'))
+ return $this->model->unite($model->getModel());
+ return $this->model->unite($model);
+ }
+
+ /**
+ * Adds another model to this MemModel.
+ * Duplicate statements are not removed.
+ * If you don't want duplicates, use unite().
+ * If any statement of the model to be added to this model contains a blankNode
+ * with an identifier already existing in this model, a new blankNode is generated.
+ *
+ * @param object Model $model
+ * @access public
+ * @throws phpErrpr
+ *
+ */
+ function addModel(&$model)
+ {
+ if (is_a($model,'ResModel'))
+ return $this->model->addModel($model->getModel());
+ return $this->model->addModel($model);
+ }
+
+ /**
+ * Create a new RDF Container from type rdf:Alt
+ * This method may return an existing container with the correct URI and model,
+ * or it may construct a fresh one, as it sees fit.
+ *
+ * Subsequent operations on the returned Container may modify this model.
+ *
+ *
+ * @param string $uri
+ * @return object ResProperty
+ * @access public
+ */
+ function createAlt($uri = null)
+ {
+ $resAlt = new ResAlt($uri);
+ $resAlt->setAssociatedModel($this);
+
+ return $resAlt;
+ }
+
+ /**
+ * Create a new RDF Container from type rdf:Bag
+ * This method may return an existing container with the correct URI and model,
+ * or it may construct a fresh one, as it sees fit.
+ *
+ * Subsequent operations on the returned Container may modify this model.
+ *
+ *
+ * @param string $uri
+ * @return object ResProperty
+ * @access public
+ */
+ function createBag($uri = null)
+ {
+ $resBag = new ResBag($uri);
+ $resBag->setAssociatedModel($this);
+
+ return $resBag;
+ }
+
+ /**
+ * Create a new RDF Container from type rdf:Seq
+ * This method may return an existing container with the correct URI and model,
+ * or it may construct a fresh one, as it sees fit.
+ *
+ * Subsequent operations on the returned Container may modify this model.
+ *
+ *
+ * @param string $uri
+ * @return object ResProperty
+ * @access public
+ */
+ function createSeq($uri = null)
+ {
+ $resSeq = new ResSeq($uri);
+ $resSeq->setAssociatedModel($this);
+
+ return $resSeq;
+ }
+
+ /**
+ * Create a new RDF Collection from type rdf:List
+ * This method may return an existing container with the correct URI and model,
+ * or it may construct a fresh one, as it sees fit.
+ *
+ * Subsequent operations on the returned Container may modify this model.
+ *
+ *
+ * @param string $uri
+ * @return object ResProperty
+ * @access public
+ */
+ function createList($uri = null)
+ {
+ $resList = new ResList($uri);
+ $resList->setAssociatedModel($this);
+
+ return $resList;
+ }
+
+ /**
+ * Returns a reference to the underlying model (Mem/DB/InfModel) that contains the statements
+ *
+ *
+ * @return object Model
+ * @access public
+ */
+ function & getModel()
+ {
+ return $this->model;
+ }
+
+
+ /**
+ * Internal method, that returns a resource URI that is unique for the Model.
+ * URIs are generated using the base_uri of the Model, the prefix and a unique number.
+ * If no prefix is defined, the bNode prefix, defined in constants.php, is used.
+ *
+ * @param string $prefix
+ * @return string
+ * @access private
+ */
+ function getUniqueResourceURI($bnodePrefix)
+ {
+ return $this->model->getUniqueResourceURI($bnodePrefix);
+ }
+
+ /**
+ * Load a model from a file containing RDF, N3 or N-Triples.
+ * This function recognizes the suffix of the filename (.n3 or .rdf) and
+ * calls a suitable parser, if no $type is given as string ("rdf" "n3" "nt");
+ * If the model is not empty, the contents of the file is added to this DbModel.
+ *
+ * @param string $filename
+ * @param string $type
+ * @param boolean $stream
+ * @access public
+ */
+ function load($filename, $type = NULL, $stream=false)
+ {
+ $this->model->load($filename, $type, $stream);
+ }
+
+ /**
+ * Return current baseURI.
+ *
+ * @return string
+ * @access public
+ */
+ function getBaseURI()
+ {
+ return $this->model->getBaseURI();
+ }
+
+ /**
+ * Saves the RDF,N3 or N-Triple serialization of the MemModel to a file.
+ * You can decide to which format the model should be serialized by using a
+ * corresponding suffix-string as $type parameter. If no $type parameter
+ * is placed this method will serialize the model to XML/RDF format.
+ * Returns FALSE if the MemModel couldn't be saved to the file.
+ *
+ * @access public
+ * @param string $filename
+ * @param string $type
+ * @throws PhpError
+ * @return boolean
+ */
+ function saveAs($filename, $type ='rdf')
+ {
+ return $this->model->saveAs($filename, $type ='rdf');
+ }
+
+ /**
+ * Writes the RDF serialization of the MemModel as HTML table.
+ *
+ * @access public
+ */
+ function writeAsHTMLTable()
+ {
+ $this->model->writeAsHtmlTable();
+ }
+
+ /**
+ * Returns a new model containing all the statements which are in both this model and another.
+ *
+ * @param object Model $model
+ * @return object MemModel
+ * @access public
+ * @throws phpErrpr
+ */
+ function & intersect(& $model)
+ {
+ if (is_a($model,'ResModel'))
+ return $this->model->intersect($model->getModel());
+ return $this->model->intersect($model);
+ }
+
+ /**
+ * converts a Resource,Blanknode,Literal into a ResResource, ResProperty, or ResLiteral
+ *
+ * @param object Node $node
+ * @param boolean $isProperty
+ * @return object ResResource / ResProperty / ResLiteral
+ * @access private
+ * @throws phpErrpr
+ */
+ function _node2ResNode($node, $isProperty = false)
+ {
+ if (is_a($node,'Literal'))
+ {
+ $return= new ResLiteral($node->getLabel(),$node->getLanguage());
+ $return->setDatatype($node->getDatatype());
+ $return->setAssociatedModel($this);
+
+ return $return;
+ }
+ if (is_a($node,'Resource'))
+ {
+ if ($isProperty)
+ {
+ $res= new ResProperty($node->getLabel());
+ } else
+ {
+ $res= new ResResource($node->getLabel());
+ }
+ $res->setAssociatedModel($this);
+ if (is_a($node,'Blanknode'))
+ $res->setIsAnon(true);
+
+ return $res;
+ }
+ }
+
+ /**
+ * converts a ResResource, ResProperty, or ResLiteral into a Resource, Blanknode, or Literal
+ *
+ * @param object ResNode $resNode
+ * @return object Node
+ * @access private
+ * @throws phpErrpr
+ */
+ function _resNode2Node($resNode)
+ {
+ if (is_a($resNode,'ResResource'))
+ {
+ if ($resNode->getIsAnon())
+ {
+ $return=new BlankNode($resNode->getURI());
+ } else
+ {
+ $return=new Resource($resNode->getURI());
+ }
+ return $return;
+ }
+
+ if (is_a($resNode,'ResLiteral'))
+ {
+ $literal=new Literal($resNode->getLabel(),$resNode->getLanguage());
+ if ($resNode->getDatatype() != null)
+ $literal->setDatatype($resNode->getDatatype());
+ return $literal;
+ }
+ }
+
+ /**
+ * Set a base URI for the MemModel.
+ * Affects creating of new resources and serialization syntax.
+ * If the URI doesn't end with # : or /, then a # is added to the URI.
+ * @param string $uri
+ * @access public
+ */
+ function setBaseURI($uri)
+ {
+ $this->model->setBaseURI($uri);
+ }
+
+ /**
+ * Writes the RDF serialization of the MemModel as HTML table.
+ *
+ * @access public
+ * @return string
+ */
+ function writeRdfToString()
+ {
+ return $this->model->writeRdfToString();
+ }
+
+ /**
+ * Perform an RDQL query on this MemModel.
+ * This method returns an associative array of variable bindings.
+ * The values of the query variables can either be RAP's objects (instances of Node)
+ * if $returnNodes set to TRUE, or their string serialization.
+ *
+ * @access public
+ * @param string $queryString
+ * @param boolean $returnNodes
+ * @return array [][?VARNAME] = object Node (if $returnNodes = TRUE)
+ * OR array [][?VARNAME] = string
+ *
+ */
+ function & rdqlQuery($queryString, $returnNodes = TRUE)
+ {
+ $ret = $this->model->rdqlQuery($queryString, $returnNodes);
+ return $ret;
+ }
+
+ /**
+ * Perform an RDQL query on this MemModel.
+ * This method returns an RdqlResultIterator of variable bindings.
+ * The values of the query variables can either be RAP's objects (instances of Node)
+ * if $returnNodes set to TRUE, or their string serialization.
+ *
+ * @access public
+ * @param string $queryString
+ * @param boolean $returnNodes
+ * @return object RdqlResultIterator = with values as object Node (if $returnNodes = TRUE)
+ * OR object RdqlResultIterator = with values as strings if (if $returnNodes = FALSE)
+ *
+ */
+ function rdqlQueryAsIterator($queryString, $returnNodes = TRUE)
+ {
+ return $this->model->rdqlQueryAsIterator($queryString, $returnNodes);
+ }
+
+
+ /**
+ * Returns the models namespaces.
+ *
+ * @author Tobias Gauß
+ * @access public
+ * @return Array
+ */
+ function getParsedNamespaces(){
+ return $this->model->getParsedNamespaces();
+ }
+
+
+
+ /**
+ * Adds the namespaces to the model. This method is called by
+ * the parser. !!!! addParsedNamespaces() not overwrites manual
+ * added namespaces in the model !!!!
+ *
+ * @author Tobias Gauß
+ * @access public
+ * @param Array $newNs
+ */
+ function addParsedNamespaces($newNs){
+ $this->model->addParsedNamespaces($newNs);
+ }
+
+
+ /**
+ * Adds a namespace and prefix to the model.
+ *
+ * @author Tobias Gauß
+ * @access public
+ * @param String $prefix, String $nmsp
+ */
+ function addNamespace($prefix, $namespace){
+ $this->model->addNamespace($prefix, $namespace);
+ }
+
+ /**
+ * removes a single namespace from the model
+ *
+ * @author Tobias Gauß
+ * @access public
+ * @param String $nmsp
+ */
+ function removeNamespace($nmsp){
+ return $this->model->removeNamespace($nmsp);
+ }
+
+
+
+
+
+
+}
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/ResModelP.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/ResModelP.php
new file mode 100755
index 00000000..276ded65
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/ResModelP.php
@@ -0,0 +1,24 @@
+
+//
+// ----------------------------------------------------------------------------------
+
+// Include ResModel classes
+require_once( RDFAPI_INCLUDE_DIR . 'resModel/ResModel.php');
+require_once( RDFAPI_INCLUDE_DIR . 'resModel/ResResource.php');
+require_once( RDFAPI_INCLUDE_DIR . 'resModel/ResContainer.php');
+require_once( RDFAPI_INCLUDE_DIR . 'resModel/ResAlt.php');
+require_once( RDFAPI_INCLUDE_DIR . 'resModel/ResBag.php');
+require_once( RDFAPI_INCLUDE_DIR . 'resModel/ResLiteral.php');
+require_once( RDFAPI_INCLUDE_DIR . 'resModel/ResProperty.php');
+require_once( RDFAPI_INCLUDE_DIR . 'resModel/ResSeq.php');
+require_once( RDFAPI_INCLUDE_DIR . 'resModel/ResIterator.php');
+require_once( RDFAPI_INCLUDE_DIR . 'resModel/ResList.php');
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/ResProperty.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/ResProperty.php
new file mode 100755
index 00000000..812b8f49
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/ResProperty.php
@@ -0,0 +1,32 @@
+
+*
+*
+* @package resModel
+* @access public
+**/
+class ResProperty extends ResResource
+{
+
+ /**
+ * Constructor
+ * You can supply a URI
+ *
+ * @param string $uri
+ * @access public
+ */
+ function ResProperty($uri)
+ {
+ parent::ResResource($uri);
+ }
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/ResResource.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/ResResource.php
new file mode 100755
index 00000000..e23ec1d6
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/ResResource.php
@@ -0,0 +1,212 @@
+
+*
+*
+* @package resModel
+* @access public
+**/
+class ResResource extends Resource
+{
+ /**
+ * Holds a reference to the associated model
+ * @var ResModel
+ * @access private
+ */
+ var $model;
+
+ /**
+ * Is true, if this resource is an anonymous node.
+ * @var boolean
+ * @access private
+ */
+ var $isAnon;
+
+
+ /**
+ * Constructor
+ * You can supply a uri
+ *
+ * @param string $uri
+ * @access public
+ */
+ function ResResource($uri)
+ {
+ parent::Resource($uri);
+ $this->isAnon = ($uri === null);
+ }
+
+ /**
+ * Sets the reference to the assocoated model.
+ *
+ * @param object Model $model
+ * @access public
+ */
+ function setAssociatedModel(& $model)
+ {
+ $this->model=& $model;
+ if ($this->isAnon)
+ $this->uri=$this->model->getUniqueResourceURI(BNODE_PREFIX);
+ }
+
+ /**
+ * Get the reference to the assocoated model.
+ *
+ * @return object Model $model
+ * @access public
+ */
+ function getAssociatedModel()
+ {
+ return $this->model;
+ }
+
+ /**
+ * Sets the URI of this resource
+ *
+ * @param string $uri
+ * @access public
+ */
+ function setURI($uri)
+ {
+ $this->uri = $uri;
+ }
+
+ /**
+ * Add a property to this resource.
+ * A statement with this resource as the subject, p as the predicate and o
+ * as the object is added to the model associated with this resource.
+ *
+ * @param ResResource $property
+ * @param ResResource/ResLiteral $object
+ * @return object ResResource
+ * @access public
+ */
+ function addProperty($property,$object)
+ {
+ $this->model->add(new Statement($this,$property,$object));
+
+ return $this;
+ }
+
+ /**
+ * List all the values with the property p as statements in an array.
+ *
+ * @param ResResource $property
+ * @return ResIterator
+ * @access public
+ */
+ function listProperties($property = null)
+ {
+ return $this->model->find($this,$property,null);
+ }
+
+ /**
+ * Answer some statement (this, p, O) in the associated model.
+ * If there are several such statements, any one of them may be returned.
+ * If no such statements exist, null is returned.
+ *
+ * @param ResResource $property
+ * @return object ResResource
+ * @access public
+ */
+ function getProperty($property)
+ {
+ return $this->model->getProperty($this,$property);
+ }
+
+ /**
+ * Determine whether this resource has any values for a given property.
+ *
+ * @param ResResource $property
+ * @param ResResource $value
+ * @return object ResResource
+ * @access public
+ */
+ function hasProperty($property, $value = null)
+ {
+ $ret= $this->model->findFirstMatchingStatement($this,$property,$value);
+
+ return ($ret!==null);
+ }
+
+ /**
+ * Determine whether this resource is an anonymous resource
+ *
+ * @return boolean
+ * @access public
+ */
+ function getIsAnon()
+ {
+ return $this->isAnon;
+ }
+
+ /**
+ * Set whether this resource is an anonymous resource
+ *
+ * @param boolean
+ * @access public
+ */
+ function setIsAnon($isAnon)
+ {
+ $this->isAnon=$isAnon;
+ }
+
+ /**
+ * Checks if the resource equals another resource.
+ * Two resources are equal, if they have the same URI
+ *
+ * @access public
+ * @param object resource $that
+ * @return boolean
+ */
+ function equals ($that)
+ {
+ if (is_a($that,'ResLiteral'))
+ return $that->equals($this);
+
+ return ($that!==null && ($this->getURI() == $that->getURI()));
+ }
+
+ /**
+ * Delete all the statements with predicate p for this resource from
+ * its associated model.
+ *
+ * @access public
+ * @param object resource $property
+ * @return object ResResource
+ */
+ function removeAll($property = null)
+ {
+ foreach ($this->model->find($this,$property,null) as $statement)
+ {
+ $this->model->remove($statement);
+ }
+ return $this;
+ }
+
+ /**
+ * Delete all the properties for this resource from the associated model.
+ *
+ * @access public
+ * @return object ResResource
+ */
+ function removeProperties()
+ {
+ $this->removeAll();
+ return $this;
+ }
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/ResSeq.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/ResSeq.php
new file mode 100755
index 00000000..7623a68a
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/resModel/ResSeq.php
@@ -0,0 +1,153 @@
+
+*
+* @package resModel
+* @access public
+**/
+class ResSeq extends ResContainer
+{
+
+ /**
+ * Constructor
+ * You can supply a URI
+ *
+ * @param string $uri
+ * @access public
+ */
+ function ResSeq($uri = null)
+ {
+ parent::ResContainer($uri);
+ $this->containerType=new ResResource(RDF_NAMESPACE_URI.RDF_SEQ);
+ }
+
+ /**
+ * Insert a new member into the sequence at the specified position.
+ * The existing member at that position, and all others with higher indexes,
+ * have their index increased by one.
+ *
+ * @param integer $index
+ * @param object ResResource/ResLiteral $resResource
+ * @return boolean
+ * @access public
+ */
+ function addAtIndex($index, $object)
+ {
+ //get a members index
+ $memberIndex= $this->getMembers();
+
+ //type this container, if it isn't already typed
+ if(!$this->hasProperty(new ResResource(RDF_NAMESPACE_URI.RDF_TYPE)))
+ $this->addProperty(new ResResource(RDF_NAMESPACE_URI.RDF_TYPE),$this->containerType);
+
+ //renumber all higher members
+ for ($i = count($memberIndex);$i >= $index ; $i--)
+ {
+ $this->removeAll($this->_getMembershipPropertyWithIndex($i));
+ $this->addProperty($this->_getMembershipPropertyWithIndex($i+1),$memberIndex[$i]);
+ }
+ //remove the old value at this position
+ $this->removeAll($this->_getMembershipPropertyWithIndex($index));
+ //add the new value
+ $this->addProperty($this->_getMembershipPropertyWithIndex($index),$object);
+
+ return $this;
+ }
+
+ /**
+ * Get the member at a given index
+ *
+ * @param integer $index
+ * @return object ResResource/ResLiteral
+ * @access public
+ */
+ function getMember($index)
+ {
+ $result=$this->listProperties($this->_getMembershipPropertyWithIndex($index));
+ if (isset($result[0]))
+ {
+ return $result[0];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Return the index of a given member of the sequence.
+ * If the same value appears more than once in the sequence, it is undefined
+ * which of the indexes will be returned.
+ * If the member is not found in this sequence, a value of 0 is returned.
+ *
+ * @param object ResResource/ResLiteral $object
+ * @return integer
+ * @access public
+ */
+ function indexOf($object)
+ {
+ //check all members, until $object is found
+ foreach ($this->listProperties() as $statement)
+ {
+ $predicateLabel=$statement->getLabelPredicate();
+ if ($this->_predicateLabelMatchesMembershipProperty($predicateLabel))
+ {
+ if($object->equals($statement->getObject()))
+ //analyze the container membership property and return the index
+ return $this->_getMemberIndexNrFromMembershipPropertyLabel($predicateLabel);
+ }
+ }
+ //return 0 if $object wasn't found
+ return 0;
+ }
+
+ /**
+ * Remove the member at the specified index.
+ * All other members with a higher index will have their index reduced by one.
+ *
+ * @param integer $index
+ * @access public
+ */
+ function removeAtIndex($index)
+ {
+ $memberIndex= $this->getMembers();
+
+
+ $this->removeAll($this->_getMembershipPropertyWithIndex($index));
+
+ for ($i = $index;$i < count($memberIndex); $i++)
+ {
+ $this->removeAll($this->_getMembershipPropertyWithIndex($i+1));
+ $this->addProperty($this->_getMembershipPropertyWithIndex($i),$memberIndex[$i+1]);
+ }
+ return $this;
+ }
+
+ /**
+ * Set the value at a given index in the sequence.
+ *
+ * If the index is not in the range of the sequence, false is returned
+ *
+ * @param integer $index
+ * @return boolean
+ * @access public
+ */
+ function set($index, $object)
+ {
+ if (!$this->hasProperty($this->_getMembershipPropertyWithIndex($index)))
+ return false;
+
+ $this->removeAll($this->_getMembershipPropertyWithIndex($index));
+ $this->addProperty($this->_getMembershipPropertyWithIndex($index),$object);
+ return true;
+ }
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/all-wcprops b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/all-wcprops
new file mode 100755
index 00000000..c66fd803
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/all-wcprops
@@ -0,0 +1,83 @@
+K 25
+svn:wc:ra_dav:version-url
+V 60
+/svnroot/rdfapi-php/!svn/ver/554/trunk/rdfapi-php/api/sparql
+END
+FilterFunctions.php
+K 25
+svn:wc:ra_dav:version-url
+V 80
+/svnroot/rdfapi-php/!svn/ver/465/trunk/rdfapi-php/api/sparql/FilterFunctions.php
+END
+SparqlEngineDb.php
+K 25
+svn:wc:ra_dav:version-url
+V 79
+/svnroot/rdfapi-php/!svn/ver/537/trunk/rdfapi-php/api/sparql/SparqlEngineDb.php
+END
+SparqlParserException.php
+K 25
+svn:wc:ra_dav:version-url
+V 86
+/svnroot/rdfapi-php/!svn/ver/465/trunk/rdfapi-php/api/sparql/SparqlParserException.php
+END
+GraphPattern.php
+K 25
+svn:wc:ra_dav:version-url
+V 77
+/svnroot/rdfapi-php/!svn/ver/465/trunk/rdfapi-php/api/sparql/GraphPattern.php
+END
+SparqlParser.php
+K 25
+svn:wc:ra_dav:version-url
+V 77
+/svnroot/rdfapi-php/!svn/ver/538/trunk/rdfapi-php/api/sparql/SparqlParser.php
+END
+SparqlClient.php
+K 25
+svn:wc:ra_dav:version-url
+V 77
+/svnroot/rdfapi-php/!svn/ver/465/trunk/rdfapi-php/api/sparql/SparqlClient.php
+END
+SPARQL.php
+K 25
+svn:wc:ra_dav:version-url
+V 71
+/svnroot/rdfapi-php/!svn/ver/425/trunk/rdfapi-php/api/sparql/SPARQL.php
+END
+ClientQuery.php
+K 25
+svn:wc:ra_dav:version-url
+V 76
+/svnroot/rdfapi-php/!svn/ver/465/trunk/rdfapi-php/api/sparql/ClientQuery.php
+END
+Constraint.php
+K 25
+svn:wc:ra_dav:version-url
+V 75
+/svnroot/rdfapi-php/!svn/ver/465/trunk/rdfapi-php/api/sparql/Constraint.php
+END
+Query.php
+K 25
+svn:wc:ra_dav:version-url
+V 70
+/svnroot/rdfapi-php/!svn/ver/548/trunk/rdfapi-php/api/sparql/Query.php
+END
+QueryTriple.php
+K 25
+svn:wc:ra_dav:version-url
+V 76
+/svnroot/rdfapi-php/!svn/ver/465/trunk/rdfapi-php/api/sparql/QueryTriple.php
+END
+SparqlEngine.php
+K 25
+svn:wc:ra_dav:version-url
+V 77
+/svnroot/rdfapi-php/!svn/ver/466/trunk/rdfapi-php/api/sparql/SparqlEngine.php
+END
+SparqlVariable.php
+K 25
+svn:wc:ra_dav:version-url
+V 79
+/svnroot/rdfapi-php/!svn/ver/465/trunk/rdfapi-php/api/sparql/SparqlVariable.php
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/entries b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/entries
new file mode 100755
index 00000000..1931791f
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/entries
@@ -0,0 +1,202 @@
+8
+
+dir
+556
+https://rdfapi-php.svn.sourceforge.net/svnroot/rdfapi-php/trunk/rdfapi-php/api/sparql
+https://rdfapi-php.svn.sourceforge.net/svnroot/rdfapi-php
+
+
+
+2007-12-05T08:18:50.037887Z
+554
+fusel2k
+
+
+svn:special svn:externals svn:needs-lock
+
+
+
+
+
+
+
+
+
+
+
+b2ee660e-c932-0410-bdee-d8da4d8102f4
+
+SparqlParserException.php
+file
+
+
+
+
+2008-02-29T14:57:47.256327Z
+52fce867873fe06a401a23ebeeb2891d
+2007-06-27T16:47:57.067358Z
+465
+cweiske
+has-props
+
+SparqlEngineDb.php
+file
+
+
+
+
+2008-02-29T14:57:47.240706Z
+df70f3cbf964025d3bedc17278c18a3c
+2007-09-18T17:55:11.280870Z
+537
+cweiske
+has-props
+
+GraphPattern.php
+file
+
+
+
+
+2008-02-29T14:57:47.256327Z
+094e348604b15b3f74f4acc02c0865ed
+2007-06-27T16:47:57.067358Z
+465
+cweiske
+has-props
+
+SparqlClient.php
+file
+
+
+
+
+2008-02-29T14:57:47.287568Z
+22707c51f0712c6366f882a3b965ea0a
+2007-06-27T16:47:57.067358Z
+465
+cweiske
+has-props
+
+SPARQL.php
+file
+
+
+
+
+2008-02-29T14:57:47.287568Z
+ac9473fe66b517131684146b7dcb072e
+2007-05-01T12:59:18.000000Z
+425
+cweiske
+has-props
+
+SparqlEngine
+dir
+
+ClientQuery.php
+file
+
+
+
+
+2008-02-29T14:57:47.287568Z
+042f95b0a1fb7f4f937d7311133884bb
+2007-06-27T16:47:57.067358Z
+465
+cweiske
+has-props
+
+Query.php
+file
+
+
+
+
+2008-02-29T14:57:47.303189Z
+396c7fc3c8c8adec28fbd14fc1fee33a
+2007-11-15T10:20:18.957776Z
+548
+fusel2k
+has-props
+
+SparqlVariable.php
+file
+
+
+
+
+2008-02-29T14:57:47.334430Z
+5f6220f5b0ed69ebb33741ac05a0787f
+2007-06-27T16:47:57.067358Z
+465
+cweiske
+
+SparqlEngineDb
+dir
+
+FilterFunctions.php
+file
+
+
+
+
+2008-02-29T14:57:47.240706Z
+ecfc1b457940a4ae21743cfe6b1cecce
+2007-06-27T16:47:57.067358Z
+465
+cweiske
+has-props
+
+SparqlParser.php
+file
+
+
+
+
+2008-02-29T14:57:47.271947Z
+57096a9f23a7ce8081766061d20fc3ce
+2007-09-19T19:35:23.227581Z
+538
+cweiske
+has-props
+
+Constraint.php
+file
+
+
+
+
+2008-02-29T14:57:47.303189Z
+7b563e3c50f93af9169fb469344ceab4
+2007-06-27T16:47:57.067358Z
+465
+cweiske
+has-props
+
+QueryTriple.php
+file
+
+
+
+
+2008-02-29T14:57:47.318809Z
+b2a8709f5397ebaa67b7fac97b32bfc0
+2007-06-27T16:47:57.067358Z
+465
+cweiske
+has-props
+
+SparqlEngine.php
+file
+
+
+
+
+2008-02-29T14:57:47.318809Z
+efddc5b74fa8beebf3213903c2ed30d6
+2007-07-04T08:44:01.466753Z
+466
+cweiske
+has-props
+
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/format b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/format
new file mode 100755
index 00000000..45a4fb75
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/format
@@ -0,0 +1 @@
+8
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/prop-base/ClientQuery.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/prop-base/ClientQuery.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/prop-base/ClientQuery.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/prop-base/Constraint.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/prop-base/Constraint.php.svn-base
new file mode 100755
index 00000000..bdbd3051
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/prop-base/Constraint.php.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:eol-style
+V 6
+native
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/prop-base/FilterFunctions.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/prop-base/FilterFunctions.php.svn-base
new file mode 100755
index 00000000..bdbd3051
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/prop-base/FilterFunctions.php.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:eol-style
+V 6
+native
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/prop-base/GraphPattern.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/prop-base/GraphPattern.php.svn-base
new file mode 100755
index 00000000..bdbd3051
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/prop-base/GraphPattern.php.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:eol-style
+V 6
+native
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/prop-base/Query.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/prop-base/Query.php.svn-base
new file mode 100755
index 00000000..bdbd3051
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/prop-base/Query.php.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:eol-style
+V 6
+native
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/prop-base/QueryTriple.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/prop-base/QueryTriple.php.svn-base
new file mode 100755
index 00000000..bdbd3051
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/prop-base/QueryTriple.php.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:eol-style
+V 6
+native
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/prop-base/SPARQL.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/prop-base/SPARQL.php.svn-base
new file mode 100755
index 00000000..bdbd3051
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/prop-base/SPARQL.php.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:eol-style
+V 6
+native
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/prop-base/SparqlClient.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/prop-base/SparqlClient.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/prop-base/SparqlClient.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/prop-base/SparqlEngine.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/prop-base/SparqlEngine.php.svn-base
new file mode 100755
index 00000000..bdbd3051
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/prop-base/SparqlEngine.php.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:eol-style
+V 6
+native
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/prop-base/SparqlEngineDb.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/prop-base/SparqlEngineDb.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/prop-base/SparqlEngineDb.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/prop-base/SparqlParser.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/prop-base/SparqlParser.php.svn-base
new file mode 100755
index 00000000..bdbd3051
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/prop-base/SparqlParser.php.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:eol-style
+V 6
+native
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/prop-base/SparqlParserException.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/prop-base/SparqlParserException.php.svn-base
new file mode 100755
index 00000000..bdbd3051
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/prop-base/SparqlParserException.php.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:eol-style
+V 6
+native
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/ClientQuery.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/ClientQuery.php.svn-base
new file mode 100755
index 00000000..a3fb5322
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/ClientQuery.php.svn-base
@@ -0,0 +1,56 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+
+class ClientQuery extends Object {
+
+ var $default = array();
+ var $named = array();
+ var $prefixes = array();
+ var $query;
+
+ /**
+ * Adds a default graph to the query object.
+ *
+ * @param String $default default graph name
+ */
+ function addDefaultGraph($default){
+ if(!in_array($this->named,$this->default))
+ $this->default[] = $default;
+ }
+ /**
+ * Adds a named graph to the query object.
+ *
+ * @param String $default named graph name
+ */
+ function addNamedGraph($named){
+ if(!in_array($named,$this->named))
+ $this->named[] = $named;
+ }
+ /**
+ * Adds the SPARQL query string to the query object.
+ *
+ * @param String $query the query string
+ */
+ function query($query){
+ $this->query = $query;
+ }
+
+}
+
+
+
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/Constraint.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/Constraint.php.svn-base
new file mode 100755
index 00000000..3d17430b
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/Constraint.php.svn-base
@@ -0,0 +1,95 @@
+
+* @version $Id$
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+Class Constraint extends Object{
+
+ /**
+ * The expression string.
+ * @var string
+ */
+ protected $expression;
+
+ /**
+ * True if it is an outer filter, false if not.
+ * @var boolean
+ */
+ protected $outer;
+
+ /**
+ * The expression tree
+ * @var array
+ */
+ protected $tree = null;
+
+ /**
+ * Adds an expression string.
+ *
+ * @param String $exp the expression String
+ * @return void
+ */
+ public function addExpression($exp)
+ {
+ $this->expression = $exp;
+ }
+
+ /**
+ * Returns the expression string.
+ *
+ * @return String the expression String
+ */
+ public function getExpression()
+ {
+ return $this->expression;
+ }
+
+
+ /**
+ * Sets the filter type to outer or inner filter.
+ * True for outer false for inner.
+ *
+ * @param boolean $boolean
+ * @return void
+ */
+ public function setOuterFilter($boolean)
+ {
+ $this->outer = $boolean;
+ }
+
+ /**
+ * Returns true if this constraint is an outer filter- false if not.
+ *
+ * @return boolean
+ */
+ public function isOuterFilter()
+ {
+ return $this->outer;
+ }
+
+
+ public function getTree()
+ {
+ return $this->tree;
+ }//public function getTree()
+
+ public function setTree($tree)
+ {
+ $this->tree = $tree;
+ }//public function setTree($tree)
+
+}
+// end class: Constraint.php
+?>
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/FilterFunctions.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/FilterFunctions.php.svn-base
new file mode 100755
index 00000000..ccd2c6ac
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/FilterFunctions.php.svn-base
@@ -0,0 +1,137 @@
+
+* @version $Id$
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+*/
+
+
+
+
+/**
+* Evaluates the regex() function. Returns true if the regex is matched false if not.
+*
+* @param String $string the string which has to be evaluated
+* @param String $pattern the regex pattern
+* @param String $flags additional flags like "i"
+* @return boolean
+*/
+function regex($string,$pattern,$flags = ''){
+ $string = trim($string);
+ $pattern = trim($pattern);
+ if(strpos($string,"str_")===0){
+ $string = substr($string,4);
+ $pattern = substr($pattern,4);
+ $flags = substr($flags,4);
+ }else{
+ return false;
+ }
+ if(preg_match('/'.$pattern.'/'.$flags,$string))
+ return true;
+ else
+ return false;
+}
+
+/**
+* Evaluates the dateTime() function.Tries to convert a date string into
+* a unix timestamp.
+*
+* @param String $string the date string
+* @return integer the corresponding unix timestamp
+*/
+function dateTime($string){
+ $string = trim($string);
+ if(strpos($string,"str_")===0)
+ $string = substr($string,4);
+
+ $time = strtotime($string);
+ if($time == -1)
+ return $string;
+ else
+ return $time;
+}
+
+
+/**
+* Evaluates the langMatches() function. Return true if the lang tag matches false if not.
+*
+* @param String $lang_range the string.
+* @param String $lang_tag the regex pattern
+* @return boolean
+*/
+function langMatches($lang_range,$lang_tag){
+
+ if($lang_range == null)
+ return false;
+
+ if(strpos($lang_range,"str_")===0)
+ $lang_range = substr($lang_range,4);
+ if(strpos($lang_tag,"str_")===0)
+ $lang_tag = substr($lang_tag,4);
+
+ if(strtolower($lang_range) == strtolower($lang_tag))
+ return true;
+ $tags = preg_match_all("/[^\-\s].[^\-\s]*/",$lang_range,$hits);
+ if($tags){
+ if($lang_tag == '*')
+ return true;
+ foreach($hits[0] as $tag){
+ if(strtolower($tag) == strtolower($lang_tag))
+ return true;
+ }
+ return false;
+ }else{
+ return false;
+ }
+}
+
+/**
+* Evaluates the str() function. Returns the string representation of a
+* variable or RDF term.
+*
+* @param String $string the string
+* @return boolean
+*/
+function str($string){
+ $str = preg_match("/\".[^\"]*\"|\'.[^\']*\'/",$string,$hits);
+ if($str != 0){
+ return "str_".$hits[0];
+ }else{
+ if(strpos($string,"str_")===0){
+ return $string;
+ }else{
+ if(strpos($string,"uri_")===0)
+ return "str_".substr($string,4);
+ if(strpos($string,'<')==0)
+ return "str_".substr($string,1,-1);
+ }
+ }
+ return false;
+}
+
+/**
+* Evaluates the lang() function. Returns lang tag of a Literal.
+*
+* @param String $string the string.
+* @return String the lang tag or false if there is no language tag.
+*/
+function lang($string){
+ $str = preg_match("/\".[^\"]*\"@(.[^\s]*)|\'.[^\']*\'@(.[^\s]*)/",$string,$hits);
+ if($str){
+ if($hits[1] != null)
+ return $hits[1];
+ else
+ return $hits[2];
+ }else{
+ return false;
+ }
+}
+
+
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/GraphPattern.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/GraphPattern.php.svn-base
new file mode 100755
index 00000000..bdddf39e
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/GraphPattern.php.svn-base
@@ -0,0 +1,295 @@
+
+* @version $Id$
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+
+class GraphPattern extends Object{
+
+ /**
+ * Graphname. 0 if its in the default graph.
+ */
+ protected $graphname = null;
+
+ /**
+ * Array of QueryTriple objects
+ * @var array
+ */
+ protected $triplePatterns = array();
+
+ /**
+ * A List of Constraint objects
+ * @var array
+ */
+ protected $constraints = array();
+
+ /**
+ * @var int Pointer to optional pattern.
+ */
+ protected $optional = null;
+
+ /**
+ * @var int Pointer to union pattern.
+ */
+ protected $union = null;
+
+ /**
+ * ID of the pattern in the pattern list that
+ * this pattern is subpattern of.
+ * @var int
+ */
+ protected $subpatternOf = null;
+
+ /**
+ * @var boolean TRUE if the pattern is open- FALSE if closed.
+ */
+ public $open = false;
+
+ /**
+ * @var boolean TRUE if the GraphPattern is a construct pattern.
+ */
+ public $isConstructPattern = false;
+
+
+ /**
+ * @var int The GraphPatterns id.
+ */
+ public $patternId = null;
+
+
+ /**
+ * Constructor
+ */
+ public function GraphPattern() {
+ $this->open = true;
+ $this->isConstructPattern = false;
+ $this->constraints = array();
+ $this->triplePatterns = array();
+ }
+
+ /**
+ * Returns the graphname.
+ *
+ * @return String
+ */
+ public function getGraphname(){
+ return $this->graphname;
+ }
+
+ /**
+ * Returns the triple pattern of the graph pattern.
+ *
+ * @return Array
+ */
+ public function getTriplePatterns(){
+ return $this->triplePatterns;
+ }
+
+ /**
+ * Returns a constraint if there is one false if not.
+ *
+ * @return Constraint
+ */
+ public function getConstraints() {
+ return $this->constraints;
+ }
+
+ /**
+ * Returns a pointer to an optional graph pattern.
+ *
+ * @return integer
+ */
+ public function getOptional() {
+ return $this->optional;
+ }
+
+ /**
+ * Returns a pointer to the parent pattern this pattern
+ * is subpattern of.
+ *
+ * @return integer
+ */
+ public function getSubpatternOf() {
+ return $this->subpatternOf;
+ }
+
+ /**
+ * Returns a pointer to a union graph pattern.
+ *
+ * @return integer
+ */
+ public function getUnion() {
+ return $this->union;
+ }
+
+ /**
+ * Sets the graphname.
+ *
+ * @param String $name
+ * @return void
+ */
+ public function setGraphname($name) {
+ $this->graphname = $name;
+ }
+
+ /**
+ * Adds List of QueryTriples to the GraphPattern.
+ *
+ * @param array $trpP
+ * @return void
+ */
+ public function addTriplePatterns($trpP) {
+ $this->triplePatterns = array_merge($this->triplePatterns, $trpP);
+ }
+
+ /**
+ * Sets the List of QueryTriples to the GraphPattern.
+ *
+ * @param array $trpP
+ * @return void
+ */
+ public function setTriplePatterns($trpP) {
+ $this->triplePatterns = $trpP;
+ }
+
+ /**
+ * Adds a single Constraint to the GraphPattern.
+ *
+ * @param Constraint $cons
+ */
+ public function addConstraint(&$cons) {
+ $this->constraints[] = $cons;
+ }
+
+ /**
+ * Adds an array of Constraint objects to the GraphPattern.
+ *
+ * @param array $cons
+ */
+ public function addConstraints(&$cons) {
+ $this->constraints = array_merge($this->constraints, $cons);
+ }
+
+ /**
+ * Adds a pointer to an optional graphPattern.
+ *
+ * @param integer $patternId
+ * @return void
+ */
+ public function setOptional($patternId) {
+ $this->optional = &$patternId;
+ }
+
+ /**
+ * Adds a pointer to a union graphPattern.
+ *
+ * @param integer $patternId
+ * @return void
+ */
+ public function setUnion($patternId) {
+ $this->union = &$patternId;
+ }
+
+ /**
+ * Adds a pointer to a pattern that
+ * this one is subpattern of
+ *
+ * @param integer $patternId
+ */
+ public function setSubpatternOf($patternId) {
+ $this->subpatternOf = $patternId;
+ }
+
+
+ /**
+ * Sets the GraphPatterns Id.
+ *
+ * @param integer $id
+ * @return void
+ */
+ public function setId($id){
+ $this->patternId = $id;
+ }
+
+ /**
+ * Returns the GraphPatterns id.
+ *
+ * @return integer
+ */
+ public function getId(){
+ return $this->patternId;
+ }
+
+
+
+ /**
+ * Returns an array of all variables used in this
+ * graph pattern.
+ * All variables are listed only once (unique).
+ *
+ * @return array Array of variable names
+ */
+ public function getVariables()
+ {
+ $arVars = array();
+
+ foreach ($this->triplePatterns as $pattern) {
+ $arVars = array_merge($arVars, $pattern->getVariables());
+ }
+
+ return array_unique($arVars);
+ }//public function getVariables()
+
+
+
+ /**
+ * Checks if the graph pattern is empty (contains no
+ * usable data).
+ * Occurs when using "{}" without pre- or suffixes
+ * WHERE
+ * {
+ * { ?person rdf:type foaf:Person } .
+ * }
+ *
+ * @return boolean True if the pattern is empty.
+ */
+ public function isEmpty()
+ {
+ return
+ count($this->triplePatterns) == 0
+ && count($this->constraints) == 0
+ && $this->getGraphname() === null
+ ;
+ }//public function isEmpty()
+
+
+
+ /**
+ * When cloning, we need to clone some subobjects, too
+ */
+ public function __clone()
+ {
+ if (count($this->triplePatterns) > 0) {
+ foreach ($this->triplePatterns as $nId => $pattern) {
+ $this->triplePatterns[$nId] = clone $this->triplePatterns[$nId];
+ }
+ }
+ if (count($this->constraints) > 0) {
+ foreach ($this->constraints as $nId => $constraint) {
+ $this->constraints[$nId] = clone $this->constraints[$nId];
+ }
+ }
+ }
+
+}// end class: GraphPattern.php
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/Query.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/Query.php.svn-base
new file mode 100755
index 00000000..2240a2f9
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/Query.php.svn-base
@@ -0,0 +1,685 @@
+
+* @version $Id$
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class Query extends Object
+{
+ /**
+ * The BASE part of the SPARQL query.
+ * @var string
+ */
+ protected $base;
+
+ /**
+ * Original SPARQL query string
+ * @var string
+ */
+ protected $queryString = null;
+
+ /**
+ * Array that contains used prefixes and namespaces.
+ * Key is the prefix, value the namespace.
+ *
+ * @example
+ * array(8) {
+ * ["rdf"] => string(43) "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ * ["rdfs"]=> string(37) "http://www.w3.org/2000/01/rdf-schema#"
+ * }
+ *
+ * @var array
+ */
+ public $prefixes = array();
+
+ /**
+ * Array of result variables that shall be returned.
+ * E.g. "?name", "?mbox"
+ *
+ * @var array
+ */
+ protected $resultVars = array();
+
+ /**
+ * What form/type of result should be returned.
+ *
+ * One of:
+ * - "ask"
+ * - "count"
+ * - "construct"
+ * - "describe"
+ * - "select"
+ * - "select distinct"
+ *
+ * @var string
+ * @see http://www.w3.org/TR/rdf-sparql-query/#QueryForms
+ */
+ protected $resultForm = null;
+
+ /**
+ * Contains the result part of the SPARQL query.
+ * Array of GraphPattern
+ *
+ * @var array
+ */
+ protected $resultPart = array();
+
+ /**
+ * Contains the FROM part of the SPARQL query.
+ * @var array
+ */
+ protected $fromPart = array();
+
+ /**
+ * Contains the FROM NAMED part of the SPARQL query.
+ * @var array
+ */
+ protected $fromNamedPart = array();
+
+ /**
+ * Optional solution modifier of the query.
+ * Array with three keys:
+ * "order by", "limit", "offset"
+ * If they are not set, their value is null
+ *
+ * "order by" can be an array with subarrays, each of those
+ * subarrays having two keys: "val" and "type".
+ * "val" determines the variable ("?mbox"), "type" is
+ * "asc" or "desc"
+ *
+ * @var array
+ */
+ protected $solutionModifier = array();
+
+ /**
+ * Blanknode counter.
+ * How many blank nodes are in $resultPart
+ *
+ * @var int
+ */
+ protected $bnodeCounter = 0;
+
+ /**
+ * GraphPattern counter.
+ * How many GraphPattern are in $resultPart
+ *
+ * @var int
+ */
+ public $graphPatternCounter = 0;
+
+ /**
+ * List of all vars used in the query.
+ * Key is the variable (e.g. "?x"), value
+ * is boolean true
+ *
+ * @var array
+ */
+ public $usedVars = array();
+
+ /**
+ * If the query type is CONSTRUCT this variable contains the
+ * CONSTRUCT graph pattern.
+ */
+ protected $constructPattern = null;
+
+ /**
+ * TRUE if the query is empty FALSE if not.
+ *
+ * @var boolean
+ */
+ public $isEmpty = null;
+
+ /**
+ * Language of variables. NULL if the variable has no
+ * language tag (e.g. @en) set.
+ * $varname => $language tag
+ * @var array
+ */
+ public $varLanguages = array();
+
+ /**
+ * Datatype of variables. NULL if the variable has no
+ * data type (e.g. ^^xsd::integer) set.
+ * $varname => $datatype
+ * @var array
+ */
+ public $varDatatypes = array();
+
+
+
+ /**
+ * Constructor
+ */
+ public function Query(){
+ $this->resultForm = null;
+ $this->solutionModifier['order by'] = null;
+ $this->solutionModifier['limit'] = null;
+ $this->solutionModifier['offset'] = null;
+ $this->bnodeCounter = 0;
+ $this->graphPatternCounter = 0;
+
+ }
+
+ /**
+ * Returns the BASE part of the query.
+ *
+ * @return String
+ */
+ public function getBase(){
+ return $this->base;
+ }
+
+ /**
+ * Returns the prefix map of the query.
+ *
+ * @return Array
+ */
+ public function getPrefixes(){
+ return $this->prefixes;
+ }
+
+ /**
+ * Returns a list containing the result vars.
+ *
+ * @return Array
+ */
+ public function getResultVar($strName) {
+ foreach ($this->resultVars as $var) {
+ if ($var->getVariable() == $strName) {
+ return $var;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns a list containing the result vars.
+ *
+ * @return Array
+ */
+ public function getResultVars(){
+ return $this->resultVars;
+ }
+
+ /**
+ * Returns the type the result shall have.
+ * E.g. "select", "select distinct", "ask", ...
+ *
+ * @see $resultForm
+ *
+ * @return string
+ */
+ public function getResultForm(){
+ return $this->resultForm;
+ }
+
+ /**
+ * Returns a list containing the graph patterns of the query.
+ *
+ * @return Array
+ */
+ public function getResultPart(){
+ return $this->resultPart;
+ }
+
+ /**
+ * Returns the FROM clause of the query.
+ *
+ * @return String
+ */
+ public function getFromPart(){
+ return $this->fromPart;
+ }
+
+ /**
+ * Returns the FROM NAMED clause of the query.
+ *
+ * @return Array
+ */
+ public function getFromNamedPart(){
+ return $this->fromNamedPart;
+ }
+
+ /**
+ * Returns $isEmpty variable
+ * @return boolean
+ */
+ public function isEmpty() {
+ return $this->isEmpty;
+ }
+
+ /**
+ * Returns an unused Bnode label.
+ *
+ * @return String
+ */
+ public function getBlanknodeLabel(){
+ return "_:bN".$this->bnodeCounter++;
+ }
+
+
+ /**
+ * Sets the base part.
+ *
+ * @param String $base
+ * @return void
+ */
+ public function setBase($base){
+ $this->base = $base;
+ }
+
+
+ /**
+ * Adds a prefix to the list of prefixes.
+ *
+ * @param String $prefix
+ * @param String $label
+ * @return void
+ */
+ public function addPrefix($prefix, $label){
+ $this->prefixes[$prefix]= $label;
+ }
+
+ /**
+ * Adds a variable to the list of result variables.
+ *
+ * @param String $var
+ * @return void
+ */
+ public function addResultVar($var){
+ $this->resultVars[] = $var;
+ $var->setDatatype($this->getDatatype($var));
+
+ $this->varLanguages[$var->getId()] = self::getLanguageTag($var);
+ $this->varDatatypes[$var->getId()] = $this->getDatatype($var);
+ }
+
+
+ /**
+ * Sets the result form.
+ *
+ * @param String $form
+ * @return void
+ */
+ public function setResultForm($form){
+ $this->resultForm = strtolower($form);
+ }
+
+
+ /**
+ * Sets the result part.
+ *
+ * @param array Array of graph patterns
+ */
+ public function setResultPart($resultPart) {
+ $this->resultPart = $resultPart;
+ }
+
+ /**
+ * Adds a graph pattern to the result part.
+ *
+ * @param GraphPattern $pattern
+ * @return void
+ */
+ public function addGraphPattern($pattern){
+ $pattern->setId($this->graphPatternCounter);
+ $this->resultPart[] = $pattern;
+ $this->graphPatternCounter++;
+ }
+
+ /**
+ * Adds a construct graph pattern to the query.
+ *
+ * @param GraphPattern $pattern
+ * @return void
+ */
+ public function addConstructGraphPattern($pattern){
+ $this->constructPattern = $pattern;
+ }
+
+
+ /**
+ * Adds a graphuri to the from part.
+ *
+ * @param String $graphURI
+ * @return void
+ */
+ public function addFrom($graphURI){
+ $this->fromPart[] = $graphURI;
+ }
+
+ /**
+ * Adds a graphuri to the from named part.
+ *
+ * @param String $graphURI
+ * @return void
+ */
+ public function addFromNamed($graphURI){
+ $this->fromNamedPart[] = $graphURI;
+ }
+
+ /**
+ * Sets a solution modifier.
+ *
+ * @param String $name
+ * @param Value $value
+ * @return void
+ */
+ public function setSolutionModifier($name, $value){
+ $this->solutionModifier[$name] = $value;
+ }
+
+
+ /**
+ * Generates a new GraphPattern. If it is a CONSTRUCT graph pattern
+ * $constr has to set to TRUE, FALSE if not.
+ *
+ * @param boolean $constr
+ * @return GraphPattern
+ */
+ public function getNewPattern($constr = false){
+ $pattern = new GraphPattern();
+ if ($constr) {
+ $this->addConstructGraphPattern($pattern);
+ } else {
+ $this->addGraphPattern($pattern);
+ }
+ return $pattern;
+ }
+
+ /**
+ * Adds a new variable to the variable list.
+ *
+ * @param String $var
+ * @return void
+ */
+ public function addUsedVar($var){
+ $this->usedVars[$var]=true;
+ }
+
+ /**
+ * Returns a list with all used variables.
+ *
+ * @return Array
+ */
+ public function getAllVars(){
+ return array_keys($this->usedVars);
+ }
+
+ /**
+ * Gets the solution modifiers of the query.
+ * $solutionModifier['order by'] = value
+ * ['limit'] = vlaue
+ * ['offset'] = value
+ *
+ *
+ * @return Array
+ */
+ public function getSolutionModifier(){
+ return $this->solutionModifier;
+ }
+
+
+ /**
+ * Returns the construvtGraphPattern of the query if there is one.
+ *
+ * @return GraphPattern
+ */
+ public function getConstructPattern(){
+ return $this->constructPattern;
+ }
+
+
+
+ /**
+ * Returns a list of variables used in the construct patterns.
+ *
+ * @return array Array of variable names, unique.
+ */
+ public function getConstructPatternVariables()
+ {
+ $arVars = array();
+/*
+ if (count($this->resultPart) > 0) {
+ foreach ($this->resultPart as $pattern) {
+ $arVars = array_merge($arVars, $pattern->getVariables());
+ }
+ }
+*/
+ if ($this->constructPattern) {
+ $arVars = array_merge($arVars, $this->constructPattern->getVariables());
+ }
+
+ return array_unique($arVars);
+ }//public function getConstructPatternVariables()
+
+
+
+ /**
+ * Returns the language of a variable if the tag is set (e.g. @en)
+ * Returns NULL if no language is set.
+ *
+ * @param string Sparql variable name
+ * @return mixed NULL or language tag
+ */
+ public static function getLanguageTag($var)
+ {
+ $nAt = strpos($var, '@');
+ if ($nAt === false) {
+ return null;
+ }
+ //in case @ and ^^ are combined
+ $nHatHat = strpos($var, '^^', $nAt + 1);
+ if ($nHatHat === false) {
+ $tag = substr($var, $nAt + 1);
+ } else {
+ $tag = substr($var, $nAt + 1, $nHatHat - $nAt - 1);
+ }
+ return $tag;
+ }//public static function getLanguageTag($var)
+
+
+
+ /**
+ * Returns the datatype of a variable if it is set.
+ *
+ * @param string Sparql variable name
+ * @return mixed NULL or datatype
+ */
+ public function getDatatype($var)
+ {
+ $nHatHat = strpos($var, '^^');
+ if ($nHatHat === false) {
+ return null;
+ }
+ $nAt = strpos($var, '@', $nHatHat + 2);
+ if ($nAt === false) {
+ $type = substr($var, $nHatHat + 2);
+ } else {
+ $type = substr($var, $nHatHat + 2, $nAt - $nHatHat - 2);
+ }
+
+ $fullUri = $this->getFullUri($type);
+ if ($fullUri === false) {
+ $fullUri = $type;
+ if ($fullUri[0] == '<' && substr($fullUri, -1) == '>') {
+ $fullUri = substr($fullUri, 1, -1);
+ }
+ }
+
+ return $fullUri;
+ }//public function getDatatype($var)
+
+
+
+ /**
+ * Gets the full URI of a qname token.
+ *
+ * @param string $token
+ * @return string The complete URI of a given token, false if $token is not
+ * a qname or the prefix is not defined
+ */
+ public function getFullUri($token)
+ {
+ $pattern="/^([^:]*):([^:]*)$/";
+ if (preg_match($pattern, $token, $hits) > 0) {
+
+ if (isset($this->prefixes{$hits{1}})) {
+ return substr($this->base, 1, -1)
+ . $this->prefixes{$hits{1}}
+ . $hits{2};
+ }
+ if ($hits{1}=='_') {
+ return "_".$hits{2};
+ }
+ }
+
+ return false;
+ }
+
+
+
+ /**
+ * Checks if the query is complete
+ * (so that querying is possible)
+ *
+ * @return boolean true if the query is complete
+ */
+ public function isComplete()
+ {
+ if ($this->resultForm === null) {
+ return false;
+ }
+ //TODO: maybe check selected vars and construct pattern depending
+ // on the resultform
+ return true;
+ }//public function isIncomplete()
+
+
+
+ /**
+ * Sets the orignal query string
+ *
+ * @param string $queryString SPARQL query string
+ */
+ public function setQueryString($queryString)
+ {
+ $this->queryString = $queryString;
+ }//public function setQueryString($queryString)
+
+
+
+ /**
+ * Returns the orignal query string
+ *
+ * @return string SPARQL query string
+ */
+ public function getQueryString()
+ {
+ return $this->queryString;
+ }//public function getQueryString()
+
+}// end class: Query.php
+
+
+
+class Query_ResultVariable
+{
+ public $variable = null;
+ public $datatype = null;
+ public $language = null;
+ public $alias = null;
+ public $func = null;
+
+
+ public function __construct($variable)
+ {
+ $this->variable = $variable;
+ $this->language = Query::getLanguageTag($variable);
+ }
+
+
+
+ public function setAlias($alias)
+ {
+ $this->alias = $alias;
+ }
+
+
+
+ public function setFunc($func)
+ {
+ $this->func = $func;
+ }
+
+
+
+ public function setDatatype($datatype)
+ {
+ $this->datatype = $datatype;
+ }
+
+
+
+ public function getId()
+ {
+ //FIXME
+ return $this->variable;
+ }
+
+
+
+ public function getFunc()
+ {
+ return $this->func;
+ }
+
+
+
+ public function getLanguage()
+ {
+ return $this->language;
+ }
+
+
+
+ public function getDatatype()
+ {
+ return $this->datatype;
+ }
+
+
+
+ public function getName()
+ {
+ if ($this->alias !== null) {
+ return $this->alias;
+ }
+ //FIXME: support for nested(functions())
+ return $this->variable;
+ }
+
+
+
+ public function getVariable()
+ {
+ return $this->variable;
+ }
+
+
+
+ public function __toString()
+ {
+ return $this->getName();
+ }
+
+}//class Query_ResultVariable
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/QueryTriple.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/QueryTriple.php.svn-base
new file mode 100755
index 00000000..c3e486a4
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/QueryTriple.php.svn-base
@@ -0,0 +1,123 @@
+
+* @version $Id$
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class QueryTriple extends Object
+{
+
+ /**
+ * The QueryTriples Subject.
+ * Can be a BlankNode or Resource, string in
+ * case of a variable
+ * @var Node/string
+ */
+ protected $subject;
+
+ /**
+ * The QueryTriples Predicate.
+ * Normally only a Resource, string in
+ * case of a variable
+ * @var Node/string
+ */
+ protected $predicate;
+
+ /**
+ * The QueryTriples Object.
+ * Can be BlankNode, Resource or Literal, string in
+ * case of a variable
+ * @var Node/string
+ */
+ protected $object;
+
+
+
+ /**
+ * Constructor
+ *
+ * @param Node $sub Subject
+ * @param Node $pred Predicate
+ * @param Node $ob Object
+ */
+ public function QueryTriple($sub,$pred,$ob)
+ {
+ $this->subject = $sub;
+ $this->predicate = $pred;
+ $this->object = $ob;
+ }
+
+ /**
+ * Returns the Triples Subject.
+ *
+ * @return Node
+ */
+ public function getSubject()
+ {
+ return $this->subject;
+ }
+
+ /**
+ * Returns the Triples Predicate.
+ *
+ * @return Node
+ */
+ public function getPredicate()
+ {
+ return $this->predicate;
+ }
+
+ /**
+ * Returns the Triples Object.
+ *
+ * @return Node
+ */
+ public function getObject()
+ {
+ return $this->object;
+ }
+
+
+
+ /**
+ * Returns an array of all variables in this triple.
+ *
+ * @return array Array of variable names
+ */
+ public function getVariables()
+ {
+ $arVars = array();
+
+ foreach (array('subject', 'predicate', 'object') as $strVar) {
+ if (SparqlVariable::isVariable($this->$strVar)) {
+ $arVars[] = $this->$strVar;
+ }
+ }
+
+ return $arVars;
+ }//public function getVariables()
+
+
+
+ public function __clone()
+ {
+ foreach (array('subject', 'predicate', 'object') as $strVar) {
+ if (is_object($this->$strVar)) {
+ $this->$strVar = clone $this->$strVar;
+ }
+ }
+ }//public function __clone()
+
+}//class QueryTriple extends Object
+
+// end class: QueryTriple.php
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/SPARQL.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/SPARQL.php.svn-base
new file mode 100755
index 00000000..f1b99888
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/SPARQL.php.svn-base
@@ -0,0 +1,20 @@
+
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/SparqlClient.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/SparqlClient.php.svn-base
new file mode 100755
index 00000000..ce0a546c
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/SparqlClient.php.svn-base
@@ -0,0 +1,160 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+
+class SparqlClient extends Object {
+
+ var $server;
+ var $output;
+
+ /**
+ * Constructor of SparlClient.
+ *
+ * @param String $server server address.
+ */
+ function SparqlClient($server){
+ $this->server = $server;
+ $this->output = "array";
+ }
+
+
+ /**
+ * Sets the output format for a SELECT or ASK query. Possible formats are "xml" for
+ * Sparql Query Results XML Format (http://www.w3.org/TR/rdf-sparql-XMLres/) or array
+ * for the format described in our SparqlEngine.
+ *
+ * @param String $format the format.
+ */
+ function setOutputFormat($format){
+ if(strtolower($format)=="xml")
+ $this->output = "xml";
+ if(strtolower($format)=="array")
+ $this->output = "array";
+
+ }
+
+ /**
+ * Main function of SparqlClient.
+ *
+ * @param ClientQuery $query the ClientQuery object.
+ * @return mixed returns an array that contains the variables an their bindings or a MemModel
+ *
+ */
+ function query($query){
+ if(!is_a($query,"ClientQuery"))
+ die;//ErrorHandling
+
+ $url = $this->_buildurl($query);
+ $result = $this->_http_get($url);
+ return $this->returnResult($result);
+
+ }
+
+
+ /**
+ * Helper function that builds the url.
+ *
+ * @param ClientQuery $query the ClientQuery Object.
+ */
+
+ function _buildurl($query){
+ $url = "";
+ $url = $this->server."?query=".urlencode($query->query);
+ foreach($query->default as $defaultg){
+ $url = $url."&default-graph-uri=".$defaultg;
+ }
+ foreach($query->named as $namedg){
+ $url = $url."&named-graph-uri=".$namedg;
+ }
+
+ return $url;
+
+ }
+
+ /**
+ * Returns the query result.
+ *
+ * @param String $result the result.
+ * @return mixed
+ */
+ function returnResult($result){
+
+ if(strpos($result,"generateModel(substr($result,strpos($result,"output == "xml"){
+ $pos = strpos($result,"output == "array"){
+ // $pos = strpos($buffer,"parseResult($result);
+ }
+ return $result;
+ }
+
+
+ function parseResult($buffer){
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_SPARQLRES);
+ $parser = new SparqlResultParser();
+ return $parser->parse($buffer);
+ }
+
+
+ /**
+ * Executes the GET Request.
+ *
+ * @param String $url the url.
+ * @return String result.
+ */
+ function _http_get($url)
+ {
+ $url = parse_url($url);
+ $port = isset($url['port']) ? $url['port'] : 80;
+
+ $fp = fsockopen($url['host'], $port);
+
+ $replace = $url['path'];
+
+ fputs($fp, "GET ".$replace."?".$url['query']." HTTP/1.0\n");
+ fputs($fp, "Host:". $url['host']." \r\n");
+ fputs($fp, "Accept: application/sparql-results+xml, application/rdf+xml\r\n");
+ fputs($fp, "Connection: close\n\n");
+
+ $buffer = "";
+ while ($tmp = fread($fp, 1024))
+ {
+ $buffer .= $tmp;
+ }
+
+ $pos1 = strpos($buffer,"\r\n\r\n");
+ $pos2 = strpos($buffer,"\n\n");
+ if ($pos1 === false) {
+ $pos = $pos2;
+ } else {
+ $pos = $pos1;
+ }
+
+ return substr($buffer,$pos);
+
+ }
+}
+
+
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/SparqlEngine.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/SparqlEngine.php.svn-base
new file mode 100755
index 00000000..574ebd23
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/SparqlEngine.php.svn-base
@@ -0,0 +1,1169 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+
+Class SparqlEngine extends Object{
+
+
+ /**
+ * The query object.
+ * @var Query
+ */
+ protected $query;
+
+ /**
+ * The RDF Dataset.
+ * @var Dataset
+ */
+ protected $dataset;
+
+
+
+ /**
+ * Use SparqlEngine::factory() instead of this
+ * constructor.
+ */
+ protected function __construct()
+ {
+ //protected to prevent direct instantiation
+ }
+
+
+ /**
+ * Creates a new instance of the SparqlEngine, depending on the
+ * given model. For example, if you pass a DbModel, you will
+ * get a SparqlEngine specialized on databases.
+ *
+ * @param Model $model RDF model that uses the engine
+ */
+ public function factory($model = null)
+ {
+ if ($model !== null && $model instanceof DbModel) {
+ require_once RDFAPI_INCLUDE_DIR . 'sparql/SparqlEngineDb.php';
+ return new SparqlEngineDb($model);
+ } else {
+ return new SparqlEngine();
+ }
+ }
+
+
+
+ /**
+ * The query engine's main method.
+ *
+ * @param Dataset $dataset the RDF Dataset
+ * @param mixed $query the parsed SPARQL query
+ * @param String $resultform the result form. If set to 'xml' the result will be
+ * SPARQL Query Results XML Format as described in http://www.w3.org/TR/rdf-sparql-XMLres/ .
+ * @return Array/String Type of the result depends on $resultform.
+ */
+ public function queryModel($dataset, Query $query, $resultform = false)
+ {
+ $this->query = $query;
+ $this->dataset = $dataset;
+
+ if($this->query->isEmpty){
+ $vartable[0]['patternResult'] = null;
+ return SparqlEngine_ResultConverter::convertFromResult(
+ $vartable,
+ $this,
+ $resultform
+ );
+ }
+
+ $graphlist = $this->preselectGraphs();
+ /// match graph patterns against the RDF Dataset
+ $patternlist = $this->matchPatterns($graphlist);
+ // filter results- apply inner filters
+ $patternlist = $this->filterPatterns($patternlist,false);
+ // join pattern results
+ $vartable = $this->joinResults($patternlist);
+ // filter results- apply outer filters
+ $vartable = $this->filterPatterns($vartable,true);
+
+ if ($vartable[0]['patternResult'] != null) {
+ // sort vars (ORDER BY, LIMIT, OFFSET)
+ $vartable = $this->sortVars($vartable[0]['patternResult']);
+ $qrf = $this->query->getResultForm();
+ if ($qrf == 'select' || $qrf == 'select distinct') {
+ $vars = $this->query->getResultVars();
+ $vartable = $this->selectVars($vartable, $vars);
+ if ($qrf == 'select distinct') {
+ $vartable = $this->distinct($vartable);
+ }
+ }
+ } else {
+ $vartable = null;
+ }
+
+ return SparqlEngine_ResultConverter::convertFromResult(
+ $vartable,
+ $this,
+ $resultform
+ );
+ }//public function queryModel($dataset, Query $query, $resultform = false)
+
+
+
+ /**
+ * Matches all graph Patterns against the dataset and generates an array which
+ * contains the result sets for every given GraphPattern.
+ *
+ * @param Array $graphlist the graphlist which contains the names of the named
+ * graphs which has to be queried.
+ * @return Array
+ */
+ protected function matchPatterns($graphlist){
+ $patternlist = array();
+ // get the result part from the query
+ $resultPart = $this->query->getResultPart();
+ // for each GrapPattern in the result part
+ if($resultPart)
+ foreach($resultPart as $graphPattern){
+ $this->matchPattern($patternlist, $graphlist, $graphPattern);
+ }
+ return $patternlist;
+ }
+
+
+
+ /**
+ * Finds tuples that match one graph pattern.
+ *
+ * @param Array $patternlist list that contains the graphPatterns
+ * @param array $graphlist the graphlist
+ * @param GraphPattern $graphPattern the pattern which has to be matched
+ * @return void
+ */
+ protected function matchPattern(&$patternlist, $graphlist, &$graphPattern) {
+ // generate an empty result set
+ $finalRes = null;
+ // if the GraphPattern has triple patterns
+ if (count($graphPattern->getTriplePatterns()) > 0) {
+ // check if the pattern has a GRAPH clause and if this Iri is in $graphlist
+ $newGraphList = $this->_checkGraphs($graphPattern,$graphlist);
+ if($newGraphList){
+ $qt = $graphPattern->getTriplePatterns();
+ $resultSet = $this->findTuplesMatchingOnePattern($qt[0], $newGraphList);
+ for ($i=1; $ifindTuplesMatchingOnePattern($qt[$i], $newGraphList);
+ $resultSet = $this->joinTuples($resultSet, $rs);
+ if(!$resultSet)
+ break;
+ }
+ if($finalRes != null){
+ $finalRes = $this->joinTuples($finalRes,$resultSet);
+ }else{
+ $finalRes = $resultSet;
+ }
+ }
+ }
+ // dependencies between pattern results
+ $patternlist[$graphPattern->getId()]['hasOptional'] = 0;
+ $patternlist[$graphPattern->getId()]['hasUnion'] = 0;
+ $patternlist[$graphPattern->getId()]['patternResult'] = $finalRes;
+
+ $op = $graphPattern->getOptional();
+ $un = $graphPattern->getUnion();
+
+ $patternlist[$graphPattern->getId()]['optionalTo'] = $op;
+ if(is_int($op))
+ $patternlist[$op]['hasOptional']++;
+
+ $patternlist[$graphPattern->getId()]['unionWith'] = $un;
+ if(is_int($un))
+ $patternlist[$un]['hasUnion']++;
+
+ $constraint = $graphPattern->getConstraints();
+ if(count($constraint) > 0){
+ foreach($constraint as $constr){
+ if($constr->isOuterFilter()){
+ $patternlist[$graphPattern->getId()]['outerFilter'][] = $constr;
+ $patternlist[$graphPattern->getId()]['innerFilter'][] = null;
+ }else{
+ $patternlist[$graphPattern->getId()]['innerFilter'][] = $constr;
+ $patternlist[$graphPattern->getId()]['outerFilter'][] = null;
+ }
+ }
+ }else{
+ $patternlist[$graphPattern->getId()]['innerFilter'] = null;
+ $patternlist[$graphPattern->getId()]['outerFilter'] = null;
+ }
+ }
+
+
+ /**
+ * Finds Tuples matching one TriplePattern.
+ *
+ * @param TriplePattern $pattern
+ * @param Array $graphlist
+ * @return Array
+ */
+ protected function findTuplesMatchingOnePattern($pattern, $graphlist){
+ $var = null;
+ $sub = $pattern->getSubject();
+ $pred = $pattern->getPredicate();
+ $obj = $pattern->getObject();
+
+ if(is_string($sub)||$sub instanceof BlankNode){
+ if(is_string($sub))
+ $var['sub'] = $sub;
+ $sub = null;
+ }
+ if(is_string($pred)||$pred instanceof BlankNode ){
+ if(is_string($pred))
+ $var['pred'] = $pred;
+ $pred = null;
+ }
+ if(is_string($obj)||$obj instanceof BlankNode){
+ if(is_string($obj))
+ $var['obj'] = $obj;
+ $obj = null;
+ }
+ $intBindings = $this->_buildIntBindings($var);
+ $k = 0;
+
+ $key = 0;
+ // search in named graphs
+ if($graphlist['var'][0] != null||$graphlist['list'][0] != null){
+ foreach($graphlist['list'] as $key => $graphnode){
+
+ // query the dataset
+ $it = $this->dataset->findInNamedGraphs($graphnode,$sub,$pred,$obj,false);
+ if($it->valid()){
+ // add statements to the result list
+ while($it->valid()){
+ if($graphnode == null){
+ $element = $it->current()->getStatement();
+ $grname = $it->current()->getGraphname();
+ }else{
+ if($it->current() instanceof Quad)
+ $element = $it->current()->getStatement();
+ else
+ $element = $it->current();
+
+ $grname = $graphnode;
+ }
+ if($this->checkIntBindings($element,$intBindings)){
+ $resmodel['trip'][$k] = $element;
+ $resmodel['graph'][$k] = $grname;
+ // $resmodel['graphvar'][$k] = $graphlist['var'][$key];
+ $resmodel['graphvar'][$k] = $graphlist['var'][0];
+ $k++;
+
+ }
+ $it->next();
+ }
+ }
+
+ }
+ }
+ // search in the default graph
+ if($graphlist['list'][0] == null && $graphlist['var'][0] == null){
+
+
+ $gr = $this->dataset->getDefaultGraph();
+
+ $res = $gr->find($sub,$pred,$obj);
+
+ foreach($res->triples as $innerkey => $element){
+ if($this->checkIntBindings($element,$intBindings)){
+ $resmodel['trip'][$k] = $element;
+ $resmodel['graph'][$k] = null;
+ $resmodel['graphvar'][$k] = $graphlist['var'][$key];
+ $k++;
+ }
+ }
+ }
+ if($k == 0)
+ return false;
+ return $this->_buildResultSet($pattern,$resmodel);
+ }
+
+ /**
+ * Checks it there are internal bindings between variables.
+ *
+ * @param Triple $trip
+ * @param Array $intBindings
+ * @return boolean
+ */
+ protected function checkIntBindings($trip, $intBindings){
+ switch($intBindings){
+ case -1:
+ return true;
+ break;
+ case 0:
+ if($trip->subj != $trip->pred)
+ return false;
+ break;
+ case 1:
+ if(is_a($trip->obj,'Literal'))
+ return false;
+ if($trip->subj != $trip->obj)
+ return false;
+ break;
+ case 2:
+ if(is_a($trip->obj,'Literal'))
+ return false;
+ if($trip->pred != $trip->obj)
+ return false;
+ break;
+ case 3:
+ if(is_a($trip->obj,'Literal'))
+ return false;
+ if($trip->pred != $trip->obj || $trip->pred != $trip->subj )
+ return false;
+ break;
+ }
+ return true;
+ }
+
+
+ /**
+ * Perform an SQL-like inner join on two resultSets.
+ *
+ * @param Array &$finalRes
+ * @param Array &$res
+ * @return Array
+ */
+ protected function joinTuples(&$finalRes, &$res) {
+
+ if (!$finalRes || !$res)
+ return array();
+
+ // find joint variables and new variables to be added to $finalRes
+ $jointVars = array();
+ $newVars = array();
+ $k = key($res);
+
+ foreach ($res[$k] as $varname => $node) {
+ if (array_key_exists($varname, $finalRes[0]))
+ $jointVars[] = $varname;
+ else
+ $newVars[] = $varname;
+ }
+
+ // eliminate rows of $finalRes in which the values of $jointVars do not have
+ // a corresponding row in $res.
+ foreach ($finalRes as $n => $fRes) {
+ foreach ($res as $i => $r) {
+ $ok = TRUE;
+ foreach ($jointVars as $j_varname)
+ if ($r[$j_varname] != $fRes[$j_varname]) {
+ $ok = FALSE;
+ break;
+ }
+ if ($ok)
+ break;
+ }
+ if (!$ok)
+ unset($finalRes[$n]);
+ }
+
+ // join $res and $finalRes
+ $joinedRes = array();
+ foreach ($res as $r) {
+ foreach ($finalRes as $n => $fRes) {
+ $ok = TRUE;
+ foreach ($jointVars as $j_varname)
+ if ($r[$j_varname] != $fRes[$j_varname]) {
+ $ok = FALSE;
+ break;
+ }
+ if ($ok) {
+ $joinedRow = $finalRes[$n];
+ foreach($newVars as $n_varname)
+ $joinedRow[$n_varname] = $r[$n_varname];
+ $joinedRes[] = $joinedRow;
+ }
+ }
+ }
+ return $joinedRes;
+ }
+
+
+ /**
+ * Joins OPTIONAL pattern results.
+ *
+ * @param Array &$finalRes
+ * @param Array &$res
+ * @return Array the joined Array
+ */
+ protected function joinOptionalTuples(&$finalRes, &$res) {
+
+ if(!$finalRes && !$res)
+ return array();
+
+ if(!$finalRes)
+ return $res;
+
+ if(!$res)
+ return $finalRes;
+
+ // find joint variables and new variables to be added to $finalRes
+ $jointVars = array();
+ $newVars = array();
+ $result = array();
+
+ $k = key($res);
+
+ foreach ($res[$k] as $varname => $node) {
+ if (array_key_exists($varname, $finalRes[0])){
+ $jointVars[] = $varname;
+ }else{
+ $newVars[] = $varname;
+ }
+ }
+ $joined = array();
+ $joinc = 0;
+ foreach($finalRes as $i =>$fRes){
+ foreach($res as $n =>$r){
+ $join = false;
+ foreach($jointVars as $j_varname){
+ if($r[$j_varname]==$fRes[$j_varname]){
+ $join = true;
+ //break;
+ }else{
+ $join = false;
+ }
+ }
+ if($join){
+ $result[$joinc] = $fRes;
+ foreach($newVars as $n_varname)
+ $result[$joinc][$n_varname] = $r[$n_varname];
+ $joined[]=$n;
+ $joinc++;
+ }
+
+ }
+ }
+
+ $count = count($result);
+ foreach($res as $k =>$val){
+ if(!in_array($k,$joined)){
+ $result[$count] = $finalRes[0];
+ foreach($result[$count] as $varname => $varVal){
+ $result[$count][$varname]='';
+ }
+
+ foreach($val as $varname2 => $varVal2){
+ $result[$count][$varname2]=$varVal2;
+ }
+ $count++;
+ }
+ }
+ return $result;
+ }
+
+
+
+ /**
+ * Looks in from and from named part of the query and
+ * adds the graphs to the graphlist.
+ *
+ * @return Array
+ */
+ protected function preselectGraphs(){
+ $fromNamed = $this->query->getFromNamedPart();
+ if($fromNamed == null)
+ $fromNamed[] = null;
+ return $fromNamed;
+ }
+
+
+ /**
+ * Evaluates the GRPAH clause if there is one. Checks if
+ * the GRAPH clause contains an IRI, variable or nothing.
+ * Returns an array which contains the graphs that has to be matched.
+ *
+ * @param GraphPattern $pattern
+ * @param Array $graphlist
+ * @return Array
+ */
+ protected function _checkGraphs(&$pattern,$graphlist){
+
+ $gr = $pattern->getGraphname();
+ if($gr instanceof Resource ){
+ if($graphlist[0]==null || in_array($gr,$graphlist)){
+ $newGraphList['list'][] = $gr;
+ $newGraphList['var'][] = null;
+ }else{
+ return false;
+ }
+ }elseif (is_string($gr)){
+ $newGraphList['list'] = $graphlist;
+ $newGraphList['var'][] = $gr;
+ }else{
+ $newGraphList['list'] = $graphlist;
+ $newGraphList['var'][] = null;
+ }
+ return $newGraphList;
+ }
+
+ /**
+ * Marks triples with internal bindings.
+ * int bindings -1 :none 0:sub=pred 1:sub=obj 2:pred=obj 3:sub=pred=obj.
+ *
+ * @param Array $var
+ * @return Array
+ */
+ protected function _buildIntBindings($var){
+ $intBindings = -1;
+ if(!$var)
+ return $intBindings;
+
+ if(isset($var['sub'])){
+ if(isset($var['pred']))
+ if($var['sub'] == $var['pred'])
+ $intBindings = 0;
+ if(isset($var['obj']))
+ if($var['sub'] == $var['obj']){
+ if( $intBindings == 0){
+ $intBindings = 3;
+ }else{
+ $intBindings = 1;
+ }
+ }
+ }
+ if(isset($var['pred'])){
+ if(isset($var['obj']))
+ if($var['pred']==$var['obj']&&$intBindings!=3)
+ $intBindings = 2;
+ }
+ return $intBindings;
+ }
+
+ /**
+ * Builds the resultset.
+ *
+ * @param GraphPattern $pattern
+ * @param Array $resmodel
+ * @return Array
+ */
+ protected function _buildResultSet($pattern,$resmodel){
+ // determine variables and their corresponding values
+ $result = null;
+ if(is_string($pattern->getSubject())){
+ $n = 0;
+ foreach($resmodel['trip'] as $key => $triple){
+ if(isset($resmodel['graphvar'][$key]))
+ $result[$n][$resmodel['graphvar'][$key]] = $resmodel['graph'][$key];
+ $result[$n++][$pattern->getSubject()] = $triple->subj;
+ }
+ }
+ if(is_string($pattern->getPredicate())){
+ $n = 0;
+ foreach($resmodel['trip'] as $key => $triple){
+ if(isset($resmodel['graphvar'][$key]))
+ $result[$n][$resmodel['graphvar'][$key]] = $resmodel['graph'][$key];
+ $result[$n++][$pattern->getPredicate()] = $triple->pred;
+ }
+ }
+ if(is_string($pattern->getObject())){
+ $n = 0;
+ foreach($resmodel['trip'] as $key => $triple){
+ if(isset($resmodel['graphvar'][$key]))
+ $result[$n][$resmodel['graphvar'][$key]] = $resmodel['graph'][$key];
+ $result[$n++][$pattern->getObject()] = $triple->obj;
+ }
+ }
+ return $result;
+ }
+
+ /**
+ * Selects the result variables and builds a result table.
+ *
+ * @param Array $table the result table
+ * @param Array $vars the result variables
+ * @return Array
+ */
+ protected function selectVars($table,$vars){
+ if($vars[0]=='*')
+ $vars = $this->query->getAllVars();
+ $resTable = array();
+ $hits = 0;
+ foreach($table as $val){
+ foreach($vars as $var){
+ if(isset($val[(string)$var])){
+ $resTable[$hits][(string)$var]=$val[(string)$var];
+ }else{
+ $resTable[$hits][(string)$var]="";
+ }
+ }
+ $hits++;
+ }
+ return $resTable;
+ }
+
+ /**
+ * Joins the results of the different Graphpatterns.
+ *
+ * @param Array $patternlist
+ * @return Array
+ */
+ protected function joinResults($patternlist){
+ $joined[0]['patternResult'] = null;
+ $joined[0]['outerFilter'] = null;
+
+ while(count($patternlist)>0){
+ foreach($patternlist as $key => $pattern){
+ if($pattern['hasOptional'] == 0 && $pattern['hasUnion'] == 0){
+ if(is_int($pattern['optionalTo'])){
+ $patternlist[$pattern['optionalTo']]['hasOptional']--;
+ $patternlist[$pattern['optionalTo']]['patternResult'] = $this->joinOptionalTuples($pattern['patternResult'],$patternlist[$pattern['optionalTo']]['patternResult']);
+ unset($patternlist[$key]);
+ break;
+ }
+ else if(is_int($pattern['unionWith'])){
+ $patternlist[$pattern['unionWith']]['hasUnion']--;
+ foreach($pattern['patternResult'] as $value)
+ array_push($patternlist[$pattern['unionWith']]['patternResult'],$value);
+ unset($patternlist[$key]);
+ break;
+ }else{
+ if($joined[0]['patternResult'] == null){
+ $joined[0]['patternResult'] = $pattern['patternResult'];
+ if($joined[0]['outerFilter'] == null )
+ $joined[0]['outerFilter'] = $pattern['outerFilter'];
+ unset($patternlist[$key]);
+ break;
+ }
+ // if($pattern['patternResult'] !=null ){
+ $joined[0]['patternResult'] = $this->joinTuples($joined[0]['patternResult'],$pattern['patternResult']);
+ $joined[0]['outerFilter'] = $pattern['outerFilter'];
+ unset($patternlist[$key]);
+ break;
+ // }
+ }
+ }
+ }
+ }
+ return $joined;
+ }
+
+ /**
+ * Filters the pattern results.
+ *
+ * @param Array $patternlist list containing the results of the GraphPatterns
+ * @param boolean $outer TRUE if its an outer filter FALSE if not
+ * @return Array the filtered patternlist
+ */
+ protected function filterPatterns($patternlist,$outer){
+ if($outer)
+ $filter = 'outerFilter';
+ else
+ $filter = 'innerFilter';
+ foreach($patternlist as $patkey => $pattern){
+ // get constraints
+ $constraint = $pattern[$filter];
+
+ if(count($constraint)>0){
+ foreach($constraint as $constr){
+ if($constr != null){
+ // extract Vars and function calls
+ $evalString = $constr->getExpression();
+ preg_match_all("/\?.[^\s\)\,]*/",$evalString,$vars);
+ preg_match_all("/bound\((.[^\)]*)\)/i",$evalString,$boundcalls);
+ preg_match_all("/isuri\((.[^\)]*)\)/i",$evalString,$isUricalls);
+ preg_match_all("/isblank\((.[^\)]*)\)/i",$evalString,$isBlankcalls);
+ preg_match_all("/isLiteral\((.[^\)]*)\)/i",$evalString,$isLiteralcalls);
+ preg_match_all("/lang\((.[^\)]*)\)/i",$evalString,$langcalls);
+ preg_match_all("/datatype\((.[^\)]*)\)/i",$evalString,$datatypecalls);
+ preg_match_all("/str\((.[^\)]*)\)/i",$evalString,$stringcalls);
+
+ // is Bound
+ if(count($boundcalls[1])>0)
+ $function['bound'] = $boundcalls[1];
+ else
+ $function['bound'] = false;
+
+ // is URI
+ if(count($isUricalls[1])>0)
+ $function['isUri'] = $isUricalls[1];
+ else
+ $function['isUri'] = false;
+
+ // is Blank
+ if(count($isBlankcalls[1])>0)
+ $function['isBlank'] = $isBlankcalls[1];
+ else
+ $function['isBlank'] = false;
+
+ // is Literal
+ if(count($isLiteralcalls[1])>0)
+ $function['isLiteral'] = $isLiteralcalls[1];
+ else
+ $function['isLiteral'] = false;
+
+ // lang
+ if(count($langcalls[1])>0)
+ $function['lang'] = $langcalls[1];
+ else
+ $function['lang'] = false;
+
+ // datatype
+ if(count($datatypecalls[1])>0)
+ $function['datatype'] = $datatypecalls[1];
+ else
+ $function['datatype'] = false;
+
+ // string
+ if(count($stringcalls[1])>0)
+ $function['string'] = $stringcalls[1];
+ else
+ $function['string'] = false;
+
+
+ foreach($pattern['patternResult'] as $key => $res){
+ $result = false;
+ $evalString = $this->fillConstraintString($vars,$res,$constr,$function);
+ $evalString = '$result =('.$evalString.');';
+ // evaluate Constraint
+ @eval($evalString);
+
+ if(!$result)
+ unset($patternlist[$patkey]['patternResult'][$key]);
+
+ }
+ }
+ }
+ }
+ }
+ return $patternlist;
+ }
+
+ /**
+ * Builds an evaluation string to determine wether the result passes
+ * the filter or not. This string is evaluatet by the php buildin eval() function
+ *
+ * @param Array $vars a list which contains the used variables
+ * @param Array $res the result part which have to be evaluated
+ * @param Constraint $constraint the Constrain object
+ * @param Array $function an Array which contains the used functions
+ * @return String
+ */
+
+ protected function fillConstraintString($vars,$res,$constraint,$function){
+
+ $boundExpr = false;
+ $evalString = $constraint->getExpression();
+
+ // extract Literals
+ $pattern1 = "/\".[^\"]*\"[^\^\@]/";
+ $pattern2 = "/\'.[^\']*\'[^\^\@]/";
+ preg_match_all($pattern1,$evalString,$hits1);
+ preg_match_all($pattern2,$evalString,$hits2);
+
+ foreach($hits1[0] as $k => $val){
+ $evalString = preg_replace('/\".[^\"]*\"[^\^]/','_REPLACED1_'.$k++,$evalString,1);
+ }
+ foreach($hits2[0] as $k => $val){
+ $evalString = preg_replace('/\".[^\"]*\"[^\^]/','_REPLACED2_'.$k++,$evalString,1);
+ }
+
+ // replace namespaces
+ $prefs = $this->query->getPrefixes();
+ foreach($prefs as $key => $val){
+ if($key == '')
+ $key = ' ';
+ $evalString = preg_replace("/^(".$key."\:)(.[^\s]*)|([\s\(]?[^\^])(".$key."\:)(.[^\s\)]*)([\s\)]?)/","$3'<".$val."$2$5>'$6",$evalString);
+
+ $evalString = preg_replace("/(\^)(".$key."\:)(.[^\s]*)/","$1<".$val."$3>",$evalString);
+ }
+
+ $xsd = "http\:\/\/www.w3.org\/2001\/XMLSchema\#";
+
+ // evaluate bound calls
+ if($function['bound']){
+ $boundExpr = true;
+ foreach($function['bound'] as $var){
+ if(isset($res[$var]) && $res[$var]!=="")
+ $replacement = 'true';
+ else
+ $replacement = 'false';
+ $evalString = preg_replace("/bound\(\\".$var."\)/i",$replacement,$evalString);
+ }
+
+ }
+ // evaluate isBlank calls
+ if($function['isBlank']){
+ foreach($function['isBlank'] as $var){
+ if(isset($res[$var]) && $res[$var]!=="" && $res[$var] instanceof BlankNode )
+ $replacement = 'true';
+ else
+ $replacement = 'false';
+ $evalString = preg_replace("/isBlank\(\\".$var."\)/i",$replacement,$evalString);
+ }
+
+ }
+ // evaluate isLiteral calls
+ if($function['isLiteral']){
+ foreach($function['isLiteral'] as $var){
+ if(isset($res[$var]) && $res[$var]!=="" && $res[$var] instanceof Literal )
+ $replacement = 'true';
+ else
+ $replacement = 'false';
+ $evalString = preg_replace("/isLiteral\(\\".$var."\)/i",$replacement,$evalString);
+ }
+
+ }
+ // evaluate isUri calls
+ if($function['isUri']){
+ foreach($function['isUri'] as $var){
+ if(isset($res[$var]) && $res[$var]!=="" && $res[$var] instanceof Resource && $res[$var]->getUri() && !$res[$var] instanceof BlankNode )
+ $replacement = 'true';
+ else
+ $replacement = 'false';
+ $evalString = preg_replace("/isUri\(\\".$var."\)/i",$replacement,$evalString);
+ }
+ }
+ // evaluate lang calls
+ if($function['lang']){
+ foreach($function['lang'] as $var){
+ if(isset($res[$var]) && $res[$var]!=="" && $res[$var] instanceof Literal && $res[$var]->getLanguage() )
+ $replacement = '"'.$res[$var]->getLanguage().'"';
+ else
+ $replacement = 'null';
+ $evalString = preg_replace("/lang\(\\".$var."\)/i",$replacement,$evalString);
+ }
+ }
+ // evaluate datatype calls
+ if($function['datatype']){
+ foreach($function['datatype'] as $var){
+ if(isset($res[$var]) && $res[$var]!=="" && $res[$var] instanceof Literal && $res[$var]->getDatatype() )
+ $replacement = '\'<'.$res[$var]->getDatatype().'>\'';
+ else
+ $replacement = 'false';
+ $evalString = preg_replace("/datatype\(\\".$var."\)/i",$replacement,$evalString);
+ }
+ }
+ // evaluate string calls
+ if($function['string']){
+ foreach($function['string'] as $var){
+ if($var{0}=='?' || $var{0}=='$'){
+ if(isset($res[$var]) && $res[$var]!==""){
+ $replacement = "'str_".$res[$var]->getLabel()."'";
+ if($res[$var] instanceof BlankNode)
+ $replacement = "''";
+ }else{
+ $replacement = 'false';
+ }
+ $evalString = preg_replace("/str\(\\".$var."\)/i",$replacement,$evalString);
+ }else{
+ if($var{0}=='<'){
+ $evalString = preg_replace("/str\(\s*\<(.[^\>]*)\>\s*\)/i","'str_$1'",$evalString);
+ }
+ if($var{0}=='"'){
+ $evalString = preg_replace("/str\(\s*\"(.[^\>]*)\"\@[a-z]*\s*\)/i","'str_$1'",$evalString);
+ }
+ }
+
+ }
+ }
+ // evaluate VARS
+ foreach($vars[0] as $var){
+ if(isset($res[$var])&&$res[$var]!== ""){
+ //$replacement = "'".$res[$var]->getLabel()."'";
+ $replacement = '" "';
+ if($res[$var] instanceof Literal){
+ if($res[$var]->getDatatype()!= null){
+ if($res[$var]->getDatatype() == XML_SCHEMA.'boolean')
+ $replacement = $res[$var]->getLabel();
+ if($res[$var]->getDatatype() == XML_SCHEMA.'double')
+ $replacement = $res[$var]->getLabel();
+ if($res[$var]->getDatatype() == XML_SCHEMA.'integer')
+ $replacement = $res[$var]->getLabel();
+ if($res[$var]->getDatatype() == XML_SCHEMA.'dateTime')
+ $replacement = strtotime($res[$var]->getLabel());
+ }else{
+ if($res[$var]->getLabel()=="")
+ $replacement = 'false';
+ else
+ $replacement = "'str_".$res[$var]->getLabel()."'";
+ }
+ }else{
+ if($res[$var] instanceof Resource){
+ $replacement = "'<".$res[$var]->getLabel().">'";
+ }
+ }
+ $evalString = preg_replace("/\\".$var."/",$replacement,$evalString);
+ }
+
+ // problem with PHP: false < 13 is true
+ if(isset($res[$var])){
+ if($res[$var] === ""){
+ if($boundExpr)
+ $evalString = preg_replace("/\\".$var."/","false",$evalString);
+ else
+ $evalString = 'false';
+ }
+ }else{
+ $evalString = preg_replace("/\\".$var."/","false",$evalString);
+ }
+
+ }
+
+ // replace '=' with '=='
+ $evalString = preg_replace("/(.[^\=])(\=)(.[^\=])/","$1==$3",$evalString);
+
+
+ // rewrite Literals
+ foreach($hits1[0] as $k => $val){
+ $pattern = '/_REPLACED1_'.$k.'/';
+ $evalString = preg_replace($pattern,$hits1[0][$k],$evalString,1);
+ }
+
+ foreach($hits2[0] as $k => $val){
+ $pattern = '/_REPLACED2_'.$k.'/';
+ $evalString = preg_replace($pattern,$hits2[0][$k],$evalString,1);
+ }
+
+ // replace xsd:boolean expressions
+ $pattern = $pattern = '/\"\s?true\s?\"\^\^\<'.$xsd.'boolean\>|\'\s?true\s?\'\^\^xsd:boolean/';
+ $evalString = preg_replace($pattern,"true",$evalString);
+
+ $pattern = $pattern = '/\"\s?false\s?\"\^\^\<'.$xsd.'boolean\>|\'\s?false\s?\'\^\^xsd:boolean/';
+ $evalString = preg_replace($pattern,"false",$evalString);
+
+ // replace xsd:date expressions
+ $pattern = "/\"(.[^\"]*)\"\^\^".$xsd."dateTime/";
+ preg_match_all($pattern,$evalString,$hits);
+
+ foreach($hits[1] as $dummy)
+ $evalString = preg_replace("/\".[^\"]*\"\^\^".$xsd."dateTime/",strtotime($dummy),$evalString,1);
+
+
+ $evalString = preg_replace("/(\'\<".$xsd."dateTime\()(.[^\)]*\))\>\'/","dateTime($2",$evalString);
+
+ $evalString = preg_replace("/(\'\<".$xsd."integer\()(.[^\)]*\))\>\'/","integer($2",$evalString);
+
+ // tag plain literals
+ $evalString = preg_replace("/\"(.[^\"]*)\"([^\^])|\"(.[^\"]*)\"$/","'str_$1$3'$2",$evalString);
+
+ return $evalString;
+ }
+
+ /**
+ * Sorts the results.
+ *
+ * @param Array $vartable List containing the unsorted result vars
+ * @return Array List containing the sorted result vars
+ */
+ protected function sortVars($vartable)
+ {
+ $newTable = array();
+ $mod = $this->query->getSolutionModifier();
+ // if no ORDER BY solution modifier return vartable
+ if($mod['order by']!= null){
+ $order = $mod['order by'];
+ $map = $this->buildVarmap($order,$vartable);
+ foreach($map as $val){
+ $newTable[] = $vartable[$val];
+ }
+ }else{
+ $newTable = $vartable;
+ }
+
+ if($mod['offset'] != null){
+ $newTable = array_slice ($newTable, $mod['offset']);
+ }
+ if($mod['limit'] != null){
+ $newTable = array_slice($newTable,0,$mod['limit']);
+ }
+
+ return $newTable;
+ }
+
+ /**
+ * Sorts the result table.
+ *
+ * @param String $order (ASC/DESC)
+ * @param Array $vartable the vartable
+ * @return Array A map that contains the new order of the result vars
+ */
+ protected function buildVarmap($order, $vartable)
+ {
+ $n= 0;
+ $result = array();
+ $num_var = array();
+ foreach($order as $variable)
+ $num_var[$variable['val']] = 0;
+
+ foreach($vartable as $k => $x){
+ foreach($order as $value){
+ // if the value is a typed Literal try to determine if it
+ // a numeric datatype
+ if($x[$value['val']] instanceof Literal){
+ $dtype = $x[$value['val']]->getDatatype();
+ if($dtype){
+ switch($dtype){
+ case XML_SCHEMA."integer":
+ $num_var[$value['val']]++;
+ break;
+ case XML_SCHEMA."double":
+ $num_var[$value['val']]++;
+ break;
+
+ }
+ }
+ }
+ if($x[$value['val']]){
+ if($x[$value['val']]instanceof Literal){
+ $pref = "2";
+ }
+ if($x[$value['val']]instanceof Resource){
+ $pref = "1";
+ }
+ if($x[$value['val']]instanceof BlankNode){
+ $pref = "0";
+ }
+ $result[$value['val']][$n] = $pref.$x[$value['val']]->getLabel();
+ }else{
+ $result[$value['val']][$n] = "";
+ }
+ }
+ $result['oldKey'][$n] = $k;
+ $n++;
+ }
+ $sortString = "";
+ foreach($order as $value){
+ if($num_var[$value['val']] == $n)
+ $sort = SORT_NUMERIC;
+ else
+ $sort = SORT_STRING;
+
+ if($value['type'] == 'asc')
+ $type = SORT_ASC;
+ else
+ $type = SORT_DESC;
+
+ $sortString = $sortString.'$result["'.$value['val'].'"],'.$type.','.$sort.',';
+ }
+ $sortString = "array_multisort(".$sortString.'$result["oldKey"]);';
+
+ @eval($sortString);
+ return $result['oldKey'];
+ }
+
+
+
+ /**
+ * Eliminates duplicate results.
+ *
+ * @param Array $vartable a table that contains the result vars and their bindings
+ * @return Array the result table without duplicate results
+ */
+ protected function distinct($vartable)
+ {
+ $index = array();
+ foreach($vartable as $key => $value){
+ $key_index="";
+ foreach($value as $k => $v)
+ if($v instanceof Object)
+ $key_index = $key_index.$k.$v->toString();
+ if(isset($index[$key_index]))
+ unset($vartable[$key]);
+ else
+ $index[$key_index]= 1;
+ }
+ return $vartable;
+ }
+
+
+ /**
+ * Prints a query result as HTML table.
+ * You can change the colors in the configuration file.
+ *
+ * @param array $queryResult [][?VARNAME] = object Node
+ * @return void
+ */
+ public function writeQueryResultAsHtmlTable($queryResult) {
+ // Import Package Utility
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_UTILITY);
+
+ if ( $queryResult[0] == null) {
+ echo 'no match
';
+ return;
+ }
+ if ( $queryResult == 'false') {
+ echo 'boolean: false
';
+ return;
+ }
+ if ( $queryResult == 'true') {
+ echo 'boolean: true
';
+ return;
+ }
+
+
+ echo '| No. | ';
+ foreach ($queryResult[0] as $varName => $value)
+ echo "$varName | ";
+ echo '
';
+
+ foreach ($queryResult as $n => $var) {
+
+
+ echo '| ' .($n + 1) .'. | ';
+ foreach ($var as $varName => $value) {
+ if($value !=''){
+ echo INDENTATION . INDENTATION . '';
+ echo ' ';
+
+ $lang = NULL;
+ $dtype = NULL;
+ if (is_a($value, 'Literal')) {
+ if ($value->getLanguage() != NULL)
+ $lang = ' (xml:lang="' . $value->getLanguage() . '") ';
+ if ($value->getDatatype() != NULL)
+ $dtype = ' (rdf:datatype="' . $value->getDatatype() . '") ';
+ }
+ echo RDFUtil::getNodeTypeName($value) .$value->getLabel() . $lang . $dtype .' ';
+ }else{
+ echo " | unbound";
+ }
+ }
+ echo ' |
';
+ }
+ echo '
';
+ }
+
+
+
+ /*
+ * Dumb getters
+ */
+
+
+
+ public function getQuery()
+ {
+ return $this->query;
+ }//public function getQuery()
+
+
+
+ public function getDataset()
+ {
+ return $this->dataset;
+ }//public function getDataset()
+
+} // end: Class SparqlEngine
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/SparqlEngineDb.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/SparqlEngineDb.php.svn-base
new file mode 100755
index 00000000..8579ea69
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/SparqlEngineDb.php.svn-base
@@ -0,0 +1,391 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlEngineDb
+{
+ /**
+ * Sparql Query object.
+ *
+ * @var Query
+ */
+ protected $query;
+
+ /**
+ * RDF dataset object.
+ * @var Dataset
+ */
+ protected $dataset;
+
+ /**
+ * Database connection object.
+ * @var ADOConnection
+ */
+ protected $dbConn;
+
+ /**
+ * Internal ID for our graph model.
+ * Stored in the database along the statements.
+ * Can be of different types:
+ * - array: array of modelIds
+ * - null: all models
+ *
+ * @var array OR null
+ */
+ protected $arModelIds;
+
+ /**
+ * Prepared SQL statements are stored in here.
+ * @var array
+ */
+ protected $arPrepared = null;
+
+ /**
+ * If the prepared statement is really prepared, or if we just emulate it.
+ * @var boolean
+ */
+ protected $bRealPrepared = false;
+
+ /**
+ * SQL generator instance
+ * @var SparqlEngineDb_SqlGenerator
+ */
+ protected $sg = null;
+
+ /**
+ * Type sorting instance
+ * @var SparqlEngineDb_TypeSorter
+ */
+ protected $ts = null;
+
+ /**
+ * Prepared statments preparator instance
+ * @var SparqlEngineDb_Preparator
+ */
+ protected $pr = null;
+
+
+
+ /**
+ * Use SparqlEngine::factory() to create the instance
+ *
+ * @param mixed $model DbModel or DbStore
+ * @param mixed $arModelIds Array of modelIds, or NULL to use all models
+ */
+ public function __construct($model, $arModelIds = null)
+ {
+ //parent::__construct();
+ if ($model instanceof DbModel) {
+ $this->dbConn = $model->getDbConn();
+ $this->arModelIds = array($model->getModelID());
+ } else if ($model instanceof DbStore) {
+ $this->dbConn = $model->getDbConn();
+ $this->arModelIds = $arModelIds;
+ }
+ }//public function __construct(DbModel $model, $arModelIds = null)
+
+
+
+ /**
+ * Query the database with the given SPARQL query.
+ *
+ *
+ * @param Dataset $dataset RDF Dataset
+ * @param Query $query Parsed SPARQL query
+ * @param string $resultform Result form. If set to 'xml' the result will be
+ * SPARQL Query Results XML Format as described in http://www.w3.org/TR/rdf-sparql-XMLres/ .
+ *
+ * @return array/string array of triple arrays, or XML. Format depends on
+ * $resultform parameter.
+ */
+ public function queryModel($dataset, Query $query, $resultform = false)
+ {
+ if (isset($GLOBALS['debugSparql']) && $GLOBALS['debugSparql']) {
+ echo "\n" . 'SPARQL query: ' . $query->getQueryString() . "\n";
+ }
+
+ $this->query = $query;
+ $this->dataset = $dataset;
+
+ $qsimp = new SparqlEngineDb_QuerySimplifier();
+ $qsimp->simplify($this->query);
+
+ $this->sg = new SparqlEngineDb_SqlGenerator ($this->query, $this->dbConn, $this->arModelIds);
+ $this->rc = new SparqlEngineDb_ResultConverter($this->query, $this->sg, $this);
+ $this->ts = new SparqlEngineDb_TypeSorter ($this->query, $this->dbConn);
+
+ $this->setOptions();
+
+ if ($this->query->isEmpty()){
+ $vartable[0]['patternResult'] = null;
+ return $this->returnResult($vartable, $resultform);
+ }
+
+
+ $arSqls = $this->sg->createSql();
+ $this->ts->setData($this->sg);
+
+ return
+ SparqlEngineDb_ResultConverter::convertFromDbResults(
+ $this->queryMultiple(
+ $this->ts->getOrderifiedSqls(
+ $arSqls
+ )
+ ),
+ $this,
+ $resultform
+ );
+ }//public function queryModel($dataset, Query $query, $resultform = false)
+
+
+
+ /**
+ * Create a prepared statement that can be executed later.
+ *
+ * @param Dataset $dataset RDF Dataset
+ * @param Query $query Parsed SPARQL query
+ *
+ * @return SparqlEngineDb_PreparedStatement Prepared statment that can
+ * be execute()d later.
+ */
+ public function prepare(Dataset $dataset, Query $query)
+ {
+ require_once RDFAPI_INCLUDE_DIR . 'sparql/SparqlEngineDb/PreparedStatement.php';
+ require_once RDFAPI_INCLUDE_DIR . 'sparql/SparqlEngineDb/Preparator.php';
+
+ $this->query = $query;
+ $this->dataset = $dataset;
+ $this->sg = new SparqlEngineDb_SqlGenerator ($this->query, $this->dbConn, $this->arModelIds);
+ $this->rc = new SparqlEngineDb_ResultConverter($this->query, $this->sg, $this);
+ $this->ts = new SparqlEngineDb_TypeSorter ($this->query, $this->dbConn);
+ $this->pr = new SparqlEngineDb_Preparator ($this->query, $this->dbConn);
+
+ $this->arPrepared = $this->sg->createSql();
+ $this->ts->setData($this->sg);
+
+ if ($this->ts->willBeDataDependent()) {
+ $this->bRealPrepared = false;
+ } else {
+ $this->bRealPrepared = true;
+ list($strSelect, $strFrom, $strWhere) = $this->arPrepared;
+ $this->arPreparedQueries = $this->ts->getOrderifiedSqls(
+ $strSelect,
+ $strFrom,
+ $strWhere
+ );
+ $this->arDbStatements = $this->pr->prepareInDb(
+ $this->arPreparedQueries,
+ $this->sg->getPlaceholders()
+ );
+ }
+
+
+ return new SparqlEngineDb_PreparedStatement(
+ $this
+ );
+ }//public function prepare(Dataset $dataset, Query $query)
+
+
+
+ /**
+ * Execute a prepared statement by filling it with variables
+ *
+ * @param array $arVariables Array with (variable name => value) pairs
+ * @param string $resultform Which form the result should have
+ *
+ * @return mixed Result according to $resultform
+ */
+ public function execute($arVariables, $resultform = false)
+ {
+ if ($this->arPrepared === null) {
+ throw new Exception('You need to prepare() the query first.');
+ }
+
+ if ($this->bRealPrepared) {
+ return
+ SparqlEngineDb_ResultConverter::convertFromDbResults(
+ $this->pr->execute(
+ $this->arDbStatements,
+ $arVariables
+ ),
+ $this,
+ $resultform
+ );
+ } else {
+ list($strSelect, $strFrom, $strWhere) = $this->arPrepared;
+
+ return SparqlEngineDb_ResultConverter::convertFromDbResults(
+ $this->queryMultiple(
+ $this->ts->getOrderifiedSqls(
+ $strSelect,
+ $strFrom,
+ $this->pr->replacePlaceholdersWithVariables(
+ $strWhere,
+ $this->sg->getPlaceholders(),
+ $arVariables
+ )
+ )
+ ),
+ $this,
+ $resultform
+ );
+ }
+ }//public function execute($arVariables, $resultform)
+
+
+
+ /**
+ * Executes multiple SQL queries and returns an array
+ * of results.
+ *
+ * @param array $arSqls Array of SQL queries
+ * @return array Array of query results
+ */
+ protected function queryMultiple($arSqls)
+ {
+ $arSM = $this->query->getSolutionModifier();
+ if ($arSM['limit'] === null && $arSM['offset'] === null) {
+ $nOffset = 0;
+ $nLimit = null;
+ $nSql = 0;
+ } else {
+ $offsetter = new SparqlEngineDb_Offsetter($this->dbConn, $this->query);
+ list($nSql, $nOffset) = $offsetter->determineOffset($arSqls);
+ $nLimit = $arSM['limit'];
+ }
+
+ $nCount = 0;
+ $arResults = array();
+ foreach ($arSqls as $nId => $arSql) {
+ if ($nId < $nSql) { continue; }
+
+ if ($nLimit != null) {
+ $nCurrentLimit = $nLimit - $nCount;
+ } else {
+ $nCurrentLimit = null;
+ }
+
+ $dbResult = $this->queryDb($arSql, $nOffset, $nCurrentLimit);
+ $nCount += $dbResult->RowCount();
+ $arResults[] = $dbResult;
+ $nOffset = 0;
+ if ($nLimit !== null && $nCount >= $nLimit) {
+ break;
+ }
+ }
+
+ return $arResults;
+ //return array_map(array($this, 'queryDb'), $arSql);
+ }//protected function queryMultiple($arSql)
+
+
+
+ /**
+ * Sends the sql to the database and returns the results.
+ *
+ * @internal Switches between ADOConnection::Execute() and
+ * ADOConnection::SelectLimit() depending on the $query parameter's
+ * $solutionModifier "limit" and "offset" settings.
+ * Uses $query variable.
+ *
+ * @param array $arSql Array that gets a SQL query string once imploded
+ *
+ * @return mixed Anything ADOConnection::Execute() may return
+ * @throws Exception If Database query does not work
+ */
+ function queryDb($arSql, $nOffset, $nLimit)
+ {
+ $strSql = SparqlEngineDb_SqlMerger::getSelect($this->query, $arSql);
+
+ if ($strSql == '()') {
+ return new ADORecordSet(false);
+ }
+
+ // I want associative arrays.
+ $oldmode = $this->dbConn->SetFetchMode(ADODB_FETCH_ASSOC);
+
+ if (isset($GLOBALS['debugSparql']) && $GLOBALS['debugSparql']) {
+ echo 'SQL query: ' . $strSql . "\n";
+ }
+
+ if ($nLimit === null && $nOffset == 0) {
+ $ret = $this->dbConn->execute($strSql);
+ } else if ($nLimit === null) {
+ $ret = $this->dbConn->SelectLimit($strSql, -1, $nOffset);
+ } else {
+ $ret = $this->dbConn->SelectLimit($strSql, $nLimit, $nOffset);
+ }
+
+ //... but others maybe not
+ $this->dbConn->SetFetchMode($oldmode);
+
+ if (!$ret) {
+ //Error occured
+ throw new Exception(
+ 'ADOdb error: ' . $this->dbConn->ErrorMsg() . "\n"
+ . $strSql
+ );
+ }
+
+ return $ret;
+ }//function queryDb($sql)
+
+
+
+ /**
+ * Set options to subobjects like SqlGenerator
+ */
+ protected function setOptions()
+ {
+ //allow changing the statements' table name
+ if (isset($GLOBALS['RAP']['conf']['database']['tblStatements'])) {
+ $this->sg->setStatementsTable(
+ $GLOBALS['RAP']['conf']['database']['tblStatements']
+ );
+ }
+ }//protected function setOptions()
+
+
+
+ /*
+ * Dumb getters
+ */
+
+
+
+ public function getQuery()
+ {
+ return $this->query;
+ }//public function getQuery()
+
+
+
+ public function getSqlGenerator()
+ {
+ return $this->sg;
+ }//public function getSqlGenerator()
+
+
+
+ public function getTypeSorter()
+ {
+ return $this->ts;
+ }//public function getTypeSorter()
+
+}//class SparqlEngineDb
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/SparqlParser.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/SparqlParser.php.svn-base
new file mode 100755
index 00000000..ece547a8
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/SparqlParser.php.svn-base
@@ -0,0 +1,1551 @@
+
+* @author Christian Weiske
+* @version $Id$
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlParser extends Object
+{
+
+ /**
+ * The query Object
+ * @var Query
+ */
+ protected $query;
+
+ /**
+ * The Querystring
+ * @var string
+ */
+ protected $queryString;
+
+ /**
+ * The tokenized Query
+ * @var array
+ */
+ protected $tokens = array();
+
+ /**
+ * Last parsed graphPattern
+ * @var int
+ */
+ protected $tmp;
+
+ /**
+ * Operators introduced by sparql
+ * @var array
+ */
+ protected static $sops = array(
+ 'regex',
+ 'bound',
+ 'isuri',
+ 'isblank',
+ 'isliteral',
+ 'str',
+ 'lang',
+ 'datatype',
+ 'langmatches'
+ );
+
+ /**
+ * Which order operators are to be treated.
+ * (11.3 Operator Mapping)
+ * @var array
+ */
+ protected static $operatorPrecedence = array(
+ '||' => 0,
+ '&&' => 1,
+ '=' => 2,
+ '!=' => 3,
+ '<' => 4,
+ '>' => 5,
+ '<=' => 6,
+ '>=' => 7,
+ '*' => 0,
+ '/' => 0,
+ '+' => 0,
+ '-' => 0,
+ );
+
+
+
+ /**
+ * Constructor of SparqlParser
+ */
+ public function SparqlParser()
+ {
+ }
+
+
+
+ /**
+ * Main function of SparqlParser. Parses a query string.
+ *
+ * @param String $queryString The SPARQL query
+ * @return Query The query object
+ * @throws SparqlParserException
+ */
+ public function parse($queryString = false)
+ {
+ $this->prepare();
+
+ if ($queryString) {
+ $this->query->setQueryString($queryString);
+ $uncommentedQuery = $this->uncomment($queryString);
+ $this->queryString = $uncommentedQuery;
+ $this->tokens = self::tokenize($uncommentedQuery);
+ $this->parseQuery();
+ if (!$this->query->isComplete()) {
+ throw new SparqlParserException(
+ "Query is incomplete.",
+ null,
+ $queryString
+ );
+ }
+ } else {
+ throw new SparqlParserException(
+ "Querystring is empty.",
+ null,
+ key($this->tokens)
+ );
+ $this->query->isEmpty = true;
+ }
+ return $this->query;
+ }//public function parse($queryString = false)
+
+
+
+ /**
+ * Set all internal variables to a clear state
+ * before we start parsing.
+ */
+ protected function prepare()
+ {
+ $this->query = new Query();
+ $this->queryString = null;
+ $this->tokens = array();
+ $this->tmp = null;
+ // add the default prefixes defined in constants.php
+ global $default_prefixes;
+ $this->query->prefixes = $default_prefixes;
+ }//protected function prepare()
+
+
+
+ /**
+ * Tokenizes the query string into $tokens.
+ * The query may not contain any comments.
+ *
+ * @param string $queryString Query to split into tokens
+ *
+ * @return array Tokens
+ */
+ public static function tokenize($queryString)
+ {
+ $queryString = trim($queryString);
+ $specialChars = array(' ', "\t", "\r", "\n", ',', '\\', '(', ')','{','}','"',"'",';','[',']');
+ $len = strlen($queryString);
+ $tokens = array('');
+ $n = 0;
+
+ for ($i = 0; $i < $len; ++$i) {
+ if (!in_array($queryString{$i}, $specialChars)) {
+ $tokens[$n] .= $queryString{$i};
+ } else {
+ if ($tokens[$n] != '') {
+ ++$n;
+ if (!isset($tokens[$n])) {
+ $tokens[$n] = '';
+ }
+ }
+ if ($queryString{$i} == "'" && $n > 1
+ && $tokens[$n - 2] == "'" && $tokens[$n - 1] == "'"
+ ) {
+ //special ''' quotation
+ $tokens[$n - 2] = "'''";
+ $tokens[$n - 1] = '';
+ unset($tokens[$n]);
+ --$n;
+ continue;
+ } else if ($queryString{$i} == '"' && $n > 1
+ && $tokens[$n - 2] == '"' && $tokens[$n - 1] == '"'
+ ) {
+ //special """ quotation
+ $tokens[$n - 2] = '"""';
+ $tokens[$n - 1] = '';
+ unset($tokens[$n]);
+ --$n;
+ continue;
+ } else if ($queryString{$i} == '\\') {
+ $tokens[$n] .= substr($queryString, $i, 2);
+ ++$i;
+ continue;
+ }
+ $tokens[$n] = $queryString{$i};
+ $tokens[++$n] = '';
+ }
+ }
+//var_dump($tokens);
+ return $tokens;
+ }//public static function tokenize($queryString)
+
+
+
+ /**
+ * Removes comments in the query string. Comments are
+ * indicated by '#'.
+ *
+ * @param String $queryString
+ * @return String The uncommented query string
+ */
+ protected function uncomment($queryString)
+ {
+ $regex ="/((\"[^\"]*\")|(\'[^\']*\')|(\<[^\>]*\>))|(#.*)/";
+ return preg_replace($regex,'\1',$queryString);
+ }//protected function uncomment($queryString)
+
+
+
+ /**
+ * Starts parsing the tokenized SPARQL Query.
+ *
+ * @return void
+ */
+ protected function parseQuery()
+ {
+ do {
+ switch (strtolower(current($this->tokens))) {
+ case "base":
+ $this->parseBase();
+ break;
+ case "prefix":
+ $this->parsePrefix();
+ break;
+ case "select":
+ $this->parseSelect();
+ break;
+ case "describe":
+ $this->parseDescribe();
+ break;
+ case "ask":
+ $this->parseAsk('ask');
+ break;
+ case "count":
+ $this->parseAsk('count');
+ break;
+ case "from":
+ $this->parseFrom();
+ break;
+ case "construct":
+ $this->parseConstruct();
+ break;
+ case "where":
+ $this->parseWhere();
+ $this->parseModifier();
+ break;
+ case "{":
+ prev($this->tokens);
+ $this->parseWhere();
+ $this->parseModifier();
+ break;
+ }
+ } while (next($this->tokens));
+
+ }//protected function parseQuery()
+
+
+
+ /**
+ * Parses the BASE part of the query.
+ *
+ * @return void
+ * @throws SparqlParserException
+ */
+ protected function parseBase()
+ {
+ $this->_fastForward();
+ if ($this->iriCheck(current($this->tokens))) {
+ $this->query->setBase(current($this->tokens));
+ } else {
+ $msg = current($this->tokens);
+ $msg = preg_replace('/', '<', $msg);
+ throw new SparqlParserException(
+ "IRI expected",
+ null,
+ key($this->tokens)
+ );
+ }
+ }
+
+
+
+ /**
+ * Adds a new namespace prefix to the query object.
+ *
+ * @return void
+ * @throws SparqlParserException
+ */
+ protected function parsePrefix()
+ {
+ $this->_fastForward();
+ $prefix = substr(current($this->tokens), 0, -1);
+ $this->_fastForward();
+ if ($this->iriCheck(current($this->tokens))) {
+ $uri = substr(current($this->tokens), 1, -1);
+ $this->query->addPrefix($prefix, $uri);
+ } else {
+ $msg = current($this->tokens);
+ $msg = preg_replace('/', '<', $msg);
+ throw new SparqlParserException(
+ "IRI expected",
+ null,
+ key($this->tokens)
+ );
+ }
+ }
+
+
+
+ /**
+ * Parses the SELECT part of a query.
+ *
+ * @return void
+ * @throws SparqlParserException
+ */
+ protected function parseSelect()
+ {
+ $this->_fastForward();
+ $curLow = strtolower(current($this->tokens));
+ prev($this->tokens);
+ if ($curLow == 'distinct') {
+ $this->query->setResultForm('select distinct');
+ } else {
+ $this->query->setResultForm('select');
+ }
+
+ $currentVar = null;
+ $currentFunc = null;
+ $bWaitForRenaming = false;
+ while ($curLow != 'from' && $curLow != 'where' &&
+ $curLow != "{"
+ ){
+ $this->_fastForward();
+ $curTok = current($this->tokens);
+ $curLow = strtolower($curTok);
+
+ if ($this->varCheck($curTok) || $curLow == '*') {
+ if ($bWaitForRenaming) {
+ $bWaitForRenaming = false;
+ $currentVar->setAlias($curTok);
+ if ($currentFunc != null) {
+ $currentVar->setFunc($currentFunc);
+ }
+ $this->query->addResultVar($currentVar);
+ $currentVar = null;
+ } else {
+ if ($currentVar != null) {
+ $this->query->addResultVar($currentVar);
+ $currentVar = null;
+ }
+ $currentVar = new Query_ResultVariable($curTok);
+ if ($currentFunc != null) {
+ $currentVar->setFunc($currentFunc);
+ }
+ }
+ $currentFunc = null;
+ } else if ($curLow == 'as') {
+ if ($currentVar === null) {
+ throw new SparqlParserException(
+ 'AS requires a variable left and right',
+ null,
+ key($this->tokens)
+ );
+ }
+ $bWaitForRenaming = true;
+ } else if (in_array($curLow, self::$sops)) {
+ $currentFunc = $curLow;
+ }
+
+ if (!current($this->tokens)) {
+ throw new SparqlParserException(
+ "Unexpected end of File.",
+ null,
+ key($this->tokens)
+ );
+ }
+ }
+
+ if ($currentVar != null) {
+ $this->query->addResultVar($currentVar);
+ }
+ prev($this->tokens);
+
+ if (count($this->query->getResultVars()) == 0) {
+ throw new SparqlParserException(
+ "Variable or '*' expected.",
+ null,
+ key($this->tokens)
+ );
+ }
+ }//protected function parseSelect()
+
+
+ /**
+ * Adds a new variable to the query and sets result form to 'DESCRIBE'.
+ *
+ * @return void
+ */
+ protected function parseDescribe()
+ {
+ while(strtolower(current($this->tokens))!='from'& strtolower(current($this->tokens))!='where'){
+ $this->_fastForward();
+ if($this->varCheck(current($this->tokens))|$this->iriCheck(current($this->tokens))){
+ $this->query->addResultVar(current($this->tokens));
+ if(!$this->query->getResultForm())
+ $this->query->setResultForm('describe');
+ }
+ if(!current($this->tokens))
+ break;
+ }
+ prev($this->tokens);
+ }
+
+ /**
+ * Sets result form to 'ASK' and 'COUNT'.
+ *
+ * @param string $form if it's an ASK or COUNT query
+ * @return void
+ */
+ protected function parseAsk($form){
+ $this->query->setResultForm($form);
+ $this->_fastForward();
+ if(current($this->tokens)=="{")
+ $this->_rewind();
+ $this->parseWhere();
+ $this->parseModifier();
+ }
+
+ /**
+ * Parses the FROM clause.
+ *
+ * @return void
+ * @throws SparqlParserException
+ */
+ protected function parseFrom(){
+ $this->_fastForward();
+ if(strtolower(current($this->tokens))!='named'){
+ if($this->iriCheck(current($this->tokens))||$this->qnameCheck(current($this->tokens))){
+ $this->query->addFrom(new Resource(substr(current($this->tokens),1,-1)));
+ }else if($this->varCheck(current($this->tokens))){
+ $this->query->addFrom(current($this->tokens));
+ }else{
+ throw new SparqlParserException("Variable, Iri or qname expected in FROM ",null,key($this->tokens));
+ }
+ $this->query->addFrom(current($this->tokens));
+ }else{
+ $this->_fastForward();
+ if($this->iriCheck(current($this->tokens))||$this->qnameCheck(current($this->tokens))){
+ $this->query->addFromNamed(new Resource(substr(current($this->tokens),1,-1)));
+ }else if($this->varCheck(current($this->tokens))){
+ $this->query->addFromNamed(current($this->tokens));
+ }else{
+ throw new SparqlParserException("Variable, Iri or qname expected in FROM NAMED ",null,key($this->tokens));
+ }
+ }
+ }
+
+
+ /**
+ * Parses the CONSTRUCT clause.
+ *
+ * @return void
+ * @throws SparqlParserException
+ */
+ protected function parseConstruct(){
+ $this->_fastForward();
+ $this->query->setResultForm('construct');
+ if(current($this->tokens)=="{"){
+ $this->parseGraphPattern(false,false,false,true);
+ }else{
+ throw new SparqlParserException("Unable to parse CONSTRUCT part. '{' expected. ",null,key($this->tokens));
+ }
+ $this->parseWhere();
+ $this->parseModifier();
+ }
+
+
+ /**
+ * Parses the WHERE clause.
+ *
+ * @return void
+ * @throws SparqlParserException
+ */
+ protected function parseWhere(){
+ $this->_fastForward();
+ if(current($this->tokens)=="{"){
+ $this->parseGraphPattern();
+ }else{
+ throw new SparqlParserException("Unable to parse WHERE part. '{' expected in Query. ",null,key($this->tokens));
+ }
+ }
+
+
+
+ /**
+ * Checks if $token is a variable.
+ *
+ * @param String $token The token
+ * @return boolean TRUE if the token is a variable false if not
+ */
+ protected function varCheck($token)
+ {
+ if (isset($token[0]) && ($token{0} == '$' || $token{0} == '?')) {
+ $this->query->addUsedVar($token);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Checks if $token is an IRI.
+ *
+ * @param String $token The token
+ * @return boolean TRUE if the token is an IRI false if not
+ */
+ protected function iriCheck($token){
+ $pattern="/^<[^>]*>\.?$/";
+ if(preg_match($pattern,$token)>0)
+ return true;
+ return false;
+ }
+
+
+ /**
+ * Checks if $token is a Blanknode.
+ *
+ * @param String $token The token
+ * @return boolean TRUE if the token is BNode false if not
+ */
+ protected function bNodeCheck($token){
+ if($token{0} == "_")
+ return true;
+ else
+ return false;
+ }
+
+
+ /**
+ * Checks if $token is a qname.
+ *
+ * @param String $token The token
+ * @return boolean TRUE if the token is a qname false if not
+ * @throws SparqlParserException
+ */
+ protected function qnameCheck($token)
+ {
+ $pattern="/^([^:^\<]*):([^:]*)$/";
+ if (preg_match($pattern,$token,$hits)>0) {
+ $prefs = $this->query->getPrefixes();
+ if (isset($prefs{$hits{1}})) {
+ return true;
+ }
+ if ($hits{1} == "_") {
+ return true;
+ }
+ throw new SparqlParserException("Unbound Prefix: ".$hits{1}."",null,key($this->tokens));
+ } else {
+ return false;
+ }
+ }
+
+
+
+ /**
+ * Checks if $token is a Literal.
+ *
+ * @param string $token The token
+ *
+ * @return boolean TRUE if the token is a Literal false if not
+ */
+ protected function literalCheck($token)
+ {
+ $pattern = "/^[\"\'].*$/";
+ if (preg_match($pattern,$token) > 0) {
+ return true;
+ }
+ return false;
+ }//protected function literalCheck($token)
+
+
+
+ /**
+ * FastForward until next token which is not blank.
+ *
+ * @return void
+ */
+ protected function _fastForward()
+ {
+ next($this->tokens);
+ while(current($this->tokens)==" "|current($this->tokens)==chr(10)|current($this->tokens)==chr(13)|current($this->tokens)==chr(9)){
+ next($this->tokens);
+ }
+ }//protected function _fastForward()
+
+
+
+ /**
+ * Rewind until next token which is not blank.
+ *
+ * @return void
+ */
+ protected function _rewind()
+ {
+ prev($this->tokens);
+ while(current($this->tokens)==" "|current($this->tokens)==chr(10)|current($this->tokens)==chr(13)|current($this->tokens)==chr(9)){
+ prev($this->tokens);
+ }
+ return;
+ }//protected function _rewind()
+
+
+
+ /**
+ * Parses a graph pattern.
+ *
+ * @param int $optional Optional graph pattern
+ * @param int $union Union graph pattern
+ * @param string $graph Graphname
+ * @param boolean $constr TRUE if the pattern is a construct pattern
+ * @param boolean $external If the parsed pattern shall be returned
+ * @param int $subpattern If the new pattern is subpattern of the
+ * pattern with the given id
+ * @return void
+ */
+ protected function parseGraphPattern(
+ $optional = false, $union = false, $graph = false,
+ $constr = false, $external = false, $subpattern = false
+ ){
+ $pattern = $this->query->getNewPattern($constr);
+ if (is_int($optional)) {
+ $pattern->setOptional($optional);
+ } else {
+ $this->tmp = $pattern->getId();
+ }
+ if (is_int($union)) {
+ $pattern->setUnion($union);
+ }
+ if (is_int($subpattern)) {
+ $pattern->setSubpatternOf($subpattern);
+ }
+ if ($graph != false) {
+ $pattern->setGraphname($graph);
+ }
+
+ $this->_fastForward();
+
+ do {
+ switch (strtolower(current($this->tokens))) {
+ case "graph":
+ $this->parseGraph();
+ break;
+ case "union":
+ $this->_fastForward();
+ $this->parseGraphPattern(
+ false, $this->tmp, false, false, false, $subpattern
+ );
+ break;
+ case "optional":
+ $this->_fastForward();
+ $this->parseGraphPattern(
+ $this->tmp, false, false, false, false, $subpattern
+ );
+ break;
+ case "filter":
+ $this->parseConstraint(
+ $pattern, true, false, false, false, $subpattern
+ );
+ $this->_fastForward();
+ break;
+ case ".":
+ $this->_fastForward();
+ break;
+ case "{":
+ if (!is_int($subpattern)) {
+ $subpattern = $pattern->getId();
+ }
+
+ $this->parseGraphPattern(
+ false, false, false, false, false, $subpattern
+ );
+ break;
+ case "}":
+ $pattern->open = false;
+ break;
+ default:
+ $this->parseTriplePattern($pattern);
+ break;
+ }
+ } while ($pattern->open);
+
+ if ($external) {
+ return $pattern;
+ }
+ $this->_fastForward();
+ }
+
+ /**
+ * Parses a triple pattern.
+ *
+ * @param GraphPattern $pattern
+ * @return void
+ */
+ protected function parseTriplePattern(&$pattern)
+ {
+ $trp = array();
+ $prev = false;
+ $prevPred = false;
+ $cont = true;
+ $sub = "";
+ $pre = "";
+ $tmp = "";
+ $tmpPred = "";
+ $obj = "";
+ do {
+//echo strtolower(current($this->tokens)) . "\n";
+ switch (strtolower(current($this->tokens))) {
+ case false:
+ $cont = false;
+ $pattern->open = false;
+ break;
+ case "filter":
+ $this->parseConstraint($pattern,false);
+ $this->_fastForward();
+ break;
+ case "optional":
+ $this->_fastForward();
+ $this->parseGraphPattern($pattern->getId(),false);
+ $cont = false;
+ break;
+ case "union":
+ $this->_fastForward();
+ $this->parseGraphPattern(
+ false, $this->tmp, false, false, false, $pattern->getId()
+ );
+ break;
+ case ";":
+ $prev = true;
+ $this->_fastForward();
+ break;
+ case ".":
+ $prev = false;
+ $this->_fastForward();
+ break;
+ case "graph":
+ $this->parseGraph();
+ break;
+ case ",":
+ $prev = true;
+ $prevPred = true;
+ $this->_fastForward();
+ break;
+ case "}":
+ $prev = false;
+ $pattern->open = false;
+ $cont = false;
+ break;
+ case '{':
+ //subpatterns opens
+ $this->parseGraphPattern(
+ false, false, false, false, false, $pattern->getId()
+ );
+ break;
+ case "[":
+ $prev = true;
+ $tmp = $this->parseNode($this->query->getBlanknodeLabel());
+ $this->_fastForward();
+ break;
+ case "]":
+ $prev = true;
+ $this->_fastForward();
+ break;
+ case "(":
+ $prev = true;
+ $tmp = $this->parseCollection($trp);
+ $this->_fastForward();
+ break;
+ case false:
+ $cont = false;
+ $pattern->open = false;
+ break;
+ default:
+ if ($prev) {
+ $sub = $tmp;
+ } else {
+ $sub = $this->parseNode();
+ $this->_fastForward();
+ $tmp = $sub;
+ }
+ if ($prevPred) {
+ $pre = $tmpPred;
+ } else {
+ $pre = $this->parseNode();
+ $this->_fastForward();
+ $tmpPred = $pre;
+ }
+ if (current($this->tokens)=="[") {
+ $tmp = $this->parseNode($this->query->getBlanknodeLabel());
+ $prev = true;
+ $obj = $tmp;
+ } else if (current($this->tokens)=="(") {
+ $obj = $this->parseCollection($trp);
+ } else {
+ $obj = $this->parseNode();
+ }
+ $trp[] = new QueryTriple($sub,$pre,$obj);
+ $this->_fastForward();
+ break;
+
+ }
+ } while ($cont);
+
+ if (count($trp) > 0) {
+ $pattern->addTriplePatterns($trp);
+ }
+ }
+
+
+
+ /**
+ * Parses a value constraint.
+ *
+ * @param GraphPattern $pattern
+ * @param boolean $outer If the constraint is an outer one.
+ * @return void
+ */
+ protected function parseConstraint(&$pattern, $outer)
+ {
+ $constraint = new Constraint();
+ $constraint->setOuterFilter($outer);
+ $this->_fastForward();
+ $this->_rewind();
+ $nBeginKey = key($this->tokens);
+ $constraint->setTree(
+ $t = $this->parseConstraintTree()
+ );
+
+ $nEndKey = key($this->tokens);
+ if (current($this->tokens) == '}') {
+ prev($this->tokens);
+ }
+
+ //for backwards compatibility with the normal sparql engine
+ // which does not use the tree array currently
+ $expression = trim(implode(
+ '',
+ array_slice(
+ $this->tokens,
+ $nBeginKey + 1,
+ $nEndKey - $nBeginKey - 1
+ )
+ ));
+ if ($expression[0] == '(' && substr($expression, -1) == ')') {
+ $expression = trim(substr($expression, 1, -1));
+ }
+ $constraint->addExpression($expression);
+
+ $pattern->addConstraint($constraint);
+ }//protected function parseConstraint(&$pattern, $outer)
+
+
+
+ /**
+ * Parses a constraint string recursively.
+ *
+ * The result array is one "element" which may contain subelements.
+ * All elements have one key "type" that determines which other
+ * array keys the element array has. Valid types are:
+ * - "value":
+ * Just a plain value with a value key, nothing else
+ * - "function"
+ * A function has a name and an array of parameter(s). Each parameter
+ * is an element.
+ * - "equation"
+ * An equation has an operator, and operand1 and operand2 which
+ * are elements themselves
+ * Any element may have the "negated" value set to true, which means
+ * that is is - negated (!).
+ *
+ * @internal The functionality of this method is being unit-tested
+ * in testSparqlParserTests::testParseFilter()
+ * "equation'-elements have another key "level" which is to be used
+ * internally only.
+ *
+ * @return array Nested tree array representing the filter
+ */
+ protected function parseConstraintTree($nLevel = 0, $bParameter = false)
+ {
+ $tree = array();
+ $part = array();
+ $chQuotes = null;
+ $litQuotes = null;
+ $strQuoted = '';
+
+ while ($tok = next($this->tokens)) {
+//var_dump(array($tok, $tok[strlen($tok) - 1]));
+ if ($chQuotes !== null && $tok != $chQuotes) {
+ $strQuoted .= $tok;
+ continue;
+ } else if ($litQuotes !== null) {
+ $strQuoted .= $tok;
+ if ($tok[strlen($tok) - 1] == '>') {
+ $tok = '>';
+ } else {
+ continue;
+ }
+ } else if ($tok == ')' || $tok == '}' || $tok == '.') {
+ break;
+ }
+
+ switch ($tok) {
+ case '"':
+ case '\'':
+ if ($chQuotes === null) {
+ $chQuotes = $tok;
+ $strQuoted = '';
+ } else {
+ $chQuotes = null;
+ $part[] = array(
+ 'type' => 'value',
+ 'value' => $strQuoted,
+ 'quoted'=> true
+ );
+ }
+ continue 2;
+ break;
+
+ case '>':
+ $litQuotes = null;
+ $part[] = array(
+ 'type' => 'value',
+ 'value' => $strQuoted,
+ 'quoted'=> false
+ );
+ continue 2;
+ break;
+
+ case '(':
+ $bFunc1 = isset($part[0]['type']) && $part[0]['type'] == 'value';
+ $bFunc2 = isset($tree['type']) && $tree['type'] == 'equation'
+ && isset($tree['operand2']) && isset($tree['operand2']['value']);
+ $part[] = $this->parseConstraintTree(
+ $nLevel + 1,
+ $bFunc1 || $bFunc2
+ );
+
+ if ($bFunc1) {
+ $tree['type'] = 'function';
+ $tree['name'] = $part[0]['value'];
+ self::fixNegationInFuncName($tree);
+ if (isset($part[1]['type'])) {
+ $part[1] = array($part[1]);
+ }
+ $tree['parameter'] = $part[1];
+ $part = array();
+ } else if ($bFunc2) {
+ $tree['operand2']['type'] = 'function';
+ $tree['operand2']['name'] = $tree['operand2']['value'];
+ self::fixNegationInFuncName($tree['operand2']);
+ $tree['operand2']['parameter'] = $part[0];
+ unset($tree['operand2']['value']);
+ unset($tree['operand2']['quoted']);
+ $part = array();
+ }
+ continue 2;
+ break;
+
+ case ' ':
+ case "\t":
+ continue 2;
+
+ case '=':
+ case '>':
+ case '<':
+ case '<=':
+ case '>=':
+ case '!=':
+ case '&&':
+ case '||':
+ if (isset($tree['type']) && $tree['type'] == 'equation'
+ && isset($tree['operand2'])) {
+ //previous equation open
+ $part = array($tree);
+ } else if (isset($tree['type']) && $tree['type'] != 'equation') {
+ $part = array($tree);
+ $tree = array();
+ }
+ $tree['type'] = 'equation';
+ $tree['level'] = $nLevel;
+ $tree['operator'] = $tok;
+ $tree['operand1'] = $part[0];
+ unset($tree['operand2']);
+ $part = array();
+ continue 2;
+ break;
+
+ case '!':
+ if ($tree != array()) {
+ throw new SparqlParserException(
+ 'Unexpected "!" negation in constraint.'
+ );
+ }
+ $tree['negated'] = true;
+ continue 2;
+
+ case ',':
+ //parameter separator
+ if (count($part) == 0 && !isset($tree['type'])) {
+ throw new SparqlParserException(
+ 'Unexpected comma'
+ );
+ }
+ $bParameter = true;
+ if (count($part) == 0) {
+ $part[] = $tree;
+ $tree = array();
+ }
+ continue 2;
+
+ default:
+ break;
+ }
+
+ if ($this->varCheck($tok)) {
+ $part[] = array(
+ 'type' => 'value',
+ 'value' => $tok,
+ 'quoted' => false
+ );
+ } else if (substr($tok, 0, 2) == '^^') {
+ $part[count($part) - 1]['datatype']
+ = $this->query->getFullUri(substr($tok, 2));
+ } else if ($tok[0] == '@') {
+ $part[count($part) - 1]['language'] = substr($tok, 1);
+ } else if ($tok[0] == '<') {
+ if ($tok[strlen($tok) - 1] == '>') {
+ //single-tokenized <> uris
+ $part[] = array(
+ 'type' => 'value',
+ 'value' => $tok,
+ 'quoted' => false
+ );
+ } else {
+ //iris split over several tokens
+ $strQuoted = $tok;
+ $litQuotes = true;
+ }
+ } else if ($tok == 'true' || $tok == 'false') {
+ $part[] = array(
+ 'type' => 'value',
+ 'value' => $tok,
+ 'quoted' => false,
+ 'datatype' => 'http://www.w3.org/2001/XMLSchema#boolean'
+ );
+ } else {
+ $part[] = array(
+ 'type' => 'value',
+ 'value' => $tok,
+ 'quoted' => false
+ );
+ }
+
+ if (isset($tree['type']) && $tree['type'] == 'equation' && isset($part[0])) {
+ $tree['operand2'] = $part[0];
+ self::balanceTree($tree);
+ $part = array();
+ }
+ }
+
+ if (!isset($tree['type']) && $bParameter) {
+ return $part;
+ } else if (isset($tree['type']) && $tree['type'] == 'equation'
+ && isset($tree['operand1']) && !isset($tree['operand2'])
+ && isset($part[0])) {
+ $tree['operand2'] = $part[0];
+ self::balanceTree($tree);
+ }
+
+ if (!isset($tree['type']) && isset($part[0])) {
+ if (isset($tree['negated'])) {
+ $part[0]['negated'] = true;
+ }
+ return $part[0];
+ }
+
+ return $tree;
+ }//protected function parseConstraintTree($nLevel = 0, $bParameter = false)
+
+
+
+ /**
+ * "Balances" the filter tree in the way that operators on the same
+ * level are nested according to their precedence defined in
+ * $operatorPrecedence array.
+ *
+ * @param array $tree Tree to be modified
+ */
+ protected static function balanceTree(&$tree)
+ {
+ if (
+ isset($tree['type']) && $tree['type'] == 'equation'
+ && isset($tree['operand1']['type']) && $tree['operand1']['type'] == 'equation'
+ && $tree['level'] == $tree['operand1']['level']
+ && self::$operatorPrecedence[$tree['operator']] > self::$operatorPrecedence[$tree['operand1']['operator']]
+ ) {
+ $op2 = array(
+ 'type' => 'equation',
+ 'level' => $tree['level'],
+ 'operator' => $tree['operator'],
+ 'operand1' => $tree['operand1']['operand2'],
+ 'operand2' => $tree['operand2']
+ );
+ $tree['operator'] = $tree['operand1']['operator'];
+ $tree['operand1'] = $tree['operand1']['operand1'];
+ $tree['operand2'] = $op2;
+ }
+ }//protected static function balanceTree(&$tree)
+
+
+
+ protected static function fixNegationInFuncName(&$tree)
+ {
+ if ($tree['type'] == 'function' && $tree['name'][0] == '!') {
+ $tree['name'] = substr($tree['name'], 1);
+ if (!isset($tree['negated'])) {
+ $tree['negated'] = true;
+ } else {
+ unset($tree['negated']);
+ }
+ //perhaps more !!
+ self::fixNegationInFuncName($tree);
+ }
+ }//protected static function fixNegationInFuncName(&$tree)
+
+
+
+ /**
+ * Parses a bracketted expression.
+ *
+ * @param Constraint $constraint
+ * @return void
+ * @throws SparqlParserException
+ */
+ protected function parseBrackettedExpression(&$constraint)
+ {
+ $open = 1;
+ $exp = "";
+ $this->_fastForward();
+ while ($open != 0 && current($this->tokens)!= false) {
+ switch (current($this->tokens)) {
+ case "(":
+ $open++;
+ $exp = $exp . current($this->tokens);
+ break;
+ case ")":
+ $open--;
+ if($open != 0){
+ $exp = $exp . current($this->tokens);
+ }
+ break;
+ case false:
+ throw new SparqlParserException(
+ "Unexpected end of query.",
+ null,
+ key($this->tokens)
+ );
+ default:
+ $exp = $exp . current($this->tokens);
+ break;
+ }
+ next($this->tokens);
+ }
+ $constraint->addExpression($exp);
+ }
+
+
+ /**
+ * Parses an expression.
+ *
+ * @param Constraint $constrain
+ * @return void
+ * @throws SparqlParserException
+ */
+ protected function parseExpression(&$constraint)
+ {
+ $exp = "";
+ while (current($this->tokens) != false && current($this->tokens) != "}") {
+ switch (current($this->tokens)) {
+ case false:
+ throw new SparqlParserException(
+ "Unexpected end of query.",
+ null,
+ key($this->tokens)
+ );
+ case ".":
+ break;
+ break;
+ default:
+ $exp = $exp . current($this->tokens);
+ break;
+ }
+ next($this->tokens);
+ }
+ $constraint->addExpression($exp);
+ }
+
+ /**
+ * Parses a GRAPH clause.
+ *
+ * @param GraphPattern $pattern
+ * @return void
+ * @throws SparqlParserException
+ */
+ protected function parseGraph(){
+ $this->_fastForward();
+ $name = current($this->tokens);
+ if(!$this->varCheck($name)&!$this->iriCheck($name)&&!$this->qnameCheck($name)){
+ $msg = $name;
+ $msg = preg_replace('/', '<', $msg);
+ throw new SparqlParserException(" IRI or Var expected. ",null,key($this->tokens));
+ }
+ $this->_fastForward();
+
+ if($this->iriCheck($name)){
+ $name = new Resource(substr($name,1,-1));
+ }else if($this->qnameCheck($name)){
+ $name = new Resource($this->query->getFullUri($name));
+ }
+ $this->parseGraphPattern(false,false,$name);
+ if(current($this->tokens)=='.')
+ $this->_fastForward();
+ }
+
+ /**
+ * Parses the solution modifiers of a query.
+ *
+ * @return void
+ * @throws SparqlParserException
+ */
+ protected function parseModifier(){
+ do{
+ switch(strtolower(current($this->tokens))){
+ case "order":
+ $this->_fastForward();
+ if(strtolower(current($this->tokens))=='by'){
+ $this->_fastForward();
+ $this->parseOrderCondition();
+ }else{
+ throw new SparqlParserException("'BY' expected.",null,key($this->tokens));
+ }
+ break;
+ case "limit":
+ $this->_fastForward();
+ $val = current($this->tokens);
+ $this->query->setSolutionModifier('limit',$val);
+ break;
+ case "offset":
+ $this->_fastForward();
+ $val = current($this->tokens);
+ $this->query->setSolutionModifier('offset',$val);
+ break;
+ default:
+ break;
+ }
+ }while(next($this->tokens));
+ }
+
+ /**
+ * Parses order conditions of a query.
+ *
+ * @return void
+ * @throws SparqlParserException
+ */
+ protected function parseOrderCondition(){
+ $valList = array();
+ $val = array();
+ while(strtolower(current($this->tokens))!='limit'
+ & strtolower(current($this->tokens))!= false
+ & strtolower(current($this->tokens))!= 'offset'){
+ switch (strtolower(current($this->tokens))){
+ case "desc":
+ $this->_fastForward();
+ $this->_fastForward();
+ if($this->varCheck(current($this->tokens))){
+ $val['val'] = current($this->tokens);
+ }else{
+ throw new SparqlParserException("Variable expected in ORDER BY clause. ",null,key($this->tokens));
+ }
+ $this->_fastForward();
+ if(current($this->tokens)!=')')
+ throw new SparqlParserException("missing ')' in ORDER BY clause.",null,key($this->tokens));
+ $val['type'] = 'desc';
+ $this->_fastForward();
+ break;
+ case "asc" :
+ $this->_fastForward();
+ $this->_fastForward();
+ if($this->varCheck(current($this->tokens))){
+ $val['val'] = current($this->tokens);
+ }else{
+ throw new SparqlParserException("Variable expected in ORDER BY clause. ",null,key($this->tokens));
+ }
+ $this->_fastForward();
+ if(current($this->tokens)!=')')
+ throw new SparqlParserException("missing ')' in ORDER BY clause.",null,key($this->tokens));
+ $val['type'] = 'asc';
+ $this->_fastForward();
+ break;
+ default:
+ if($this->varCheck(current($this->tokens))){
+ $val['val'] = current($this->tokens);
+ $val['type'] = 'asc';
+ }else{
+ throw new SparqlParserException("Variable expected in ORDER BY clause. ",null,key($this->tokens));
+ }
+ $this->_fastForward();
+ break;
+ }
+ $valList[] = $val;
+ }
+ prev($this->tokens);
+ $this->query->setSolutionModifier('order by',$valList);
+ }
+
+ /**
+ * Parses a String to an RDF node.
+ *
+ * @param String $node
+ *
+ * @return Node The parsed RDF node
+ * @throws SparqlParserException
+ */
+ protected function parseNode($node = false)
+ {
+ //$eon = false;
+ if ($node) {
+ $node = $node;
+ } else {
+ $node = current($this->tokens);
+ }
+ if ($node{strlen($node)-1} == '.') {
+ $node = substr($node,0,-1);
+ }
+ if ($this->dtypeCheck($node)) {
+ return $node;
+ }
+ if ($this->bNodeCheck($node)) {
+ $node = '?'.$node;
+ $this->query->addUsedVar($node);
+ return $node;
+ }
+ if ($node == '[') {
+ $node = '?' . substr($this->query->getBlanknodeLabel(), 1);
+ $this->query->addUsedVar($node);
+ $this->_fastForward();
+ if(current($this->tokens)!=']') {
+ prev($this->tokens);
+ }
+ return $node;
+ }
+ if ($this->iriCheck($node)){
+ $base = $this->query->getBase();
+ if ($base!=null) {
+ $node = new Resource(substr(substr($base,0,-1).substr($node,1),1,-1));
+ } else {
+ $node = new Resource(substr($node,1,-1));
+ }
+ return $node;
+ } else if ($this->qnameCheck($node)) {
+ $node = $this->query->getFullUri($node);
+ $node = new Resource($node);
+ return $node;
+ } else if ($this->literalCheck($node)) {
+ $ch = substr($node, 0, 1);
+ $chLong = str_repeat($ch, 3);
+ if (substr($node, 0, 3) == $chLong) {
+ $ch = $chLong;
+ }
+ $this->parseLiteral($node, $ch);
+ } else if ($this->varCheck($node)) {
+ $pos = strpos($node,'.');
+ if ($pos) {
+ return substr($node,0,$pos);
+ } else {
+ return $node;
+ }
+ } else if ($node[0] == '<') {
+ //partial IRI? loop tokens until we find a closing >
+ while (next($this->tokens)) {
+ $node .= current($this->tokens);
+ if (substr($node, -1) == '>') {
+ break;
+ }
+ }
+ if (substr($node, -1) != '>') {
+ throw new SparqlParserException(
+ "Unclosed IRI: " . $node,
+ null,
+ key($this->tokens)
+ );
+ }
+ return $this->parseNode($node);
+ } else {
+ throw new SparqlParserException(
+ '"' . $node . '" is neither a valid rdf- node nor a variable.',
+ null,
+ key($this->tokens)
+ );
+ }
+ return $node;
+ }//protected function parseNode($node = false)
+
+
+
+ /**
+ * Checks if there is a datatype given and appends it to the node.
+ *
+ * @param string $node Node to check
+ *
+ * @return void
+ */
+ protected function checkDtypeLang(&$node, $nSubstrLength = 1)
+ {
+ $this->_fastForward();
+ switch (substr(current($this->tokens), 0, 1)) {
+ case '^':
+ if (substr(current($this->tokens),0,2)=='^^') {
+ $node = new Literal(substr($node,1,-1));
+ $node->setDatatype(
+ $this->query->getFullUri(
+ substr(current($this->tokens), 2)
+ )
+ );
+ }
+ break;
+ case '@':
+ $node = new Literal(
+ substr($node, $nSubstrLength, -$nSubstrLength),
+ substr(current($this->tokens), $nSubstrLength)
+ );
+ break;
+ default:
+ prev($this->tokens);
+ $node = new Literal(substr($node, $nSubstrLength, -$nSubstrLength));
+ break;
+
+ }
+ }//protected function checkDtypeLang(&$node, $nSubstrLength = 1)
+
+
+
+ /**
+ * Parses a literal.
+ *
+ * @param String $node
+ * @param String $sep used separator " or '
+ *
+ * @return void
+ */
+ protected function parseLiteral(&$node, $sep)
+ {
+ do {
+ next($this->tokens);
+ $node = $node.current($this->tokens);
+ } while (current($this->tokens) != $sep);
+ $this->checkDtypeLang($node, strlen($sep));
+ }//protected function parseLiteral(&$node, $sep)
+
+
+
+ /**
+ * Checks if the Node is a typed Literal.
+ *
+ * @param String $node
+ *
+ * @return boolean TRUE if typed FALSE if not
+ */
+ protected function dtypeCheck(&$node)
+ {
+ $patternInt = "/^-?[0-9]+$/";
+ $match = preg_match($patternInt,$node,$hits);
+ if($match>0){
+ $node = new Literal($hits[0]);
+ $node->setDatatype(XML_SCHEMA.'integer');
+ return true;
+ }
+ $patternBool = "/^(true|false)$/";
+ $match = preg_match($patternBool,$node,$hits);
+ if($match>0){
+ $node = new Literal($hits[0]);
+ $node->setDatatype(XML_SCHEMA.'boolean');
+ return true;
+ }
+ $patternType = "/^a$/";
+ $match = preg_match($patternType,$node,$hits);
+ if($match>0){
+ $node = new Resource(RDF_NAMESPACE_URI.'type');
+ return true;
+ }
+ $patternDouble = "/^-?[0-9]+.[0-9]+[e|E]?-?[0-9]*/";
+ $match = preg_match($patternDouble,$node,$hits);
+ if($match>0){
+ $node = new Literal($hits[0]);
+ $node->setDatatype(XML_SCHEMA.'double');
+ return true;
+ }
+ return false;
+ }//protected function dtypeCheck(&$node)
+
+
+
+ /**
+ * Parses an RDF collection.
+ *
+ * @param TriplePattern $trp
+ *
+ * @return Node The first parsed label
+ */
+ protected function parseCollection(&$trp)
+ {
+ $tmpLabel = $this->query->getBlanknodeLabel();
+ $firstLabel = $this->parseNode($tmpLabel);
+ $this->_fastForward();
+ $i = 0;
+ while (current($this->tokens)!=")") {
+ if($i>0)
+ $trp[] = new QueryTriple($this->parseNode($tmpLabel),new Resource("http://www.w3.org/1999/02/22-rdf-syntax-ns#rest"),$this->parseNode($tmpLabel = $this->query->getBlanknodeLabel()));
+ $trp[] = new QueryTriple($this->parseNode($tmpLabel),new Resource("http://www.w3.org/1999/02/22-rdf-syntax-ns#first"),$this->parseNode());
+ $this->_fastForward();
+ $i++;
+ }
+ $trp[] = new QueryTriple($this->parseNode($tmpLabel),new Resource("http://www.w3.org/1999/02/22-rdf-syntax-ns#rest"),new Resource("http://www.w3.org/1999/02/22-rdf-syntax-ns#nil"));
+ return $firstLabel;
+ }//protected function parseCollection(&$trp)
+
+}// end class: SparqlParser.php
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/SparqlParserException.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/SparqlParserException.php.svn-base
new file mode 100755
index 00000000..2a62734f
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/SparqlParserException.php.svn-base
@@ -0,0 +1,33 @@
+
+* @version $Id$
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+Class SparqlParserException extends Exception{
+
+ private $tokenPointer;
+
+ public function __construct($message, $code = 0, $pointer){
+
+ $this->tokenPointer = $pointer;
+ parent::__construct($message, $code);
+ }
+
+ /**
+ * Returns a pointer to the token which caused the exception.
+ * @return int
+ */
+ public function getPointer(){
+ return $this->tokenPointer;
+ }
+
+}
+?>
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/SparqlVariable.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/SparqlVariable.php.svn-base
new file mode 100755
index 00000000..5db6e665
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/.svn/text-base/SparqlVariable.php.svn-base
@@ -0,0 +1,40 @@
+name = $name;
+ }
+
+
+
+ public function __toString()
+ {
+ return $this->name;
+ }
+
+
+
+ /**
+ * Checks if the given subject/predicate/object
+ * is a variable name.
+ *
+ * @return boolean
+ */
+ public static function isVariable($bject)
+ {
+ return is_string($bject) && strlen($bject) >= 2
+ && ($bject[0] == '?' || $bject[0] == '$');
+ }//public static function isVariable($bject)
+
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/ClientQuery.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/ClientQuery.php
new file mode 100755
index 00000000..511bb22c
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/ClientQuery.php
@@ -0,0 +1,56 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+
+class ClientQuery extends Object {
+
+ var $default = array();
+ var $named = array();
+ var $prefixes = array();
+ var $query;
+
+ /**
+ * Adds a default graph to the query object.
+ *
+ * @param String $default default graph name
+ */
+ function addDefaultGraph($default){
+ if(!in_array($this->named,$this->default))
+ $this->default[] = $default;
+ }
+ /**
+ * Adds a named graph to the query object.
+ *
+ * @param String $default named graph name
+ */
+ function addNamedGraph($named){
+ if(!in_array($named,$this->named))
+ $this->named[] = $named;
+ }
+ /**
+ * Adds the SPARQL query string to the query object.
+ *
+ * @param String $query the query string
+ */
+ function query($query){
+ $this->query = $query;
+ }
+
+}
+
+
+
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/Constraint.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/Constraint.php
new file mode 100755
index 00000000..383446e8
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/Constraint.php
@@ -0,0 +1,95 @@
+
+* @version $Id$
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+Class Constraint extends Object{
+
+ /**
+ * The expression string.
+ * @var string
+ */
+ protected $expression;
+
+ /**
+ * True if it is an outer filter, false if not.
+ * @var boolean
+ */
+ protected $outer;
+
+ /**
+ * The expression tree
+ * @var array
+ */
+ protected $tree = null;
+
+ /**
+ * Adds an expression string.
+ *
+ * @param String $exp the expression String
+ * @return void
+ */
+ public function addExpression($exp)
+ {
+ $this->expression = $exp;
+ }
+
+ /**
+ * Returns the expression string.
+ *
+ * @return String the expression String
+ */
+ public function getExpression()
+ {
+ return $this->expression;
+ }
+
+
+ /**
+ * Sets the filter type to outer or inner filter.
+ * True for outer false for inner.
+ *
+ * @param boolean $boolean
+ * @return void
+ */
+ public function setOuterFilter($boolean)
+ {
+ $this->outer = $boolean;
+ }
+
+ /**
+ * Returns true if this constraint is an outer filter- false if not.
+ *
+ * @return boolean
+ */
+ public function isOuterFilter()
+ {
+ return $this->outer;
+ }
+
+
+ public function getTree()
+ {
+ return $this->tree;
+ }//public function getTree()
+
+ public function setTree($tree)
+ {
+ $this->tree = $tree;
+ }//public function setTree($tree)
+
+}
+// end class: Constraint.php
+?>
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/FilterFunctions.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/FilterFunctions.php
new file mode 100755
index 00000000..8c243c43
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/FilterFunctions.php
@@ -0,0 +1,137 @@
+
+* @version $Id$
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+*/
+
+
+
+
+/**
+* Evaluates the regex() function. Returns true if the regex is matched false if not.
+*
+* @param String $string the string which has to be evaluated
+* @param String $pattern the regex pattern
+* @param String $flags additional flags like "i"
+* @return boolean
+*/
+function regex($string,$pattern,$flags = ''){
+ $string = trim($string);
+ $pattern = trim($pattern);
+ if(strpos($string,"str_")===0){
+ $string = substr($string,4);
+ $pattern = substr($pattern,4);
+ $flags = substr($flags,4);
+ }else{
+ return false;
+ }
+ if(preg_match('/'.$pattern.'/'.$flags,$string))
+ return true;
+ else
+ return false;
+}
+
+/**
+* Evaluates the dateTime() function.Tries to convert a date string into
+* a unix timestamp.
+*
+* @param String $string the date string
+* @return integer the corresponding unix timestamp
+*/
+function dateTime($string){
+ $string = trim($string);
+ if(strpos($string,"str_")===0)
+ $string = substr($string,4);
+
+ $time = strtotime($string);
+ if($time == -1)
+ return $string;
+ else
+ return $time;
+}
+
+
+/**
+* Evaluates the langMatches() function. Return true if the lang tag matches false if not.
+*
+* @param String $lang_range the string.
+* @param String $lang_tag the regex pattern
+* @return boolean
+*/
+function langMatches($lang_range,$lang_tag){
+
+ if($lang_range == null)
+ return false;
+
+ if(strpos($lang_range,"str_")===0)
+ $lang_range = substr($lang_range,4);
+ if(strpos($lang_tag,"str_")===0)
+ $lang_tag = substr($lang_tag,4);
+
+ if(strtolower($lang_range) == strtolower($lang_tag))
+ return true;
+ $tags = preg_match_all("/[^\-\s].[^\-\s]*/",$lang_range,$hits);
+ if($tags){
+ if($lang_tag == '*')
+ return true;
+ foreach($hits[0] as $tag){
+ if(strtolower($tag) == strtolower($lang_tag))
+ return true;
+ }
+ return false;
+ }else{
+ return false;
+ }
+}
+
+/**
+* Evaluates the str() function. Returns the string representation of a
+* variable or RDF term.
+*
+* @param String $string the string
+* @return boolean
+*/
+function str($string){
+ $str = preg_match("/\".[^\"]*\"|\'.[^\']*\'/",$string,$hits);
+ if($str != 0){
+ return "str_".$hits[0];
+ }else{
+ if(strpos($string,"str_")===0){
+ return $string;
+ }else{
+ if(strpos($string,"uri_")===0)
+ return "str_".substr($string,4);
+ if(strpos($string,'<')==0)
+ return "str_".substr($string,1,-1);
+ }
+ }
+ return false;
+}
+
+/**
+* Evaluates the lang() function. Returns lang tag of a Literal.
+*
+* @param String $string the string.
+* @return String the lang tag or false if there is no language tag.
+*/
+function lang($string){
+ $str = preg_match("/\".[^\"]*\"@(.[^\s]*)|\'.[^\']*\'@(.[^\s]*)/",$string,$hits);
+ if($str){
+ if($hits[1] != null)
+ return $hits[1];
+ else
+ return $hits[2];
+ }else{
+ return false;
+ }
+}
+
+
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/GraphPattern.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/GraphPattern.php
new file mode 100755
index 00000000..f768687c
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/GraphPattern.php
@@ -0,0 +1,295 @@
+
+* @version $Id$
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+
+class GraphPattern extends Object{
+
+ /**
+ * Graphname. 0 if its in the default graph.
+ */
+ protected $graphname = null;
+
+ /**
+ * Array of QueryTriple objects
+ * @var array
+ */
+ protected $triplePatterns = array();
+
+ /**
+ * A List of Constraint objects
+ * @var array
+ */
+ protected $constraints = array();
+
+ /**
+ * @var int Pointer to optional pattern.
+ */
+ protected $optional = null;
+
+ /**
+ * @var int Pointer to union pattern.
+ */
+ protected $union = null;
+
+ /**
+ * ID of the pattern in the pattern list that
+ * this pattern is subpattern of.
+ * @var int
+ */
+ protected $subpatternOf = null;
+
+ /**
+ * @var boolean TRUE if the pattern is open- FALSE if closed.
+ */
+ public $open = false;
+
+ /**
+ * @var boolean TRUE if the GraphPattern is a construct pattern.
+ */
+ public $isConstructPattern = false;
+
+
+ /**
+ * @var int The GraphPatterns id.
+ */
+ public $patternId = null;
+
+
+ /**
+ * Constructor
+ */
+ public function GraphPattern() {
+ $this->open = true;
+ $this->isConstructPattern = false;
+ $this->constraints = array();
+ $this->triplePatterns = array();
+ }
+
+ /**
+ * Returns the graphname.
+ *
+ * @return String
+ */
+ public function getGraphname(){
+ return $this->graphname;
+ }
+
+ /**
+ * Returns the triple pattern of the graph pattern.
+ *
+ * @return Array
+ */
+ public function getTriplePatterns(){
+ return $this->triplePatterns;
+ }
+
+ /**
+ * Returns a constraint if there is one false if not.
+ *
+ * @return Constraint
+ */
+ public function getConstraints() {
+ return $this->constraints;
+ }
+
+ /**
+ * Returns a pointer to an optional graph pattern.
+ *
+ * @return integer
+ */
+ public function getOptional() {
+ return $this->optional;
+ }
+
+ /**
+ * Returns a pointer to the parent pattern this pattern
+ * is subpattern of.
+ *
+ * @return integer
+ */
+ public function getSubpatternOf() {
+ return $this->subpatternOf;
+ }
+
+ /**
+ * Returns a pointer to a union graph pattern.
+ *
+ * @return integer
+ */
+ public function getUnion() {
+ return $this->union;
+ }
+
+ /**
+ * Sets the graphname.
+ *
+ * @param String $name
+ * @return void
+ */
+ public function setGraphname($name) {
+ $this->graphname = $name;
+ }
+
+ /**
+ * Adds List of QueryTriples to the GraphPattern.
+ *
+ * @param array $trpP
+ * @return void
+ */
+ public function addTriplePatterns($trpP) {
+ $this->triplePatterns = array_merge($this->triplePatterns, $trpP);
+ }
+
+ /**
+ * Sets the List of QueryTriples to the GraphPattern.
+ *
+ * @param array $trpP
+ * @return void
+ */
+ public function setTriplePatterns($trpP) {
+ $this->triplePatterns = $trpP;
+ }
+
+ /**
+ * Adds a single Constraint to the GraphPattern.
+ *
+ * @param Constraint $cons
+ */
+ public function addConstraint(&$cons) {
+ $this->constraints[] = $cons;
+ }
+
+ /**
+ * Adds an array of Constraint objects to the GraphPattern.
+ *
+ * @param array $cons
+ */
+ public function addConstraints(&$cons) {
+ $this->constraints = array_merge($this->constraints, $cons);
+ }
+
+ /**
+ * Adds a pointer to an optional graphPattern.
+ *
+ * @param integer $patternId
+ * @return void
+ */
+ public function setOptional($patternId) {
+ $this->optional = &$patternId;
+ }
+
+ /**
+ * Adds a pointer to a union graphPattern.
+ *
+ * @param integer $patternId
+ * @return void
+ */
+ public function setUnion($patternId) {
+ $this->union = &$patternId;
+ }
+
+ /**
+ * Adds a pointer to a pattern that
+ * this one is subpattern of
+ *
+ * @param integer $patternId
+ */
+ public function setSubpatternOf($patternId) {
+ $this->subpatternOf = $patternId;
+ }
+
+
+ /**
+ * Sets the GraphPatterns Id.
+ *
+ * @param integer $id
+ * @return void
+ */
+ public function setId($id){
+ $this->patternId = $id;
+ }
+
+ /**
+ * Returns the GraphPatterns id.
+ *
+ * @return integer
+ */
+ public function getId(){
+ return $this->patternId;
+ }
+
+
+
+ /**
+ * Returns an array of all variables used in this
+ * graph pattern.
+ * All variables are listed only once (unique).
+ *
+ * @return array Array of variable names
+ */
+ public function getVariables()
+ {
+ $arVars = array();
+
+ foreach ($this->triplePatterns as $pattern) {
+ $arVars = array_merge($arVars, $pattern->getVariables());
+ }
+
+ return array_unique($arVars);
+ }//public function getVariables()
+
+
+
+ /**
+ * Checks if the graph pattern is empty (contains no
+ * usable data).
+ * Occurs when using "{}" without pre- or suffixes
+ * WHERE
+ * {
+ * { ?person rdf:type foaf:Person } .
+ * }
+ *
+ * @return boolean True if the pattern is empty.
+ */
+ public function isEmpty()
+ {
+ return
+ count($this->triplePatterns) == 0
+ && count($this->constraints) == 0
+ && $this->getGraphname() === null
+ ;
+ }//public function isEmpty()
+
+
+
+ /**
+ * When cloning, we need to clone some subobjects, too
+ */
+ public function __clone()
+ {
+ if (count($this->triplePatterns) > 0) {
+ foreach ($this->triplePatterns as $nId => $pattern) {
+ $this->triplePatterns[$nId] = clone $this->triplePatterns[$nId];
+ }
+ }
+ if (count($this->constraints) > 0) {
+ foreach ($this->constraints as $nId => $constraint) {
+ $this->constraints[$nId] = clone $this->constraints[$nId];
+ }
+ }
+ }
+
+}// end class: GraphPattern.php
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/Query.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/Query.php
new file mode 100755
index 00000000..c85a60ec
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/Query.php
@@ -0,0 +1,685 @@
+
+* @version $Id$
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class Query extends Object
+{
+ /**
+ * The BASE part of the SPARQL query.
+ * @var string
+ */
+ protected $base;
+
+ /**
+ * Original SPARQL query string
+ * @var string
+ */
+ protected $queryString = null;
+
+ /**
+ * Array that contains used prefixes and namespaces.
+ * Key is the prefix, value the namespace.
+ *
+ * @example
+ * array(8) {
+ * ["rdf"] => string(43) "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ * ["rdfs"]=> string(37) "http://www.w3.org/2000/01/rdf-schema#"
+ * }
+ *
+ * @var array
+ */
+ public $prefixes = array();
+
+ /**
+ * Array of result variables that shall be returned.
+ * E.g. "?name", "?mbox"
+ *
+ * @var array
+ */
+ protected $resultVars = array();
+
+ /**
+ * What form/type of result should be returned.
+ *
+ * One of:
+ * - "ask"
+ * - "count"
+ * - "construct"
+ * - "describe"
+ * - "select"
+ * - "select distinct"
+ *
+ * @var string
+ * @see http://www.w3.org/TR/rdf-sparql-query/#QueryForms
+ */
+ protected $resultForm = null;
+
+ /**
+ * Contains the result part of the SPARQL query.
+ * Array of GraphPattern
+ *
+ * @var array
+ */
+ protected $resultPart = array();
+
+ /**
+ * Contains the FROM part of the SPARQL query.
+ * @var array
+ */
+ protected $fromPart = array();
+
+ /**
+ * Contains the FROM NAMED part of the SPARQL query.
+ * @var array
+ */
+ protected $fromNamedPart = array();
+
+ /**
+ * Optional solution modifier of the query.
+ * Array with three keys:
+ * "order by", "limit", "offset"
+ * If they are not set, their value is null
+ *
+ * "order by" can be an array with subarrays, each of those
+ * subarrays having two keys: "val" and "type".
+ * "val" determines the variable ("?mbox"), "type" is
+ * "asc" or "desc"
+ *
+ * @var array
+ */
+ protected $solutionModifier = array();
+
+ /**
+ * Blanknode counter.
+ * How many blank nodes are in $resultPart
+ *
+ * @var int
+ */
+ protected $bnodeCounter = 0;
+
+ /**
+ * GraphPattern counter.
+ * How many GraphPattern are in $resultPart
+ *
+ * @var int
+ */
+ public $graphPatternCounter = 0;
+
+ /**
+ * List of all vars used in the query.
+ * Key is the variable (e.g. "?x"), value
+ * is boolean true
+ *
+ * @var array
+ */
+ public $usedVars = array();
+
+ /**
+ * If the query type is CONSTRUCT this variable contains the
+ * CONSTRUCT graph pattern.
+ */
+ protected $constructPattern = null;
+
+ /**
+ * TRUE if the query is empty FALSE if not.
+ *
+ * @var boolean
+ */
+ public $isEmpty = null;
+
+ /**
+ * Language of variables. NULL if the variable has no
+ * language tag (e.g. @en) set.
+ * $varname => $language tag
+ * @var array
+ */
+ public $varLanguages = array();
+
+ /**
+ * Datatype of variables. NULL if the variable has no
+ * data type (e.g. ^^xsd::integer) set.
+ * $varname => $datatype
+ * @var array
+ */
+ public $varDatatypes = array();
+
+
+
+ /**
+ * Constructor
+ */
+ public function Query(){
+ $this->resultForm = null;
+ $this->solutionModifier['order by'] = null;
+ $this->solutionModifier['limit'] = null;
+ $this->solutionModifier['offset'] = null;
+ $this->bnodeCounter = 0;
+ $this->graphPatternCounter = 0;
+
+ }
+
+ /**
+ * Returns the BASE part of the query.
+ *
+ * @return String
+ */
+ public function getBase(){
+ return $this->base;
+ }
+
+ /**
+ * Returns the prefix map of the query.
+ *
+ * @return Array
+ */
+ public function getPrefixes(){
+ return $this->prefixes;
+ }
+
+ /**
+ * Returns a list containing the result vars.
+ *
+ * @return Array
+ */
+ public function getResultVar($strName) {
+ foreach ($this->resultVars as $var) {
+ if ($var->getVariable() == $strName) {
+ return $var;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns a list containing the result vars.
+ *
+ * @return Array
+ */
+ public function getResultVars(){
+ return $this->resultVars;
+ }
+
+ /**
+ * Returns the type the result shall have.
+ * E.g. "select", "select distinct", "ask", ...
+ *
+ * @see $resultForm
+ *
+ * @return string
+ */
+ public function getResultForm(){
+ return $this->resultForm;
+ }
+
+ /**
+ * Returns a list containing the graph patterns of the query.
+ *
+ * @return Array
+ */
+ public function getResultPart(){
+ return $this->resultPart;
+ }
+
+ /**
+ * Returns the FROM clause of the query.
+ *
+ * @return String
+ */
+ public function getFromPart(){
+ return $this->fromPart;
+ }
+
+ /**
+ * Returns the FROM NAMED clause of the query.
+ *
+ * @return Array
+ */
+ public function getFromNamedPart(){
+ return $this->fromNamedPart;
+ }
+
+ /**
+ * Returns $isEmpty variable
+ * @return boolean
+ */
+ public function isEmpty() {
+ return $this->isEmpty;
+ }
+
+ /**
+ * Returns an unused Bnode label.
+ *
+ * @return String
+ */
+ public function getBlanknodeLabel(){
+ return "_:bN".$this->bnodeCounter++;
+ }
+
+
+ /**
+ * Sets the base part.
+ *
+ * @param String $base
+ * @return void
+ */
+ public function setBase($base){
+ $this->base = $base;
+ }
+
+
+ /**
+ * Adds a prefix to the list of prefixes.
+ *
+ * @param String $prefix
+ * @param String $label
+ * @return void
+ */
+ public function addPrefix($prefix, $label){
+ $this->prefixes[$prefix]= $label;
+ }
+
+ /**
+ * Adds a variable to the list of result variables.
+ *
+ * @param String $var
+ * @return void
+ */
+ public function addResultVar($var){
+ $this->resultVars[] = $var;
+ $var->setDatatype($this->getDatatype($var));
+
+ $this->varLanguages[$var->getId()] = self::getLanguageTag($var);
+ $this->varDatatypes[$var->getId()] = $this->getDatatype($var);
+ }
+
+
+ /**
+ * Sets the result form.
+ *
+ * @param String $form
+ * @return void
+ */
+ public function setResultForm($form){
+ $this->resultForm = strtolower($form);
+ }
+
+
+ /**
+ * Sets the result part.
+ *
+ * @param array Array of graph patterns
+ */
+ public function setResultPart($resultPart) {
+ $this->resultPart = $resultPart;
+ }
+
+ /**
+ * Adds a graph pattern to the result part.
+ *
+ * @param GraphPattern $pattern
+ * @return void
+ */
+ public function addGraphPattern($pattern){
+ $pattern->setId($this->graphPatternCounter);
+ $this->resultPart[] = $pattern;
+ $this->graphPatternCounter++;
+ }
+
+ /**
+ * Adds a construct graph pattern to the query.
+ *
+ * @param GraphPattern $pattern
+ * @return void
+ */
+ public function addConstructGraphPattern($pattern){
+ $this->constructPattern = $pattern;
+ }
+
+
+ /**
+ * Adds a graphuri to the from part.
+ *
+ * @param String $graphURI
+ * @return void
+ */
+ public function addFrom($graphURI){
+ $this->fromPart[] = $graphURI;
+ }
+
+ /**
+ * Adds a graphuri to the from named part.
+ *
+ * @param String $graphURI
+ * @return void
+ */
+ public function addFromNamed($graphURI){
+ $this->fromNamedPart[] = $graphURI;
+ }
+
+ /**
+ * Sets a solution modifier.
+ *
+ * @param String $name
+ * @param Value $value
+ * @return void
+ */
+ public function setSolutionModifier($name, $value){
+ $this->solutionModifier[$name] = $value;
+ }
+
+
+ /**
+ * Generates a new GraphPattern. If it is a CONSTRUCT graph pattern
+ * $constr has to set to TRUE, FALSE if not.
+ *
+ * @param boolean $constr
+ * @return GraphPattern
+ */
+ public function getNewPattern($constr = false){
+ $pattern = new GraphPattern();
+ if ($constr) {
+ $this->addConstructGraphPattern($pattern);
+ } else {
+ $this->addGraphPattern($pattern);
+ }
+ return $pattern;
+ }
+
+ /**
+ * Adds a new variable to the variable list.
+ *
+ * @param String $var
+ * @return void
+ */
+ public function addUsedVar($var){
+ $this->usedVars[$var]=true;
+ }
+
+ /**
+ * Returns a list with all used variables.
+ *
+ * @return Array
+ */
+ public function getAllVars(){
+ return array_keys($this->usedVars);
+ }
+
+ /**
+ * Gets the solution modifiers of the query.
+ * $solutionModifier['order by'] = value
+ * ['limit'] = vlaue
+ * ['offset'] = value
+ *
+ *
+ * @return Array
+ */
+ public function getSolutionModifier(){
+ return $this->solutionModifier;
+ }
+
+
+ /**
+ * Returns the construvtGraphPattern of the query if there is one.
+ *
+ * @return GraphPattern
+ */
+ public function getConstructPattern(){
+ return $this->constructPattern;
+ }
+
+
+
+ /**
+ * Returns a list of variables used in the construct patterns.
+ *
+ * @return array Array of variable names, unique.
+ */
+ public function getConstructPatternVariables()
+ {
+ $arVars = array();
+/*
+ if (count($this->resultPart) > 0) {
+ foreach ($this->resultPart as $pattern) {
+ $arVars = array_merge($arVars, $pattern->getVariables());
+ }
+ }
+*/
+ if ($this->constructPattern) {
+ $arVars = array_merge($arVars, $this->constructPattern->getVariables());
+ }
+
+ return array_unique($arVars);
+ }//public function getConstructPatternVariables()
+
+
+
+ /**
+ * Returns the language of a variable if the tag is set (e.g. @en)
+ * Returns NULL if no language is set.
+ *
+ * @param string Sparql variable name
+ * @return mixed NULL or language tag
+ */
+ public static function getLanguageTag($var)
+ {
+ $nAt = strpos($var, '@');
+ if ($nAt === false) {
+ return null;
+ }
+ //in case @ and ^^ are combined
+ $nHatHat = strpos($var, '^^', $nAt + 1);
+ if ($nHatHat === false) {
+ $tag = substr($var, $nAt + 1);
+ } else {
+ $tag = substr($var, $nAt + 1, $nHatHat - $nAt - 1);
+ }
+ return $tag;
+ }//public static function getLanguageTag($var)
+
+
+
+ /**
+ * Returns the datatype of a variable if it is set.
+ *
+ * @param string Sparql variable name
+ * @return mixed NULL or datatype
+ */
+ public function getDatatype($var)
+ {
+ $nHatHat = strpos($var, '^^');
+ if ($nHatHat === false) {
+ return null;
+ }
+ $nAt = strpos($var, '@', $nHatHat + 2);
+ if ($nAt === false) {
+ $type = substr($var, $nHatHat + 2);
+ } else {
+ $type = substr($var, $nHatHat + 2, $nAt - $nHatHat - 2);
+ }
+
+ $fullUri = $this->getFullUri($type);
+ if ($fullUri === false) {
+ $fullUri = $type;
+ if ($fullUri[0] == '<' && substr($fullUri, -1) == '>') {
+ $fullUri = substr($fullUri, 1, -1);
+ }
+ }
+
+ return $fullUri;
+ }//public function getDatatype($var)
+
+
+
+ /**
+ * Gets the full URI of a qname token.
+ *
+ * @param string $token
+ * @return string The complete URI of a given token, false if $token is not
+ * a qname or the prefix is not defined
+ */
+ public function getFullUri($token)
+ {
+ $pattern="/^([^:]*):([^:]*)$/";
+ if (preg_match($pattern, $token, $hits) > 0) {
+
+ if (isset($this->prefixes{$hits{1}})) {
+ return substr($this->base, 1, -1)
+ . $this->prefixes{$hits{1}}
+ . $hits{2};
+ }
+ if ($hits{1}=='_') {
+ return "_".$hits{2};
+ }
+ }
+
+ return false;
+ }
+
+
+
+ /**
+ * Checks if the query is complete
+ * (so that querying is possible)
+ *
+ * @return boolean true if the query is complete
+ */
+ public function isComplete()
+ {
+ if ($this->resultForm === null) {
+ return false;
+ }
+ //TODO: maybe check selected vars and construct pattern depending
+ // on the resultform
+ return true;
+ }//public function isIncomplete()
+
+
+
+ /**
+ * Sets the orignal query string
+ *
+ * @param string $queryString SPARQL query string
+ */
+ public function setQueryString($queryString)
+ {
+ $this->queryString = $queryString;
+ }//public function setQueryString($queryString)
+
+
+
+ /**
+ * Returns the orignal query string
+ *
+ * @return string SPARQL query string
+ */
+ public function getQueryString()
+ {
+ return $this->queryString;
+ }//public function getQueryString()
+
+}// end class: Query.php
+
+
+
+class Query_ResultVariable
+{
+ public $variable = null;
+ public $datatype = null;
+ public $language = null;
+ public $alias = null;
+ public $func = null;
+
+
+ public function __construct($variable)
+ {
+ $this->variable = $variable;
+ $this->language = Query::getLanguageTag($variable);
+ }
+
+
+
+ public function setAlias($alias)
+ {
+ $this->alias = $alias;
+ }
+
+
+
+ public function setFunc($func)
+ {
+ $this->func = $func;
+ }
+
+
+
+ public function setDatatype($datatype)
+ {
+ $this->datatype = $datatype;
+ }
+
+
+
+ public function getId()
+ {
+ //FIXME
+ return $this->variable;
+ }
+
+
+
+ public function getFunc()
+ {
+ return $this->func;
+ }
+
+
+
+ public function getLanguage()
+ {
+ return $this->language;
+ }
+
+
+
+ public function getDatatype()
+ {
+ return $this->datatype;
+ }
+
+
+
+ public function getName()
+ {
+ if ($this->alias !== null) {
+ return $this->alias;
+ }
+ //FIXME: support for nested(functions())
+ return $this->variable;
+ }
+
+
+
+ public function getVariable()
+ {
+ return $this->variable;
+ }
+
+
+
+ public function __toString()
+ {
+ return $this->getName();
+ }
+
+}//class Query_ResultVariable
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/QueryTriple.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/QueryTriple.php
new file mode 100755
index 00000000..4f8dcca2
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/QueryTriple.php
@@ -0,0 +1,123 @@
+
+* @version $Id$
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class QueryTriple extends Object
+{
+
+ /**
+ * The QueryTriples Subject.
+ * Can be a BlankNode or Resource, string in
+ * case of a variable
+ * @var Node/string
+ */
+ protected $subject;
+
+ /**
+ * The QueryTriples Predicate.
+ * Normally only a Resource, string in
+ * case of a variable
+ * @var Node/string
+ */
+ protected $predicate;
+
+ /**
+ * The QueryTriples Object.
+ * Can be BlankNode, Resource or Literal, string in
+ * case of a variable
+ * @var Node/string
+ */
+ protected $object;
+
+
+
+ /**
+ * Constructor
+ *
+ * @param Node $sub Subject
+ * @param Node $pred Predicate
+ * @param Node $ob Object
+ */
+ public function QueryTriple($sub,$pred,$ob)
+ {
+ $this->subject = $sub;
+ $this->predicate = $pred;
+ $this->object = $ob;
+ }
+
+ /**
+ * Returns the Triples Subject.
+ *
+ * @return Node
+ */
+ public function getSubject()
+ {
+ return $this->subject;
+ }
+
+ /**
+ * Returns the Triples Predicate.
+ *
+ * @return Node
+ */
+ public function getPredicate()
+ {
+ return $this->predicate;
+ }
+
+ /**
+ * Returns the Triples Object.
+ *
+ * @return Node
+ */
+ public function getObject()
+ {
+ return $this->object;
+ }
+
+
+
+ /**
+ * Returns an array of all variables in this triple.
+ *
+ * @return array Array of variable names
+ */
+ public function getVariables()
+ {
+ $arVars = array();
+
+ foreach (array('subject', 'predicate', 'object') as $strVar) {
+ if (SparqlVariable::isVariable($this->$strVar)) {
+ $arVars[] = $this->$strVar;
+ }
+ }
+
+ return $arVars;
+ }//public function getVariables()
+
+
+
+ public function __clone()
+ {
+ foreach (array('subject', 'predicate', 'object') as $strVar) {
+ if (is_object($this->$strVar)) {
+ $this->$strVar = clone $this->$strVar;
+ }
+ }
+ }//public function __clone()
+
+}//class QueryTriple extends Object
+
+// end class: QueryTriple.php
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SPARQL.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SPARQL.php
new file mode 100755
index 00000000..b35f82ef
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SPARQL.php
@@ -0,0 +1,20 @@
+
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlClient.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlClient.php
new file mode 100755
index 00000000..9db93c96
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlClient.php
@@ -0,0 +1,160 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+
+class SparqlClient extends Object {
+
+ var $server;
+ var $output;
+
+ /**
+ * Constructor of SparlClient.
+ *
+ * @param String $server server address.
+ */
+ function SparqlClient($server){
+ $this->server = $server;
+ $this->output = "array";
+ }
+
+
+ /**
+ * Sets the output format for a SELECT or ASK query. Possible formats are "xml" for
+ * Sparql Query Results XML Format (http://www.w3.org/TR/rdf-sparql-XMLres/) or array
+ * for the format described in our SparqlEngine.
+ *
+ * @param String $format the format.
+ */
+ function setOutputFormat($format){
+ if(strtolower($format)=="xml")
+ $this->output = "xml";
+ if(strtolower($format)=="array")
+ $this->output = "array";
+
+ }
+
+ /**
+ * Main function of SparqlClient.
+ *
+ * @param ClientQuery $query the ClientQuery object.
+ * @return mixed returns an array that contains the variables an their bindings or a MemModel
+ *
+ */
+ function query($query){
+ if(!is_a($query,"ClientQuery"))
+ die;//ErrorHandling
+
+ $url = $this->_buildurl($query);
+ $result = $this->_http_get($url);
+ return $this->returnResult($result);
+
+ }
+
+
+ /**
+ * Helper function that builds the url.
+ *
+ * @param ClientQuery $query the ClientQuery Object.
+ */
+
+ function _buildurl($query){
+ $url = "";
+ $url = $this->server."?query=".urlencode($query->query);
+ foreach($query->default as $defaultg){
+ $url = $url."&default-graph-uri=".$defaultg;
+ }
+ foreach($query->named as $namedg){
+ $url = $url."&named-graph-uri=".$namedg;
+ }
+
+ return $url;
+
+ }
+
+ /**
+ * Returns the query result.
+ *
+ * @param String $result the result.
+ * @return mixed
+ */
+ function returnResult($result){
+
+ if(strpos($result,"generateModel(substr($result,strpos($result,"output == "xml"){
+ $pos = strpos($result,"output == "array"){
+ // $pos = strpos($buffer,"parseResult($result);
+ }
+ return $result;
+ }
+
+
+ function parseResult($buffer){
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_SPARQLRES);
+ $parser = new SparqlResultParser();
+ return $parser->parse($buffer);
+ }
+
+
+ /**
+ * Executes the GET Request.
+ *
+ * @param String $url the url.
+ * @return String result.
+ */
+ function _http_get($url)
+ {
+ $url = parse_url($url);
+ $port = isset($url['port']) ? $url['port'] : 80;
+
+ $fp = fsockopen($url['host'], $port);
+
+ $replace = $url['path'];
+
+ fputs($fp, "GET ".$replace."?".$url['query']." HTTP/1.0\n");
+ fputs($fp, "Host:". $url['host']." \r\n");
+ fputs($fp, "Accept: application/sparql-results+xml, application/rdf+xml\r\n");
+ fputs($fp, "Connection: close\n\n");
+
+ $buffer = "";
+ while ($tmp = fread($fp, 1024))
+ {
+ $buffer .= $tmp;
+ }
+
+ $pos1 = strpos($buffer,"\r\n\r\n");
+ $pos2 = strpos($buffer,"\n\n");
+ if ($pos1 === false) {
+ $pos = $pos2;
+ } else {
+ $pos = $pos1;
+ }
+
+ return substr($buffer,$pos);
+
+ }
+}
+
+
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine.php
new file mode 100755
index 00000000..06f6c804
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine.php
@@ -0,0 +1,1169 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+
+Class SparqlEngine extends Object{
+
+
+ /**
+ * The query object.
+ * @var Query
+ */
+ protected $query;
+
+ /**
+ * The RDF Dataset.
+ * @var Dataset
+ */
+ protected $dataset;
+
+
+
+ /**
+ * Use SparqlEngine::factory() instead of this
+ * constructor.
+ */
+ protected function __construct()
+ {
+ //protected to prevent direct instantiation
+ }
+
+
+ /**
+ * Creates a new instance of the SparqlEngine, depending on the
+ * given model. For example, if you pass a DbModel, you will
+ * get a SparqlEngine specialized on databases.
+ *
+ * @param Model $model RDF model that uses the engine
+ */
+ public function factory($model = null)
+ {
+ if ($model !== null && $model instanceof DbModel) {
+ require_once RDFAPI_INCLUDE_DIR . 'sparql/SparqlEngineDb.php';
+ return new SparqlEngineDb($model);
+ } else {
+ return new SparqlEngine();
+ }
+ }
+
+
+
+ /**
+ * The query engine's main method.
+ *
+ * @param Dataset $dataset the RDF Dataset
+ * @param mixed $query the parsed SPARQL query
+ * @param String $resultform the result form. If set to 'xml' the result will be
+ * SPARQL Query Results XML Format as described in http://www.w3.org/TR/rdf-sparql-XMLres/ .
+ * @return Array/String Type of the result depends on $resultform.
+ */
+ public function queryModel($dataset, Query $query, $resultform = false)
+ {
+ $this->query = $query;
+ $this->dataset = $dataset;
+
+ if($this->query->isEmpty){
+ $vartable[0]['patternResult'] = null;
+ return SparqlEngine_ResultConverter::convertFromResult(
+ $vartable,
+ $this,
+ $resultform
+ );
+ }
+
+ $graphlist = $this->preselectGraphs();
+ /// match graph patterns against the RDF Dataset
+ $patternlist = $this->matchPatterns($graphlist);
+ // filter results- apply inner filters
+ $patternlist = $this->filterPatterns($patternlist,false);
+ // join pattern results
+ $vartable = $this->joinResults($patternlist);
+ // filter results- apply outer filters
+ $vartable = $this->filterPatterns($vartable,true);
+
+ if ($vartable[0]['patternResult'] != null) {
+ // sort vars (ORDER BY, LIMIT, OFFSET)
+ $vartable = $this->sortVars($vartable[0]['patternResult']);
+ $qrf = $this->query->getResultForm();
+ if ($qrf == 'select' || $qrf == 'select distinct') {
+ $vars = $this->query->getResultVars();
+ $vartable = $this->selectVars($vartable, $vars);
+ if ($qrf == 'select distinct') {
+ $vartable = $this->distinct($vartable);
+ }
+ }
+ } else {
+ $vartable = null;
+ }
+
+ return SparqlEngine_ResultConverter::convertFromResult(
+ $vartable,
+ $this,
+ $resultform
+ );
+ }//public function queryModel($dataset, Query $query, $resultform = false)
+
+
+
+ /**
+ * Matches all graph Patterns against the dataset and generates an array which
+ * contains the result sets for every given GraphPattern.
+ *
+ * @param Array $graphlist the graphlist which contains the names of the named
+ * graphs which has to be queried.
+ * @return Array
+ */
+ protected function matchPatterns($graphlist){
+ $patternlist = array();
+ // get the result part from the query
+ $resultPart = $this->query->getResultPart();
+ // for each GrapPattern in the result part
+ if($resultPart)
+ foreach($resultPart as $graphPattern){
+ $this->matchPattern($patternlist, $graphlist, $graphPattern);
+ }
+ return $patternlist;
+ }
+
+
+
+ /**
+ * Finds tuples that match one graph pattern.
+ *
+ * @param Array $patternlist list that contains the graphPatterns
+ * @param array $graphlist the graphlist
+ * @param GraphPattern $graphPattern the pattern which has to be matched
+ * @return void
+ */
+ protected function matchPattern(&$patternlist, $graphlist, &$graphPattern) {
+ // generate an empty result set
+ $finalRes = null;
+ // if the GraphPattern has triple patterns
+ if (count($graphPattern->getTriplePatterns()) > 0) {
+ // check if the pattern has a GRAPH clause and if this Iri is in $graphlist
+ $newGraphList = $this->_checkGraphs($graphPattern,$graphlist);
+ if($newGraphList){
+ $qt = $graphPattern->getTriplePatterns();
+ $resultSet = $this->findTuplesMatchingOnePattern($qt[0], $newGraphList);
+ for ($i=1; $ifindTuplesMatchingOnePattern($qt[$i], $newGraphList);
+ $resultSet = $this->joinTuples($resultSet, $rs);
+ if(!$resultSet)
+ break;
+ }
+ if($finalRes != null){
+ $finalRes = $this->joinTuples($finalRes,$resultSet);
+ }else{
+ $finalRes = $resultSet;
+ }
+ }
+ }
+ // dependencies between pattern results
+ $patternlist[$graphPattern->getId()]['hasOptional'] = 0;
+ $patternlist[$graphPattern->getId()]['hasUnion'] = 0;
+ $patternlist[$graphPattern->getId()]['patternResult'] = $finalRes;
+
+ $op = $graphPattern->getOptional();
+ $un = $graphPattern->getUnion();
+
+ $patternlist[$graphPattern->getId()]['optionalTo'] = $op;
+ if(is_int($op))
+ $patternlist[$op]['hasOptional']++;
+
+ $patternlist[$graphPattern->getId()]['unionWith'] = $un;
+ if(is_int($un))
+ $patternlist[$un]['hasUnion']++;
+
+ $constraint = $graphPattern->getConstraints();
+ if(count($constraint) > 0){
+ foreach($constraint as $constr){
+ if($constr->isOuterFilter()){
+ $patternlist[$graphPattern->getId()]['outerFilter'][] = $constr;
+ $patternlist[$graphPattern->getId()]['innerFilter'][] = null;
+ }else{
+ $patternlist[$graphPattern->getId()]['innerFilter'][] = $constr;
+ $patternlist[$graphPattern->getId()]['outerFilter'][] = null;
+ }
+ }
+ }else{
+ $patternlist[$graphPattern->getId()]['innerFilter'] = null;
+ $patternlist[$graphPattern->getId()]['outerFilter'] = null;
+ }
+ }
+
+
+ /**
+ * Finds Tuples matching one TriplePattern.
+ *
+ * @param TriplePattern $pattern
+ * @param Array $graphlist
+ * @return Array
+ */
+ protected function findTuplesMatchingOnePattern($pattern, $graphlist){
+ $var = null;
+ $sub = $pattern->getSubject();
+ $pred = $pattern->getPredicate();
+ $obj = $pattern->getObject();
+
+ if(is_string($sub)||$sub instanceof BlankNode){
+ if(is_string($sub))
+ $var['sub'] = $sub;
+ $sub = null;
+ }
+ if(is_string($pred)||$pred instanceof BlankNode ){
+ if(is_string($pred))
+ $var['pred'] = $pred;
+ $pred = null;
+ }
+ if(is_string($obj)||$obj instanceof BlankNode){
+ if(is_string($obj))
+ $var['obj'] = $obj;
+ $obj = null;
+ }
+ $intBindings = $this->_buildIntBindings($var);
+ $k = 0;
+
+ $key = 0;
+ // search in named graphs
+ if($graphlist['var'][0] != null||$graphlist['list'][0] != null){
+ foreach($graphlist['list'] as $key => $graphnode){
+
+ // query the dataset
+ $it = $this->dataset->findInNamedGraphs($graphnode,$sub,$pred,$obj,false);
+ if($it->valid()){
+ // add statements to the result list
+ while($it->valid()){
+ if($graphnode == null){
+ $element = $it->current()->getStatement();
+ $grname = $it->current()->getGraphname();
+ }else{
+ if($it->current() instanceof Quad)
+ $element = $it->current()->getStatement();
+ else
+ $element = $it->current();
+
+ $grname = $graphnode;
+ }
+ if($this->checkIntBindings($element,$intBindings)){
+ $resmodel['trip'][$k] = $element;
+ $resmodel['graph'][$k] = $grname;
+ // $resmodel['graphvar'][$k] = $graphlist['var'][$key];
+ $resmodel['graphvar'][$k] = $graphlist['var'][0];
+ $k++;
+
+ }
+ $it->next();
+ }
+ }
+
+ }
+ }
+ // search in the default graph
+ if($graphlist['list'][0] == null && $graphlist['var'][0] == null){
+
+
+ $gr = $this->dataset->getDefaultGraph();
+
+ $res = $gr->find($sub,$pred,$obj);
+
+ foreach($res->triples as $innerkey => $element){
+ if($this->checkIntBindings($element,$intBindings)){
+ $resmodel['trip'][$k] = $element;
+ $resmodel['graph'][$k] = null;
+ $resmodel['graphvar'][$k] = $graphlist['var'][$key];
+ $k++;
+ }
+ }
+ }
+ if($k == 0)
+ return false;
+ return $this->_buildResultSet($pattern,$resmodel);
+ }
+
+ /**
+ * Checks it there are internal bindings between variables.
+ *
+ * @param Triple $trip
+ * @param Array $intBindings
+ * @return boolean
+ */
+ protected function checkIntBindings($trip, $intBindings){
+ switch($intBindings){
+ case -1:
+ return true;
+ break;
+ case 0:
+ if($trip->subj != $trip->pred)
+ return false;
+ break;
+ case 1:
+ if(is_a($trip->obj,'Literal'))
+ return false;
+ if($trip->subj != $trip->obj)
+ return false;
+ break;
+ case 2:
+ if(is_a($trip->obj,'Literal'))
+ return false;
+ if($trip->pred != $trip->obj)
+ return false;
+ break;
+ case 3:
+ if(is_a($trip->obj,'Literal'))
+ return false;
+ if($trip->pred != $trip->obj || $trip->pred != $trip->subj )
+ return false;
+ break;
+ }
+ return true;
+ }
+
+
+ /**
+ * Perform an SQL-like inner join on two resultSets.
+ *
+ * @param Array &$finalRes
+ * @param Array &$res
+ * @return Array
+ */
+ protected function joinTuples(&$finalRes, &$res) {
+
+ if (!$finalRes || !$res)
+ return array();
+
+ // find joint variables and new variables to be added to $finalRes
+ $jointVars = array();
+ $newVars = array();
+ $k = key($res);
+
+ foreach ($res[$k] as $varname => $node) {
+ if (array_key_exists($varname, $finalRes[0]))
+ $jointVars[] = $varname;
+ else
+ $newVars[] = $varname;
+ }
+
+ // eliminate rows of $finalRes in which the values of $jointVars do not have
+ // a corresponding row in $res.
+ foreach ($finalRes as $n => $fRes) {
+ foreach ($res as $i => $r) {
+ $ok = TRUE;
+ foreach ($jointVars as $j_varname)
+ if ($r[$j_varname] != $fRes[$j_varname]) {
+ $ok = FALSE;
+ break;
+ }
+ if ($ok)
+ break;
+ }
+ if (!$ok)
+ unset($finalRes[$n]);
+ }
+
+ // join $res and $finalRes
+ $joinedRes = array();
+ foreach ($res as $r) {
+ foreach ($finalRes as $n => $fRes) {
+ $ok = TRUE;
+ foreach ($jointVars as $j_varname)
+ if ($r[$j_varname] != $fRes[$j_varname]) {
+ $ok = FALSE;
+ break;
+ }
+ if ($ok) {
+ $joinedRow = $finalRes[$n];
+ foreach($newVars as $n_varname)
+ $joinedRow[$n_varname] = $r[$n_varname];
+ $joinedRes[] = $joinedRow;
+ }
+ }
+ }
+ return $joinedRes;
+ }
+
+
+ /**
+ * Joins OPTIONAL pattern results.
+ *
+ * @param Array &$finalRes
+ * @param Array &$res
+ * @return Array the joined Array
+ */
+ protected function joinOptionalTuples(&$finalRes, &$res) {
+
+ if(!$finalRes && !$res)
+ return array();
+
+ if(!$finalRes)
+ return $res;
+
+ if(!$res)
+ return $finalRes;
+
+ // find joint variables and new variables to be added to $finalRes
+ $jointVars = array();
+ $newVars = array();
+ $result = array();
+
+ $k = key($res);
+
+ foreach ($res[$k] as $varname => $node) {
+ if (array_key_exists($varname, $finalRes[0])){
+ $jointVars[] = $varname;
+ }else{
+ $newVars[] = $varname;
+ }
+ }
+ $joined = array();
+ $joinc = 0;
+ foreach($finalRes as $i =>$fRes){
+ foreach($res as $n =>$r){
+ $join = false;
+ foreach($jointVars as $j_varname){
+ if($r[$j_varname]==$fRes[$j_varname]){
+ $join = true;
+ //break;
+ }else{
+ $join = false;
+ }
+ }
+ if($join){
+ $result[$joinc] = $fRes;
+ foreach($newVars as $n_varname)
+ $result[$joinc][$n_varname] = $r[$n_varname];
+ $joined[]=$n;
+ $joinc++;
+ }
+
+ }
+ }
+
+ $count = count($result);
+ foreach($res as $k =>$val){
+ if(!in_array($k,$joined)){
+ $result[$count] = $finalRes[0];
+ foreach($result[$count] as $varname => $varVal){
+ $result[$count][$varname]='';
+ }
+
+ foreach($val as $varname2 => $varVal2){
+ $result[$count][$varname2]=$varVal2;
+ }
+ $count++;
+ }
+ }
+ return $result;
+ }
+
+
+
+ /**
+ * Looks in from and from named part of the query and
+ * adds the graphs to the graphlist.
+ *
+ * @return Array
+ */
+ protected function preselectGraphs(){
+ $fromNamed = $this->query->getFromNamedPart();
+ if($fromNamed == null)
+ $fromNamed[] = null;
+ return $fromNamed;
+ }
+
+
+ /**
+ * Evaluates the GRPAH clause if there is one. Checks if
+ * the GRAPH clause contains an IRI, variable or nothing.
+ * Returns an array which contains the graphs that has to be matched.
+ *
+ * @param GraphPattern $pattern
+ * @param Array $graphlist
+ * @return Array
+ */
+ protected function _checkGraphs(&$pattern,$graphlist){
+
+ $gr = $pattern->getGraphname();
+ if($gr instanceof Resource ){
+ if($graphlist[0]==null || in_array($gr,$graphlist)){
+ $newGraphList['list'][] = $gr;
+ $newGraphList['var'][] = null;
+ }else{
+ return false;
+ }
+ }elseif (is_string($gr)){
+ $newGraphList['list'] = $graphlist;
+ $newGraphList['var'][] = $gr;
+ }else{
+ $newGraphList['list'] = $graphlist;
+ $newGraphList['var'][] = null;
+ }
+ return $newGraphList;
+ }
+
+ /**
+ * Marks triples with internal bindings.
+ * int bindings -1 :none 0:sub=pred 1:sub=obj 2:pred=obj 3:sub=pred=obj.
+ *
+ * @param Array $var
+ * @return Array
+ */
+ protected function _buildIntBindings($var){
+ $intBindings = -1;
+ if(!$var)
+ return $intBindings;
+
+ if(isset($var['sub'])){
+ if(isset($var['pred']))
+ if($var['sub'] == $var['pred'])
+ $intBindings = 0;
+ if(isset($var['obj']))
+ if($var['sub'] == $var['obj']){
+ if( $intBindings == 0){
+ $intBindings = 3;
+ }else{
+ $intBindings = 1;
+ }
+ }
+ }
+ if(isset($var['pred'])){
+ if(isset($var['obj']))
+ if($var['pred']==$var['obj']&&$intBindings!=3)
+ $intBindings = 2;
+ }
+ return $intBindings;
+ }
+
+ /**
+ * Builds the resultset.
+ *
+ * @param GraphPattern $pattern
+ * @param Array $resmodel
+ * @return Array
+ */
+ protected function _buildResultSet($pattern,$resmodel){
+ // determine variables and their corresponding values
+ $result = null;
+ if(is_string($pattern->getSubject())){
+ $n = 0;
+ foreach($resmodel['trip'] as $key => $triple){
+ if(isset($resmodel['graphvar'][$key]))
+ $result[$n][$resmodel['graphvar'][$key]] = $resmodel['graph'][$key];
+ $result[$n++][$pattern->getSubject()] = $triple->subj;
+ }
+ }
+ if(is_string($pattern->getPredicate())){
+ $n = 0;
+ foreach($resmodel['trip'] as $key => $triple){
+ if(isset($resmodel['graphvar'][$key]))
+ $result[$n][$resmodel['graphvar'][$key]] = $resmodel['graph'][$key];
+ $result[$n++][$pattern->getPredicate()] = $triple->pred;
+ }
+ }
+ if(is_string($pattern->getObject())){
+ $n = 0;
+ foreach($resmodel['trip'] as $key => $triple){
+ if(isset($resmodel['graphvar'][$key]))
+ $result[$n][$resmodel['graphvar'][$key]] = $resmodel['graph'][$key];
+ $result[$n++][$pattern->getObject()] = $triple->obj;
+ }
+ }
+ return $result;
+ }
+
+ /**
+ * Selects the result variables and builds a result table.
+ *
+ * @param Array $table the result table
+ * @param Array $vars the result variables
+ * @return Array
+ */
+ protected function selectVars($table,$vars){
+ if($vars[0]=='*')
+ $vars = $this->query->getAllVars();
+ $resTable = array();
+ $hits = 0;
+ foreach($table as $val){
+ foreach($vars as $var){
+ if(isset($val[(string)$var])){
+ $resTable[$hits][(string)$var]=$val[(string)$var];
+ }else{
+ $resTable[$hits][(string)$var]="";
+ }
+ }
+ $hits++;
+ }
+ return $resTable;
+ }
+
+ /**
+ * Joins the results of the different Graphpatterns.
+ *
+ * @param Array $patternlist
+ * @return Array
+ */
+ protected function joinResults($patternlist){
+ $joined[0]['patternResult'] = null;
+ $joined[0]['outerFilter'] = null;
+
+ while(count($patternlist)>0){
+ foreach($patternlist as $key => $pattern){
+ if($pattern['hasOptional'] == 0 && $pattern['hasUnion'] == 0){
+ if(is_int($pattern['optionalTo'])){
+ $patternlist[$pattern['optionalTo']]['hasOptional']--;
+ $patternlist[$pattern['optionalTo']]['patternResult'] = $this->joinOptionalTuples($pattern['patternResult'],$patternlist[$pattern['optionalTo']]['patternResult']);
+ unset($patternlist[$key]);
+ break;
+ }
+ else if(is_int($pattern['unionWith'])){
+ $patternlist[$pattern['unionWith']]['hasUnion']--;
+ foreach($pattern['patternResult'] as $value)
+ array_push($patternlist[$pattern['unionWith']]['patternResult'],$value);
+ unset($patternlist[$key]);
+ break;
+ }else{
+ if($joined[0]['patternResult'] == null){
+ $joined[0]['patternResult'] = $pattern['patternResult'];
+ if($joined[0]['outerFilter'] == null )
+ $joined[0]['outerFilter'] = $pattern['outerFilter'];
+ unset($patternlist[$key]);
+ break;
+ }
+ // if($pattern['patternResult'] !=null ){
+ $joined[0]['patternResult'] = $this->joinTuples($joined[0]['patternResult'],$pattern['patternResult']);
+ $joined[0]['outerFilter'] = $pattern['outerFilter'];
+ unset($patternlist[$key]);
+ break;
+ // }
+ }
+ }
+ }
+ }
+ return $joined;
+ }
+
+ /**
+ * Filters the pattern results.
+ *
+ * @param Array $patternlist list containing the results of the GraphPatterns
+ * @param boolean $outer TRUE if its an outer filter FALSE if not
+ * @return Array the filtered patternlist
+ */
+ protected function filterPatterns($patternlist,$outer){
+ if($outer)
+ $filter = 'outerFilter';
+ else
+ $filter = 'innerFilter';
+ foreach($patternlist as $patkey => $pattern){
+ // get constraints
+ $constraint = $pattern[$filter];
+
+ if(count($constraint)>0){
+ foreach($constraint as $constr){
+ if($constr != null){
+ // extract Vars and function calls
+ $evalString = $constr->getExpression();
+ preg_match_all("/\?.[^\s\)\,]*/",$evalString,$vars);
+ preg_match_all("/bound\((.[^\)]*)\)/i",$evalString,$boundcalls);
+ preg_match_all("/isuri\((.[^\)]*)\)/i",$evalString,$isUricalls);
+ preg_match_all("/isblank\((.[^\)]*)\)/i",$evalString,$isBlankcalls);
+ preg_match_all("/isLiteral\((.[^\)]*)\)/i",$evalString,$isLiteralcalls);
+ preg_match_all("/lang\((.[^\)]*)\)/i",$evalString,$langcalls);
+ preg_match_all("/datatype\((.[^\)]*)\)/i",$evalString,$datatypecalls);
+ preg_match_all("/str\((.[^\)]*)\)/i",$evalString,$stringcalls);
+
+ // is Bound
+ if(count($boundcalls[1])>0)
+ $function['bound'] = $boundcalls[1];
+ else
+ $function['bound'] = false;
+
+ // is URI
+ if(count($isUricalls[1])>0)
+ $function['isUri'] = $isUricalls[1];
+ else
+ $function['isUri'] = false;
+
+ // is Blank
+ if(count($isBlankcalls[1])>0)
+ $function['isBlank'] = $isBlankcalls[1];
+ else
+ $function['isBlank'] = false;
+
+ // is Literal
+ if(count($isLiteralcalls[1])>0)
+ $function['isLiteral'] = $isLiteralcalls[1];
+ else
+ $function['isLiteral'] = false;
+
+ // lang
+ if(count($langcalls[1])>0)
+ $function['lang'] = $langcalls[1];
+ else
+ $function['lang'] = false;
+
+ // datatype
+ if(count($datatypecalls[1])>0)
+ $function['datatype'] = $datatypecalls[1];
+ else
+ $function['datatype'] = false;
+
+ // string
+ if(count($stringcalls[1])>0)
+ $function['string'] = $stringcalls[1];
+ else
+ $function['string'] = false;
+
+
+ foreach($pattern['patternResult'] as $key => $res){
+ $result = false;
+ $evalString = $this->fillConstraintString($vars,$res,$constr,$function);
+ $evalString = '$result =('.$evalString.');';
+ // evaluate Constraint
+ @eval($evalString);
+
+ if(!$result)
+ unset($patternlist[$patkey]['patternResult'][$key]);
+
+ }
+ }
+ }
+ }
+ }
+ return $patternlist;
+ }
+
+ /**
+ * Builds an evaluation string to determine wether the result passes
+ * the filter or not. This string is evaluatet by the php buildin eval() function
+ *
+ * @param Array $vars a list which contains the used variables
+ * @param Array $res the result part which have to be evaluated
+ * @param Constraint $constraint the Constrain object
+ * @param Array $function an Array which contains the used functions
+ * @return String
+ */
+
+ protected function fillConstraintString($vars,$res,$constraint,$function){
+
+ $boundExpr = false;
+ $evalString = $constraint->getExpression();
+
+ // extract Literals
+ $pattern1 = "/\".[^\"]*\"[^\^\@]/";
+ $pattern2 = "/\'.[^\']*\'[^\^\@]/";
+ preg_match_all($pattern1,$evalString,$hits1);
+ preg_match_all($pattern2,$evalString,$hits2);
+
+ foreach($hits1[0] as $k => $val){
+ $evalString = preg_replace('/\".[^\"]*\"[^\^]/','_REPLACED1_'.$k++,$evalString,1);
+ }
+ foreach($hits2[0] as $k => $val){
+ $evalString = preg_replace('/\".[^\"]*\"[^\^]/','_REPLACED2_'.$k++,$evalString,1);
+ }
+
+ // replace namespaces
+ $prefs = $this->query->getPrefixes();
+ foreach($prefs as $key => $val){
+ if($key == '')
+ $key = ' ';
+ $evalString = preg_replace("/^(".$key."\:)(.[^\s]*)|([\s\(]?[^\^])(".$key."\:)(.[^\s\)]*)([\s\)]?)/","$3'<".$val."$2$5>'$6",$evalString);
+
+ $evalString = preg_replace("/(\^)(".$key."\:)(.[^\s]*)/","$1<".$val."$3>",$evalString);
+ }
+
+ $xsd = "http\:\/\/www.w3.org\/2001\/XMLSchema\#";
+
+ // evaluate bound calls
+ if($function['bound']){
+ $boundExpr = true;
+ foreach($function['bound'] as $var){
+ if(isset($res[$var]) && $res[$var]!=="")
+ $replacement = 'true';
+ else
+ $replacement = 'false';
+ $evalString = preg_replace("/bound\(\\".$var."\)/i",$replacement,$evalString);
+ }
+
+ }
+ // evaluate isBlank calls
+ if($function['isBlank']){
+ foreach($function['isBlank'] as $var){
+ if(isset($res[$var]) && $res[$var]!=="" && $res[$var] instanceof BlankNode )
+ $replacement = 'true';
+ else
+ $replacement = 'false';
+ $evalString = preg_replace("/isBlank\(\\".$var."\)/i",$replacement,$evalString);
+ }
+
+ }
+ // evaluate isLiteral calls
+ if($function['isLiteral']){
+ foreach($function['isLiteral'] as $var){
+ if(isset($res[$var]) && $res[$var]!=="" && $res[$var] instanceof Literal )
+ $replacement = 'true';
+ else
+ $replacement = 'false';
+ $evalString = preg_replace("/isLiteral\(\\".$var."\)/i",$replacement,$evalString);
+ }
+
+ }
+ // evaluate isUri calls
+ if($function['isUri']){
+ foreach($function['isUri'] as $var){
+ if(isset($res[$var]) && $res[$var]!=="" && $res[$var] instanceof Resource && $res[$var]->getUri() && !$res[$var] instanceof BlankNode )
+ $replacement = 'true';
+ else
+ $replacement = 'false';
+ $evalString = preg_replace("/isUri\(\\".$var."\)/i",$replacement,$evalString);
+ }
+ }
+ // evaluate lang calls
+ if($function['lang']){
+ foreach($function['lang'] as $var){
+ if(isset($res[$var]) && $res[$var]!=="" && $res[$var] instanceof Literal && $res[$var]->getLanguage() )
+ $replacement = '"'.$res[$var]->getLanguage().'"';
+ else
+ $replacement = 'null';
+ $evalString = preg_replace("/lang\(\\".$var."\)/i",$replacement,$evalString);
+ }
+ }
+ // evaluate datatype calls
+ if($function['datatype']){
+ foreach($function['datatype'] as $var){
+ if(isset($res[$var]) && $res[$var]!=="" && $res[$var] instanceof Literal && $res[$var]->getDatatype() )
+ $replacement = '\'<'.$res[$var]->getDatatype().'>\'';
+ else
+ $replacement = 'false';
+ $evalString = preg_replace("/datatype\(\\".$var."\)/i",$replacement,$evalString);
+ }
+ }
+ // evaluate string calls
+ if($function['string']){
+ foreach($function['string'] as $var){
+ if($var{0}=='?' || $var{0}=='$'){
+ if(isset($res[$var]) && $res[$var]!==""){
+ $replacement = "'str_".$res[$var]->getLabel()."'";
+ if($res[$var] instanceof BlankNode)
+ $replacement = "''";
+ }else{
+ $replacement = 'false';
+ }
+ $evalString = preg_replace("/str\(\\".$var."\)/i",$replacement,$evalString);
+ }else{
+ if($var{0}=='<'){
+ $evalString = preg_replace("/str\(\s*\<(.[^\>]*)\>\s*\)/i","'str_$1'",$evalString);
+ }
+ if($var{0}=='"'){
+ $evalString = preg_replace("/str\(\s*\"(.[^\>]*)\"\@[a-z]*\s*\)/i","'str_$1'",$evalString);
+ }
+ }
+
+ }
+ }
+ // evaluate VARS
+ foreach($vars[0] as $var){
+ if(isset($res[$var])&&$res[$var]!== ""){
+ //$replacement = "'".$res[$var]->getLabel()."'";
+ $replacement = '" "';
+ if($res[$var] instanceof Literal){
+ if($res[$var]->getDatatype()!= null){
+ if($res[$var]->getDatatype() == XML_SCHEMA.'boolean')
+ $replacement = $res[$var]->getLabel();
+ if($res[$var]->getDatatype() == XML_SCHEMA.'double')
+ $replacement = $res[$var]->getLabel();
+ if($res[$var]->getDatatype() == XML_SCHEMA.'integer')
+ $replacement = $res[$var]->getLabel();
+ if($res[$var]->getDatatype() == XML_SCHEMA.'dateTime')
+ $replacement = strtotime($res[$var]->getLabel());
+ }else{
+ if($res[$var]->getLabel()=="")
+ $replacement = 'false';
+ else
+ $replacement = "'str_".$res[$var]->getLabel()."'";
+ }
+ }else{
+ if($res[$var] instanceof Resource){
+ $replacement = "'<".$res[$var]->getLabel().">'";
+ }
+ }
+ $evalString = preg_replace("/\\".$var."/",$replacement,$evalString);
+ }
+
+ // problem with PHP: false < 13 is true
+ if(isset($res[$var])){
+ if($res[$var] === ""){
+ if($boundExpr)
+ $evalString = preg_replace("/\\".$var."/","false",$evalString);
+ else
+ $evalString = 'false';
+ }
+ }else{
+ $evalString = preg_replace("/\\".$var."/","false",$evalString);
+ }
+
+ }
+
+ // replace '=' with '=='
+ $evalString = preg_replace("/(.[^\=])(\=)(.[^\=])/","$1==$3",$evalString);
+
+
+ // rewrite Literals
+ foreach($hits1[0] as $k => $val){
+ $pattern = '/_REPLACED1_'.$k.'/';
+ $evalString = preg_replace($pattern,$hits1[0][$k],$evalString,1);
+ }
+
+ foreach($hits2[0] as $k => $val){
+ $pattern = '/_REPLACED2_'.$k.'/';
+ $evalString = preg_replace($pattern,$hits2[0][$k],$evalString,1);
+ }
+
+ // replace xsd:boolean expressions
+ $pattern = $pattern = '/\"\s?true\s?\"\^\^\<'.$xsd.'boolean\>|\'\s?true\s?\'\^\^xsd:boolean/';
+ $evalString = preg_replace($pattern,"true",$evalString);
+
+ $pattern = $pattern = '/\"\s?false\s?\"\^\^\<'.$xsd.'boolean\>|\'\s?false\s?\'\^\^xsd:boolean/';
+ $evalString = preg_replace($pattern,"false",$evalString);
+
+ // replace xsd:date expressions
+ $pattern = "/\"(.[^\"]*)\"\^\^".$xsd."dateTime/";
+ preg_match_all($pattern,$evalString,$hits);
+
+ foreach($hits[1] as $dummy)
+ $evalString = preg_replace("/\".[^\"]*\"\^\^".$xsd."dateTime/",strtotime($dummy),$evalString,1);
+
+
+ $evalString = preg_replace("/(\'\<".$xsd."dateTime\()(.[^\)]*\))\>\'/","dateTime($2",$evalString);
+
+ $evalString = preg_replace("/(\'\<".$xsd."integer\()(.[^\)]*\))\>\'/","integer($2",$evalString);
+
+ // tag plain literals
+ $evalString = preg_replace("/\"(.[^\"]*)\"([^\^])|\"(.[^\"]*)\"$/","'str_$1$3'$2",$evalString);
+
+ return $evalString;
+ }
+
+ /**
+ * Sorts the results.
+ *
+ * @param Array $vartable List containing the unsorted result vars
+ * @return Array List containing the sorted result vars
+ */
+ protected function sortVars($vartable)
+ {
+ $newTable = array();
+ $mod = $this->query->getSolutionModifier();
+ // if no ORDER BY solution modifier return vartable
+ if($mod['order by']!= null){
+ $order = $mod['order by'];
+ $map = $this->buildVarmap($order,$vartable);
+ foreach($map as $val){
+ $newTable[] = $vartable[$val];
+ }
+ }else{
+ $newTable = $vartable;
+ }
+
+ if($mod['offset'] != null){
+ $newTable = array_slice ($newTable, $mod['offset']);
+ }
+ if($mod['limit'] != null){
+ $newTable = array_slice($newTable,0,$mod['limit']);
+ }
+
+ return $newTable;
+ }
+
+ /**
+ * Sorts the result table.
+ *
+ * @param String $order (ASC/DESC)
+ * @param Array $vartable the vartable
+ * @return Array A map that contains the new order of the result vars
+ */
+ protected function buildVarmap($order, $vartable)
+ {
+ $n= 0;
+ $result = array();
+ $num_var = array();
+ foreach($order as $variable)
+ $num_var[$variable['val']] = 0;
+
+ foreach($vartable as $k => $x){
+ foreach($order as $value){
+ // if the value is a typed Literal try to determine if it
+ // a numeric datatype
+ if($x[$value['val']] instanceof Literal){
+ $dtype = $x[$value['val']]->getDatatype();
+ if($dtype){
+ switch($dtype){
+ case XML_SCHEMA."integer":
+ $num_var[$value['val']]++;
+ break;
+ case XML_SCHEMA."double":
+ $num_var[$value['val']]++;
+ break;
+
+ }
+ }
+ }
+ if($x[$value['val']]){
+ if($x[$value['val']]instanceof Literal){
+ $pref = "2";
+ }
+ if($x[$value['val']]instanceof Resource){
+ $pref = "1";
+ }
+ if($x[$value['val']]instanceof BlankNode){
+ $pref = "0";
+ }
+ $result[$value['val']][$n] = $pref.$x[$value['val']]->getLabel();
+ }else{
+ $result[$value['val']][$n] = "";
+ }
+ }
+ $result['oldKey'][$n] = $k;
+ $n++;
+ }
+ $sortString = "";
+ foreach($order as $value){
+ if($num_var[$value['val']] == $n)
+ $sort = SORT_NUMERIC;
+ else
+ $sort = SORT_STRING;
+
+ if($value['type'] == 'asc')
+ $type = SORT_ASC;
+ else
+ $type = SORT_DESC;
+
+ $sortString = $sortString.'$result["'.$value['val'].'"],'.$type.','.$sort.',';
+ }
+ $sortString = "array_multisort(".$sortString.'$result["oldKey"]);';
+
+ @eval($sortString);
+ return $result['oldKey'];
+ }
+
+
+
+ /**
+ * Eliminates duplicate results.
+ *
+ * @param Array $vartable a table that contains the result vars and their bindings
+ * @return Array the result table without duplicate results
+ */
+ protected function distinct($vartable)
+ {
+ $index = array();
+ foreach($vartable as $key => $value){
+ $key_index="";
+ foreach($value as $k => $v)
+ if($v instanceof Object)
+ $key_index = $key_index.$k.$v->toString();
+ if(isset($index[$key_index]))
+ unset($vartable[$key]);
+ else
+ $index[$key_index]= 1;
+ }
+ return $vartable;
+ }
+
+
+ /**
+ * Prints a query result as HTML table.
+ * You can change the colors in the configuration file.
+ *
+ * @param array $queryResult [][?VARNAME] = object Node
+ * @return void
+ */
+ public function writeQueryResultAsHtmlTable($queryResult) {
+ // Import Package Utility
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_UTILITY);
+
+ if ( $queryResult[0] == null) {
+ echo 'no match
';
+ return;
+ }
+ if ( $queryResult == 'false') {
+ echo 'boolean: false
';
+ return;
+ }
+ if ( $queryResult == 'true') {
+ echo 'boolean: true
';
+ return;
+ }
+
+
+ echo '| No. | ';
+ foreach ($queryResult[0] as $varName => $value)
+ echo "$varName | ";
+ echo '
';
+
+ foreach ($queryResult as $n => $var) {
+
+
+ echo '| ' .($n + 1) .'. | ';
+ foreach ($var as $varName => $value) {
+ if($value !=''){
+ echo INDENTATION . INDENTATION . '';
+ echo ' ';
+
+ $lang = NULL;
+ $dtype = NULL;
+ if (is_a($value, 'Literal')) {
+ if ($value->getLanguage() != NULL)
+ $lang = ' (xml:lang="' . $value->getLanguage() . '") ';
+ if ($value->getDatatype() != NULL)
+ $dtype = ' (rdf:datatype="' . $value->getDatatype() . '") ';
+ }
+ echo RDFUtil::getNodeTypeName($value) .$value->getLabel() . $lang . $dtype .' ';
+ }else{
+ echo " | unbound";
+ }
+ }
+ echo ' |
';
+ }
+ echo '
';
+ }
+
+
+
+ /*
+ * Dumb getters
+ */
+
+
+
+ public function getQuery()
+ {
+ return $this->query;
+ }//public function getQuery()
+
+
+
+ public function getDataset()
+ {
+ return $this->dataset;
+ }//public function getDataset()
+
+} // end: Class SparqlEngine
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/.svn/all-wcprops b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/.svn/all-wcprops
new file mode 100755
index 00000000..9e9e0117
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/.svn/all-wcprops
@@ -0,0 +1,23 @@
+K 25
+svn:wc:ra_dav:version-url
+V 73
+/svnroot/rdfapi-php/!svn/ver/484/trunk/rdfapi-php/api/sparql/SparqlEngine
+END
+ResultRenderer.php
+K 25
+svn:wc:ra_dav:version-url
+V 92
+/svnroot/rdfapi-php/!svn/ver/465/trunk/rdfapi-php/api/sparql/SparqlEngine/ResultRenderer.php
+END
+ResultConverter.php
+K 25
+svn:wc:ra_dav:version-url
+V 93
+/svnroot/rdfapi-php/!svn/ver/484/trunk/rdfapi-php/api/sparql/SparqlEngine/ResultConverter.php
+END
+PreparedStatement.php
+K 25
+svn:wc:ra_dav:version-url
+V 95
+/svnroot/rdfapi-php/!svn/ver/465/trunk/rdfapi-php/api/sparql/SparqlEngine/PreparedStatement.php
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/.svn/entries b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/.svn/entries
new file mode 100755
index 00000000..d1915baf
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/.svn/entries
@@ -0,0 +1,70 @@
+8
+
+dir
+556
+https://rdfapi-php.svn.sourceforge.net/svnroot/rdfapi-php/trunk/rdfapi-php/api/sparql/SparqlEngine
+https://rdfapi-php.svn.sourceforge.net/svnroot/rdfapi-php
+
+
+
+2007-08-12T11:33:13.029340Z
+484
+cweiske
+
+
+svn:special svn:externals svn:needs-lock
+
+
+
+
+
+
+
+
+
+
+
+b2ee660e-c932-0410-bdee-d8da4d8102f4
+
+ResultRenderer
+dir
+
+ResultRenderer.php
+file
+
+
+
+
+2008-02-29T14:57:45.475578Z
+3931687e275d501be758875979380b0f
+2007-06-27T16:47:57.067358Z
+465
+cweiske
+has-props
+
+ResultConverter.php
+file
+
+
+
+
+2008-02-29T14:57:45.475578Z
+ad3a44eccfa94ffb613bc7274648b2ad
+2007-08-12T11:33:13.029340Z
+484
+cweiske
+has-props
+
+PreparedStatement.php
+file
+
+
+
+
+2008-02-29T14:57:45.491199Z
+4dd6460f65bfabc61f5af876f45fc164
+2007-06-27T16:47:57.067358Z
+465
+cweiske
+has-props
+
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/.svn/format b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/.svn/format
new file mode 100755
index 00000000..45a4fb75
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/.svn/format
@@ -0,0 +1 @@
+8
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/.svn/prop-base/PreparedStatement.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/.svn/prop-base/PreparedStatement.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/.svn/prop-base/PreparedStatement.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/.svn/prop-base/ResultConverter.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/.svn/prop-base/ResultConverter.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/.svn/prop-base/ResultConverter.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/.svn/prop-base/ResultRenderer.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/.svn/prop-base/ResultRenderer.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/.svn/prop-base/ResultRenderer.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/.svn/text-base/PreparedStatement.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/.svn/text-base/PreparedStatement.php.svn-base
new file mode 100755
index 00000000..eeac1b0c
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/.svn/text-base/PreparedStatement.php.svn-base
@@ -0,0 +1,17 @@
+
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/.svn/text-base/ResultConverter.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/.svn/text-base/ResultConverter.php.svn-base
new file mode 100755
index 00000000..42cdedf2
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/.svn/text-base/ResultConverter.php.svn-base
@@ -0,0 +1,115 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlEngine_ResultConverter
+{
+ /**
+ * Determines the correct renderer and calls it.
+ *
+ * The $resultform may be:
+ * - false: The default renderer is taken then
+ * - an object that implements SparqlEngine_ResultRenderer interface
+ * - a string like "HTML" or "XML". The appropriate renderer is used then.
+ * - a full class name, e.g. SparqlEngine_ResultRenderer_XML
+ *
+ * @param array $arVartable Variable table
+ * @param SparqlEngine $engine Sparql database engine.
+ * @param mixed $resultform Which format the results shall be in (false or "xml")
+ *
+ * @return mixed Most likely an array or a boolean value,
+ * or anything else as determined by $resultform
+ */
+ public static function convertFromResult($arVartable, SparqlEngine $engine, $resultform = false)
+ {
+ if (is_object($resultform)) {
+ if ($resultform instanceof SparqlEngine_ResultRenderer) {
+ return $resultform->convertFromResult(
+ $arVartable,
+ $engine->getQuery(),
+ $engine
+ );
+ } else {
+ throw new Exception(
+ 'Result renderer object needs to implement'
+ . ' SparqlEngine_ResultRenderer interface'
+ );
+ }
+ }
+
+ if ($resultform === false) {
+ $resultform = 'Default';
+ } else if ($resultform == 'xml') {
+ //kept for BC reasons
+ $resultform = 'XML';
+ }
+
+ if ($strClass = self::loadClass($resultform)) {
+ $rrObj = new $strClass();
+ if ($rrObj instanceof SparqlEngine_ResultRenderer) {
+ return $rrObj->convertFromResult(
+ $arVartable,
+ $engine->getQuery(),
+ $engine
+ );
+ } else {
+ throw new Exception(
+ 'Result renderer class "' . $strClass . '" needs to implement'
+ . ' SparqlEngine_ResultRenderer interface'
+ );
+ }
+ } else {
+ throw new Exception(
+ 'Result renderer class "' . $resultform . '" could not be loaded.'
+ );
+ }
+ }//public static function convertFromResult($arVartable, SparqlEngine $engine, $resultform = false)
+
+
+
+ /**
+ * Tries to load a given class if it doesn't exist,
+ * and returns true if the class can be used.
+ *
+ * @param string $strClass Classname
+ * @return mixed Class name if the class is loaded and can be used, false if not.
+ */
+ protected static function loadClass($strClass)
+ {
+ if (class_exists($strClass, false)) {
+ return $strClass;
+ }
+
+ //RAP style, shortcut notation
+ $strFile = 'SparqlEngine/ResultRenderer/' . $strClass . '.php';
+ @include_once RDFAPI_INCLUDE_DIR . 'sparql/' . $strFile;
+ if (class_exists('SparqlEngine_ResultRenderer_' . $strClass, false)) {
+ return 'SparqlEngine_ResultRenderer_' . $strClass;
+ }
+
+ //RAP style
+ $strFile = str_replace('_', '/', $strClass) . '.php';
+ @include_once RDFAPI_INCLUDE_DIR . 'sparql/' . $strFile;
+ if (class_exists($strClass, false)) {
+ return $strClass;
+ }
+
+ //PEAR style
+ @include_once $strFile;
+ if (class_exists($strClass, false)) {
+ return $strClass;
+ }
+
+ return false;
+ }//protected static function loadClass($strClass)
+
+}//class SparqlEngine_ResultConverter
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/.svn/text-base/ResultRenderer.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/.svn/text-base/ResultRenderer.php.svn-base
new file mode 100755
index 00000000..f22afd0c
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/.svn/text-base/ResultRenderer.php.svn-base
@@ -0,0 +1,29 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+interface SparqlEngine_ResultRenderer
+{
+ /**
+ * Converts the database results into the desired output format
+ * and returns the result.
+ *
+ * @param array $arVartable Variable table
+ * @param Query $query SPARQL query object
+ * @param SparqlEngine $engine Sparql Engine to query the database
+ * @return mixed The result as rendered by the result renderers.
+ */
+ public function convertFromResult($arVartable, Query $query, SparqlEngine $engine);
+
+}//interface SparqlEngine_ResultRenderer
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/PreparedStatement.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/PreparedStatement.php
new file mode 100755
index 00000000..37a97a78
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/PreparedStatement.php
@@ -0,0 +1,17 @@
+
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultConverter.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultConverter.php
new file mode 100755
index 00000000..f08d3567
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultConverter.php
@@ -0,0 +1,115 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlEngine_ResultConverter
+{
+ /**
+ * Determines the correct renderer and calls it.
+ *
+ * The $resultform may be:
+ * - false: The default renderer is taken then
+ * - an object that implements SparqlEngine_ResultRenderer interface
+ * - a string like "HTML" or "XML". The appropriate renderer is used then.
+ * - a full class name, e.g. SparqlEngine_ResultRenderer_XML
+ *
+ * @param array $arVartable Variable table
+ * @param SparqlEngine $engine Sparql database engine.
+ * @param mixed $resultform Which format the results shall be in (false or "xml")
+ *
+ * @return mixed Most likely an array or a boolean value,
+ * or anything else as determined by $resultform
+ */
+ public static function convertFromResult($arVartable, SparqlEngine $engine, $resultform = false)
+ {
+ if (is_object($resultform)) {
+ if ($resultform instanceof SparqlEngine_ResultRenderer) {
+ return $resultform->convertFromResult(
+ $arVartable,
+ $engine->getQuery(),
+ $engine
+ );
+ } else {
+ throw new Exception(
+ 'Result renderer object needs to implement'
+ . ' SparqlEngine_ResultRenderer interface'
+ );
+ }
+ }
+
+ if ($resultform === false) {
+ $resultform = 'Default';
+ } else if ($resultform == 'xml') {
+ //kept for BC reasons
+ $resultform = 'XML';
+ }
+
+ if ($strClass = self::loadClass($resultform)) {
+ $rrObj = new $strClass();
+ if ($rrObj instanceof SparqlEngine_ResultRenderer) {
+ return $rrObj->convertFromResult(
+ $arVartable,
+ $engine->getQuery(),
+ $engine
+ );
+ } else {
+ throw new Exception(
+ 'Result renderer class "' . $strClass . '" needs to implement'
+ . ' SparqlEngine_ResultRenderer interface'
+ );
+ }
+ } else {
+ throw new Exception(
+ 'Result renderer class "' . $resultform . '" could not be loaded.'
+ );
+ }
+ }//public static function convertFromResult($arVartable, SparqlEngine $engine, $resultform = false)
+
+
+
+ /**
+ * Tries to load a given class if it doesn't exist,
+ * and returns true if the class can be used.
+ *
+ * @param string $strClass Classname
+ * @return mixed Class name if the class is loaded and can be used, false if not.
+ */
+ protected static function loadClass($strClass)
+ {
+ if (class_exists($strClass, false)) {
+ return $strClass;
+ }
+
+ //RAP style, shortcut notation
+ $strFile = 'SparqlEngine/ResultRenderer/' . $strClass . '.php';
+ @include_once RDFAPI_INCLUDE_DIR . 'sparql/' . $strFile;
+ if (class_exists('SparqlEngine_ResultRenderer_' . $strClass, false)) {
+ return 'SparqlEngine_ResultRenderer_' . $strClass;
+ }
+
+ //RAP style
+ $strFile = str_replace('_', '/', $strClass) . '.php';
+ @include_once RDFAPI_INCLUDE_DIR . 'sparql/' . $strFile;
+ if (class_exists($strClass, false)) {
+ return $strClass;
+ }
+
+ //PEAR style
+ @include_once $strFile;
+ if (class_exists($strClass, false)) {
+ return $strClass;
+ }
+
+ return false;
+ }//protected static function loadClass($strClass)
+
+}//class SparqlEngine_ResultConverter
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer.php
new file mode 100755
index 00000000..8d7efb6d
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer.php
@@ -0,0 +1,29 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+interface SparqlEngine_ResultRenderer
+{
+ /**
+ * Converts the database results into the desired output format
+ * and returns the result.
+ *
+ * @param array $arVartable Variable table
+ * @param Query $query SPARQL query object
+ * @param SparqlEngine $engine Sparql Engine to query the database
+ * @return mixed The result as rendered by the result renderers.
+ */
+ public function convertFromResult($arVartable, Query $query, SparqlEngine $engine);
+
+}//interface SparqlEngine_ResultRenderer
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer/.svn/all-wcprops b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer/.svn/all-wcprops
new file mode 100755
index 00000000..4fa0b95a
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer/.svn/all-wcprops
@@ -0,0 +1,23 @@
+K 25
+svn:wc:ra_dav:version-url
+V 88
+/svnroot/rdfapi-php/!svn/ver/465/trunk/rdfapi-php/api/sparql/SparqlEngine/ResultRenderer
+END
+XML.php
+K 25
+svn:wc:ra_dav:version-url
+V 96
+/svnroot/rdfapi-php/!svn/ver/465/trunk/rdfapi-php/api/sparql/SparqlEngine/ResultRenderer/XML.php
+END
+Default.php
+K 25
+svn:wc:ra_dav:version-url
+V 100
+/svnroot/rdfapi-php/!svn/ver/465/trunk/rdfapi-php/api/sparql/SparqlEngine/ResultRenderer/Default.php
+END
+HTML.php
+K 25
+svn:wc:ra_dav:version-url
+V 97
+/svnroot/rdfapi-php/!svn/ver/465/trunk/rdfapi-php/api/sparql/SparqlEngine/ResultRenderer/HTML.php
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer/.svn/entries b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer/.svn/entries
new file mode 100755
index 00000000..997b67a1
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer/.svn/entries
@@ -0,0 +1,67 @@
+8
+
+dir
+556
+https://rdfapi-php.svn.sourceforge.net/svnroot/rdfapi-php/trunk/rdfapi-php/api/sparql/SparqlEngine/ResultRenderer
+https://rdfapi-php.svn.sourceforge.net/svnroot/rdfapi-php
+
+
+
+2007-06-27T16:47:57.067358Z
+465
+cweiske
+
+
+svn:special svn:externals svn:needs-lock
+
+
+
+
+
+
+
+
+
+
+
+b2ee660e-c932-0410-bdee-d8da4d8102f4
+
+XML.php
+file
+
+
+
+
+2008-02-29T14:57:45.397475Z
+560f228f1283b4826f59cf509940fd35
+2007-06-27T16:47:57.067358Z
+465
+cweiske
+has-props
+
+Default.php
+file
+
+
+
+
+2008-02-29T14:57:45.397475Z
+4eb871818f0a7e8db82d5e1977048119
+2007-06-27T16:47:57.067358Z
+465
+cweiske
+has-props
+
+HTML.php
+file
+
+
+
+
+2008-02-29T14:57:45.413096Z
+3a8f82e43f05fbf5ba22ab4d48886248
+2007-06-27T16:47:57.067358Z
+465
+cweiske
+has-props
+
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer/.svn/format b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer/.svn/format
new file mode 100755
index 00000000..45a4fb75
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer/.svn/format
@@ -0,0 +1 @@
+8
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer/.svn/prop-base/Default.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer/.svn/prop-base/Default.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer/.svn/prop-base/Default.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer/.svn/prop-base/HTML.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer/.svn/prop-base/HTML.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer/.svn/prop-base/HTML.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer/.svn/prop-base/XML.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer/.svn/prop-base/XML.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer/.svn/prop-base/XML.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer/.svn/text-base/Default.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer/.svn/text-base/Default.php.svn-base
new file mode 100755
index 00000000..7f2860a4
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer/.svn/text-base/Default.php.svn-base
@@ -0,0 +1,262 @@
+
+* @author Christian Weiske
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlEngine_ResultRenderer_Default implements SparqlEngine_ResultRenderer
+{
+ /**
+ * Converts the database results into the output format
+ * and returns the result.
+ *
+ * @param array $arVartable Variable table
+ * @param Query $query SPARQL query object
+ * @param SparqlEngine $engine Sparql Engine to query the database
+ * @return mixed Most likely an array
+ */
+ public function convertFromResult($arVartable, Query $query, SparqlEngine $engine)
+ {
+ $this->query = $query;
+ $this->engine = $engine;
+ $this->dataset = $engine->getDataset();
+
+ $result = false;
+ $qrf = $this->query->getResultForm();
+
+ if ($arVartable != null) {
+ switch ($qrf) {
+ case 'ask':
+ if (count($arVartable) > 0) {
+ $result = true;
+ } else {
+ $result = false;
+ }
+ break;
+ case 'count':
+ $result = count($arVartable);
+ break;
+ case 'construct':
+ $result = $this->constructGraph(
+ $arVartable,
+ $this->query->getConstructPattern()
+ );
+ break;
+ case 'describe':
+ $result = $this->describeGraph($arVartable);
+ break;
+ default:
+ $result = $arVartable;
+ break;
+ }
+ } else if ($qrf == 'describe'){
+ $result = $this->describeGraph(null);
+ } else if ($qrf == 'construct'){
+ $result = $this->constructGraph(
+ false,
+ $this->query->getConstructPattern()
+ );
+ }
+
+ return $result;
+ }//public function convertFromResult($arVartable, Query $query, SparqlEngine $engine)
+
+
+
+ /**
+ * Constructs a result graph.
+ *
+ * @param array $arVartable A table containing the result vars and their bindings
+ * @param GraphPattern $constructPattern The CONSTRUCT pattern
+ * @return MemModel The result graph which matches the CONSTRUCT pattern
+ */
+ function constructGraph($arVartable, $constructPattern)
+ {
+ $resultGraph = new MemModel();
+
+ if (!$arVartable) {
+ return $resultGraph;
+ }
+
+ $tp = $constructPattern->getTriplePatterns();
+
+ $bnode = 0;
+ foreach ($arVartable as $value) {
+ foreach ($tp as $triple) {
+ $sub = $triple->getSubject();
+ $pred = $triple->getPredicate();
+ $obj = $triple->getObject();
+
+ if (is_string($sub) && $sub{1} == '_') {
+ $sub = new BlankNode("_bN".$bnode);
+ }
+ if (is_string($pred) && $pred{1} == '_') {
+ $pred = new BlankNode("_bN".$bnode);
+ }
+ if (is_string($obj) && $obj{1} == '_') {
+ $obj = new BlankNode("_bN".$bnode);
+ }
+
+
+ if (is_string($sub)) {
+ $sub = $value[$sub];
+ }
+ if (is_string($pred)) {
+ $pred = $value[$pred];
+ }
+ if (is_string($obj)) {
+ $obj = $value[$obj];
+ }
+
+ if ($sub !== "" && $pred !== "" && $obj !== "") {
+ $resultGraph->add(new Statement($sub,$pred,$obj));
+ }
+ }
+ $bnode++;
+ }
+ return $resultGraph;
+ }//function constructGraph($arVartable, $constructPattern)
+
+
+
+ /**
+ * Builds a describing named graph. To define an attribute list for a
+ * several rdf:type look at constants.php
+ *
+ * @param array $arVartable
+ * @return MemModel
+ */
+ function describeGraph($arVartable)
+ {
+ // build empty named graph
+ $resultGraph = new MemModel();
+ // if no where clause fill $arVartable
+ $vars = $this->query->getResultVars();
+ if ($arVartable == null) {
+ if ($vars) {
+ $arVartable[0] = array('?x' => new Resource(substr($vars[0],1,-1)));
+ $vars[0] = '?x';
+ }
+ }
+ // fetch attribute list from constants.php
+ global $sparql_describe;
+ // for each resultset
+ foreach ($arVartable as $resultset) {
+ foreach ($vars as $varname) {
+ $varvalue = $resultset[$varname];
+ // try to determine rdf:type of the variable
+ $type = $this->_determineType($varvalue, $resultGraph);
+ // search attribute list defined in constants.php
+ $list = null;
+ if ($type) {
+ $strLuri = strtolower($type->getUri());
+ if (isset($sparql_describe[$strLuri])) {
+ $list = $sparql_describe[$strLuri] ;
+ }
+ }
+ // search in dataset
+ $this->_getAttributes($list, $resultGraph, $varvalue);
+ }
+ }
+
+ return $resultGraph;
+ }//function describeGraph($arVartable)
+
+
+
+ /**
+ * Tries to determine the rdf:type of the variable.
+ *
+ * @param Node $var The variable
+ * @param MemModel $resultGraph The result graph which describes the Resource
+ * @return String Uri of the rdf:type
+ */
+ protected function _determineType($var, $resultGraph)
+ {
+ $type = null;
+ // find in namedGraphs
+ if (!$var instanceof Literal) {
+ $iter = $this->dataset->findInNamedGraphs(
+ null,
+ $var,
+ new Resource(RDF_NAMESPACE_URI.'type'),
+ null,
+ true
+ );
+ while ($iter->valid()) {
+ $statement = $iter->current();
+ $type = $statement->getObject();
+ $resultGraph->add($iter->current());
+ break;
+ }
+ }
+ // if no type information found find in default graph
+ if (!$type) {
+ if (!$var instanceof Literal) {
+ $iter1 = $this->dataset->findInDefaultGraph(
+ $var,
+ new Resource(RDF_NAMESPACE_URI.'type'),
+ null
+ );
+ $type = null;
+ while ($iter1->valid()) {
+ $statement = $iter1->current();
+ $type = $statement->getObject();
+ $resultGraph->add($iter1->current());
+ break;
+ }
+ }
+ }
+ return $type;
+ }//protected function _determineType($var, $resultGraph)
+
+
+
+ /**
+ * Search the attributes listed in $list in the dataset.
+ * Modifies $resultGraph
+ *
+ * @param Array $list List containing the attributes
+ * @param MemModel $resultGraph The result graph which describes the Resource
+ * @return void
+ */
+ protected function _getAttributes($list, $resultGraph, $varvalue)
+ {
+ if ($list){
+ foreach ($list as $attribute) {
+ if (!$varvalue instanceof Literal) {
+ $iter2 = $this->dataset->findInNamedGraphs(
+ null,
+ $varvalue,
+ new Resource($attribute),
+ null,
+ true
+ );
+ while ($iter2->valid()) {
+ $resultGraph->add($iter2->current());
+ $iter2->next();
+ }
+ $iter3 = $this->dataset->findInDefaultGraph(
+ $varvalue,
+ new Resource($attribute),
+ null
+ );
+ while ($iter3->valid()) {
+ $resultGraph->add($iter3->current());
+ $iter3->next();
+ }
+ }
+ }
+ }
+ }//protected function _getAttributes($list, $resultGraph, $varvalue)
+
+
+}//class SparqlEngine_ResultRenderer_Default implements SparqlEngine_ResultRenderer
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer/.svn/text-base/HTML.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer/.svn/text-base/HTML.php.svn-base
new file mode 100755
index 00000000..ae5946a8
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer/.svn/text-base/HTML.php.svn-base
@@ -0,0 +1,199 @@
+
+* @author Christian Weiske
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlEngine_ResultRenderer_HTML implements SparqlEngine_ResultRenderer
+{
+ /**
+ * If the result HTML should be wrapped in a div
+ * @var boolean
+ */
+ protected $bWrap = true;
+
+
+
+ /**
+ * Converts the database results into the output format
+ * and returns the result.
+ *
+ * @param array $arVartable Variable table
+ * @param Query $query SPARQL query object
+ * @param SparqlEngine $engine Sparql Engine to query the database
+ * @return string HTML result
+ */
+ public function convertFromResult($arVartable, Query $query, SparqlEngine $engine)
+ {
+ $this->query = $query;
+ $this->engine = $engine;
+ $this->dataset = $engine->getDataset();
+
+ $strCode = '';
+
+ $strResultForm = $query->getResultForm();
+ switch ($strResultForm) {
+ case 'select':
+ case 'select distinct':
+ $strCode = $this->createTableFromRecords($arVartable);
+ break;
+
+ case 'construct':
+ case 'describe':
+ throw new Exception(
+ 'Construct and describe are currently not supported by the'
+ . ' HTML renderer'
+ );
+
+ case 'count':
+ case 'ask':
+ $nCount = count($arVartable);
+
+ if ($strResultForm == 'ask') {
+ $strCode = 'There were results.';
+ } else {
+ $strCode = 'There are ' . $nCount . ' results.';
+ }
+ break;
+
+ default:
+ throw new Exception('Unsupported result form: ' . $strResultForm);
+ }
+
+ return $this->wrapCode($strCode);
+ }//public function convertFromResult($arVartable, Query $query, SparqlEngine $engine)
+
+
+
+ protected function wrapCode($strCode)
+ {
+ if (!$this->bWrap) {
+ return $strCode;
+ }
+
+ return
+ '' . "\n"
+ . $strCode . "\n"
+ . "
\n";
+ }//protected function wrapCode($strCode)
+
+
+
+ protected function createTableFromRecords($arVartable)
+ {
+ if (count($arVartable) == 0) {
+ return 'No result rows.';
+ }
+
+ $arResult = array();
+ foreach ($arVartable as $row) {
+ $arResultRow = array();
+ foreach ($row as $strVarName => $value) {
+ $arResultRow[$strVarName] = $this->createValue($value);
+ }
+ $arResult[] = $arResultRow;
+ }
+
+ //I always wanted to to this :)
+ return
+ "\n"
+ . " SPARQL result with " . count($arResult) . " rows\n"
+ . " | "
+ . implode(' | ', array_keys(reset($arResult)))
+ . " | \n"
+ . " \n "
+ . implode(
+ "
\n ",
+ array_map(
+ create_function(
+ '$ar',
+ 'return implode("", $ar);'
+ ),
+ $arResult
+ )
+ )
+ . "
\n \n"
+ . "
\n";
+ }//protected function createTableFromRecords($arRecordSets)
+
+
+
+ /**
+ * Creates an RDF object object
+ * contained in the given $dbRecordSet object.
+ *
+ * @see convertFromDbResult() to understand $strVarBase necessity
+ *
+ * @param ADORecordSet $dbRecordSet Record set returned from ADOConnection::Execute()
+ * @param string $strVarBase Prefix of the columns the recordset fields have.
+ *
+ * @return string HTML code
+ */
+ protected function createValue($value)
+ {
+ if ($value === null) {
+ $strCode = $this->getHtmlNull();
+ }
+ if ($value instanceof Literal) {
+ $strCode = $this->getHtmlLiteral(
+ $value->getLabel(),
+ $value->getLanguage(),
+ $value->getDatatype()
+ );
+ } else if ($value instanceof Resource) {
+ $strCode = $this->getHtmlResource($value->getURI());
+ } else {
+ $strCode = $this->getHtmlBlank();
+ }
+
+ return ''
+ . $strCode
+ . ' | ';
+ }//protected function createObjectFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVarName)
+
+
+
+ protected function getHtmlNull()
+ {
+ return 'NULL
';
+ }//protected function getHtmlNull()
+
+
+
+ protected function getHtmlBlank($value)
+ {
+ return 'Blank node';
+ }//protected function getHtmlBlank($value)
+
+
+
+ protected function getHtmlResource($value)
+ {
+ return htmlspecialchars($value);
+ }//protected function getHtmlResource($value)
+
+
+
+ protected function getHtmlLiteral($value, $language, $datatype)
+ {
+ $strCode = htmlspecialchars($value);
+ if ($language) {
+ $strCode .= '
xml:lang=' . $language;
+ }
+ if ($datatype) {
+ $strCode .= '
rdf:type=' . $datatype;
+ }
+ return $strCode;
+ }//protected function getHtmlLiteral($value, $language, $datatype)
+
+}//class SparqlEngine_ResultRenderer_HTML implements SparqlEngine_ResultRenderer
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer/.svn/text-base/XML.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer/.svn/text-base/XML.php.svn-base
new file mode 100755
index 00000000..4982367d
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer/.svn/text-base/XML.php.svn-base
@@ -0,0 +1,125 @@
+
+* @author Christian Weiske
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlEngine_ResultRenderer_XML implements SparqlEngine_ResultRenderer
+{
+ /**
+ * Converts the database results into the output format
+ * and returns the result.
+ *
+ * @param array $arVartable Variable table
+ * @param Query $query SPARQL query object
+ * @param SparqlEngine $engine Sparql Engine to query the database
+ * @return string XML result
+ */
+ public function convertFromResult($arVartable, Query $query, SparqlEngine $engine)
+ {
+ $this->query = $query;
+ $this->engine = $engine;
+ $this->dataset = $engine->getDataset();
+
+ if ($arVartable instanceof NamedGraphMem) {
+ return $arVartable->writeRdfToString();
+ }
+
+ $result = '';
+ $header = '';
+
+ // build header
+ if (is_array($arVartable)) {
+ $vars = $this->query->getResultVars();
+ $header = '';
+ foreach ($vars as $value) {
+ $header = $header
+ . '';
+ }
+ $header = $header . '';
+
+ // build results
+ $solm = $this->query->getSolutionModifier();
+ $sel = $this->query->getResultForm();
+
+ $distinct = 'false';
+ if ($sel == 'select distinct') {
+ $distinct = 'true';
+ }
+
+ $ordered = 'false';
+ if ($solm['order by'] != 0) {
+ $ordered = 'true';
+ }
+
+ $results = '';
+ foreach ($arVartable as $value) {
+ $results = $results.'';
+ foreach ($value as $varname => $varvalue) {
+ $results = $results
+ . $this->_getBindingString(
+ substr($varname, 1),
+ $varvalue
+ );
+ }
+ $results = $results . '';
+ }
+ $results = $results . '';
+ } else {
+ $results = '' . $vartable . '';
+ }
+
+ $result = $result . $header . $results . '';
+ $result = simplexml_load_string($result);
+ return $result->asXML();
+ }//public function convertFromResult($arVartable, Query $query, SparqlEngine $engine)
+
+
+
+ /**
+ * Helper Function for function buildXmlResult($vartable). Generates
+ * an xml string for a single variable an their corresponding value.
+ *
+ * @param String $varname The variables name
+ * @param Node $varvalue The value of the variable
+ * @return String The xml string
+ */
+ protected function _getBindingString($varname, $varvalue)
+ {
+ $binding = '';
+ $value = '';
+
+ if ($varvalue instanceof BlankNode) {
+ $value = '' . $varvalue->getLabel() . '';
+ } else if ($varvalue instanceof Resource) {
+ $value = '' . $varvalue->getUri() . '';
+ } else if ($varvalue instanceof Literal) {
+ $label = htmlspecialchars($varvalue->getLabel());
+ $value = ''.$label.'';
+ if ($varvalue->getDatatype() != null) {
+ $value = ''
+ . $label
+ . '';
+ }
+ if ($varvalue->getLanguage() != null) {
+ $value = ''
+ . $label
+ . '';
+ }
+ }
+ $binding = $binding . $value . '';
+
+ return $binding;
+ }//protected function _getBindingString($varname, $varvalue)
+
+}//class SparqlEngine_ResultRenderer_XML implements SparqlEngine_ResultRenderer
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer/Default.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer/Default.php
new file mode 100755
index 00000000..5ced9ccb
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer/Default.php
@@ -0,0 +1,262 @@
+
+* @author Christian Weiske
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlEngine_ResultRenderer_Default implements SparqlEngine_ResultRenderer
+{
+ /**
+ * Converts the database results into the output format
+ * and returns the result.
+ *
+ * @param array $arVartable Variable table
+ * @param Query $query SPARQL query object
+ * @param SparqlEngine $engine Sparql Engine to query the database
+ * @return mixed Most likely an array
+ */
+ public function convertFromResult($arVartable, Query $query, SparqlEngine $engine)
+ {
+ $this->query = $query;
+ $this->engine = $engine;
+ $this->dataset = $engine->getDataset();
+
+ $result = false;
+ $qrf = $this->query->getResultForm();
+
+ if ($arVartable != null) {
+ switch ($qrf) {
+ case 'ask':
+ if (count($arVartable) > 0) {
+ $result = true;
+ } else {
+ $result = false;
+ }
+ break;
+ case 'count':
+ $result = count($arVartable);
+ break;
+ case 'construct':
+ $result = $this->constructGraph(
+ $arVartable,
+ $this->query->getConstructPattern()
+ );
+ break;
+ case 'describe':
+ $result = $this->describeGraph($arVartable);
+ break;
+ default:
+ $result = $arVartable;
+ break;
+ }
+ } else if ($qrf == 'describe'){
+ $result = $this->describeGraph(null);
+ } else if ($qrf == 'construct'){
+ $result = $this->constructGraph(
+ false,
+ $this->query->getConstructPattern()
+ );
+ }
+
+ return $result;
+ }//public function convertFromResult($arVartable, Query $query, SparqlEngine $engine)
+
+
+
+ /**
+ * Constructs a result graph.
+ *
+ * @param array $arVartable A table containing the result vars and their bindings
+ * @param GraphPattern $constructPattern The CONSTRUCT pattern
+ * @return MemModel The result graph which matches the CONSTRUCT pattern
+ */
+ function constructGraph($arVartable, $constructPattern)
+ {
+ $resultGraph = new MemModel();
+
+ if (!$arVartable) {
+ return $resultGraph;
+ }
+
+ $tp = $constructPattern->getTriplePatterns();
+
+ $bnode = 0;
+ foreach ($arVartable as $value) {
+ foreach ($tp as $triple) {
+ $sub = $triple->getSubject();
+ $pred = $triple->getPredicate();
+ $obj = $triple->getObject();
+
+ if (is_string($sub) && $sub{1} == '_') {
+ $sub = new BlankNode("_bN".$bnode);
+ }
+ if (is_string($pred) && $pred{1} == '_') {
+ $pred = new BlankNode("_bN".$bnode);
+ }
+ if (is_string($obj) && $obj{1} == '_') {
+ $obj = new BlankNode("_bN".$bnode);
+ }
+
+
+ if (is_string($sub)) {
+ $sub = $value[$sub];
+ }
+ if (is_string($pred)) {
+ $pred = $value[$pred];
+ }
+ if (is_string($obj)) {
+ $obj = $value[$obj];
+ }
+
+ if ($sub !== "" && $pred !== "" && $obj !== "") {
+ $resultGraph->add(new Statement($sub,$pred,$obj));
+ }
+ }
+ $bnode++;
+ }
+ return $resultGraph;
+ }//function constructGraph($arVartable, $constructPattern)
+
+
+
+ /**
+ * Builds a describing named graph. To define an attribute list for a
+ * several rdf:type look at constants.php
+ *
+ * @param array $arVartable
+ * @return MemModel
+ */
+ function describeGraph($arVartable)
+ {
+ // build empty named graph
+ $resultGraph = new MemModel();
+ // if no where clause fill $arVartable
+ $vars = $this->query->getResultVars();
+ if ($arVartable == null) {
+ if ($vars) {
+ $arVartable[0] = array('?x' => new Resource(substr($vars[0],1,-1)));
+ $vars[0] = '?x';
+ }
+ }
+ // fetch attribute list from constants.php
+ global $sparql_describe;
+ // for each resultset
+ foreach ($arVartable as $resultset) {
+ foreach ($vars as $varname) {
+ $varvalue = $resultset[$varname];
+ // try to determine rdf:type of the variable
+ $type = $this->_determineType($varvalue, $resultGraph);
+ // search attribute list defined in constants.php
+ $list = null;
+ if ($type) {
+ $strLuri = strtolower($type->getUri());
+ if (isset($sparql_describe[$strLuri])) {
+ $list = $sparql_describe[$strLuri] ;
+ }
+ }
+ // search in dataset
+ $this->_getAttributes($list, $resultGraph, $varvalue);
+ }
+ }
+
+ return $resultGraph;
+ }//function describeGraph($arVartable)
+
+
+
+ /**
+ * Tries to determine the rdf:type of the variable.
+ *
+ * @param Node $var The variable
+ * @param MemModel $resultGraph The result graph which describes the Resource
+ * @return String Uri of the rdf:type
+ */
+ protected function _determineType($var, $resultGraph)
+ {
+ $type = null;
+ // find in namedGraphs
+ if (!$var instanceof Literal) {
+ $iter = $this->dataset->findInNamedGraphs(
+ null,
+ $var,
+ new Resource(RDF_NAMESPACE_URI.'type'),
+ null,
+ true
+ );
+ while ($iter->valid()) {
+ $statement = $iter->current();
+ $type = $statement->getObject();
+ $resultGraph->add($iter->current());
+ break;
+ }
+ }
+ // if no type information found find in default graph
+ if (!$type) {
+ if (!$var instanceof Literal) {
+ $iter1 = $this->dataset->findInDefaultGraph(
+ $var,
+ new Resource(RDF_NAMESPACE_URI.'type'),
+ null
+ );
+ $type = null;
+ while ($iter1->valid()) {
+ $statement = $iter1->current();
+ $type = $statement->getObject();
+ $resultGraph->add($iter1->current());
+ break;
+ }
+ }
+ }
+ return $type;
+ }//protected function _determineType($var, $resultGraph)
+
+
+
+ /**
+ * Search the attributes listed in $list in the dataset.
+ * Modifies $resultGraph
+ *
+ * @param Array $list List containing the attributes
+ * @param MemModel $resultGraph The result graph which describes the Resource
+ * @return void
+ */
+ protected function _getAttributes($list, $resultGraph, $varvalue)
+ {
+ if ($list){
+ foreach ($list as $attribute) {
+ if (!$varvalue instanceof Literal) {
+ $iter2 = $this->dataset->findInNamedGraphs(
+ null,
+ $varvalue,
+ new Resource($attribute),
+ null,
+ true
+ );
+ while ($iter2->valid()) {
+ $resultGraph->add($iter2->current());
+ $iter2->next();
+ }
+ $iter3 = $this->dataset->findInDefaultGraph(
+ $varvalue,
+ new Resource($attribute),
+ null
+ );
+ while ($iter3->valid()) {
+ $resultGraph->add($iter3->current());
+ $iter3->next();
+ }
+ }
+ }
+ }
+ }//protected function _getAttributes($list, $resultGraph, $varvalue)
+
+
+}//class SparqlEngine_ResultRenderer_Default implements SparqlEngine_ResultRenderer
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer/HTML.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer/HTML.php
new file mode 100755
index 00000000..2741f227
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer/HTML.php
@@ -0,0 +1,199 @@
+
+* @author Christian Weiske
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlEngine_ResultRenderer_HTML implements SparqlEngine_ResultRenderer
+{
+ /**
+ * If the result HTML should be wrapped in a div
+ * @var boolean
+ */
+ protected $bWrap = true;
+
+
+
+ /**
+ * Converts the database results into the output format
+ * and returns the result.
+ *
+ * @param array $arVartable Variable table
+ * @param Query $query SPARQL query object
+ * @param SparqlEngine $engine Sparql Engine to query the database
+ * @return string HTML result
+ */
+ public function convertFromResult($arVartable, Query $query, SparqlEngine $engine)
+ {
+ $this->query = $query;
+ $this->engine = $engine;
+ $this->dataset = $engine->getDataset();
+
+ $strCode = '';
+
+ $strResultForm = $query->getResultForm();
+ switch ($strResultForm) {
+ case 'select':
+ case 'select distinct':
+ $strCode = $this->createTableFromRecords($arVartable);
+ break;
+
+ case 'construct':
+ case 'describe':
+ throw new Exception(
+ 'Construct and describe are currently not supported by the'
+ . ' HTML renderer'
+ );
+
+ case 'count':
+ case 'ask':
+ $nCount = count($arVartable);
+
+ if ($strResultForm == 'ask') {
+ $strCode = 'There were results.';
+ } else {
+ $strCode = 'There are ' . $nCount . ' results.';
+ }
+ break;
+
+ default:
+ throw new Exception('Unsupported result form: ' . $strResultForm);
+ }
+
+ return $this->wrapCode($strCode);
+ }//public function convertFromResult($arVartable, Query $query, SparqlEngine $engine)
+
+
+
+ protected function wrapCode($strCode)
+ {
+ if (!$this->bWrap) {
+ return $strCode;
+ }
+
+ return
+ '' . "\n"
+ . $strCode . "\n"
+ . "
\n";
+ }//protected function wrapCode($strCode)
+
+
+
+ protected function createTableFromRecords($arVartable)
+ {
+ if (count($arVartable) == 0) {
+ return 'No result rows.';
+ }
+
+ $arResult = array();
+ foreach ($arVartable as $row) {
+ $arResultRow = array();
+ foreach ($row as $strVarName => $value) {
+ $arResultRow[$strVarName] = $this->createValue($value);
+ }
+ $arResult[] = $arResultRow;
+ }
+
+ //I always wanted to to this :)
+ return
+ "\n"
+ . " SPARQL result with " . count($arResult) . " rows\n"
+ . " | "
+ . implode(' | ', array_keys(reset($arResult)))
+ . " | \n"
+ . " \n "
+ . implode(
+ "
\n ",
+ array_map(
+ create_function(
+ '$ar',
+ 'return implode("", $ar);'
+ ),
+ $arResult
+ )
+ )
+ . "
\n \n"
+ . "
\n";
+ }//protected function createTableFromRecords($arRecordSets)
+
+
+
+ /**
+ * Creates an RDF object object
+ * contained in the given $dbRecordSet object.
+ *
+ * @see convertFromDbResult() to understand $strVarBase necessity
+ *
+ * @param ADORecordSet $dbRecordSet Record set returned from ADOConnection::Execute()
+ * @param string $strVarBase Prefix of the columns the recordset fields have.
+ *
+ * @return string HTML code
+ */
+ protected function createValue($value)
+ {
+ if ($value === null) {
+ $strCode = $this->getHtmlNull();
+ }
+ if ($value instanceof Literal) {
+ $strCode = $this->getHtmlLiteral(
+ $value->getLabel(),
+ $value->getLanguage(),
+ $value->getDatatype()
+ );
+ } else if ($value instanceof Resource) {
+ $strCode = $this->getHtmlResource($value->getURI());
+ } else {
+ $strCode = $this->getHtmlBlank();
+ }
+
+ return ''
+ . $strCode
+ . ' | ';
+ }//protected function createObjectFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVarName)
+
+
+
+ protected function getHtmlNull()
+ {
+ return 'NULL
';
+ }//protected function getHtmlNull()
+
+
+
+ protected function getHtmlBlank($value)
+ {
+ return 'Blank node';
+ }//protected function getHtmlBlank($value)
+
+
+
+ protected function getHtmlResource($value)
+ {
+ return htmlspecialchars($value);
+ }//protected function getHtmlResource($value)
+
+
+
+ protected function getHtmlLiteral($value, $language, $datatype)
+ {
+ $strCode = htmlspecialchars($value);
+ if ($language) {
+ $strCode .= '
xml:lang=' . $language;
+ }
+ if ($datatype) {
+ $strCode .= '
rdf:type=' . $datatype;
+ }
+ return $strCode;
+ }//protected function getHtmlLiteral($value, $language, $datatype)
+
+}//class SparqlEngine_ResultRenderer_HTML implements SparqlEngine_ResultRenderer
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer/XML.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer/XML.php
new file mode 100755
index 00000000..9bbef27b
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngine/ResultRenderer/XML.php
@@ -0,0 +1,125 @@
+
+* @author Christian Weiske
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlEngine_ResultRenderer_XML implements SparqlEngine_ResultRenderer
+{
+ /**
+ * Converts the database results into the output format
+ * and returns the result.
+ *
+ * @param array $arVartable Variable table
+ * @param Query $query SPARQL query object
+ * @param SparqlEngine $engine Sparql Engine to query the database
+ * @return string XML result
+ */
+ public function convertFromResult($arVartable, Query $query, SparqlEngine $engine)
+ {
+ $this->query = $query;
+ $this->engine = $engine;
+ $this->dataset = $engine->getDataset();
+
+ if ($arVartable instanceof NamedGraphMem) {
+ return $arVartable->writeRdfToString();
+ }
+
+ $result = '';
+ $header = '';
+
+ // build header
+ if (is_array($arVartable)) {
+ $vars = $this->query->getResultVars();
+ $header = '';
+ foreach ($vars as $value) {
+ $header = $header
+ . '';
+ }
+ $header = $header . '';
+
+ // build results
+ $solm = $this->query->getSolutionModifier();
+ $sel = $this->query->getResultForm();
+
+ $distinct = 'false';
+ if ($sel == 'select distinct') {
+ $distinct = 'true';
+ }
+
+ $ordered = 'false';
+ if ($solm['order by'] != 0) {
+ $ordered = 'true';
+ }
+
+ $results = '';
+ foreach ($arVartable as $value) {
+ $results = $results.'';
+ foreach ($value as $varname => $varvalue) {
+ $results = $results
+ . $this->_getBindingString(
+ substr($varname, 1),
+ $varvalue
+ );
+ }
+ $results = $results . '';
+ }
+ $results = $results . '';
+ } else {
+ $results = '' . $vartable . '';
+ }
+
+ $result = $result . $header . $results . '';
+ $result = simplexml_load_string($result);
+ return $result->asXML();
+ }//public function convertFromResult($arVartable, Query $query, SparqlEngine $engine)
+
+
+
+ /**
+ * Helper Function for function buildXmlResult($vartable). Generates
+ * an xml string for a single variable an their corresponding value.
+ *
+ * @param String $varname The variables name
+ * @param Node $varvalue The value of the variable
+ * @return String The xml string
+ */
+ protected function _getBindingString($varname, $varvalue)
+ {
+ $binding = '';
+ $value = '';
+
+ if ($varvalue instanceof BlankNode) {
+ $value = '' . $varvalue->getLabel() . '';
+ } else if ($varvalue instanceof Resource) {
+ $value = '' . $varvalue->getUri() . '';
+ } else if ($varvalue instanceof Literal) {
+ $label = htmlspecialchars($varvalue->getLabel());
+ $value = ''.$label.'';
+ if ($varvalue->getDatatype() != null) {
+ $value = ''
+ . $label
+ . '';
+ }
+ if ($varvalue->getLanguage() != null) {
+ $value = ''
+ . $label
+ . '';
+ }
+ }
+ $binding = $binding . $value . '';
+
+ return $binding;
+ }//protected function _getBindingString($varname, $varvalue)
+
+}//class SparqlEngine_ResultRenderer_XML implements SparqlEngine_ResultRenderer
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb.php
new file mode 100755
index 00000000..4e7050d0
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb.php
@@ -0,0 +1,391 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlEngineDb
+{
+ /**
+ * Sparql Query object.
+ *
+ * @var Query
+ */
+ protected $query;
+
+ /**
+ * RDF dataset object.
+ * @var Dataset
+ */
+ protected $dataset;
+
+ /**
+ * Database connection object.
+ * @var ADOConnection
+ */
+ protected $dbConn;
+
+ /**
+ * Internal ID for our graph model.
+ * Stored in the database along the statements.
+ * Can be of different types:
+ * - array: array of modelIds
+ * - null: all models
+ *
+ * @var array OR null
+ */
+ protected $arModelIds;
+
+ /**
+ * Prepared SQL statements are stored in here.
+ * @var array
+ */
+ protected $arPrepared = null;
+
+ /**
+ * If the prepared statement is really prepared, or if we just emulate it.
+ * @var boolean
+ */
+ protected $bRealPrepared = false;
+
+ /**
+ * SQL generator instance
+ * @var SparqlEngineDb_SqlGenerator
+ */
+ protected $sg = null;
+
+ /**
+ * Type sorting instance
+ * @var SparqlEngineDb_TypeSorter
+ */
+ protected $ts = null;
+
+ /**
+ * Prepared statments preparator instance
+ * @var SparqlEngineDb_Preparator
+ */
+ protected $pr = null;
+
+
+
+ /**
+ * Use SparqlEngine::factory() to create the instance
+ *
+ * @param mixed $model DbModel or DbStore
+ * @param mixed $arModelIds Array of modelIds, or NULL to use all models
+ */
+ public function __construct($model, $arModelIds = null)
+ {
+ //parent::__construct();
+ if ($model instanceof DbModel) {
+ $this->dbConn = $model->getDbConn();
+ $this->arModelIds = array($model->getModelID());
+ } else if ($model instanceof DbStore) {
+ $this->dbConn = $model->getDbConn();
+ $this->arModelIds = $arModelIds;
+ }
+ }//public function __construct(DbModel $model, $arModelIds = null)
+
+
+
+ /**
+ * Query the database with the given SPARQL query.
+ *
+ *
+ * @param Dataset $dataset RDF Dataset
+ * @param Query $query Parsed SPARQL query
+ * @param string $resultform Result form. If set to 'xml' the result will be
+ * SPARQL Query Results XML Format as described in http://www.w3.org/TR/rdf-sparql-XMLres/ .
+ *
+ * @return array/string array of triple arrays, or XML. Format depends on
+ * $resultform parameter.
+ */
+ public function queryModel($dataset, Query $query, $resultform = false)
+ {
+ if (isset($GLOBALS['debugSparql']) && $GLOBALS['debugSparql']) {
+ echo "\n" . 'SPARQL query: ' . $query->getQueryString() . "\n";
+ }
+
+ $this->query = $query;
+ $this->dataset = $dataset;
+
+ $qsimp = new SparqlEngineDb_QuerySimplifier();
+ $qsimp->simplify($this->query);
+
+ $this->sg = new SparqlEngineDb_SqlGenerator ($this->query, $this->dbConn, $this->arModelIds);
+ $this->rc = new SparqlEngineDb_ResultConverter($this->query, $this->sg, $this);
+ $this->ts = new SparqlEngineDb_TypeSorter ($this->query, $this->dbConn);
+
+ $this->setOptions();
+
+ if ($this->query->isEmpty()){
+ $vartable[0]['patternResult'] = null;
+ return $this->returnResult($vartable, $resultform);
+ }
+
+
+ $arSqls = $this->sg->createSql();
+ $this->ts->setData($this->sg);
+
+ return
+ SparqlEngineDb_ResultConverter::convertFromDbResults(
+ $this->queryMultiple(
+ $this->ts->getOrderifiedSqls(
+ $arSqls
+ )
+ ),
+ $this,
+ $resultform
+ );
+ }//public function queryModel($dataset, Query $query, $resultform = false)
+
+
+
+ /**
+ * Create a prepared statement that can be executed later.
+ *
+ * @param Dataset $dataset RDF Dataset
+ * @param Query $query Parsed SPARQL query
+ *
+ * @return SparqlEngineDb_PreparedStatement Prepared statment that can
+ * be execute()d later.
+ */
+ public function prepare(Dataset $dataset, Query $query)
+ {
+ require_once RDFAPI_INCLUDE_DIR . 'sparql/SparqlEngineDb/PreparedStatement.php';
+ require_once RDFAPI_INCLUDE_DIR . 'sparql/SparqlEngineDb/Preparator.php';
+
+ $this->query = $query;
+ $this->dataset = $dataset;
+ $this->sg = new SparqlEngineDb_SqlGenerator ($this->query, $this->dbConn, $this->arModelIds);
+ $this->rc = new SparqlEngineDb_ResultConverter($this->query, $this->sg, $this);
+ $this->ts = new SparqlEngineDb_TypeSorter ($this->query, $this->dbConn);
+ $this->pr = new SparqlEngineDb_Preparator ($this->query, $this->dbConn);
+
+ $this->arPrepared = $this->sg->createSql();
+ $this->ts->setData($this->sg);
+
+ if ($this->ts->willBeDataDependent()) {
+ $this->bRealPrepared = false;
+ } else {
+ $this->bRealPrepared = true;
+ list($strSelect, $strFrom, $strWhere) = $this->arPrepared;
+ $this->arPreparedQueries = $this->ts->getOrderifiedSqls(
+ $strSelect,
+ $strFrom,
+ $strWhere
+ );
+ $this->arDbStatements = $this->pr->prepareInDb(
+ $this->arPreparedQueries,
+ $this->sg->getPlaceholders()
+ );
+ }
+
+
+ return new SparqlEngineDb_PreparedStatement(
+ $this
+ );
+ }//public function prepare(Dataset $dataset, Query $query)
+
+
+
+ /**
+ * Execute a prepared statement by filling it with variables
+ *
+ * @param array $arVariables Array with (variable name => value) pairs
+ * @param string $resultform Which form the result should have
+ *
+ * @return mixed Result according to $resultform
+ */
+ public function execute($arVariables, $resultform = false)
+ {
+ if ($this->arPrepared === null) {
+ throw new Exception('You need to prepare() the query first.');
+ }
+
+ if ($this->bRealPrepared) {
+ return
+ SparqlEngineDb_ResultConverter::convertFromDbResults(
+ $this->pr->execute(
+ $this->arDbStatements,
+ $arVariables
+ ),
+ $this,
+ $resultform
+ );
+ } else {
+ list($strSelect, $strFrom, $strWhere) = $this->arPrepared;
+
+ return SparqlEngineDb_ResultConverter::convertFromDbResults(
+ $this->queryMultiple(
+ $this->ts->getOrderifiedSqls(
+ $strSelect,
+ $strFrom,
+ $this->pr->replacePlaceholdersWithVariables(
+ $strWhere,
+ $this->sg->getPlaceholders(),
+ $arVariables
+ )
+ )
+ ),
+ $this,
+ $resultform
+ );
+ }
+ }//public function execute($arVariables, $resultform)
+
+
+
+ /**
+ * Executes multiple SQL queries and returns an array
+ * of results.
+ *
+ * @param array $arSqls Array of SQL queries
+ * @return array Array of query results
+ */
+ protected function queryMultiple($arSqls)
+ {
+ $arSM = $this->query->getSolutionModifier();
+ if ($arSM['limit'] === null && $arSM['offset'] === null) {
+ $nOffset = 0;
+ $nLimit = null;
+ $nSql = 0;
+ } else {
+ $offsetter = new SparqlEngineDb_Offsetter($this->dbConn, $this->query);
+ list($nSql, $nOffset) = $offsetter->determineOffset($arSqls);
+ $nLimit = $arSM['limit'];
+ }
+
+ $nCount = 0;
+ $arResults = array();
+ foreach ($arSqls as $nId => $arSql) {
+ if ($nId < $nSql) { continue; }
+
+ if ($nLimit != null) {
+ $nCurrentLimit = $nLimit - $nCount;
+ } else {
+ $nCurrentLimit = null;
+ }
+
+ $dbResult = $this->queryDb($arSql, $nOffset, $nCurrentLimit);
+ $nCount += $dbResult->RowCount();
+ $arResults[] = $dbResult;
+ $nOffset = 0;
+ if ($nLimit !== null && $nCount >= $nLimit) {
+ break;
+ }
+ }
+
+ return $arResults;
+ //return array_map(array($this, 'queryDb'), $arSql);
+ }//protected function queryMultiple($arSql)
+
+
+
+ /**
+ * Sends the sql to the database and returns the results.
+ *
+ * @internal Switches between ADOConnection::Execute() and
+ * ADOConnection::SelectLimit() depending on the $query parameter's
+ * $solutionModifier "limit" and "offset" settings.
+ * Uses $query variable.
+ *
+ * @param array $arSql Array that gets a SQL query string once imploded
+ *
+ * @return mixed Anything ADOConnection::Execute() may return
+ * @throws Exception If Database query does not work
+ */
+ function queryDb($arSql, $nOffset, $nLimit)
+ {
+ $strSql = SparqlEngineDb_SqlMerger::getSelect($this->query, $arSql);
+
+ if ($strSql == '()') {
+ return new ADORecordSet(false);
+ }
+
+ // I want associative arrays.
+ $oldmode = $this->dbConn->SetFetchMode(ADODB_FETCH_ASSOC);
+
+ if (isset($GLOBALS['debugSparql']) && $GLOBALS['debugSparql']) {
+ echo 'SQL query: ' . $strSql . "\n";
+ }
+
+ if ($nLimit === null && $nOffset == 0) {
+ $ret = $this->dbConn->execute($strSql);
+ } else if ($nLimit === null) {
+ $ret = $this->dbConn->SelectLimit($strSql, -1, $nOffset);
+ } else {
+ $ret = $this->dbConn->SelectLimit($strSql, $nLimit, $nOffset);
+ }
+
+ //... but others maybe not
+ $this->dbConn->SetFetchMode($oldmode);
+
+ if (!$ret) {
+ //Error occured
+ throw new Exception(
+ 'ADOdb error: ' . $this->dbConn->ErrorMsg() . "\n"
+ . $strSql
+ );
+ }
+
+ return $ret;
+ }//function queryDb($sql)
+
+
+
+ /**
+ * Set options to subobjects like SqlGenerator
+ */
+ protected function setOptions()
+ {
+ //allow changing the statements' table name
+ if (isset($GLOBALS['RAP']['conf']['database']['tblStatements'])) {
+ $this->sg->setStatementsTable(
+ $GLOBALS['RAP']['conf']['database']['tblStatements']
+ );
+ }
+ }//protected function setOptions()
+
+
+
+ /*
+ * Dumb getters
+ */
+
+
+
+ public function getQuery()
+ {
+ return $this->query;
+ }//public function getQuery()
+
+
+
+ public function getSqlGenerator()
+ {
+ return $this->sg;
+ }//public function getSqlGenerator()
+
+
+
+ public function getTypeSorter()
+ {
+ return $this->ts;
+ }//public function getTypeSorter()
+
+}//class SparqlEngineDb
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/all-wcprops b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/all-wcprops
new file mode 100755
index 00000000..470b7a26
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/all-wcprops
@@ -0,0 +1,71 @@
+K 25
+svn:wc:ra_dav:version-url
+V 75
+/svnroot/rdfapi-php/!svn/ver/554/trunk/rdfapi-php/api/sparql/SparqlEngineDb
+END
+QuerySimplifier.php
+K 25
+svn:wc:ra_dav:version-url
+V 95
+/svnroot/rdfapi-php/!svn/ver/465/trunk/rdfapi-php/api/sparql/SparqlEngineDb/QuerySimplifier.php
+END
+FilterGenerator.php
+K 25
+svn:wc:ra_dav:version-url
+V 95
+/svnroot/rdfapi-php/!svn/ver/476/trunk/rdfapi-php/api/sparql/SparqlEngineDb/FilterGenerator.php
+END
+Preparator.php
+K 25
+svn:wc:ra_dav:version-url
+V 90
+/svnroot/rdfapi-php/!svn/ver/465/trunk/rdfapi-php/api/sparql/SparqlEngineDb/Preparator.php
+END
+TypeSorter.php
+K 25
+svn:wc:ra_dav:version-url
+V 90
+/svnroot/rdfapi-php/!svn/ver/536/trunk/rdfapi-php/api/sparql/SparqlEngineDb/TypeSorter.php
+END
+Offsetter.php
+K 25
+svn:wc:ra_dav:version-url
+V 89
+/svnroot/rdfapi-php/!svn/ver/465/trunk/rdfapi-php/api/sparql/SparqlEngineDb/Offsetter.php
+END
+SqlMerger.php
+K 25
+svn:wc:ra_dav:version-url
+V 89
+/svnroot/rdfapi-php/!svn/ver/465/trunk/rdfapi-php/api/sparql/SparqlEngineDb/SqlMerger.php
+END
+ResultRenderer.php
+K 25
+svn:wc:ra_dav:version-url
+V 94
+/svnroot/rdfapi-php/!svn/ver/465/trunk/rdfapi-php/api/sparql/SparqlEngineDb/ResultRenderer.php
+END
+SqlGeneratorException.php
+K 25
+svn:wc:ra_dav:version-url
+V 101
+/svnroot/rdfapi-php/!svn/ver/465/trunk/rdfapi-php/api/sparql/SparqlEngineDb/SqlGeneratorException.php
+END
+ResultConverter.php
+K 25
+svn:wc:ra_dav:version-url
+V 95
+/svnroot/rdfapi-php/!svn/ver/485/trunk/rdfapi-php/api/sparql/SparqlEngineDb/ResultConverter.php
+END
+SqlGenerator.php
+K 25
+svn:wc:ra_dav:version-url
+V 92
+/svnroot/rdfapi-php/!svn/ver/472/trunk/rdfapi-php/api/sparql/SparqlEngineDb/SqlGenerator.php
+END
+PreparedStatement.php
+K 25
+svn:wc:ra_dav:version-url
+V 97
+/svnroot/rdfapi-php/!svn/ver/465/trunk/rdfapi-php/api/sparql/SparqlEngineDb/PreparedStatement.php
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/entries b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/entries
new file mode 100755
index 00000000..f511e2e0
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/entries
@@ -0,0 +1,173 @@
+8
+
+dir
+556
+https://rdfapi-php.svn.sourceforge.net/svnroot/rdfapi-php/trunk/rdfapi-php/api/sparql/SparqlEngineDb
+https://rdfapi-php.svn.sourceforge.net/svnroot/rdfapi-php
+
+
+
+2007-12-05T08:18:50.037887Z
+554
+fusel2k
+
+
+svn:special svn:externals svn:needs-lock
+
+
+
+
+
+
+
+
+
+
+
+b2ee660e-c932-0410-bdee-d8da4d8102f4
+
+QuerySimplifier.php
+file
+
+
+
+
+2008-02-29T14:57:47.115741Z
+3c0ba98e3c6ea3d594c3645c2f779917
+2007-06-27T16:47:57.067358Z
+465
+cweiske
+
+FilterGenerator.php
+file
+
+
+
+
+2008-02-29T14:57:47.131362Z
+f4ced98870e781243de014d5f6340364
+2007-08-08T13:48:22.439560Z
+476
+cweiske
+has-props
+
+ResultRenderer
+dir
+
+Preparator.php
+file
+
+
+
+
+2008-02-29T14:57:47.131362Z
+51f969eeaaaca65372f53ecd720dc9e6
+2007-06-27T16:47:57.067358Z
+465
+cweiske
+has-props
+
+TypeSorter.php
+file
+
+
+
+
+2008-02-29T14:57:47.146983Z
+130848f8c0cc36f263774a7d3e711f2d
+2007-08-20T17:21:35.303811Z
+536
+cweiske
+has-props
+
+Offsetter.php
+file
+
+
+
+
+2008-02-29T14:57:47.146983Z
+73910f040f4deed2439301a2a1f9fc1a
+2007-06-27T16:47:57.067358Z
+465
+cweiske
+has-props
+
+SqlMerger.php
+file
+
+
+
+
+2008-02-29T14:57:47.162603Z
+f2ed9300171a830350ca217f11238649
+2007-06-27T16:47:57.067358Z
+465
+cweiske
+has-props
+
+ResultRenderer.php
+file
+
+
+
+
+2008-02-29T14:57:47.162603Z
+f293569f66b31ebadf3b53e7c67467fe
+2007-06-27T16:47:57.067358Z
+465
+cweiske
+has-props
+
+SqlGeneratorException.php
+file
+
+
+
+
+2008-02-29T14:57:47.178224Z
+f9e0b14e53c647017827ed143e481a0a
+2007-06-27T16:47:57.067358Z
+465
+cweiske
+has-props
+
+ResultConverter.php
+file
+
+
+
+
+2008-02-29T14:57:47.178224Z
+b996d6f54e8963884e3c5b0775b29f36
+2007-08-12T11:33:30.127896Z
+485
+cweiske
+has-props
+
+SqlGenerator.php
+file
+
+
+
+
+2008-02-29T14:57:47.193844Z
+bb0e74447781677e82d9927b2b2f5cb5
+2007-08-02T21:19:57.083490Z
+472
+cweiske
+has-props
+
+PreparedStatement.php
+file
+
+
+
+
+2008-02-29T14:57:47.193844Z
+4094f6cd26373a4ebbab87d395b6b806
+2007-06-27T16:47:57.067358Z
+465
+cweiske
+has-props
+
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/format b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/format
new file mode 100755
index 00000000..45a4fb75
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/format
@@ -0,0 +1 @@
+8
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/prop-base/FilterGenerator.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/prop-base/FilterGenerator.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/prop-base/FilterGenerator.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/prop-base/Offsetter.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/prop-base/Offsetter.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/prop-base/Offsetter.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/prop-base/Preparator.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/prop-base/Preparator.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/prop-base/Preparator.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/prop-base/PreparedStatement.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/prop-base/PreparedStatement.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/prop-base/PreparedStatement.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/prop-base/ResultConverter.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/prop-base/ResultConverter.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/prop-base/ResultConverter.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/prop-base/ResultRenderer.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/prop-base/ResultRenderer.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/prop-base/ResultRenderer.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/prop-base/SqlGenerator.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/prop-base/SqlGenerator.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/prop-base/SqlGenerator.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/prop-base/SqlGeneratorException.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/prop-base/SqlGeneratorException.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/prop-base/SqlGeneratorException.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/prop-base/SqlMerger.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/prop-base/SqlMerger.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/prop-base/SqlMerger.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/prop-base/TypeSorter.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/prop-base/TypeSorter.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/prop-base/TypeSorter.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/text-base/FilterGenerator.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/text-base/FilterGenerator.php.svn-base
new file mode 100755
index 00000000..abc7cba3
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/text-base/FilterGenerator.php.svn-base
@@ -0,0 +1,846 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlEngineDb_FilterGenerator
+{
+ /**
+ * SQL Generator
+ * @var SparqlEngineDb_SqlGenerator
+ */
+ protected $sg = null;
+
+ /**
+ * If the filter is in an optional statement
+ * @var boolean
+ */
+ protected $bOptional = false;
+
+ /**
+ * Number of parameters for the functions supported.
+ * First value is minimum, second is maximum.
+ * @var array
+ */
+ protected static $arFuncParamNumbers = array(
+ 'bound' => array(1, 1),
+ 'datatype' => array(1, 1),
+ 'isblank' => array(1, 1),
+ 'isiri' => array(1, 1),
+ 'isliteral' => array(1, 1),
+ 'isuri' => array(1, 1),
+ 'lang' => array(1, 1),
+ 'langmatches' => array(2, 2),
+ 'regex' => array(2, 3),
+ 'sameterm' => array(2, 2),
+ 'str' => array(1, 1),
+ 'xsd:datetime' => array(1, 1),
+ );
+
+ /**
+ * List of operators and their counterpart if operands are switched.
+ * (a > b) => (b < a)
+ * @var array
+ */
+ protected static $arOperatorSwitches = array(
+ '>' => '<',
+ '<' => '>',
+ '>=' => '<=',
+ '<=' => '>=',
+ );
+
+ protected static $arDumbOperators = array(
+ '&&', '||'
+ );
+
+ protected static $typeXsdBoolean = 'http://www.w3.org/2001/XMLSchema#boolean';
+ protected static $typeXsdDateTime = 'http://www.w3.org/2001/XMLSchema#dateTime';
+ protected static $typeXsdDouble = 'http://www.w3.org/2001/XMLSchema#double';
+ protected static $typeXsdInteger = 'http://www.w3.org/2001/XMLSchema#integer';
+ protected static $typeXsdString = 'http://www.w3.org/2001/XMLSchema#string';
+ protected static $typeVariable = 'variable';
+
+
+
+ public function __construct(SparqlEngineDb_SqlGenerator $sg)
+ {
+ $this->sg = $sg;
+ }//public function __construct(SparqlEngineDb_SqlGenerator $sqlgen)
+
+
+
+ /**
+ * Creates the SQL representing a Sparql FILTER.
+ *
+ * @param array $tree Filter element tree as returned by
+ * SparqlParser::parseConstraintTree()
+ * @param boolean $bOptional If the filter is in an optional statement
+ * @return string SQL WHERE part with prefixed AND
+ */
+ public function createFilterSql($tree, $bOptional, $nUnionCount)
+ {
+ if (count($tree) == 0) {
+ //empty filter pattern?
+ return '';
+ }
+
+ $this->bOptional = $bOptional;
+ $this->nUnionCount = $nUnionCount;
+
+ return ' AND ' . $this->createTreeSql($tree, null);
+ }//public function createFilterSql($tree)
+
+
+
+ /**
+ *
+ */
+ protected function createTreeSql($tree, $parent)
+ {
+ switch ($tree['type']) {
+ case 'equation':
+ $sql = $this->createEquation($tree);
+ break;
+ case 'value':
+ if ($parent != null) {
+ $bDumbParent = $parent['type'] == 'equation'
+ && in_array($parent['operator'], self::$arDumbOperators);
+ } else {
+ $bDumbParent = true;
+ }
+ $sql = $this->createValue($tree, $bDumbParent);
+ break;
+ case 'function':
+ $sql = $this->createFunction($tree);
+ break;
+ default:
+ //var_dump($tree);
+ throw new SparqlEngineDb_SqlGeneratorException('Unsupported tree type: ' . $tree['type']);
+ break;
+ }
+
+ if (isset($tree['negated'])) {
+ $sql = '!(' . $sql . ')';
+ }
+
+ return $sql;
+ }//protected function createTreeSql($tree, $strParentType)
+
+
+
+ /**
+ * Creates the sql for an element of type "value".
+ *
+ * @param array $tree Element
+ * @param boolean $bDumbParent True if the parent is a boolean equation or null.
+ */
+ protected function createValue($tree, $bDumbParent)
+ {
+ $strValue = stripslashes($tree['value']);
+ if (SparqlVariable::isVariable($strValue)) {
+ if (!isset($this->sg->arUnionVarAssignments[$this->nUnionCount][$strValue])) {
+ throw new SparqlEngineDb_SqlGeneratorException(
+ 'Unknown variable in filter: ' . $strValue
+ );
+ }
+
+ if ($bDumbParent) {
+ return $this->createBooleanValue($tree);
+ } else if ($this->isObject($tree)) {
+ //convert datetime to datetime if necessary
+ return self::mkVal(
+ '(CASE'
+ . ' WHEN ' . $this->getDatatypeCol($tree) . ' = "' . self::$typeXsdBoolean . '"'
+ . ' THEN IF(LOWER(' . $this->getValueCol($tree) . ') = "true", TRUE, FALSE)'
+ . ' ELSE ' . $this->getValueCol($tree)
+ . ' END)',
+ self::$typeVariable
+ );
+ } else {
+ return self::mkVal(
+ $this->getValueCol($tree),
+ self::$typeVariable
+ );
+ }
+ }
+
+ if ($this->isNumber($tree)) {
+ return $strValue;
+ } else if ($tree['quoted'] === false &&
+ (!isset($tree['datatype']) || $tree['datatype'] != self::$typeXsdBoolean)
+ ) {
+ $strValueNew = $this->sg->query->getFullUri($strValue);
+ if ($strValueNew === false) {
+ if ($strValue[0] == '<' && substr($strValue, -1) == '>') {
+ $strValue = substr($strValue, 1, -1);
+ } else {
+var_dump($tree);
+ throw new SparqlEngineDb_SqlGeneratorException(
+ 'Unexpected value "' . $strValue . '" (expected datatype)'
+ );
+ }
+ } else {
+ $strValue = $strValueNew;
+ }
+ } else if (isset($tree['datatype'])) {
+ switch ($tree['datatype']) {
+ case self::$typeXsdBoolean:
+ if (strtolower($strValue) == 'false') {
+ //fix: (bool)"false" === true
+ $strValue = false;
+ }
+ return self::mkVal(
+ (bool)$strValue ? 'TRUE' : 'FALSE',
+ self::$typeXsdBoolean
+ );
+
+ default:
+ throw new SparqlEngineDb_SqlGeneratorException(
+ 'Unsupported datatype "' . $tree['datatype']
+ );
+ }
+ }
+
+ return self::mkVal(
+ '"' . addslashes($strValue) . '"',
+ self::$typeXsdString
+ );
+ }//protected function createValue($tree)
+
+
+
+ protected function createBooleanValue($tree)
+ {
+ list($strTable, $chType) = $this->sg->arUnionVarAssignments[$this->nUnionCount][$tree['value']];
+ if (!$this->isObject($tree)) {
+ //Maybe needs a fix
+ $strSqlCol = SparqlEngineDb_SqlGenerator::$arTableColumnNames[$chType]['value'];
+ return self::mkVal(
+ $strTable . '.' . $strSqlCol . ' != ""',
+ self::$typeXsdBoolean
+ );
+ }
+
+ $cType = $strTable . '.l_datatype';
+ $cValue = $strTable . '.object';
+ $xsd = 'http://www.w3.org/2001/XMLSchema';
+
+ return self::mkVal(
+ '('
+ . "(($cType = '' || $cType = '$xsd#string') AND $cValue != '')"
+ . " OR ($cType = '$xsd#boolean' AND $cValue != 'false')"
+ . " OR (($cType = '$xsd#integer' || $cType = '$xsd#double') AND CAST($cValue AS DECIMAL(15,10)) != 0)"
+ //plain check for all unknown datatypes
+ . " OR ($cType != '' AND $cType != '$xsd#string' AND $cType != '$xsd#boolean' AND $cType != '$xsd#integer' AND $cType != '$xsd#double' AND $cValue != '')"
+ . ')',
+ self::$typeXsdBoolean
+ );
+ }//protected function createBooleanValue($tree)
+
+
+
+ protected function createFunction($tree)
+ {
+ $strFuncName = strtolower($tree['name']);
+ if (!isset(self::$arFuncParamNumbers[$strFuncName])) {
+ throw new SparqlEngineDb_SqlGeneratorException(
+ 'Unsupported FILTER function: ' . $strFuncName
+ );
+ }
+
+ $nParams = count($tree['parameter']);
+ if ($nParams < self::$arFuncParamNumbers[$strFuncName][0]
+ || $nParams > self::$arFuncParamNumbers[$strFuncName][1]
+ ) {
+ throw new SparqlEngineDb_SqlGeneratorException(
+ 'Wrong parameter count for FILTER function: ' . $strFuncName
+ . ' (got ' . $nParams . ', expected '
+ . self::$arFuncParamNumbers[$strFuncName][0]
+ . '-' . self::$arFuncParamNumbers[$strFuncName][1]
+ );
+ }
+
+ $strThisFunc = 'createFunction_' . str_replace(':', '_', $strFuncName);
+ return $this->$strThisFunc($tree);
+ }//protected function createFunction($tree)
+
+
+
+ protected function createEquation($tree)
+ {
+ $strExtra = '';
+ $strIsNull = '';
+ $strIsNullEnd = '';
+
+ if (($this->isNumber($tree['operand1']) || $this->isPlainString($tree['operand1']))
+ && $this->isObject($tree['operand2'])
+ ) {
+ //switch operands and operator
+ $tmp = $tree['operand1'];
+ $tree['operand1'] = $tree['operand2'];
+ $tree['operand2'] = $tmp;
+ $tree['operator'] = self::switchOperator($tree['operator']);
+ }
+
+ $val1 = $this->createTreeSql($tree['operand1'], $tree);
+ $val2 = $this->createTreeSql($tree['operand2'], $tree);
+
+ if ($this->isObject($tree['operand1'])) {
+ if ($this->bOptional) {
+ $strIsNull = '(';
+ $strIsNullEnd = ' OR ' . $val1 . ' IS NULL)';
+ }
+ if (isset($tree['operand2']['language'])) {
+ $strColLanguage = $this->getLangCol($tree['operand1']);
+ $strExtra .= ' AND ' . $strColLanguage . ' = "'
+ . addslashes($tree['operand2']['language'])
+ . '"';
+ }
+
+ if ($this->isNumber($tree['operand2'])) {
+ $strColDatatype = $this->getDatatypeCol($tree['operand1']);
+ $strExtra .= ' AND (' . $strColDatatype . ' = "' . self::$typeXsdDouble . '"'
+ . ' OR ' . $strColDatatype . ' = "' . self::$typeXsdInteger . '"'
+ . ')';
+ return $strIsNull . '('
+ . 'CAST(' . $val1 . ' AS DECIMAL(15,10))'
+ . ' ' . $tree['operator'] . ' '
+ . $val2
+ . $strExtra
+ . ')' . $strIsNullEnd;
+ }
+ }
+
+ //I don't check the operator since it is already checked in the parser
+ return $strIsNull . '('
+ . '('
+ . $val1
+ . ' ' . $tree['operator'] . ' '
+ . $val2
+ . $strExtra
+ . ')'
+ . $this->createTypeEquation(
+ $tree['operator'], $val1, $val2,
+ $tree['operand1'], $tree['operand2']
+ )
+ . ')' . $strIsNullEnd;
+ }//protected function createEquation($tree)
+
+
+
+ /**
+ * Generates sql code to make sure the datatypes of the two operands match
+ */
+ protected function createTypeEquation($operator, $val1, $val2, $tree1, $tree2)
+ {
+ if (in_array($operator, array('&&', '||'))) {
+ return '';
+ }
+
+ if ($val1->type != self::$typeVariable && $val2->type != self::$typeVariable) {
+ //both are not variables -> type needs to be the same
+ return $val1->type == $val2->type ? '' : ' AND FALSE';
+ }
+ $so1 = $this->isObjectOrSubject($tree1);
+ $so2 = $this->isObjectOrSubject($tree2);
+ $o1 = $this->isObject($tree1);
+ $o2 = $this->isObject($tree2);
+
+ if ($so1 && $so2) {
+ $sql = ' AND ' . $this->getIsCol($tree1) . ' = ' . $this->getIsCol($tree2);
+ if ($o1 && $o2) {
+ //maybe needs string fix
+ $sql .= ' AND ' . $this->getDatatypeCol($tree1) . ' = '
+ . $this->getDatatypeCol($tree2);
+ }
+ return $sql;
+ }
+
+ if ($o1 && $val2->type != self::$typeVariable) {
+ return $this->createSingleTypeCheck($val2, $tree1);
+ } else if ($o2 && $val1->type != self::$typeVariable) {
+ return $this->createSingleTypeCheck($val1, $tree2);
+ }
+
+ //fixme
+ return '';
+ }//protected function createTypeEquation($operator, $val1, $val2, $tree1, $tree2)
+
+
+
+ /**
+ * Creates sql to ensure the type between $val and variable $tree
+ * is the same.
+ */
+ protected function createSingleTypeCheck($val, $tree)
+ {
+ if ($val->type == self::$typeXsdString) {
+ //string can be empty type or xsd type
+ return ' AND ('
+ . $this->getDatatypeCol($tree) . ' = "' . $val->type . '"'
+ . ' OR '
+ . $this->getDatatypeCol($tree) . ' = ""'
+ . ')';
+ }
+ return ' AND ' . $this->getDatatypeCol($tree) . ' = "' . $val->type . '"';
+ }//protected function createSingleTypeCheck($val, $tree)
+
+
+
+ /*
+ * SQL generation functions
+ */
+
+
+
+ /**
+ * Creates an sql statement that returns if the element is a blank node
+ */
+ protected function createFunction_bound($tree)
+ {
+ if ($this->isVariable($tree['parameter'][0])) {
+ return self::mkVal(
+ $this->getValueCol($tree['parameter'][0]) . ' IS NOT NULL',
+ self::$typeXsdBoolean
+ );
+ }
+
+ //We'll see which other cases occur here
+ return self::mkVal('TRUE', self::$typeXsdBoolean);
+ }//protected function createFunction_bound($tree)
+
+
+
+ protected function createFunction_datatype($tree)
+ {
+ if (!$this->isObject($tree['parameter'][0])) {
+ throw new SparqlEngineDb_SqlGeneratorException(
+ 'datatype\'s first parameter needs to be an object'
+ );
+ }
+
+ return self::mkVal(
+ $this->getDatatypeCol($tree['parameter'][0]),
+ self::$typeXsdString
+ );
+ }//protected function createFunction_datatype($tree)
+
+
+
+ /**
+ * Creates an sql statement that returns if the element is a blank node
+ */
+ protected function createFunction_isblank($tree)
+ {
+ if (!$this->isObjectOrSubject($tree['parameter'][0])) {
+ throw new SparqlEngineDb_SqlGeneratorException(
+ 'isBlank\'s first parameter needs to be an object or subject'
+ );
+ }
+
+ return self::mkVal(
+ $this->getIsCol($tree['parameter'][0]) . ' = "b"',
+ self::$typeXsdBoolean
+ );
+ }//protected function createFunction_isblank($tree)
+
+
+
+ protected function createFunction_isiri($tree)
+ {
+ return $this->createFunction_isuri($tree);
+ }//protected function createFunction_isiri($tree)
+
+
+
+ /**
+ * Creates an sql statement that returns the language of the object
+ */
+ protected function createFunction_isliteral($tree)
+ {
+ if ($this->isObjectOrSubject($tree['parameter'][0])) {
+ return $this->getIsCol($tree['parameter'][0]) . ' = "l"';
+ }
+
+ //This does not take combined functions into account (subfunctions)
+ return self::mkVal(
+ $this->isPlainString($tree) ? 'TRUE' : 'FALSE',
+ self::$typeXsdBoolean
+ );
+ }//protected function createFunction_isliteral($tree)
+
+
+
+ protected function createFunction_isuri($tree)
+ {
+ if ($this->isObjectOrSubject($tree['parameter'][0])) {
+ return self::mkVal(
+ $this->getIsCol($tree['parameter'][0]) . ' = "r"',
+ self::$typeXsdBoolean
+ );
+ } else {
+ //predicates are iris
+ return self::mkVal('TRUE', self::$typeXsdBoolean);
+ }
+ }//protected function createFunction_isuri($tree)
+
+
+
+ /**
+ * Creates an sql statement that returns the language of the object
+ */
+ protected function createFunction_lang($tree)
+ {
+ if (!$this->isObject($tree['parameter'][0])) {
+ throw new SparqlEngineDb_SqlGeneratorException(
+ 'lang\'s first parameter needs to be an object'
+ );
+ }
+ return self::mkVal(
+ $this->getLangCol($tree['parameter'][0]),
+ self::$typeXsdString
+ );
+ }//protected function createFunction_lang($tree)
+
+
+
+ /**
+ * Creates an sql statement that checks if the variable
+ * matches a given language
+ */
+ protected function createFunction_langmatches($tree)
+ {
+ //those two restrictions are needed until we have a mysql-only
+ // langmatches function
+ if ($tree['parameter'][0]['type'] != 'function'
+ || $tree['parameter'][0]['name'] != 'lang'
+ ) {
+ throw new SparqlEngineDb_SqlGeneratorException(
+ 'langMatches\' first parameter needs to be a lang() function'
+ );
+ }
+
+ if (!$this->isPlainString($tree['parameter'][1])) {
+ throw new SparqlEngineDb_SqlGeneratorException(
+ 'langMatches\' second parameter needs to be a string'
+ );
+ }
+
+ $lang = $tree['parameter'][1]['value'];
+ $col = $this->createTreeSql($tree['parameter'][0], $tree);
+
+ switch ($lang) {
+ case '*':
+ //anything but nothing
+ $sql = $col . ' != ""';
+ break;
+ case '':
+ //nothing
+ $sql = $col . ' = ""';
+ break;
+ default:
+ //language, maybe with different subcode
+ // en -> en, en-US
+ $sql = '(' . $col . ' = "' . addslashes($lang) . '" OR '
+ . $col . ' LIKE "' . addslashes($lang) . '-%")';
+ break;
+ }
+
+ return self::mkVal($sql, self::$typeXsdBoolean);
+ }//protected function createFunction_isuri($tree)
+
+
+
+ /**
+ * Creates an sql statement that checks if the given part matches
+ * an regex
+ */
+ protected function createFunction_regex($tree)
+ {
+ $strVar = $this->createTreeSql($tree['parameter'][0], $tree);
+ $strRegex = $this->createTreeSql($tree['parameter'][1], $tree);
+
+ if (isset($tree['parameter'][2])) {
+ //is quoted
+ $strMod = $this->createTreeSql($tree['parameter'][2], $tree);
+ switch ($strMod) {
+ case '':
+ case '""':
+ $sql = $strVar . ' REGEXP ' . $strRegex;
+ break;
+
+ case '"i"':
+ $sql = 'CAST(' . $strVar . ' AS CHAR) REGEXP ' . $strRegex;
+ break;
+
+ default:
+ throw new SparqlEngineDb_SqlGeneratorException(
+ 'Unsupported regex modifier "'
+ . $strMod
+ . '"'
+ );
+ }
+ } else {
+ $sql = $strVar . ' REGEXP ' . $strRegex;
+ }
+
+ if ($this->isObject($tree['parameter'][0])) {
+ $col = $this->getIsCol($tree['parameter'][0]);
+ $sql = "($sql AND $col = 'l')";
+ }
+
+ return self::mkVal($sql, self::$typeXsdBoolean);
+ }//protected function createFunction_regex($tree)
+
+
+
+ /**
+ * Creates an sql statement that checks if both terms are the same
+ */
+ protected function createFunction_sameterm($tree)
+ {
+ //FIXME: dead simple implementation that does not cover all cases
+ return self::mkVal(
+ $this->createTreeSql($tree['parameter'][0], $tree)
+ . ' = '
+ . $this->createTreeSql($tree['parameter'][1], $tree),
+ self::$typeXsdBoolean
+ );
+ }//protected function createFunction_sameterm($tree)
+
+
+
+ /**
+ * Creates an sql statement that returns the string representation
+ * of the given element
+ */
+ protected function createFunction_str($tree)
+ {
+ if ($this->isObject($tree['parameter'][0])) {
+ return self::mkVal(
+ '(CASE ' . $this->getIsCol($tree['parameter'][0])
+ . ' WHEN "b" THEN ""'
+ . ' ELSE ' . $this->getValueCol($tree['parameter'][0])
+ . ' END)',
+ self::$typeXsdString
+ );
+ }
+
+ return $this->createTreeSql($tree['parameter'][0], $tree);
+ }//protected function createFunction_str($tree)
+
+
+
+ /**
+ * Creates an sql statement that returns the datetime representation
+ * of the given element
+ */
+ protected function createFunction_xsd_datetime($tree)
+ {
+ $val = $this->createTreeSql($tree['parameter'][0], $tree);
+ if ($val->type == self::$typeXsdDateTime
+ || $val->type == self::$typeVariable) {
+ //no need to cast again
+ return $val;
+ }
+ return self::mkVal(
+ $this->getDateConversionSql($val),
+ self::$typeXsdDateTime
+ );
+ }//protected function createFunction_xsd_datetime($tree)
+
+
+
+
+ /*
+ * Helper methods
+ */
+
+
+
+ protected static function mkVal($value, $type = null) {
+ return new SparqlEngineDb_FilterGenerator_Value($value, $type);
+ }
+
+
+
+ protected function getCol($tree, $type)
+ {
+ list($strTable, $chType) = $this->sg->arUnionVarAssignments[$this->nUnionCount][$tree['value']];
+ if (!isset(SparqlEngineDb_SqlGenerator::$arTableColumnNames[$chType][$type])) {
+ return false;
+ }
+ $strSqlCol = SparqlEngineDb_SqlGenerator::$arTableColumnNames[$chType][$type];
+ return $strTable . '.' . $strSqlCol;
+ }
+
+
+
+ protected function getDatatypeCol($tree)
+ {
+ list($strTable, $chType) = $this->sg->arUnionVarAssignments[$this->nUnionCount][$tree['value']];
+ return $strTable . '.l_datatype';
+ }
+
+
+
+ protected function getDateConversionSql($strValue)
+ {
+ return 'STR_TO_DATE(' . $strValue . ', "%Y-%m-%dT%H:%i:%sZ")';
+ }//protected function getDateConversionSql($strValue)
+
+
+
+ protected function getIsCol($tree)
+ {
+ return $this->getCol($tree, 'is');
+ }
+
+
+
+ protected function getLangCol($tree)
+ {
+ list($strTable, $chType) = $this->sg->arUnionVarAssignments[$this->nUnionCount][$tree['value']];
+ return $strTable . '.l_language';
+ }
+
+
+
+ protected function getValueCol($tree)
+ {
+ return $this->getCol($tree, 'value');
+ }
+
+
+
+ protected function isNumber($tree)
+ {
+ return $tree['type'] == 'value'
+ && $tree['quoted'] === false
+ && preg_match('#^[0-9.]+$#', $tree['value'])
+ && floatval($tree['value']) == $tree['value'];
+ }//protected function isNumber($tree)
+
+
+
+ /**
+ * Checks if the given tree element is a variable
+ * and the variable is actually an object in the database.
+ *
+ * @param array $tree Tree element
+ * @return boolean True if the element is an object
+ */
+ protected function isObject($tree)
+ {
+ return $this->isVariable($tree)
+ && $this->sg->arUnionVarAssignments[$this->nUnionCount][$tree['value']][1] == 'o';
+ }//protected function isVariable($tree)
+
+
+
+ /**
+ * Checks if the given tree element is a variable
+ * and the variable is actually an object or a subject in the database.
+ *
+ * @param array $tree Tree element
+ * @return boolean True if the element is an object or an subject
+ */
+ protected function isObjectOrSubject($tree)
+ {
+ return $this->isVariable($tree)
+ && (
+ $this->sg->arUnionVarAssignments[$this->nUnionCount][$tree['value']][1] == 'o'
+ || $this->sg->arUnionVarAssignments[$this->nUnionCount][$tree['value']][1] == 's'
+ );
+ }//protected function isObjectOrSubject($tree)
+
+
+
+ /**
+ * Checks if the given tree element is a plain string (no variable)
+ *
+ * @param array $tree Tree element
+ * @return boolean True if the element is a string
+ */
+ protected function isPlainString($tree)
+ {
+ return $tree['type'] == 'value'
+ && $tree['quoted'] === true;
+ }//protected function isPlainString($tree)
+
+
+
+ protected function isValueButNotVariableNorString($tree)
+ {
+ return $tree['type'] == 'value'
+ && $tree['type']['quoted'] === false
+ && !SparqlVariable::isVariable($tree['value']);
+ }//protected function isValueButNotVariableNorString($tree)
+
+
+
+ /**
+ * Checks if the given tree element is a variable
+ *
+ * @param array $tree Tree element
+ * @return boolean True if the element is a variable
+ */
+ protected function isVariable($tree)
+ {
+ return $tree['type'] == 'value'
+ && $tree['quoted'] === false
+ && SparqlVariable::isVariable($tree['value'])
+ && isset($this->sg->arUnionVarAssignments[$this->nUnionCount][$tree['value']]);
+ }//protected function isVariable($tree)
+
+
+
+ protected static function switchOperator($op)
+ {
+ if (!isset(self::$arOperatorSwitches[$op])) {
+ return $op;
+ } else {
+ return self::$arOperatorSwitches[$op];
+ }
+ }//protected static function switchOperator($op)
+
+}//class SparqlEngineDb_FilterGenerator
+
+
+
+
+/**
+* Value class that holds some arbitrary value
+* and a datatype.
+* Objects of this class can transparently be used in strings since
+* its __toString() returns the value.
+*/
+class SparqlEngineDb_FilterGenerator_Value
+{
+ public $value = null;
+ public $type = null;
+
+
+
+ public function __construct($value, $type = null)
+ {
+ $this->value = $value;
+ $this->type = $type;
+ }
+
+
+
+ public function __toString()
+ {
+ return $this->value;
+ }
+
+}//class SparqlEngineDb_FilterGenerator_Value
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/text-base/Offsetter.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/text-base/Offsetter.php.svn-base
new file mode 100755
index 00000000..5c2d1744
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/text-base/Offsetter.php.svn-base
@@ -0,0 +1,102 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlEngineDb_Offsetter
+{
+ public function __construct(ADOConnection $dbConn, Query $query)
+ {
+ $this->dbConn = $dbConn;
+ $this->query = $query;
+ }//public function __construct(ADOConnection $dbConn, Query $query)
+
+
+
+ /**
+ * Determines the offset in the sqls, the position to start form.
+ *
+ * @param array $arSqls Array of SQL query parts as returned by
+ * SparqlEngine_TypeSorter::getOrderifiedSqls()
+ * @return array Array of two values: The first determines the
+ * index of the sql query to begin with, the second
+ * is the row offset that should be used in the final
+ * SQL query.
+ */
+ public function determineOffset($arSqls)
+ {
+ $arSM = $this->query->getSolutionModifier();
+ if ($arSM['offset'] === null) {
+ return array(0, 0);
+ }
+
+ $nCount = 0;
+ foreach ($arSqls as $nId => $arSql) {
+ $nCurrentCount = $this->getCount($arSql);
+ if ($nCurrentCount + $nCount > $arSM['offset']) {
+ return array($nId, $arSM['offset'] - $nCount);
+ }
+ $nCount += $nCurrentCount;
+ }
+ //nothing found - no results for this offset
+ return array(count($arSqls), 0);
+ }//public function determineOffset($arSql)
+
+
+
+ /**
+ * Returns the number of rows that the given query will return.
+ *
+ * @param array $arSql Array with sql parts and at least keys
+ * 'from' and 'where' set.
+ * @return int Number of rows returned.
+ */
+ protected function getCount($arSql)
+ {
+ $sql = SparqlEngineDb_SqlMerger::getCount($this->query, $arSql);
+ $dbResult = $this->dbConn->execute($sql);
+
+ $nCount = 0;
+ foreach ($dbResult as $row) {
+ $nCount = intval($row[0]);
+ break;
+ }
+ return $nCount;
+ }//protected function getCount($arSql)
+
+
+
+ /**
+ * Creates a sql LIMIT statement if the sparql query needs one.
+ * This method is needed because AdoDb does not support limits with
+ * prepared statements. It's a pity.
+ *
+ * @return string SQL command to be appended to a query, to limit
+ * the number of result rows returned.
+ */
+ public static function getLimitSql(Query $query, ADOConnection $dbConn)
+ {
+ $arSM = $query->getSolutionModifier();
+ if ($arSM['limit'] === null && $arSM['offset'] === null) {
+ return '';
+ }
+ //this here is mysql syntax. if anyone has problems, write it
+ //dependent on $dbConn's type
+ if ($arSM['offset'] === null) {
+ return ' LIMIT ' . $arSM['limit'];
+ } else if ($arSM['limit'] === null) {
+ return ' LIMIT ' . $arSM['offset'] . ', 18446744073709551615';
+ } else {
+ return ' LIMIT ' . $arSM['offset'] . ', ' . $arSM['limit'];
+ }
+ }//public static function getLimitSql(Query $query, ADOConnection $dbConn)
+
+}//class SparqlEngineDb_Offsetter
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/text-base/Preparator.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/text-base/Preparator.php.svn-base
new file mode 100755
index 00000000..f5f5016d
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/text-base/Preparator.php.svn-base
@@ -0,0 +1,229 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlEngineDb_Preparator
+{
+
+
+
+ public function __construct(Query $query, ADOConnection $dbConn)
+ {
+ $this->query = $query;
+ $this->dbConn = $dbConn;
+ $this->arPrefixes = $this->query->getPrefixes();
+ }//public function __construct(Query $query, ADOConnection $dbConn)
+
+
+
+ /**
+ * Converts the given queries into sql prepared statments,
+ * calls the prepare command in the database and returns
+ * an array consisting of subarrays. They contain
+ * the db's prepared statement as first value, and an array
+ * of variable positions as second value (key is the position,
+ * the sparql variable is the value).
+ *
+ * @param array $arQueries Array of sql queries part arrays
+ * @param array $arPlaceholders Array of sparql (variable name =>
+ * placeholder name) pairs
+ * @return array Array of (prepared statment, variable positions) pairs
+ */
+ public function prepareInDb($arQueries, $arPlaceholders)
+ {
+ $arDbStatements = array();
+
+ foreach ($arQueries as $arQuery) {
+ list($strPrepared, $arVariablePositions) = $this->replacePlaceholders(
+ implode('', $arQuery),
+ $arPlaceholders
+ );
+ if (count($arQueries) == 1) {
+ //I currently haven't seens one case in which the count was > 1
+ //if that happens, we will need to add a fix
+ $strPrepared .= SparqlEngineDb_Offsetter::getLimitSql(
+ $this->query,
+ $this->dbConn
+ );
+ }
+ $stmt = $this->dbConn->Prepare($strPrepared);
+ $arDbStatements[] = array(
+ $stmt,
+ $arVariablePositions
+ );
+ }
+
+ return $arDbStatements;
+ }//public function prepareInDb($arQueries, $arPlaceholders)
+
+
+
+ /**
+ * Replaces the placeholders in the given SQL statement with real
+ * SQL prepared statements placeholders.
+ *
+ * @param string $strQuery SQL query with placeholders
+ * @param array $arPlaceholders Array of sparql (variable name =>
+ * placeholder name) pairs
+ * @return array (prepared sql query string, variable positions) pair
+ */
+ protected function replacePlaceholders($strQuery, $arPlaceholders)
+ {
+ $arVariablePositions = array();
+ $this->arTmpVariablePositions = array();
+ $this->arTmpPlaceholders = $arPlaceholders;
+ $strQuery = preg_replace_callback(
+ '/@\\$%_PLACEHOLDER_[0-9]+_%\\$@/',
+ array($this, 'replacePlaceholdersCb'),
+ $strQuery
+ );
+ return array($strQuery, $this->arTmpVariablePositions);
+ }//protected function replacePlaceholders($strQuery, $arPlaceholders)
+
+
+
+ /**
+ * Callback method internally used by replacePlaceholders() method.
+ */
+ protected function replacePlaceholdersCb($matches)
+ {
+ $strPlaceholder = $matches[0];
+ $strSparqlVariable = array_search(
+ $strPlaceholder,
+ $this->arTmpPlaceholders
+ );
+ $strDbPlaceholder = $this->dbConn->Param($strSparqlVariable);
+ $this->arTmpVariablePositions[] = $strSparqlVariable;
+
+ return $strDbPlaceholder;
+ }//protected function replacePlaceholdersCb($matches)
+
+
+
+ /**
+ * Executes the given prepared statments, filling the placeholders
+ * with the given values.
+ *
+ * @param array $arDbStatements Return value of prepareInDb()
+ * @param array $arVariableValues Array of (variable name, value) pairs
+ *
+ * @return array Array of database results as returned by Execute()
+ */
+ public function execute($arDbStatements, $arVariableValues)
+ {
+ $arResults = array();
+ $oldmode = $this->dbConn->SetFetchMode(ADODB_FETCH_ASSOC);
+
+ foreach ($arDbStatements as $arStatement) {
+ list($stmt, $arVariablePositions) = $arStatement;
+ $arVariables = $this->createVariableArray(
+ $arVariablePositions,
+ $arVariableValues
+ );
+ $arResults[] = $this->dbConn->Execute($stmt, $arVariables);
+ }
+
+ $this->dbConn->SetFetchMode($oldmode);
+
+ return $arResults;
+ }//public function execute($arDbStatements, $arVariableValues)
+
+
+
+ /**
+ * Creates an array full of variables to be passed to the Execute() method
+ * of the database connection object.
+ * Uses the variable positions array to get the positions of the variables
+ * in the result array, and the variable value array to get the actual
+ * values for the prepared statement.
+ *
+ * @param array $arVariablePositions Positions of the variables as returned
+ * by replacePlaceholders().
+ * @param array $arVariableValues Array of (variable name, value) pairs
+ *
+ * @return array Array of variable values
+ */
+ protected function createVariableArray($arVariablePositions, $arVariableValues)
+ {
+ $arVariables = array();
+
+ foreach ($arVariablePositions as $nPos => $strVariable) {
+ if (!isset($arVariableValues[$strVariable])) {
+ throw new Exception('No value for variable "' . $strVariable . '" in prepared statement');
+ }
+
+ $strValue = self::replacePrefix(
+ $arVariableValues[$strVariable],
+ $this->arPrefixes
+ );
+
+ $arVariables[$nPos] = $strValue;
+ }
+
+ return $arVariables;
+ }//protected function createVariableArray($arVariablePositions, $arVariableValues)
+
+
+
+ /**
+ * Replaces all placeholders with their actual values.
+ */
+ public function replacePlaceholdersWithVariables($strQuery, $arPlaceholders, $arVariableValues)
+ {
+ $this->arTmpPlaceholders = $arPlaceholders;
+ $this->arTmpVariableValues = $arVariableValues;
+
+ $strQuery = preg_replace_callback(
+ '/@\\$%_PLACEHOLDER_[0-9]+_%\\$@/',
+ array($this, 'replacePlaceholdersWithVariablesCb'),
+ $strQuery
+ );
+
+ return $strQuery;
+ }//public function replacePlaceholdersWithVariables($strQuery, $arPlaceholders, $arVariableValues)
+
+
+
+ /**
+ * Callback method internally used by
+ * replacePlaceholdersWithVariables() method.
+ */
+ protected function replacePlaceholdersWithVariablesCb($matches)
+ {
+ $strPlaceholder = $matches[0];
+ $strSparqlVariable = array_search(
+ $strPlaceholder,
+ $this->arTmpPlaceholders
+ );
+ return $this->dbConn->qstr(
+ self::replacePrefix(
+ $this->arTmpVariableValues[$strSparqlVariable],
+ $this->arPrefixes
+ )
+ );
+ }//protected function replacePlaceholdersWithVariablesCb($matches)
+
+
+
+ protected static function replacePrefix($strValue, $arPrefixes)
+ {
+ //replace prefixes?
+ if (count($arParts = explode(':', $strValue, 2)) == 2) {
+ if (isset($arPrefixes[$arParts[0]])) {
+ $strValue = $arPrefixes[$arParts[0]] . $arParts[1];
+ }
+ }
+ return $strValue;
+ }//protected static function replacePrefix($strValue, $arPrefixes)
+
+}//class SparqlEngineDb_Preparator
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/text-base/PreparedStatement.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/text-base/PreparedStatement.php.svn-base
new file mode 100755
index 00000000..c7c03413
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/text-base/PreparedStatement.php.svn-base
@@ -0,0 +1,38 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlEngineDb_PreparedStatement extends SparqlEngine_PreparedStatement
+{
+ protected $sparqlEngine = null;
+
+
+ public function __construct(SparqlEngineDb $sparqlEngine)
+ {
+ $this->sparqlEngine = $sparqlEngine;
+ }//public function __construct(SparqlEngineDb $sparqlEngine)
+
+
+
+ /**
+ * Execute the prepared statement and returns the result.
+ *
+ * @param array $arVariables Array of sparql query variables => values
+ * @param string $resultform Which result form you need
+ * @return mixed Anything a sparql query can return
+ */
+ public function execute($arVariables, $resultform = false)
+ {
+ return $this->sparqlEngine->execute($arVariables, $resultform);
+ }//public function execute($arVariables, $resultform)
+
+}//class SparqlEngineDb_PreparedStatement extends SparqlEngine_PreparedStatement
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/text-base/QuerySimplifier.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/text-base/QuerySimplifier.php.svn-base
new file mode 100755
index 00000000..2988fd98
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/text-base/QuerySimplifier.php.svn-base
@@ -0,0 +1,169 @@
+ 'asd'}
+* UNION
+* {?person3 'three'}
+* }
+* is represented internally as three graph patterns, the latter
+* two referencing the first to be their pattern (they are subpatternOf).
+* Now this can be flattened to this which is the same:
+* {?g ?h ?i . ?person 'asd'}
+* UNION
+* {?g ?h ?i .?person3 'three'}
+*
+* This class does this.
+*
+* @author Christian Weiske
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*/
+class SparqlEngineDb_QuerySimplifier
+{
+
+ /**
+ * Simplify the query by flattening out subqueries.
+ * Modifies the passed query object directly.
+ */
+ public function simplify(Query $query)
+ {
+ $arPatterns = $query->getResultPart();
+ self::dropEmpty($arPatterns);
+ $arPlan = $this->createPlan($arPatterns);
+ if (count($arPlan) == 0) {
+ $query->setResultPart($arPatterns);
+ return 0;
+ }
+
+ $this->executePlan($arPatterns, $arPlan);
+ $query->setResultPart($arPatterns);
+ }//public function simplify(Query $query)
+
+
+
+ /**
+ * Creates a plan what to do.
+ *
+ * @return array Array of arrays. Key is the parent pattern id,
+ * value is an array of subpatterns that belong to
+ * that parental pattern.
+ */
+ protected function createPlan(&$arPatterns)
+ {
+ $arNumbers = $this->getNumbers($arPatterns);
+ if (count($arNumbers) == 0) {
+ return array();
+ }
+
+ $arPlan = array();
+
+ foreach ($arNumbers as $nId => $nPatternCount) {
+ $nParent = $arPatterns[$nId]->getSubpatternOf();
+ $arPlan[$nParent][$nId] = true;
+ }
+
+ return $arPlan;
+ }//protected function createPlan(&$arPatterns)
+
+
+
+ /**
+ * Executes the plan
+ *
+ * @param array $arPatterns Array of GraphPatterns
+ * @param array $arPlan Plan array as returned by createPlan()
+ */
+ protected function executePlan(&$arPatterns, &$arPlan)
+ {
+ foreach ($arPlan as $nParent => $arChildren) {
+ $base = $arPatterns[$nParent];
+ $grandParent = $base->getSubpatternOf();
+ $nNextId = $nParent;
+ foreach ($arChildren as $nChild => $null) {
+ $new = clone $base;
+ $new->addTriplePatterns($arPatterns[$nChild]->getTriplePatterns());
+ $new->addConstraints( $arPatterns[$nChild]->getConstraints());
+ $new->setId($nNextId);
+ if ($nParent != $nNextId) {
+ $new->setUnion($nParent);
+ }
+ $arPatterns[$nNextId] = $new;
+
+ if ($grandParent !== null) {
+ //dynamically adjust plan
+ $arPlan[$grandParent][$nNextId] = true;
+ }
+
+ $nNextId = $nChild;
+ }
+ //last one is not not needed anymore
+ unset($arPatterns[$nNextId]);
+ }
+ }//protected function executePlan(&$arPatterns, &$arPlan)
+
+
+
+ /**
+ * Returns an array of id-value pairs determining
+ * which pattern IDs (array id) are deepest nested
+ * (higher value).
+ * Array is sorted in reverse order, highest values
+ * first.
+ *
+ * @param array $arPatterns Array with GraphPatterns
+ * @return array Array with key-value pairs
+ */
+ protected function getNumbers(&$arPatterns)
+ {
+ $arNumbers = array();
+ foreach ($arPatterns as $nId => &$pattern) {
+ $nParent = $pattern->getSubpatternOf();
+ if ($nParent !== null) {
+ $arNumbers[$nId] = $arNumbers[$nParent] + 1;
+ } else {
+ $arNumbers[$nId] = 0;
+ }
+ }
+ //remove the not so interesting ones
+ foreach ($arNumbers as $nId => $nNumber) {
+ if ($nNumber == 0) {
+ unset($arNumbers[$nId]);
+ }
+ }
+
+ arsort($arNumbers);
+
+ return $arNumbers;
+ }//protected function getNumbers(&$arPatterns)
+
+
+
+ /**
+ * Removes all empty graph patterns from the array.
+ * Modifies it directly.
+ */
+ protected static function dropEmpty(&$arPatterns)
+ {
+ foreach ($arPatterns as $nId => &$pattern) {
+ if ($pattern->isEmpty()) {
+ unset($arPatterns[$nId]);
+ }
+ }
+
+ foreach ($arPatterns as $nId => &$pattern) {
+ $nParent = $pattern->getSubpatternOf();
+ if (!isset($arPatterns[$nParent])) {
+ $arPatterns[$nId]->setSubpatternOf(null);
+ }
+ }
+ //FIXME: continued indexes?
+ }//protected static function dropEmpty(&$arPatterns)
+
+}//class SparqlEngineDb_QuerySimplifier
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/text-base/ResultConverter.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/text-base/ResultConverter.php.svn-base
new file mode 100755
index 00000000..875b47e0
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/text-base/ResultConverter.php.svn-base
@@ -0,0 +1,115 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlEngineDb_ResultConverter
+{
+ /**
+ * Determines the correct renderer and calls it.
+ *
+ * The $resultform may be:
+ * - false: The default renderer is taken then
+ * - an object that implements SparqlEngineDb_ResultRenderer interface
+ * - a string like "HTML" or "XML". The appropriate renderer is used then.
+ * - a full class name, e.g. SparqlEngineDb_ResultRenderer_XML
+ *
+ * @param array $arRecordSets Array of anything ADOConnection::Execute() can return
+ * @param SparqlEngineDb $engine Sparql database engine.
+ * @param mixed $resultform Which format the results shall be in (false or "xml")
+ *
+ * @return mixed Most likely an array or a boolean value,
+ * or anything else as determined by $resultform
+ */
+ public static function convertFromDbResults($arRecordSets, SparqlEngineDb $engine, $resultform = false)
+ {
+ if (is_object($resultform)) {
+ if ($resultform instanceof SparqlEngineDb_ResultRenderer) {
+ return $resultform->convertFromDbResults(
+ $arRecordSets,
+ $engine->getQuery(),
+ $engine
+ );
+ } else {
+ throw new Exception(
+ 'Result renderer object needs to implement'
+ . ' SparqlEngineDb_ResultRenderer interface'
+ );
+ }
+ }
+
+ if ($resultform === false) {
+ $resultform = 'Default';
+ } else if ($resultform == 'xml') {
+ //kept for BC reasons
+ $resultform = 'XML';
+ }
+
+ if ($strClass = self::loadClass($resultform)) {
+ $rrObj = new $strClass();
+ if ($rrObj instanceof SparqlEngineDb_ResultRenderer) {
+ return $rrObj->convertFromDbResults(
+ $arRecordSets,
+ $engine->getQuery(),
+ $engine
+ );
+ } else {
+ throw new Exception(
+ 'Result renderer class "' . $strClass . '" needs to implement'
+ . ' SparqlEngineDb_ResultRenderer interface'
+ );
+ }
+ } else {
+ throw new Exception(
+ 'Result renderer class "' . $resultform . '" could not be loaded.'
+ );
+ }
+ }//public static function convertFromDbResults($arRecordSets, SparqlEngineDb $engine, $resultform = false)
+
+
+
+ /**
+ * Tries to load a given class if it doesn't exist,
+ * and returns true if the class can be used.
+ *
+ * @param string $strClass Classname
+ * @return mixed Class name if the class is loaded and can be used, false if not.
+ */
+ protected static function loadClass($strClass)
+ {
+ if (class_exists($strClass, false)) {
+ return $strClass;
+ }
+
+ //RAP style, shortcut notation
+ $strFile = 'SparqlEngineDb/ResultRenderer/' . $strClass . '.php';
+ @include_once RDFAPI_INCLUDE_DIR . 'sparql/' . $strFile;
+ if (class_exists('SparqlEngineDb_ResultRenderer_' . $strClass, false)) {
+ return 'SparqlEngineDb_ResultRenderer_' . $strClass;
+ }
+
+ //RAP style
+ $strFile = str_replace('_', '/', $strClass) . '.php';
+ @include_once RDFAPI_INCLUDE_DIR . 'sparql/' . $strFile;
+ if (class_exists($strClass, false)) {
+ return $strClass;
+ }
+
+ //PEAR style
+ @include_once $strFile;
+ if (class_exists($strClass, false)) {
+ return $strClass;
+ }
+
+ return false;
+ }//protected static function loadClass($strClass)
+
+}//class SparqlEngineDb_ResultConverter
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/text-base/ResultRenderer.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/text-base/ResultRenderer.php.svn-base
new file mode 100755
index 00000000..7714b781
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/text-base/ResultRenderer.php.svn-base
@@ -0,0 +1,29 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+interface SparqlEngineDb_ResultRenderer
+{
+ /**
+ * Converts the database results into the desired output format
+ * and returns the result.
+ *
+ * @param array $arRecordSets Array of (possibly several) SQL query results.
+ * @param Query $query SPARQL query object
+ * @param SparqlEngineDb $engine Sparql Engine to query the database
+ * @return mixed The result as rendered by the result renderers.
+ */
+ public function convertFromDbResults($arRecordSets, Query $query, SparqlEngineDb $engine);
+
+}//interface SparqlEngineDb_ResultRenderer
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/text-base/SqlGenerator.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/text-base/SqlGenerator.php.svn-base
new file mode 100755
index 00000000..3794c110
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/text-base/SqlGenerator.php.svn-base
@@ -0,0 +1,999 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlEngineDb_SqlGenerator
+{
+ public $query = null;
+
+ /**
+ * Determines which variables can be found
+ * in which SQL result column.
+ * @example
+ * array(
+ * '?person' => array('t1', 's'),
+ ' '?p' => array('t1', 'p'),
+ * '?mbox' => array('t2', 'o')
+ * )
+ * Would express that variable ?person is the subject
+ * in result table t1, and ?mbox is the object in
+ * table t2.
+ *
+ * @see $arCreationMethods
+ *
+ * @internal The array is created in createSql()
+ * and used in convertFromDbResult().
+ *
+ * @var array
+ */
+ public $arVarAssignments = array();
+
+ /**
+ * Array of variable name => table.col assignments
+ * for all variables used in the query not only
+ * the ones that shall be returned.
+ *
+ * @example
+ * array(
+ * '?person' => 't0.subject'
+ * )
+ *
+ * @var array
+ */
+ public $arUsedVarAssignments = array();
+
+ /**
+ * Array of arrays that contain all variable names
+ * which are to be found in the result of
+ * an sql statement in a union.
+ *
+ * @example
+ * array(
+ * 0 => array(
+ * '?person' => 's',
+ * '?p' => 'o'
+ * ),
+ * 1 => array(
+ * '?person' => 's',
+ * '?mbox' => 'o'
+ * )
+ * )
+ *
+ * @var array
+ */
+ public $arUnionVarAssignments = array();
+
+ /**
+ * Which variables have been used as which type?
+ * key is variable name, value is an array of
+ * max. three keys (s, p, o)
+ *
+ * @example
+ * array(
+ * '?person' => array(
+ * 's' => true
+ * ),
+ * '?mbox' => array(
+ * 'o' => true
+ * )
+ * )
+ *
+ * @var array
+ */
+ protected $arUsedVarTypes = array();
+
+ /**
+ * Array with placeholders of prepared statements variables.
+ * key is the variable name (without "??"), value is the
+ * placeholder.
+ * @var array
+ */
+ protected $arPlaceholders = array();
+
+ /**
+ * Column names for subjects, predicates and
+ * objects for easy access via their character
+ * names (spo).
+ *
+ * @var array
+ */
+ public static $arTableColumnNames = array(
+ 's' => array(
+ 'value' => 'subject',
+ 'is' => 'subject_is'
+ ),
+ 'p' => array(
+ 'value' => 'predicate'
+ ),
+ 'o' => array(
+ 'value' => 'object',
+ 'is' => 'object_is'
+ )
+ );
+
+ /**
+ * Current UNION part number
+ * @var int
+ */
+ protected $nUnionCount = 0;
+
+ protected $nSqlVariableNameCount = 0;
+
+ /**
+ * Name of the statements table
+ */
+ protected $tblStatements = 'statements';
+
+
+
+ public function __construct(Query $query, ADOConnection $dbConn, $arModelIds)
+ {
+ $this->query = $query;
+ $this->dbConn = $dbConn;
+ $this->arModelIds = $arModelIds;
+ }//public function __construct(Query $query, ADOConnection $dbConn, $arModelIds)
+
+
+
+ /**
+ * Creates an SQL query string from the given Sparql query object.
+ *
+ * @internal uses $query variable
+ *
+ * @return array Array of arrays of SQL query string parts: select, from and where
+ *
+ * @throws SparqlEngineDb_SqlGeneratorException If there is no variable in the result set.
+ */
+ function createSql()
+ {
+//var_dump($this->query);
+ $arSelect = array();
+ $arFrom = array();
+ $arWhere = array();
+
+ $strResultForm = $this->query->getResultForm();
+ $filterGen = new SparqlEngineDb_FilterGenerator($this);
+ switch ($strResultForm) {
+ case 'construct':
+ $arResultVars = $this->query->getConstructPatternVariables();
+ break;
+ default:
+ $arResultVars = $this->query->getResultVars();
+ break;
+ }
+
+ $this->nTableId = 0;
+ $this->nGraphPatternCount = 0;
+ $this->nUnionCount = 0;
+ $this->nUnionTriplePatternCount = 0;
+ $this->arUnionVarAssignments[0] = array();
+
+ foreach ($this->query->getResultPart() as $graphPattern) {
+ if ($graphPattern->isEmpty()) {
+ continue;
+ }
+ if ($graphPattern->getUnion() !== null) {
+ ++$this->nUnionCount;
+ $this->nTableId = 0;
+ $this->nUnionTriplePatternCount = 0;
+ $this->nGraphPatternCount = 0;
+ $this->arUnionVarAssignments[$this->nUnionCount] = array();
+ }
+ $this->nTriplePatternCount = 0;
+ $arTriplePattern = $graphPattern->getTriplePatterns();
+ if ($arTriplePattern != null) {
+ foreach ($arTriplePattern as $triplePattern) {
+ list (
+ $arSelect[$this->nUnionCount][],
+ $arFrom [$this->nUnionCount][],
+ $arWhere [$this->nUnionCount][]
+ ) =
+ $this->getTripleSql(
+ $triplePattern,
+ $graphPattern,
+ $arResultVars
+ );
+ ++$this->nTableId;
+ ++$this->nTriplePatternCount;
+ ++$this->nUnionTriplePatternCount;
+ }
+ }
+ ++$this->nGraphPatternCount;
+
+ }
+
+ //constraints extra. needed, since OPTIONAL parts are put after
+ // the current pattern while the constraint already refers to variables
+ // defined in there
+ $this->nGraphPatternCount = 0;
+ $this->nUnionCount = 0;
+ foreach ($this->query->getResultPart() as $graphPattern) {
+ if ($graphPattern->getUnion() !== null) {
+ ++$this->nUnionCount;
+ }
+ $arConstraints = $graphPattern->getConstraints();
+ if ($arConstraints != null) {
+ foreach ($arConstraints as $constraint) {
+ $arWhere[$this->nUnionCount][count($arWhere[$this->nUnionCount]) - 1]
+ .= $filterGen->createFilterSql(
+ $constraint->getTree(),
+ $graphPattern->getOptional() !== null,
+ $this->nUnionCount
+ );
+ }
+ }
+ ++$this->nGraphPatternCount;
+ }
+
+ $arSelect = $this->createEqualSelects($arSelect);
+ $arStrSelect = array();
+
+ switch ($strResultForm) {
+ case 'construct':
+ case 'describe':
+ $strSelectType = 'SELECT';
+ case 'select':
+ case 'select distinct':
+ if (!isset($strSelectType)) {
+ $strSelectType = $strResultForm;
+ }
+ foreach ($arSelect as $nUnionCount => $arSelectPart) {
+ $arSelectPart = self::removeNull($arSelectPart);
+ if (count($arSelectPart) == 0
+ || (count($arSelectPart) == 1 && $arSelectPart[0] == '')) {
+ //test "test-1-07" suggests we return no rows in this case
+ //throw new SparqlEngineDb_SqlGeneratorException('No variable that could be returned.');
+ } else {
+ $arStrSelect[$nUnionCount] = strtoupper($strSelectType) . ' ' . implode(', ' , $arSelectPart);
+ }
+ }
+ break;
+
+ case 'ask':
+ case 'count':
+ $arStrSelect = array('SELECT COUNT(*) as count');
+ break;
+
+ default:
+ throw new SparqlEngineDb_SqlGeneratorException('Unsupported query type "' . $strResultForm . '"');
+ break;
+ }
+
+ $arSqls = array();
+ foreach ($arStrSelect as $nUnionCount => $arSelectPart) {
+ $arSqls[] = array(
+ 'select' => $arStrSelect[$nUnionCount],
+ 'from' => ' FROM ' . implode(' ' , self::removeNull($arFrom[$nUnionCount])),
+ 'where' => ' WHERE ' . self::fixWhere(
+ implode(' ' , self::removeNull($arWhere[$nUnionCount]))
+ )
+ );
+ }
+ return $arSqls;
+ }//function createSql()
+
+
+
+ /**
+ * Creates some SQL statements from the given triple pattern
+ * array.
+ *
+ * @param QueryTriple $triple Array containing subject, predicate and object
+ * @param GraphPattern $graphPattern Graph pattern object
+ *
+ * @return array Array consisting of on array and two string values:
+ * SELECT, FROM and WHERE part
+ */
+ function getTripleSql(QueryTriple $triple, GraphPattern $graphPattern, $arResultVars)
+ {
+ $arSelect = array();
+ $strFrom = null;
+ $strWhere = null;
+ $strWhereEquality = '';
+ $bWhereEqualitySubject = false;
+ $bWhereEqualityPredicate = false;
+ $bWhereEqualityObject = false;
+
+ $subject = $triple->getSubject();
+ $predicate = $triple->getPredicate();
+ $object = $triple->getObject();
+
+ $arRefVars = array();
+ $strTablePrefix = 't' . $this->nTableId;
+
+ /**
+ * SELECT part
+ * We do select only the columns we need for variables
+ */
+ if (SparqlVariable::isVariable($subject)) {
+ if (isset($this->arUnionVarAssignments[$this->nUnionCount][$subject])) {
+ //already selected -> add equality check
+ $bWhereEqualitySubject = true;
+ $this->arUsedVarTypes[$subject]['s'] = true;
+ } else {
+ if (isset($this->arVarAssignments[$subject][0])) {
+ $strTablePrefix = $this->arVarAssignments[$subject][0];
+ }
+ $this->arVarAssignments[$subject] = array($strTablePrefix, 's');
+ $this->arUnionVarAssignments[$this->nUnionCount][$subject] = array($strTablePrefix, 's');
+ $this->arUsedVarTypes[$subject]['s'] = true;
+ if (self::isResultVar($subject, $arResultVars)) {
+ //new variable that needs to be selected
+ $arSelect[$subject] = $this->createVariableSelectArray(
+ 's', $subject, $strTablePrefix
+ );
+ if (isset($this->arUsedVarAssignments[$subject])) {
+ $arRefVars[$subject] = $strTablePrefix . '.subject';
+ } else {
+ $this->arUsedVarAssignments[$subject] = $strTablePrefix . '.subject';
+ }
+ }
+ }
+ }
+
+ if (SparqlVariable::isVariable($predicate)) {
+ if (isset($this->arUnionVarAssignments[$this->nUnionCount][$predicate])) {
+ //already selected -> add equality check
+ $bWhereEqualityPredicate = true;
+ $this->arUsedVarTypes[$predicate]['p'] = true;
+ } else {
+ if (isset($this->arVarAssignments[$predicate][0])) {
+ $strTablePrefix = $this->arVarAssignments[$predicate][0];
+ }
+ $this->arVarAssignments[$predicate] = array($strTablePrefix, 'p');
+ $this->arUnionVarAssignments[$this->nUnionCount][$predicate] = array($strTablePrefix, 'p');
+ $this->arUsedVarTypes[$predicate]['p'] = true;
+ if (self::isResultVar($predicate, $arResultVars)) {
+ $arSelect[$predicate] = $this->createVariableSelectArray(
+ 'p', $predicate, $strTablePrefix
+ );
+ if (isset($this->arUsedVarAssignments[$predicate])) {
+ $arRefVars[$predicate] = $strTablePrefix . '.predicate';
+ } else {
+ $this->arUsedVarAssignments[$predicate] = $strTablePrefix . '.predicate';
+ }
+ }
+ }
+ }
+
+ if (SparqlVariable::isVariable($object)) {
+ if (isset($this->arUnionVarAssignments[$this->nUnionCount][$object])) {
+ //already selected -> add equality check
+ $bWhereEqualityObject = true;
+ $this->arUsedVarTypes[$object]['o'] = true;
+ } else {
+ if (isset($this->arVarAssignments[$object][0])) {
+ $strTablePrefix = $this->arVarAssignments[$object][0];
+ }
+ $this->arVarAssignments[$object] = array($strTablePrefix, 'o');
+ $this->arUnionVarAssignments[$this->nUnionCount][$object] = array($strTablePrefix, 'o');
+ $this->arUsedVarTypes[$object]['o'] = true;
+ if (self::isResultVar($object, $arResultVars)) {
+ $arSelect[$object] = $this->createVariableSelectArray(
+ 'o', $object, $strTablePrefix
+ );
+ if (isset($this->arUsedVarAssignments[$object])) {
+ $arRefVars[$object] = $strTablePrefix . '.object';
+ } else {
+ $this->arUsedVarAssignments[$object] = $strTablePrefix . '.object';
+ }
+ }
+ if (isset($this->query->varLanguages[$object])
+ && $this->query->varLanguages[$object] !== null
+ ) {
+ $strWhereEquality .=
+ ' AND ' . $strTablePrefix . '.l_language = "'
+ . addslashes($this->query->varLanguages[$object]) . '"';
+ }
+ if (isset($this->query->varDatatypes[$object])
+ && $this->query->varDatatypes[$object] !== null
+ ) {
+ $strWhereEquality .=
+ ' AND ' . $strTablePrefix . '.l_datatype = "'
+ . addslashes($this->query->varDatatypes[$object]) . '"';
+ }
+ }
+ }
+
+ /**
+ * WhereEquality - needs to be done now because strTablePrefix may change
+ */
+ if ($bWhereEqualitySubject) {
+ $strWhereEquality .= ' AND ' . self::getSqlEqualityCondition(
+ array($strTablePrefix, 's'),
+ $this->arVarAssignments[$subject]
+ );
+ }
+ if ($bWhereEqualityPredicate) {
+ $strWhereEquality .= ' AND ' . self::getSqlEqualityCondition(
+ array($strTablePrefix, 'p'),
+ $this->arVarAssignments[$predicate]
+ );
+ }
+ if ($bWhereEqualityObject) {
+ $strWhereEquality .= ' AND ' . self::getSqlEqualityCondition(
+ array($strTablePrefix, 'o'),
+ $this->arVarAssignments[$object]
+ );
+ }
+
+
+ /**
+ * FROM part
+ */
+ if ($this->nUnionTriplePatternCount == 0) {
+ //first FROM
+ $strFrom = $this->tblStatements . ' as ' . $strTablePrefix;
+ } else {
+ //normal join
+ if (count($this->arModelIds) == 1) {
+ $strFrom = 'LEFT JOIN ' . $this->tblStatements . ' as ' . $strTablePrefix
+ . ' ON t0.modelID = ' . $strTablePrefix . '.modelID';
+ } else if (count($this->arModelIds) > 1) {
+ $arIDs = array();
+ foreach ($this->arModelIds as $nId) {
+ $arIDs[] = $strTablePrefix . '.modelID = ' . intval($nId);
+ }
+ $strFrom = 'LEFT JOIN ' . $this->tblStatements . ' as ' . $strTablePrefix
+ . ' ON (' . implode(' OR ', $arIDs) . ')';
+ } else {
+ $strFrom = 'LEFT JOIN ' . $this->tblStatements . ' as ' . $strTablePrefix
+ . ' ON t0.modelID = ' . $strTablePrefix . '.modelID';
+ }
+
+ foreach ($arRefVars as $strRefVar => $strSqlVar) {
+ $strFrom .= ' AND ' . $this->arUsedVarAssignments[$strRefVar] . ' = ' . $strSqlVar;
+ }
+
+ if ($graphPattern->getOptional() !== null) {
+ $strFrom .= $this->getSqlCondition($subject , $strTablePrefix, 'subject')
+ . $this->getSqlCondition($predicate, $strTablePrefix, 'predicate')
+ . $this->getSqlCondition($object , $strTablePrefix, 'object')
+ . $strWhereEquality;
+ }
+ }
+
+
+ /**
+ * WHERE part
+ */
+ if ($this->nUnionTriplePatternCount == 0) {
+ if (count($this->arModelIds) == 1) {
+ $strWhere = $strTablePrefix . '.modelID = ' . intval(reset($this->arModelIds));
+ } else if (count($this->arModelIds) > 1) {
+ $arIDs = array();
+ foreach ($this->arModelIds as $nId) {
+ $arIDs[] = $strTablePrefix . '.modelID = ' . intval($nId);
+ }
+ $strWhere = '(' . implode(' OR ', $arIDs) . ')';
+ } else {
+ //so that we can append an AND
+ $strWhere = '1';
+ }
+ }
+ if ($graphPattern->getOptional() === null || $this->nGraphPatternCount == 0) {
+ $strWhere .= $this->getSqlCondition($subject , $strTablePrefix, 'subject')
+ . $this->getSqlCondition($predicate, $strTablePrefix, 'predicate')
+ . $this->getSqlCondition($object , $strTablePrefix, 'object')
+ . $strWhereEquality;
+ }
+
+ return array($arSelect, $strFrom, $strWhere);
+ }//function getTripleSql(QueryTriple $triple)
+
+
+
+
+ protected function createVariableSelectArray($chType, $varname, $strTablePrefix)
+ {
+ $var = $this->query->getResultVar($varname);
+ if ($var !== false) {
+ if ((string)$var != $varname) {
+ //copy over var assignments
+ $this->arVarAssignments[(string)$var] = $this->arVarAssignments[$varname];
+ }
+
+ //works on non-* only
+ $func = $var->getFunc();
+ if ($func != null) {
+ if ($func == 'datatype') {
+ if ($chType != 'o') {
+ throw new SparqlEngineDb_SqlGeneratorException(
+ 'datatype() works on objects only'
+ );
+ }
+ return array(
+ $strTablePrefix . '.l_datatype as "' . $strTablePrefix . '.' . $this->getSqlVariableNameValue($var) . '"',
+ '"r"' . ' as "' . $strTablePrefix . '.' . $this->getSqlVariableNameIs($var) . '"',
+ '""' . ' as "' . $strTablePrefix . '.' . $this->getSqlVariableNameLanguage($var) . '"',
+ '""' . ' as "' . $strTablePrefix . '.' . $this->getSqlVariableNameDatatype($var) . '"',
+ );
+ } else if ($func == 'lang') {
+ if ($chType != 'o') {
+ throw new SparqlEngineDb_SqlGeneratorException(
+ 'lang() works on objects only'
+ );
+ }
+ return array(
+ $strTablePrefix . '.l_language as "' . $strTablePrefix . '.' . $this->getSqlVariableNameValue($var) . '"',
+ '"l"' . ' as "' . $strTablePrefix . '.' . $this->getSqlVariableNameIs($var) . '"',
+ '""' . ' as "' . $strTablePrefix . '.' . $this->getSqlVariableNameLanguage($var) . '"',
+ '""' . ' as "' . $strTablePrefix . '.' . $this->getSqlVariableNameDatatype($var) . '"',
+ );
+ } else {
+ throw new SparqlEngineDb_SqlGeneratorException(
+ 'Unsupported function for select "' . $func . '"'
+ );
+ }
+ }
+ }
+
+ switch ($chType) {
+ case 's':
+ return array(
+ $strTablePrefix . '.subject as "' . $strTablePrefix . '.' . $this->getSqlVariableNameValue($varname) . '"',
+ $strTablePrefix . '.subject_is as "' . $strTablePrefix . '.' . $this->getSqlVariableNameIs($varname) . '"'
+ );
+ case 'p':
+ return array(
+ $strTablePrefix . '.predicate as "' . $strTablePrefix . '.' . $this->getSqlVariableNameValue($varname) . '"'
+ );
+ case 'o':
+ return array(
+ $strTablePrefix . '.object as "' . $strTablePrefix . '.' . $this->getSqlVariableNameValue($varname) . '"',
+ $strTablePrefix . '.object_is as "' . $strTablePrefix . '.' . $this->getSqlVariableNameIs($varname) . '"',
+ $strTablePrefix . '.l_language as "' . $strTablePrefix . '.' . $this->getSqlVariableNameLanguage($varname) . '"',
+ $strTablePrefix . '.l_datatype as "' . $strTablePrefix . '.' . $this->getSqlVariableNameDatatype($varname) . '"',
+ );
+ default:
+ throw new SparqlEngineDb_SqlGeneratorException(
+ 'Unknown sentence type "' . $chType . "', one of (s,p,o) expected"
+ );
+ }
+ }//protected function createVariableSelectArray($chType, $value, $strTablePrefix)
+
+
+
+ /**
+ * Creates SELECT statements that have the same number of columns.
+ * Needed for UNIONs.
+ *
+ * @param array $arSelect Array of arrays.
+ * array(
+ * //for each union part one
+ * 0 => array(
+ * //foreach triple pattern
+ * 0 => array(
+ * '?person' => array(
+ * 't0.subject as "t0.subject"'
+ * )
+ * )
+ * )
+ * )
+ * @return array Array of SELECT strings
+ */
+ protected function createEqualSelects($arSelect)
+ {
+ $arNewSelect = array();
+ if (count($arSelect) == 1) {
+ if ($arSelect[0] == array(array())) {
+ //ASK and COUNT
+ return array(array(''));
+ }
+
+ foreach ($arSelect[0] as $arTripleVars) {
+ $ar = array();
+ foreach ($arTripleVars as $arVarParts) {
+ $ar[] = implode(', ', $arVarParts);
+ }
+ if (count($ar) > 0) {
+ $arNewSelect[0][] = implode(', ', $ar);
+ }
+ }
+ return $arNewSelect;
+ }
+
+ $arVars = array();
+ foreach ($arSelect as $arUnionVars) {
+ foreach ($arUnionVars as $arTripleVars) {
+ $arVars = array_merge($arVars, array_keys($arTripleVars));
+ }
+ }
+ $arVars = array_unique($arVars);
+
+ foreach ($arSelect as $nUnionCount => $arUnionVars) {
+ $arSelectVars = array();
+ foreach ($arUnionVars as $arTripleVars) {
+ foreach ($arTripleVars as $strVar => $arVarParts) {
+ $arSelectVars[$strVar] = $arVarParts;
+ }
+ }
+
+ $ars = array();
+ foreach ($arVars as $strVar) {
+ if (isset($arSelectVars[$strVar])) {
+ $ar = $arSelectVars[$strVar];
+ $nCount = count($arSelectVars[$strVar]);
+ } else {
+ $ar = array();
+ $nCount = 0;
+ }
+
+ if ($nCount == 0) {
+ //nothing of this variable in this union part
+ $ar[] = 'NULL as '
+ . '"' . $this->arVarAssignments[$strVar][0] . '.' . $this->arVarAssignments[$strVar]['sql_value'] . '"';
+ }
+ if ((
+ isset($this->arUsedVarTypes[$strVar]['o'])
+ || isset($this->arUsedVarTypes[$strVar]['s'])
+ ) && $nCount < 2
+ ) {
+ //it's a subject or object, but we don't want the type
+ $ar[] = 'NULL as '
+ . '"' . $this->arVarAssignments[$strVar][0] . '.' . $this->arVarAssignments[$strVar]['sql_is'] . '"';
+ }
+ if (isset($this->arUsedVarTypes[$strVar]['o']) && $nCount < 4) {
+ //it's a subject or object, but we don't want the type
+ if (isset($this->arVarAssignments[$strVar]['sql_lang'])) {
+ $strColLanguage = $this->arVarAssignments[$strVar]['sql_lang'];
+ } else {
+ $strColLanguage = 'dummyLang';
+ }
+ if (isset($this->arVarAssignments[$strVar]['sql_type'])) {
+ $strColDatatype = $this->arVarAssignments[$strVar]['sql_type'];
+ } else {
+ $strColDatatype = 'dummyType';
+ }
+ $ar[] = 'NULL as '
+ . '"' . $this->arVarAssignments[$strVar][0] . '.' . $strColLanguage . '"';
+ $ar[] = 'NULL as '
+ . '"' . $this->arVarAssignments[$strVar][0] . '.' . $strColDatatype . '"';
+ }
+ $ars[] = implode(', ', $ar);
+ }
+ $arNewSelect[$nUnionCount] = $ars;
+ }
+
+ return $arNewSelect;
+ }//protected function createEqualSelects($arSelect)
+
+
+
+ /**
+ * Creates an SQL statement that checks for the value
+ * of some subject/predicate/object
+ *
+ * @param mixed $bject subject|predicate|object
+ * @param string $strTablePrefix Table prefix (e.g. "t0")
+ * @param string $strType Type of $bject ('subject'|'predicate'|'object')
+ * @return string Part of the SQL query (prefixed with AND)
+ */
+ function getSqlCondition($bject, $strTablePrefix, $strType)
+ {
+ if (is_string($bject)) {
+ if (SparqlVariable::isVariable($bject)) {
+ //variable?
+ if (self::isPreparedVariable($bject)) {
+ //no, not really
+ $value = $this->getPreparedVariablePlaceholder($bject);
+ } else {
+ //yes
+ return null;
+ }
+ } else {
+ $value = $this->dbConn->qstr($bject);
+ }
+ //literal
+ return ' AND ' . $strTablePrefix . '.' . $strType . ' = ' . $value;
+ }
+
+ if ($bject instanceof BlankNode) {
+ //Blank node
+ throw new SparqlEngineDb_SqlGeneratorException(
+ 'FIXME: Querying for blank nodes not supported'
+ );
+
+ } else if ($bject instanceof Resource) {
+ //Resource
+ $r = ' AND ' . $strTablePrefix . '.' . $strType . ' = '
+ . $this->dbConn->qstr($bject->getURI());
+ if ($strType !== 'predicate') {
+ $r .= ' AND ' . $strTablePrefix . '.' . $strType . '_is ='
+ . ' "r"';
+ }
+ return $r;
+
+ } else if ($bject instanceof Literal) {
+ //Literal
+ //I'm doubling Filter code here, but what the hell
+ $strColDatatype = $strTablePrefix . '.l_datatype';
+ if ($bject->dtype == 'http://www.w3.org/2001/XMLSchema#integer'
+ || $bject->dtype == 'http://www.w3.org/2001/XMLSchema#double'
+ ) {
+ $strVariable = 'CAST(' . $strTablePrefix . '.' . $strType . ' AS DECIMAL(15,10))';
+ $strValue = $bject->getLabel();
+ } else {
+ $strVariable = $strTablePrefix . '.' . $strType;
+ $strValue = $this->dbConn->qstr($bject->getLabel());
+ }
+ $r = ' AND ' . $strVariable . ' = ' . $strValue;
+ if ($strType !== 'predicate') {
+ $r .= ' AND ' . $strTablePrefix . '.' . $strType . '_is ='
+ . ' "l"';
+ }
+
+ if ($strType == 'object') {
+ if ($bject->dtype == '' || $bject->dtype == 'http://www.w3.org/2001/XMLSchema#string') {
+ //string
+ $r .= ' AND ('
+ . $strColDatatype . ' = ""'
+ . ' OR ' . $strColDatatype . ' = "http://www.w3.org/2001/XMLSchema#string"'
+ . ')';
+ } else {
+ $r .= ' AND ' . $strColDatatype . ' = "'
+ . $bject->dtype
+ . '"';
+ }
+ }
+
+ if ($bject->lang != '') {
+ $strColLanguage = $strTablePrefix . '.l_language';
+ $r .= ' AND ' . $strColLanguage . ' = '
+ . $this->dbConn->qstr($bject->lang);
+ }
+ return $r;
+
+ } else {
+ throw new SparqlEngineDb_SqlGeneratorException(
+ 'Unsupported sentence part: ' . get_class($bject)
+ );
+ }
+ }//function getSqlCondition($bject, $strTablePrefix, $strType)
+
+
+
+ /**
+ * Checks if the sentence part (subject, predicate or object) in
+ * $arNew has the same content as $arOld.
+ * Required for queries like ":x ?a ?a" where predicate and object
+ * need to have the same value
+ *
+ * @param array $arNew array($strTablePrefix, $strType = s|p|o)
+ * @param array $arOld array($strTablePrefix, $strType = s|p|o)
+ * @return string
+ */
+ protected static function getSqlEqualityCondition($arNew, $arOld)
+ {
+ $chTypeNew = $arNew[1]; $chTypeOld = $arOld[1];
+ $strTablePrefixNew = $arNew[0]; $strTablePrefixOld = $arOld[0];
+
+ if ($chTypeNew == 'p' || $chTypeOld == 'p') {
+ //just check value
+ //FIXME: it might be I need to check for resource type in object and subject
+ return
+ $strTablePrefixNew . '.' . self::$arTableColumnNames[$chTypeNew]['value']
+ . ' = '
+ . $strTablePrefixOld . '.' . self::$arTableColumnNames[$chTypeOld]['value']
+ ;
+ } else if ($chTypeNew == 's' || $chTypeOld == 's') {
+ //check value and type
+ return
+ $strTablePrefixNew . '.' . self::$arTableColumnNames[$chTypeNew]['value']
+ . ' = '
+ . $strTablePrefixOld . '.' . self::$arTableColumnNames[$chTypeOld]['value']
+ . ' AND '
+ . $strTablePrefixNew . '.' . self::$arTableColumnNames[$chTypeNew]['is']
+ . ' = '
+ . $strTablePrefixOld . '.' . self::$arTableColumnNames[$chTypeOld]['is']
+ ;
+ } else {
+ //two objects -> check everything
+ return
+ $strTablePrefixNew . '.object = ' . $strTablePrefixOld . '.object'
+ . ' AND '
+ . $strTablePrefixNew . '.object_is = ' . $strTablePrefixOld . '.object_is'
+ . ' AND '
+ . $strTablePrefixNew . '.l_language = ' . $strTablePrefixOld . '.l_language'
+ . ' AND '
+ . $strTablePrefixNew . '.l_datatype = ' . $strTablePrefixOld . '.l_datatype'
+ ;
+ }
+ }//protected static function getSqlEqualityCondition($arNew, $arOld)
+
+
+
+ /**
+ * Checks if the given variable name is part of the result
+ * variables list.
+ * Needed since $arResultVars may contain "*" that captures all variables.
+ *
+ * @param string $strVar Variable name (e.g. "?p")
+ * @param array $arResultVars Array with result variables
+ * @return boolean true if it is a result variable
+ */
+ protected static function isResultVar($strVar, &$arResultVars)
+ {
+ foreach ($arResultVars as $var) {
+ if ($var == '*') {
+ return true;
+ } else if ((is_string($var) && $var == $strVar)
+ || (is_object($var) && $var->getVariable() == $strVar)) {
+ return true;
+ }
+ }
+ return false;
+ }//protected static function isResultVar($strVar, &$arResultVars)
+
+
+
+ /**
+ * Checks if the given variable is a replacement
+ * for a prepared statement.
+ *
+ * @return boolean
+ */
+ public static function isPreparedVariable($bject)
+ {
+ return is_string($bject) && strlen($bject) >= 3
+ && ($bject[0] == '?' || $bject[0] == '$')
+ && ($bject[1] == '?' || $bject[1] == '$')
+ ;
+ }//public static function isPreparedVariable($bject)
+
+
+
+ /**
+ * Returns a placeholder to be included in the sql statement.
+ * It will be replaced with a real prepared statement variable later on.
+ * Also adds it to the internal placeholder array.
+ *
+ * @param string $strVariable The variable to get a placeholder for
+ * @return string placeholder
+ */
+ protected function getPreparedVariablePlaceholder($strVariable)
+ {
+ $strName = substr($strVariable, 2);
+ if (!isset($this->arPlaceholders[$strName])) {
+ $this->arPlaceholders[$strName] = '@$%_PLACEHOLDER_'
+ . count($this->arPlaceholders) . '_%$@';
+ }
+ return $this->arPlaceholders[$strName];
+ }//protected function getPreparedVariablePlaceholder($strVariable)
+
+
+
+ public function getPlaceholders()
+ {
+ return $this->arPlaceholders;
+ }//public function getPlaceholders()
+
+
+
+ public function getVarAssignments()
+ {
+ return $this->arVarAssignments;
+ }//public function getVarAssignments()
+
+
+
+ public function getUsedVarAssignments()
+ {
+ return $this->arUsedVarAssignments;
+ }//public function getUsedVarAssignments()
+
+
+
+ public function getUsedVarTypes()
+ {
+ return $this->arUsedVarTypes;
+ }//public function getUsedVarTypes()
+
+
+
+ /**
+ * Removes all NULL values from an array and returns it.
+ *
+ * @param array $array Some array
+ * @return array $array without the NULL values.
+ */
+ protected static function removeNull($array)
+ {
+ foreach ($array as $key => &$value) {
+ if ($value === null) {
+ unset($array[$key]);
+ }
+ }
+ return $array;
+ }//protected static function removeNull($array)
+
+
+
+ /**
+ * Removes a leading AND from the where clause which would render
+ * the sql illegal.
+ */
+ protected function fixWhere($strWhere)
+ {
+ $strWhere = ltrim($strWhere);
+ if (substr($strWhere, 0, 4) == 'AND ') {
+ $strWhere = substr($strWhere, 4);
+ }
+ return $strWhere;
+ }//protected function fixWhere($strWhere)
+
+
+
+ protected function getSqlVariableName($var)
+ {
+ $strSparqlVar = (string)$var;
+ if (!isset($this->arVarAssignments[$strSparqlVar]['sqlname'])) {
+ if (preg_match('/[a-zA-Z0-9]+/', substr($strSparqlVar, 1))) {
+ $strName = 'v_' . substr($strSparqlVar, 1);
+ } else {
+ $strName = 'va_' . $this->nSqlVariableNameCount++;
+ }
+ $this->arVarAssignments[$strSparqlVar]['sqlname'] = $strName;
+ }
+ return $this->arVarAssignments[$strSparqlVar]['sqlname'];
+ }//protected function getSqlVariableName($var)
+
+
+
+ protected function getSqlVariableNameValue($var)
+ {
+ $strSparqlVar = (string)$var;
+ $this->arVarAssignments[$strSparqlVar]['sql_value'] =
+ 'value_' . $this->getSqlVariableName($var);
+ return $this->arVarAssignments[$strSparqlVar]['sql_value'];
+ }//protected function getSqlVariableNameValue($var)
+
+
+
+ protected function getSqlVariableNameIs($var)
+ {
+ $strSparqlVar = (string)$var;
+ $this->arVarAssignments[$strSparqlVar]['sql_is'] =
+ 'is_' . $this->getSqlVariableName($var);
+ return $this->arVarAssignments[$strSparqlVar]['sql_is'];
+ }//protected function getSqlVariableNameIs($var)
+
+
+
+ protected function getSqlVariableNameLanguage($var)
+ {
+ $strSparqlVar = (string)$var;
+ $this->arVarAssignments[$strSparqlVar]['sql_lang'] =
+ 'lang_' . $this->getSqlVariableName($var);
+ return $this->arVarAssignments[$strSparqlVar]['sql_lang'];
+ }//protected function getSqlVariableNameLanguage($var)
+
+
+
+ protected function getSqlVariableNameDatatype($var)
+ {
+ $strSparqlVar = (string)$var;
+ $this->arVarAssignments[$strSparqlVar]['sql_type'] =
+ 'type_' . $this->getSqlVariableName($var);
+ return $this->arVarAssignments[$strSparqlVar]['sql_type'];
+ }//protected function getSqlVariableNameDatatype($var)
+
+
+
+ public function setStatementsTable($tblStatements)
+ {
+ $this->tblStatements = $tblStatements;
+ }//public function setStatementsTable($tblStatements)
+
+}//class SparqlEngineDb_SqlGenerator
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/text-base/SqlGeneratorException.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/text-base/SqlGeneratorException.php.svn-base
new file mode 100755
index 00000000..fd3d14f9
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/text-base/SqlGeneratorException.php.svn-base
@@ -0,0 +1,14 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlEngineDb_SqlGeneratorException extends Exception
+{
+}
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/text-base/SqlMerger.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/text-base/SqlMerger.php.svn-base
new file mode 100755
index 00000000..53e0685c
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/text-base/SqlMerger.php.svn-base
@@ -0,0 +1,46 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlEngineDb_SqlMerger
+{
+ public static function getSelect(Query $query, $arSqls, $strAdditional = '')
+ {
+ if (count($arSqls) == 1) {
+ return implode('', $arSqls[0]) . $strAdditional;
+ }
+
+ //union
+ $strUnion = 'UNION' .
+ ($query->getResultForm() == 'select distinct' ? '' : ' ALL');
+ $ar = array();
+ foreach ($arSqls as $arSql) {
+ $ar[] = implode('', $arSql) . $strAdditional;
+ }
+ return '(' . implode(') ' . $strUnion . ' (', $ar) . ')';
+ }//public static function getSelect(Query $query, $arSqls, $strAdditional = '')
+
+
+
+ public static function getCount(Query $query, $arSqls, $strAdditional = '')
+ {
+ if (count($arSqls) == 1) {
+ return 'SELECT COUNT(*) as count ' . $arSqls[0]['from'] . $arSqls[0]['where'] . $strAdditional;
+ }
+
+ $ar = array();
+ foreach ($arSqls as $arSql) {
+ $ar[] = implode('', $arSql) . $strAdditional;
+ }
+ return 'SELECT (' . implode(') + (', $ar) . ') as count';
+ }//public static function getCount(Query $query, $arSqls, $strAdditional = '')
+
+}//class SparqlEngineDb_SqlMerger
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/text-base/TypeSorter.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/text-base/TypeSorter.php.svn-base
new file mode 100755
index 00000000..8efc4ef4
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/.svn/text-base/TypeSorter.php.svn-base
@@ -0,0 +1,450 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlEngineDb_TypeSorter
+{
+ /**
+ * Defines the sort order for value types in the database,
+ * so that they get sorted correctly as the specs want it.
+ * @var array
+ */
+ public static $arTypeNumbers = array(
+ null => 0,//empty
+ 'b' => 1,//blank
+ 'r' => 2,//resource
+ 'l' => 3,//literal
+ );
+
+ /**
+ * SQL types to cast XSD schema types to, so that they will get
+ * sorted correctly.
+ * @var array
+ */
+ public static $arCastTypes = array(
+ 'http://www.w3.org/2001/XMLSchema#integer' => 'SIGNED INTEGER',
+ 'http://www.w3.org/2001/XMLSchema#decimal' => 'DECIMAL',
+ //yes, this does not work with multiple time zones.
+ 'http://www.w3.org/2001/XMLSchema#dateTime' => 'CHAR',
+ 'http://www.w3.org/2001/XMLSchema#date' => 'CHAR',
+ );
+
+
+
+ public function __construct(Query $query, ADOConnection $dbConn)
+ {
+ $this->dbConn = $dbConn;
+ $this->query = $query;
+ }
+
+
+ /**
+ * Needs to be executed before getOrderifiedSqls and willBeDataDependent
+ *
+ * @param SparqlEngineDb_SqlGenerator $sg SQL generator object
+ */
+ public function setData(SparqlEngineDb_SqlGenerator $sg)
+ {
+ $this->arUsedVarTypes = $sg->getUsedVarTypes();
+ $this->arUsedVarAssignments = $sg->getUsedVarAssignments();
+ $this->arVarAssignments = $sg->getVarAssignments();
+ }//public function setData(SparqlEngineDb_SqlGenerator $sg)
+
+
+
+ /**
+ * Returns an array of sql statements that need to be executed
+ * and deliver the full result set when combined.
+ *
+ * Execute setData() before this.
+ *
+ * @internal It is not possible (ok, it is - but it would really complicate
+ * the queries and the code here) to use UNION to combine the sqls to
+ * a single one - UNION merges the results and does not keep the order
+ * of the rows. Citing the mysql manual:
+ * Use of ORDER BY for individual SELECT statements implies nothing
+ * about the order in which the rows appear in the final result because
+ * UNION by default produces an unordered set of rows. If ORDER BY
+ * appears with LIMIT, it is used to determine the subset of the
+ * selected rows to retrieve for the SELECT, but does not necessarily
+ * affect the order of those rows in the final UNION result.
+ * If ORDER BY appears without LIMIT in a SELECT, it is
+ * optimized away because it will have no effect anyway.
+ *
+ * @param string $strSelect SELECT clause
+ * @param string $strFrom FROM clause
+ * @param string $strWhere WHERE clause
+ * @return array Array of arrays. Imploding an array will give
+ * a complete sql statement. The array will have the keys
+ * select/from/where/order.
+ */
+ public function getOrderifiedSqls($arSqls)
+ {
+ if (count($arSqls) == 0) {
+ return $arSqls;
+ }
+
+ $strSelect = $arSqls[0]['select'];
+ $strFrom = $arSqls[0]['from'];
+ $strWhere = $arSqls[0]['where'];
+
+ $strResultForm = $this->query->getResultForm();
+ if ($strResultForm == 'ask' || $strResultForm == 'count') {
+ return array(
+ $arSqls
+ );
+ }
+
+ $arSpecial = $this->getSpecialOrderVariables();
+ if (count($arSpecial) == 0) {
+ $strOrder = $this->getSqlOrderBy();
+ foreach ($arSqls as &$arSql) {
+ $arSql['order'] = $strOrder;
+ }
+ return array(
+ $arSqls
+ );
+ }
+
+ $arTypeSets = $this->orderTypeSets(
+ $this->getTypeSets($arSpecial, $strFrom, $strWhere)
+ );
+
+ $arNewSqls = array();
+ foreach ($arTypeSets as $arTypeSet) {
+ $arSqlParts = array();
+ foreach ($arSqls as $arSql) {
+ $arSql['where'] .= $this->getTypesetWhereClause($arTypeSet);
+ $arSql['order'] = $this->getSqlOrderBy($arTypeSet);
+ $arSqlParts[] = $arSql;
+ }
+ $arNewSqls[] = $arSqlParts;
+ }
+
+ return $arNewSqls;
+ }//public function getOrderifiedSqls($arUsedVarAssignments, $strSelect, $strFrom, $strWhere)
+
+
+
+ /**
+ * Returns wether the returned queries will depend on the data or not.
+ * If the queries depend on the data, they cannot be prepare()d and
+ * thus won't be that fast when executing.
+ *
+ * Execute setData() before this.
+ *
+ * @return boolean
+ */
+ public function willBeDataDependent()
+ {
+ $strResultForm = $this->query->getResultForm();
+ return !(
+ $strResultForm == 'ask' || $strResultForm == 'count'
+ || count($this->getSpecialOrderVariables()) == 0
+ );
+ }//public function willBeDataDependent()
+
+
+
+ /**
+ * Returns an array of variables that the result is going to be
+ * ordered by and that need to be sorted multiple times
+ * (because they may contain different data types)
+ *
+ * @return array Array of sparql variable names
+ */
+ protected function getSpecialOrderVariables()
+ {
+ $arSM = $this->query->getSolutionModifier();
+ if ($arSM['order by'] === null) {
+ return array();
+ }
+
+ $arSpecial = array();
+ foreach ($arSM['order by'] as $arVar) {
+ if ($this->isSpecialOrderVariable($arVar['val'])) {
+ $arSpecial[] = $arVar['val'];
+ }
+ }
+ return $arSpecial;
+ }//protected function getSpecialOrderVariables()
+
+
+
+ /**
+ * Checks if a given variable name is a variable that
+ * needs special care when used in ORDER BY statements.
+ *
+ * @param string $strVar SPARQL variable name
+ * @return boolean true if the variable needs special care
+ */
+ protected function isSpecialOrderVariable($strVar)
+ {
+ return !isset($this->arUsedVarTypes[$strVar]['s'])
+ && !isset($this->arUsedVarTypes[$strVar]['p']);
+ }//protected function isSpecialOrderVariable($arVar)
+
+
+
+ /**
+ * Determines the type sets in the query results.
+ * A type set is a distinct set of variables and their types,
+ * e.g. the variable and its type (r/b/l) and its datatype
+ * if its an object.
+ *
+ * @param array $arSpecialVars Special variables as returned by
+ * getSpecialOrderVariables()
+ * @param string $strFrom FROM part of the sql query
+ * @param string $strWhere WHERE part of the sql query
+ *
+ * @return array Key is the sparql variable name, value is an
+ * array. This one has one key 'type' with a
+ * value of b/l/r. It might have another key
+ * 'datatype' with the resource's datatype.
+ */
+ protected function getTypeSets($arSpecialVars, $strFrom, $strWhere)
+ {
+ $arSel = array();
+ foreach ($arSpecialVars as $strSparqlVar) {
+ if ($this->arVarAssignments[$strSparqlVar][1] == 'o') {
+ $arSel[] = $this->arVarAssignments[$strSparqlVar][0] . '.l_datatype'
+ . ' as "' . $strSparqlVar . '-datatype"';
+ }
+ $strTypeCol = $this->arVarAssignments[$strSparqlVar][1] == 'o'
+ ? 'object_is' : 'subject_is';
+ $this->arVarAssignments[$strSparqlVar][2] = $strTypeCol;
+ $arSel[] = $this->arVarAssignments[$strSparqlVar][0] . '.' . $strTypeCol
+ . ' as "' . $strSparqlVar . '-type"';
+ }
+
+ $oldmode = $this->dbConn->SetFetchMode(ADODB_FETCH_ASSOC);
+ $sql = 'SELECT DISTINCT ' . implode(', ', $arSel) . ' ' . $strFrom . $strWhere;
+ $arResult = $this->dbConn->execute($sql);
+ $this->dbConn->SetFetchMode($oldmode);
+
+ if ($arResult === false) {
+ throw new SparqlEngineDb_SqlGeneratorException(
+ 'Error reading typesets: ' . $sql
+ );
+ }
+
+ $arTypes = array();
+ foreach ($arResult as $arRow) {
+ $nLine = count($arTypes);
+ foreach ($arRow as $key => $value) {
+ list($strSparqlVar, $strType) = explode('-', $key);
+ $arTypes[$nLine][$strSparqlVar][$strType] = $value;
+ }
+ }
+
+ return $arTypes;
+ }//protected function getTypeSets($arSpecialVars, $strFrom, $strWhere)
+
+
+
+ /**
+ * Takes an array of type sets (as returned by getTypeSets()) and
+ * sorts the variables according to the SPARQL specs.
+ *
+ * @param array $arTypes Array of type sets
+ * @return array Ordered array of type sets
+ */
+ protected function orderTypeSets($arTypes)
+ {
+ $arSM = $this->query->getSolutionModifier();
+ if ($arSM['order by'] !== null) {
+ $this->arDirection = array();
+ foreach ($arSM['order by'] as $arVar) {
+ $this->arDirection[$arVar['val']] =
+ (strtoupper($arVar['type']) == 'ASC' ? 1 : -1);
+ }
+ }
+
+ usort($arTypes, array($this, 'compareTypeSet'));
+
+ return $arTypes;
+ }//protected function orderTypeSets($arTypes)
+
+
+
+ /**
+ * Compares two type sets. Works like a normal comparision
+ * method that returns -1/0/1 for use in usort()
+ *
+ * @param array $arTs1 First typeset
+ * @param array $arTs2 Second typeset
+ * @return int Comparison value
+ */
+ public function compareTypeSet($arTs1, $arTs2)
+ {
+ foreach ($arTs1 as $strSparqlVar => $arType1) {
+ //compare types
+ $n = self::$arTypeNumbers[$arType1['type']]
+ - self::$arTypeNumbers[$arTs2[$strSparqlVar]['type']];
+ if ($n != 0) {
+ //and take ASC/DESC into account
+ return $n * $this->arDirection[$strSparqlVar];
+ }
+
+ //compare the datatypes
+ $n = self::compareXsdType(
+ $arType1['datatype'],
+ $arTs2[$strSparqlVar]['datatype']
+ );
+ //if they are not equal, return the value
+ if ($n != 0) {
+ //and take ASC/DESC into account
+ return $n * $this->arDirection[$strSparqlVar];
+ }
+ }
+
+ //they are equal
+ return 0;
+ }//public function compareTypeSet($arTs1, $arTs2)
+
+
+
+ /**
+ * Compares two XSD data types and returns the comparison number.
+ *
+ * @param string $strType1 First data type
+ * @param string $strType2 Second data type
+ * @return int Comparison number (<0 if $strType1 is less than
+ * $strType2, 0 if equal, >0 if type2 is greater)
+ */
+ public static function compareXsdType($strType1, $strType2)
+ {
+ return self::getXsdTypeNumber($strType1) - self::getXsdTypeNumber($strType2);
+ }//public static function compareXsdType($strType1, $strType2)
+
+
+
+ /**
+ * Returns the type number for an xsd data type.
+ *
+ * @param string $strType XSD data type
+ * @return int Some integer to compare two types.
+ */
+ public static function getXsdTypeNumber($strType)
+ {
+ if ($strType === null) {
+ return 0;
+ } else if ($strType == '') {
+ return 1;
+ } else {
+ return 2;
+ }
+ }//public static function getXsdTypeNumber($strType)
+
+
+
+ /**
+ * Returns the ORDER BY sql query string
+ * if neccessary for the query. The returned string
+ * already has ORDER BY prefixed.
+ *
+ * @internal Also takes care of casting the data if the type
+ * is listed in $arCastTypes. See getCastMethod() for more info.
+ *
+ * @param arrray $arTypeSet Single typeset
+ * @return string ORDER BY ... string or empty string
+ */
+ function getSqlOrderBy($arTypeSet = array())
+ {
+ $arSM = $this->query->getSolutionModifier();
+ if ($arSM['order by'] === null) {
+ return '';
+ }
+
+ $sqlOrder = array();
+ foreach ($arSM['order by'] as $arVar) {
+ $strSparqlVar = $arVar['val'];
+ if (isset($this->arUsedVarAssignments[$strSparqlVar])) {
+ if (!isset($arTypeSet[$strSparqlVar]['datatype'])
+ || $arTypeSet[$strSparqlVar]['datatype'] == '') {
+ $sqlOrder[] = $this->arUsedVarAssignments[$strSparqlVar] . ' ' . strtoupper($arVar['type']);
+ } else {
+ $sqlOrder[] = self::getCastMethod(
+ $arTypeSet[$strSparqlVar]['datatype'],
+ $this->arUsedVarAssignments[$strSparqlVar]
+ ) . ' ' . strtoupper($arVar['type']);
+ }
+ }
+ }
+
+ return ' ORDER BY ' . implode(', ', $sqlOrder);
+ }//function getSqlOrderBy($arTypeSet = array())
+
+
+
+ /**
+ * Returns the SQL statement needed to case the given variable to
+ * the given type.
+ *
+ * @param string $strType XML data type
+ * @param string $strSqlVar SQL variable name
+ * @return string SQL command to cast the variable
+ */
+ protected static function getCastMethod($strType, $strSqlVar)
+ {
+ if (isset(self::$arCastTypes[$strType])) {
+ return 'CAST(' . $strSqlVar . ' as ' . self::$arCastTypes[$strType] . ')';
+ } else {
+ //unsupported type!
+ throw new Exception('Unsupported cast type in order by: ' . $strType);
+ return $strSqlVar;
+ }
+ }//protected static function getCastMethod($strType, $strSqlVar)
+
+
+
+ /**
+ * Creates and returns the SQL WHERE clauses needed to get only
+ * data in the given typeset.
+ *
+ * @param array $arTypeSet Typeset
+ * @return string Clauses for the WHERE part in an SQL query
+ */
+ protected function getTypesetWhereClause($arTypeSet)
+ {
+ $strWhereTypes = '';
+ foreach ($arTypeSet as $strSparqlVar => $arType) {
+ //check type
+ $strWhereTypes .= ' AND ' . $this->arVarAssignments[$strSparqlVar][0]
+ . '.' . $this->arVarAssignments[$strSparqlVar][2]
+ . $this->getStringNullComparison($arType['type']);
+ //check datatype
+ if (isset($arType['datatype'])) {
+ $strWhereTypes .= ' AND ' . $this->arVarAssignments[$strSparqlVar][0]
+ . '.l_datatype '
+ . $this->getStringNullComparison($arType['datatype']);
+ }
+ }
+ return $strWhereTypes;
+ }//protected function getTypesetWhereClause($arTypeSet)
+
+
+
+ /**
+ * Returns the correct sql string comparison method.
+ *
+ * @internal If the string is NULL, an "IS NULL" sql statment
+ * will be returned, and a normal "= 'something'" if it is
+ * a normal string.
+ */
+ protected function getStringNullComparison($str)
+ {
+ if ($str === null) {
+ return ' IS NULL';
+ } else {
+ return ' = ' . $this->dbConn->qstr($str) . '';
+ }
+ }//protected function getStringNullComparison($str)
+
+}//class SparqlEngineDb_TypeSorter
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/FilterGenerator.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/FilterGenerator.php
new file mode 100755
index 00000000..501aeb5f
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/FilterGenerator.php
@@ -0,0 +1,846 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlEngineDb_FilterGenerator
+{
+ /**
+ * SQL Generator
+ * @var SparqlEngineDb_SqlGenerator
+ */
+ protected $sg = null;
+
+ /**
+ * If the filter is in an optional statement
+ * @var boolean
+ */
+ protected $bOptional = false;
+
+ /**
+ * Number of parameters for the functions supported.
+ * First value is minimum, second is maximum.
+ * @var array
+ */
+ protected static $arFuncParamNumbers = array(
+ 'bound' => array(1, 1),
+ 'datatype' => array(1, 1),
+ 'isblank' => array(1, 1),
+ 'isiri' => array(1, 1),
+ 'isliteral' => array(1, 1),
+ 'isuri' => array(1, 1),
+ 'lang' => array(1, 1),
+ 'langmatches' => array(2, 2),
+ 'regex' => array(2, 3),
+ 'sameterm' => array(2, 2),
+ 'str' => array(1, 1),
+ 'xsd:datetime' => array(1, 1),
+ );
+
+ /**
+ * List of operators and their counterpart if operands are switched.
+ * (a > b) => (b < a)
+ * @var array
+ */
+ protected static $arOperatorSwitches = array(
+ '>' => '<',
+ '<' => '>',
+ '>=' => '<=',
+ '<=' => '>=',
+ );
+
+ protected static $arDumbOperators = array(
+ '&&', '||'
+ );
+
+ protected static $typeXsdBoolean = 'http://www.w3.org/2001/XMLSchema#boolean';
+ protected static $typeXsdDateTime = 'http://www.w3.org/2001/XMLSchema#dateTime';
+ protected static $typeXsdDouble = 'http://www.w3.org/2001/XMLSchema#double';
+ protected static $typeXsdInteger = 'http://www.w3.org/2001/XMLSchema#integer';
+ protected static $typeXsdString = 'http://www.w3.org/2001/XMLSchema#string';
+ protected static $typeVariable = 'variable';
+
+
+
+ public function __construct(SparqlEngineDb_SqlGenerator $sg)
+ {
+ $this->sg = $sg;
+ }//public function __construct(SparqlEngineDb_SqlGenerator $sqlgen)
+
+
+
+ /**
+ * Creates the SQL representing a Sparql FILTER.
+ *
+ * @param array $tree Filter element tree as returned by
+ * SparqlParser::parseConstraintTree()
+ * @param boolean $bOptional If the filter is in an optional statement
+ * @return string SQL WHERE part with prefixed AND
+ */
+ public function createFilterSql($tree, $bOptional, $nUnionCount)
+ {
+ if (count($tree) == 0) {
+ //empty filter pattern?
+ return '';
+ }
+
+ $this->bOptional = $bOptional;
+ $this->nUnionCount = $nUnionCount;
+
+ return ' AND ' . $this->createTreeSql($tree, null);
+ }//public function createFilterSql($tree)
+
+
+
+ /**
+ *
+ */
+ protected function createTreeSql($tree, $parent)
+ {
+ switch ($tree['type']) {
+ case 'equation':
+ $sql = $this->createEquation($tree);
+ break;
+ case 'value':
+ if ($parent != null) {
+ $bDumbParent = $parent['type'] == 'equation'
+ && in_array($parent['operator'], self::$arDumbOperators);
+ } else {
+ $bDumbParent = true;
+ }
+ $sql = $this->createValue($tree, $bDumbParent);
+ break;
+ case 'function':
+ $sql = $this->createFunction($tree);
+ break;
+ default:
+ //var_dump($tree);
+ throw new SparqlEngineDb_SqlGeneratorException('Unsupported tree type: ' . $tree['type']);
+ break;
+ }
+
+ if (isset($tree['negated'])) {
+ $sql = '!(' . $sql . ')';
+ }
+
+ return $sql;
+ }//protected function createTreeSql($tree, $strParentType)
+
+
+
+ /**
+ * Creates the sql for an element of type "value".
+ *
+ * @param array $tree Element
+ * @param boolean $bDumbParent True if the parent is a boolean equation or null.
+ */
+ protected function createValue($tree, $bDumbParent)
+ {
+ $strValue = stripslashes($tree['value']);
+ if (SparqlVariable::isVariable($strValue)) {
+ if (!isset($this->sg->arUnionVarAssignments[$this->nUnionCount][$strValue])) {
+ throw new SparqlEngineDb_SqlGeneratorException(
+ 'Unknown variable in filter: ' . $strValue
+ );
+ }
+
+ if ($bDumbParent) {
+ return $this->createBooleanValue($tree);
+ } else if ($this->isObject($tree)) {
+ //convert datetime to datetime if necessary
+ return self::mkVal(
+ '(CASE'
+ . ' WHEN ' . $this->getDatatypeCol($tree) . ' = "' . self::$typeXsdBoolean . '"'
+ . ' THEN IF(LOWER(' . $this->getValueCol($tree) . ') = "true", TRUE, FALSE)'
+ . ' ELSE ' . $this->getValueCol($tree)
+ . ' END)',
+ self::$typeVariable
+ );
+ } else {
+ return self::mkVal(
+ $this->getValueCol($tree),
+ self::$typeVariable
+ );
+ }
+ }
+
+ if ($this->isNumber($tree)) {
+ return $strValue;
+ } else if ($tree['quoted'] === false &&
+ (!isset($tree['datatype']) || $tree['datatype'] != self::$typeXsdBoolean)
+ ) {
+ $strValueNew = $this->sg->query->getFullUri($strValue);
+ if ($strValueNew === false) {
+ if ($strValue[0] == '<' && substr($strValue, -1) == '>') {
+ $strValue = substr($strValue, 1, -1);
+ } else {
+var_dump($tree);
+ throw new SparqlEngineDb_SqlGeneratorException(
+ 'Unexpected value "' . $strValue . '" (expected datatype)'
+ );
+ }
+ } else {
+ $strValue = $strValueNew;
+ }
+ } else if (isset($tree['datatype'])) {
+ switch ($tree['datatype']) {
+ case self::$typeXsdBoolean:
+ if (strtolower($strValue) == 'false') {
+ //fix: (bool)"false" === true
+ $strValue = false;
+ }
+ return self::mkVal(
+ (bool)$strValue ? 'TRUE' : 'FALSE',
+ self::$typeXsdBoolean
+ );
+
+ default:
+ throw new SparqlEngineDb_SqlGeneratorException(
+ 'Unsupported datatype "' . $tree['datatype']
+ );
+ }
+ }
+
+ return self::mkVal(
+ '"' . addslashes($strValue) . '"',
+ self::$typeXsdString
+ );
+ }//protected function createValue($tree)
+
+
+
+ protected function createBooleanValue($tree)
+ {
+ list($strTable, $chType) = $this->sg->arUnionVarAssignments[$this->nUnionCount][$tree['value']];
+ if (!$this->isObject($tree)) {
+ //Maybe needs a fix
+ $strSqlCol = SparqlEngineDb_SqlGenerator::$arTableColumnNames[$chType]['value'];
+ return self::mkVal(
+ $strTable . '.' . $strSqlCol . ' != ""',
+ self::$typeXsdBoolean
+ );
+ }
+
+ $cType = $strTable . '.l_datatype';
+ $cValue = $strTable . '.object';
+ $xsd = 'http://www.w3.org/2001/XMLSchema';
+
+ return self::mkVal(
+ '('
+ . "(($cType = '' || $cType = '$xsd#string') AND $cValue != '')"
+ . " OR ($cType = '$xsd#boolean' AND $cValue != 'false')"
+ . " OR (($cType = '$xsd#integer' || $cType = '$xsd#double') AND CAST($cValue AS DECIMAL(15,10)) != 0)"
+ //plain check for all unknown datatypes
+ . " OR ($cType != '' AND $cType != '$xsd#string' AND $cType != '$xsd#boolean' AND $cType != '$xsd#integer' AND $cType != '$xsd#double' AND $cValue != '')"
+ . ')',
+ self::$typeXsdBoolean
+ );
+ }//protected function createBooleanValue($tree)
+
+
+
+ protected function createFunction($tree)
+ {
+ $strFuncName = strtolower($tree['name']);
+ if (!isset(self::$arFuncParamNumbers[$strFuncName])) {
+ throw new SparqlEngineDb_SqlGeneratorException(
+ 'Unsupported FILTER function: ' . $strFuncName
+ );
+ }
+
+ $nParams = count($tree['parameter']);
+ if ($nParams < self::$arFuncParamNumbers[$strFuncName][0]
+ || $nParams > self::$arFuncParamNumbers[$strFuncName][1]
+ ) {
+ throw new SparqlEngineDb_SqlGeneratorException(
+ 'Wrong parameter count for FILTER function: ' . $strFuncName
+ . ' (got ' . $nParams . ', expected '
+ . self::$arFuncParamNumbers[$strFuncName][0]
+ . '-' . self::$arFuncParamNumbers[$strFuncName][1]
+ );
+ }
+
+ $strThisFunc = 'createFunction_' . str_replace(':', '_', $strFuncName);
+ return $this->$strThisFunc($tree);
+ }//protected function createFunction($tree)
+
+
+
+ protected function createEquation($tree)
+ {
+ $strExtra = '';
+ $strIsNull = '';
+ $strIsNullEnd = '';
+
+ if (($this->isNumber($tree['operand1']) || $this->isPlainString($tree['operand1']))
+ && $this->isObject($tree['operand2'])
+ ) {
+ //switch operands and operator
+ $tmp = $tree['operand1'];
+ $tree['operand1'] = $tree['operand2'];
+ $tree['operand2'] = $tmp;
+ $tree['operator'] = self::switchOperator($tree['operator']);
+ }
+
+ $val1 = $this->createTreeSql($tree['operand1'], $tree);
+ $val2 = $this->createTreeSql($tree['operand2'], $tree);
+
+ if ($this->isObject($tree['operand1'])) {
+ if ($this->bOptional) {
+ $strIsNull = '(';
+ $strIsNullEnd = ' OR ' . $val1 . ' IS NULL)';
+ }
+ if (isset($tree['operand2']['language'])) {
+ $strColLanguage = $this->getLangCol($tree['operand1']);
+ $strExtra .= ' AND ' . $strColLanguage . ' = "'
+ . addslashes($tree['operand2']['language'])
+ . '"';
+ }
+
+ if ($this->isNumber($tree['operand2'])) {
+ $strColDatatype = $this->getDatatypeCol($tree['operand1']);
+ $strExtra .= ' AND (' . $strColDatatype . ' = "' . self::$typeXsdDouble . '"'
+ . ' OR ' . $strColDatatype . ' = "' . self::$typeXsdInteger . '"'
+ . ')';
+ return $strIsNull . '('
+ . 'CAST(' . $val1 . ' AS DECIMAL(15,10))'
+ . ' ' . $tree['operator'] . ' '
+ . $val2
+ . $strExtra
+ . ')' . $strIsNullEnd;
+ }
+ }
+
+ //I don't check the operator since it is already checked in the parser
+ return $strIsNull . '('
+ . '('
+ . $val1
+ . ' ' . $tree['operator'] . ' '
+ . $val2
+ . $strExtra
+ . ')'
+ . $this->createTypeEquation(
+ $tree['operator'], $val1, $val2,
+ $tree['operand1'], $tree['operand2']
+ )
+ . ')' . $strIsNullEnd;
+ }//protected function createEquation($tree)
+
+
+
+ /**
+ * Generates sql code to make sure the datatypes of the two operands match
+ */
+ protected function createTypeEquation($operator, $val1, $val2, $tree1, $tree2)
+ {
+ if (in_array($operator, array('&&', '||'))) {
+ return '';
+ }
+
+ if ($val1->type != self::$typeVariable && $val2->type != self::$typeVariable) {
+ //both are not variables -> type needs to be the same
+ return $val1->type == $val2->type ? '' : ' AND FALSE';
+ }
+ $so1 = $this->isObjectOrSubject($tree1);
+ $so2 = $this->isObjectOrSubject($tree2);
+ $o1 = $this->isObject($tree1);
+ $o2 = $this->isObject($tree2);
+
+ if ($so1 && $so2) {
+ $sql = ' AND ' . $this->getIsCol($tree1) . ' = ' . $this->getIsCol($tree2);
+ if ($o1 && $o2) {
+ //maybe needs string fix
+ $sql .= ' AND ' . $this->getDatatypeCol($tree1) . ' = '
+ . $this->getDatatypeCol($tree2);
+ }
+ return $sql;
+ }
+
+ if ($o1 && $val2->type != self::$typeVariable) {
+ return $this->createSingleTypeCheck($val2, $tree1);
+ } else if ($o2 && $val1->type != self::$typeVariable) {
+ return $this->createSingleTypeCheck($val1, $tree2);
+ }
+
+ //fixme
+ return '';
+ }//protected function createTypeEquation($operator, $val1, $val2, $tree1, $tree2)
+
+
+
+ /**
+ * Creates sql to ensure the type between $val and variable $tree
+ * is the same.
+ */
+ protected function createSingleTypeCheck($val, $tree)
+ {
+ if ($val->type == self::$typeXsdString) {
+ //string can be empty type or xsd type
+ return ' AND ('
+ . $this->getDatatypeCol($tree) . ' = "' . $val->type . '"'
+ . ' OR '
+ . $this->getDatatypeCol($tree) . ' = ""'
+ . ')';
+ }
+ return ' AND ' . $this->getDatatypeCol($tree) . ' = "' . $val->type . '"';
+ }//protected function createSingleTypeCheck($val, $tree)
+
+
+
+ /*
+ * SQL generation functions
+ */
+
+
+
+ /**
+ * Creates an sql statement that returns if the element is a blank node
+ */
+ protected function createFunction_bound($tree)
+ {
+ if ($this->isVariable($tree['parameter'][0])) {
+ return self::mkVal(
+ $this->getValueCol($tree['parameter'][0]) . ' IS NOT NULL',
+ self::$typeXsdBoolean
+ );
+ }
+
+ //We'll see which other cases occur here
+ return self::mkVal('TRUE', self::$typeXsdBoolean);
+ }//protected function createFunction_bound($tree)
+
+
+
+ protected function createFunction_datatype($tree)
+ {
+ if (!$this->isObject($tree['parameter'][0])) {
+ throw new SparqlEngineDb_SqlGeneratorException(
+ 'datatype\'s first parameter needs to be an object'
+ );
+ }
+
+ return self::mkVal(
+ $this->getDatatypeCol($tree['parameter'][0]),
+ self::$typeXsdString
+ );
+ }//protected function createFunction_datatype($tree)
+
+
+
+ /**
+ * Creates an sql statement that returns if the element is a blank node
+ */
+ protected function createFunction_isblank($tree)
+ {
+ if (!$this->isObjectOrSubject($tree['parameter'][0])) {
+ throw new SparqlEngineDb_SqlGeneratorException(
+ 'isBlank\'s first parameter needs to be an object or subject'
+ );
+ }
+
+ return self::mkVal(
+ $this->getIsCol($tree['parameter'][0]) . ' = "b"',
+ self::$typeXsdBoolean
+ );
+ }//protected function createFunction_isblank($tree)
+
+
+
+ protected function createFunction_isiri($tree)
+ {
+ return $this->createFunction_isuri($tree);
+ }//protected function createFunction_isiri($tree)
+
+
+
+ /**
+ * Creates an sql statement that returns the language of the object
+ */
+ protected function createFunction_isliteral($tree)
+ {
+ if ($this->isObjectOrSubject($tree['parameter'][0])) {
+ return $this->getIsCol($tree['parameter'][0]) . ' = "l"';
+ }
+
+ //This does not take combined functions into account (subfunctions)
+ return self::mkVal(
+ $this->isPlainString($tree) ? 'TRUE' : 'FALSE',
+ self::$typeXsdBoolean
+ );
+ }//protected function createFunction_isliteral($tree)
+
+
+
+ protected function createFunction_isuri($tree)
+ {
+ if ($this->isObjectOrSubject($tree['parameter'][0])) {
+ return self::mkVal(
+ $this->getIsCol($tree['parameter'][0]) . ' = "r"',
+ self::$typeXsdBoolean
+ );
+ } else {
+ //predicates are iris
+ return self::mkVal('TRUE', self::$typeXsdBoolean);
+ }
+ }//protected function createFunction_isuri($tree)
+
+
+
+ /**
+ * Creates an sql statement that returns the language of the object
+ */
+ protected function createFunction_lang($tree)
+ {
+ if (!$this->isObject($tree['parameter'][0])) {
+ throw new SparqlEngineDb_SqlGeneratorException(
+ 'lang\'s first parameter needs to be an object'
+ );
+ }
+ return self::mkVal(
+ $this->getLangCol($tree['parameter'][0]),
+ self::$typeXsdString
+ );
+ }//protected function createFunction_lang($tree)
+
+
+
+ /**
+ * Creates an sql statement that checks if the variable
+ * matches a given language
+ */
+ protected function createFunction_langmatches($tree)
+ {
+ //those two restrictions are needed until we have a mysql-only
+ // langmatches function
+ if ($tree['parameter'][0]['type'] != 'function'
+ || $tree['parameter'][0]['name'] != 'lang'
+ ) {
+ throw new SparqlEngineDb_SqlGeneratorException(
+ 'langMatches\' first parameter needs to be a lang() function'
+ );
+ }
+
+ if (!$this->isPlainString($tree['parameter'][1])) {
+ throw new SparqlEngineDb_SqlGeneratorException(
+ 'langMatches\' second parameter needs to be a string'
+ );
+ }
+
+ $lang = $tree['parameter'][1]['value'];
+ $col = $this->createTreeSql($tree['parameter'][0], $tree);
+
+ switch ($lang) {
+ case '*':
+ //anything but nothing
+ $sql = $col . ' != ""';
+ break;
+ case '':
+ //nothing
+ $sql = $col . ' = ""';
+ break;
+ default:
+ //language, maybe with different subcode
+ // en -> en, en-US
+ $sql = '(' . $col . ' = "' . addslashes($lang) . '" OR '
+ . $col . ' LIKE "' . addslashes($lang) . '-%")';
+ break;
+ }
+
+ return self::mkVal($sql, self::$typeXsdBoolean);
+ }//protected function createFunction_isuri($tree)
+
+
+
+ /**
+ * Creates an sql statement that checks if the given part matches
+ * an regex
+ */
+ protected function createFunction_regex($tree)
+ {
+ $strVar = $this->createTreeSql($tree['parameter'][0], $tree);
+ $strRegex = $this->createTreeSql($tree['parameter'][1], $tree);
+
+ if (isset($tree['parameter'][2])) {
+ //is quoted
+ $strMod = $this->createTreeSql($tree['parameter'][2], $tree);
+ switch ($strMod) {
+ case '':
+ case '""':
+ $sql = $strVar . ' REGEXP ' . $strRegex;
+ break;
+
+ case '"i"':
+ $sql = 'CAST(' . $strVar . ' AS CHAR) REGEXP ' . $strRegex;
+ break;
+
+ default:
+ throw new SparqlEngineDb_SqlGeneratorException(
+ 'Unsupported regex modifier "'
+ . $strMod
+ . '"'
+ );
+ }
+ } else {
+ $sql = $strVar . ' REGEXP ' . $strRegex;
+ }
+
+ if ($this->isObject($tree['parameter'][0])) {
+ $col = $this->getIsCol($tree['parameter'][0]);
+ $sql = "($sql AND $col = 'l')";
+ }
+
+ return self::mkVal($sql, self::$typeXsdBoolean);
+ }//protected function createFunction_regex($tree)
+
+
+
+ /**
+ * Creates an sql statement that checks if both terms are the same
+ */
+ protected function createFunction_sameterm($tree)
+ {
+ //FIXME: dead simple implementation that does not cover all cases
+ return self::mkVal(
+ $this->createTreeSql($tree['parameter'][0], $tree)
+ . ' = '
+ . $this->createTreeSql($tree['parameter'][1], $tree),
+ self::$typeXsdBoolean
+ );
+ }//protected function createFunction_sameterm($tree)
+
+
+
+ /**
+ * Creates an sql statement that returns the string representation
+ * of the given element
+ */
+ protected function createFunction_str($tree)
+ {
+ if ($this->isObject($tree['parameter'][0])) {
+ return self::mkVal(
+ '(CASE ' . $this->getIsCol($tree['parameter'][0])
+ . ' WHEN "b" THEN ""'
+ . ' ELSE ' . $this->getValueCol($tree['parameter'][0])
+ . ' END)',
+ self::$typeXsdString
+ );
+ }
+
+ return $this->createTreeSql($tree['parameter'][0], $tree);
+ }//protected function createFunction_str($tree)
+
+
+
+ /**
+ * Creates an sql statement that returns the datetime representation
+ * of the given element
+ */
+ protected function createFunction_xsd_datetime($tree)
+ {
+ $val = $this->createTreeSql($tree['parameter'][0], $tree);
+ if ($val->type == self::$typeXsdDateTime
+ || $val->type == self::$typeVariable) {
+ //no need to cast again
+ return $val;
+ }
+ return self::mkVal(
+ $this->getDateConversionSql($val),
+ self::$typeXsdDateTime
+ );
+ }//protected function createFunction_xsd_datetime($tree)
+
+
+
+
+ /*
+ * Helper methods
+ */
+
+
+
+ protected static function mkVal($value, $type = null) {
+ return new SparqlEngineDb_FilterGenerator_Value($value, $type);
+ }
+
+
+
+ protected function getCol($tree, $type)
+ {
+ list($strTable, $chType) = $this->sg->arUnionVarAssignments[$this->nUnionCount][$tree['value']];
+ if (!isset(SparqlEngineDb_SqlGenerator::$arTableColumnNames[$chType][$type])) {
+ return false;
+ }
+ $strSqlCol = SparqlEngineDb_SqlGenerator::$arTableColumnNames[$chType][$type];
+ return $strTable . '.' . $strSqlCol;
+ }
+
+
+
+ protected function getDatatypeCol($tree)
+ {
+ list($strTable, $chType) = $this->sg->arUnionVarAssignments[$this->nUnionCount][$tree['value']];
+ return $strTable . '.l_datatype';
+ }
+
+
+
+ protected function getDateConversionSql($strValue)
+ {
+ return 'STR_TO_DATE(' . $strValue . ', "%Y-%m-%dT%H:%i:%sZ")';
+ }//protected function getDateConversionSql($strValue)
+
+
+
+ protected function getIsCol($tree)
+ {
+ return $this->getCol($tree, 'is');
+ }
+
+
+
+ protected function getLangCol($tree)
+ {
+ list($strTable, $chType) = $this->sg->arUnionVarAssignments[$this->nUnionCount][$tree['value']];
+ return $strTable . '.l_language';
+ }
+
+
+
+ protected function getValueCol($tree)
+ {
+ return $this->getCol($tree, 'value');
+ }
+
+
+
+ protected function isNumber($tree)
+ {
+ return $tree['type'] == 'value'
+ && $tree['quoted'] === false
+ && preg_match('#^[0-9.]+$#', $tree['value'])
+ && floatval($tree['value']) == $tree['value'];
+ }//protected function isNumber($tree)
+
+
+
+ /**
+ * Checks if the given tree element is a variable
+ * and the variable is actually an object in the database.
+ *
+ * @param array $tree Tree element
+ * @return boolean True if the element is an object
+ */
+ protected function isObject($tree)
+ {
+ return $this->isVariable($tree)
+ && $this->sg->arUnionVarAssignments[$this->nUnionCount][$tree['value']][1] == 'o';
+ }//protected function isVariable($tree)
+
+
+
+ /**
+ * Checks if the given tree element is a variable
+ * and the variable is actually an object or a subject in the database.
+ *
+ * @param array $tree Tree element
+ * @return boolean True if the element is an object or an subject
+ */
+ protected function isObjectOrSubject($tree)
+ {
+ return $this->isVariable($tree)
+ && (
+ $this->sg->arUnionVarAssignments[$this->nUnionCount][$tree['value']][1] == 'o'
+ || $this->sg->arUnionVarAssignments[$this->nUnionCount][$tree['value']][1] == 's'
+ );
+ }//protected function isObjectOrSubject($tree)
+
+
+
+ /**
+ * Checks if the given tree element is a plain string (no variable)
+ *
+ * @param array $tree Tree element
+ * @return boolean True if the element is a string
+ */
+ protected function isPlainString($tree)
+ {
+ return $tree['type'] == 'value'
+ && $tree['quoted'] === true;
+ }//protected function isPlainString($tree)
+
+
+
+ protected function isValueButNotVariableNorString($tree)
+ {
+ return $tree['type'] == 'value'
+ && $tree['type']['quoted'] === false
+ && !SparqlVariable::isVariable($tree['value']);
+ }//protected function isValueButNotVariableNorString($tree)
+
+
+
+ /**
+ * Checks if the given tree element is a variable
+ *
+ * @param array $tree Tree element
+ * @return boolean True if the element is a variable
+ */
+ protected function isVariable($tree)
+ {
+ return $tree['type'] == 'value'
+ && $tree['quoted'] === false
+ && SparqlVariable::isVariable($tree['value'])
+ && isset($this->sg->arUnionVarAssignments[$this->nUnionCount][$tree['value']]);
+ }//protected function isVariable($tree)
+
+
+
+ protected static function switchOperator($op)
+ {
+ if (!isset(self::$arOperatorSwitches[$op])) {
+ return $op;
+ } else {
+ return self::$arOperatorSwitches[$op];
+ }
+ }//protected static function switchOperator($op)
+
+}//class SparqlEngineDb_FilterGenerator
+
+
+
+
+/**
+* Value class that holds some arbitrary value
+* and a datatype.
+* Objects of this class can transparently be used in strings since
+* its __toString() returns the value.
+*/
+class SparqlEngineDb_FilterGenerator_Value
+{
+ public $value = null;
+ public $type = null;
+
+
+
+ public function __construct($value, $type = null)
+ {
+ $this->value = $value;
+ $this->type = $type;
+ }
+
+
+
+ public function __toString()
+ {
+ return $this->value;
+ }
+
+}//class SparqlEngineDb_FilterGenerator_Value
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/Offsetter.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/Offsetter.php
new file mode 100755
index 00000000..c4ff226a
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/Offsetter.php
@@ -0,0 +1,102 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlEngineDb_Offsetter
+{
+ public function __construct(ADOConnection $dbConn, Query $query)
+ {
+ $this->dbConn = $dbConn;
+ $this->query = $query;
+ }//public function __construct(ADOConnection $dbConn, Query $query)
+
+
+
+ /**
+ * Determines the offset in the sqls, the position to start form.
+ *
+ * @param array $arSqls Array of SQL query parts as returned by
+ * SparqlEngine_TypeSorter::getOrderifiedSqls()
+ * @return array Array of two values: The first determines the
+ * index of the sql query to begin with, the second
+ * is the row offset that should be used in the final
+ * SQL query.
+ */
+ public function determineOffset($arSqls)
+ {
+ $arSM = $this->query->getSolutionModifier();
+ if ($arSM['offset'] === null) {
+ return array(0, 0);
+ }
+
+ $nCount = 0;
+ foreach ($arSqls as $nId => $arSql) {
+ $nCurrentCount = $this->getCount($arSql);
+ if ($nCurrentCount + $nCount > $arSM['offset']) {
+ return array($nId, $arSM['offset'] - $nCount);
+ }
+ $nCount += $nCurrentCount;
+ }
+ //nothing found - no results for this offset
+ return array(count($arSqls), 0);
+ }//public function determineOffset($arSql)
+
+
+
+ /**
+ * Returns the number of rows that the given query will return.
+ *
+ * @param array $arSql Array with sql parts and at least keys
+ * 'from' and 'where' set.
+ * @return int Number of rows returned.
+ */
+ protected function getCount($arSql)
+ {
+ $sql = SparqlEngineDb_SqlMerger::getCount($this->query, $arSql);
+ $dbResult = $this->dbConn->execute($sql);
+
+ $nCount = 0;
+ foreach ($dbResult as $row) {
+ $nCount = intval($row[0]);
+ break;
+ }
+ return $nCount;
+ }//protected function getCount($arSql)
+
+
+
+ /**
+ * Creates a sql LIMIT statement if the sparql query needs one.
+ * This method is needed because AdoDb does not support limits with
+ * prepared statements. It's a pity.
+ *
+ * @return string SQL command to be appended to a query, to limit
+ * the number of result rows returned.
+ */
+ public static function getLimitSql(Query $query, ADOConnection $dbConn)
+ {
+ $arSM = $query->getSolutionModifier();
+ if ($arSM['limit'] === null && $arSM['offset'] === null) {
+ return '';
+ }
+ //this here is mysql syntax. if anyone has problems, write it
+ //dependent on $dbConn's type
+ if ($arSM['offset'] === null) {
+ return ' LIMIT ' . $arSM['limit'];
+ } else if ($arSM['limit'] === null) {
+ return ' LIMIT ' . $arSM['offset'] . ', 18446744073709551615';
+ } else {
+ return ' LIMIT ' . $arSM['offset'] . ', ' . $arSM['limit'];
+ }
+ }//public static function getLimitSql(Query $query, ADOConnection $dbConn)
+
+}//class SparqlEngineDb_Offsetter
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/Preparator.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/Preparator.php
new file mode 100755
index 00000000..bedd8b6b
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/Preparator.php
@@ -0,0 +1,229 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlEngineDb_Preparator
+{
+
+
+
+ public function __construct(Query $query, ADOConnection $dbConn)
+ {
+ $this->query = $query;
+ $this->dbConn = $dbConn;
+ $this->arPrefixes = $this->query->getPrefixes();
+ }//public function __construct(Query $query, ADOConnection $dbConn)
+
+
+
+ /**
+ * Converts the given queries into sql prepared statments,
+ * calls the prepare command in the database and returns
+ * an array consisting of subarrays. They contain
+ * the db's prepared statement as first value, and an array
+ * of variable positions as second value (key is the position,
+ * the sparql variable is the value).
+ *
+ * @param array $arQueries Array of sql queries part arrays
+ * @param array $arPlaceholders Array of sparql (variable name =>
+ * placeholder name) pairs
+ * @return array Array of (prepared statment, variable positions) pairs
+ */
+ public function prepareInDb($arQueries, $arPlaceholders)
+ {
+ $arDbStatements = array();
+
+ foreach ($arQueries as $arQuery) {
+ list($strPrepared, $arVariablePositions) = $this->replacePlaceholders(
+ implode('', $arQuery),
+ $arPlaceholders
+ );
+ if (count($arQueries) == 1) {
+ //I currently haven't seens one case in which the count was > 1
+ //if that happens, we will need to add a fix
+ $strPrepared .= SparqlEngineDb_Offsetter::getLimitSql(
+ $this->query,
+ $this->dbConn
+ );
+ }
+ $stmt = $this->dbConn->Prepare($strPrepared);
+ $arDbStatements[] = array(
+ $stmt,
+ $arVariablePositions
+ );
+ }
+
+ return $arDbStatements;
+ }//public function prepareInDb($arQueries, $arPlaceholders)
+
+
+
+ /**
+ * Replaces the placeholders in the given SQL statement with real
+ * SQL prepared statements placeholders.
+ *
+ * @param string $strQuery SQL query with placeholders
+ * @param array $arPlaceholders Array of sparql (variable name =>
+ * placeholder name) pairs
+ * @return array (prepared sql query string, variable positions) pair
+ */
+ protected function replacePlaceholders($strQuery, $arPlaceholders)
+ {
+ $arVariablePositions = array();
+ $this->arTmpVariablePositions = array();
+ $this->arTmpPlaceholders = $arPlaceholders;
+ $strQuery = preg_replace_callback(
+ '/@\\$%_PLACEHOLDER_[0-9]+_%\\$@/',
+ array($this, 'replacePlaceholdersCb'),
+ $strQuery
+ );
+ return array($strQuery, $this->arTmpVariablePositions);
+ }//protected function replacePlaceholders($strQuery, $arPlaceholders)
+
+
+
+ /**
+ * Callback method internally used by replacePlaceholders() method.
+ */
+ protected function replacePlaceholdersCb($matches)
+ {
+ $strPlaceholder = $matches[0];
+ $strSparqlVariable = array_search(
+ $strPlaceholder,
+ $this->arTmpPlaceholders
+ );
+ $strDbPlaceholder = $this->dbConn->Param($strSparqlVariable);
+ $this->arTmpVariablePositions[] = $strSparqlVariable;
+
+ return $strDbPlaceholder;
+ }//protected function replacePlaceholdersCb($matches)
+
+
+
+ /**
+ * Executes the given prepared statments, filling the placeholders
+ * with the given values.
+ *
+ * @param array $arDbStatements Return value of prepareInDb()
+ * @param array $arVariableValues Array of (variable name, value) pairs
+ *
+ * @return array Array of database results as returned by Execute()
+ */
+ public function execute($arDbStatements, $arVariableValues)
+ {
+ $arResults = array();
+ $oldmode = $this->dbConn->SetFetchMode(ADODB_FETCH_ASSOC);
+
+ foreach ($arDbStatements as $arStatement) {
+ list($stmt, $arVariablePositions) = $arStatement;
+ $arVariables = $this->createVariableArray(
+ $arVariablePositions,
+ $arVariableValues
+ );
+ $arResults[] = $this->dbConn->Execute($stmt, $arVariables);
+ }
+
+ $this->dbConn->SetFetchMode($oldmode);
+
+ return $arResults;
+ }//public function execute($arDbStatements, $arVariableValues)
+
+
+
+ /**
+ * Creates an array full of variables to be passed to the Execute() method
+ * of the database connection object.
+ * Uses the variable positions array to get the positions of the variables
+ * in the result array, and the variable value array to get the actual
+ * values for the prepared statement.
+ *
+ * @param array $arVariablePositions Positions of the variables as returned
+ * by replacePlaceholders().
+ * @param array $arVariableValues Array of (variable name, value) pairs
+ *
+ * @return array Array of variable values
+ */
+ protected function createVariableArray($arVariablePositions, $arVariableValues)
+ {
+ $arVariables = array();
+
+ foreach ($arVariablePositions as $nPos => $strVariable) {
+ if (!isset($arVariableValues[$strVariable])) {
+ throw new Exception('No value for variable "' . $strVariable . '" in prepared statement');
+ }
+
+ $strValue = self::replacePrefix(
+ $arVariableValues[$strVariable],
+ $this->arPrefixes
+ );
+
+ $arVariables[$nPos] = $strValue;
+ }
+
+ return $arVariables;
+ }//protected function createVariableArray($arVariablePositions, $arVariableValues)
+
+
+
+ /**
+ * Replaces all placeholders with their actual values.
+ */
+ public function replacePlaceholdersWithVariables($strQuery, $arPlaceholders, $arVariableValues)
+ {
+ $this->arTmpPlaceholders = $arPlaceholders;
+ $this->arTmpVariableValues = $arVariableValues;
+
+ $strQuery = preg_replace_callback(
+ '/@\\$%_PLACEHOLDER_[0-9]+_%\\$@/',
+ array($this, 'replacePlaceholdersWithVariablesCb'),
+ $strQuery
+ );
+
+ return $strQuery;
+ }//public function replacePlaceholdersWithVariables($strQuery, $arPlaceholders, $arVariableValues)
+
+
+
+ /**
+ * Callback method internally used by
+ * replacePlaceholdersWithVariables() method.
+ */
+ protected function replacePlaceholdersWithVariablesCb($matches)
+ {
+ $strPlaceholder = $matches[0];
+ $strSparqlVariable = array_search(
+ $strPlaceholder,
+ $this->arTmpPlaceholders
+ );
+ return $this->dbConn->qstr(
+ self::replacePrefix(
+ $this->arTmpVariableValues[$strSparqlVariable],
+ $this->arPrefixes
+ )
+ );
+ }//protected function replacePlaceholdersWithVariablesCb($matches)
+
+
+
+ protected static function replacePrefix($strValue, $arPrefixes)
+ {
+ //replace prefixes?
+ if (count($arParts = explode(':', $strValue, 2)) == 2) {
+ if (isset($arPrefixes[$arParts[0]])) {
+ $strValue = $arPrefixes[$arParts[0]] . $arParts[1];
+ }
+ }
+ return $strValue;
+ }//protected static function replacePrefix($strValue, $arPrefixes)
+
+}//class SparqlEngineDb_Preparator
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/PreparedStatement.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/PreparedStatement.php
new file mode 100755
index 00000000..e54af3c7
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/PreparedStatement.php
@@ -0,0 +1,38 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlEngineDb_PreparedStatement extends SparqlEngine_PreparedStatement
+{
+ protected $sparqlEngine = null;
+
+
+ public function __construct(SparqlEngineDb $sparqlEngine)
+ {
+ $this->sparqlEngine = $sparqlEngine;
+ }//public function __construct(SparqlEngineDb $sparqlEngine)
+
+
+
+ /**
+ * Execute the prepared statement and returns the result.
+ *
+ * @param array $arVariables Array of sparql query variables => values
+ * @param string $resultform Which result form you need
+ * @return mixed Anything a sparql query can return
+ */
+ public function execute($arVariables, $resultform = false)
+ {
+ return $this->sparqlEngine->execute($arVariables, $resultform);
+ }//public function execute($arVariables, $resultform)
+
+}//class SparqlEngineDb_PreparedStatement extends SparqlEngine_PreparedStatement
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/QuerySimplifier.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/QuerySimplifier.php
new file mode 100755
index 00000000..2988fd98
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/QuerySimplifier.php
@@ -0,0 +1,169 @@
+ 'asd'}
+* UNION
+* {?person3 'three'}
+* }
+* is represented internally as three graph patterns, the latter
+* two referencing the first to be their pattern (they are subpatternOf).
+* Now this can be flattened to this which is the same:
+* {?g ?h ?i . ?person 'asd'}
+* UNION
+* {?g ?h ?i .?person3 'three'}
+*
+* This class does this.
+*
+* @author Christian Weiske
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*/
+class SparqlEngineDb_QuerySimplifier
+{
+
+ /**
+ * Simplify the query by flattening out subqueries.
+ * Modifies the passed query object directly.
+ */
+ public function simplify(Query $query)
+ {
+ $arPatterns = $query->getResultPart();
+ self::dropEmpty($arPatterns);
+ $arPlan = $this->createPlan($arPatterns);
+ if (count($arPlan) == 0) {
+ $query->setResultPart($arPatterns);
+ return 0;
+ }
+
+ $this->executePlan($arPatterns, $arPlan);
+ $query->setResultPart($arPatterns);
+ }//public function simplify(Query $query)
+
+
+
+ /**
+ * Creates a plan what to do.
+ *
+ * @return array Array of arrays. Key is the parent pattern id,
+ * value is an array of subpatterns that belong to
+ * that parental pattern.
+ */
+ protected function createPlan(&$arPatterns)
+ {
+ $arNumbers = $this->getNumbers($arPatterns);
+ if (count($arNumbers) == 0) {
+ return array();
+ }
+
+ $arPlan = array();
+
+ foreach ($arNumbers as $nId => $nPatternCount) {
+ $nParent = $arPatterns[$nId]->getSubpatternOf();
+ $arPlan[$nParent][$nId] = true;
+ }
+
+ return $arPlan;
+ }//protected function createPlan(&$arPatterns)
+
+
+
+ /**
+ * Executes the plan
+ *
+ * @param array $arPatterns Array of GraphPatterns
+ * @param array $arPlan Plan array as returned by createPlan()
+ */
+ protected function executePlan(&$arPatterns, &$arPlan)
+ {
+ foreach ($arPlan as $nParent => $arChildren) {
+ $base = $arPatterns[$nParent];
+ $grandParent = $base->getSubpatternOf();
+ $nNextId = $nParent;
+ foreach ($arChildren as $nChild => $null) {
+ $new = clone $base;
+ $new->addTriplePatterns($arPatterns[$nChild]->getTriplePatterns());
+ $new->addConstraints( $arPatterns[$nChild]->getConstraints());
+ $new->setId($nNextId);
+ if ($nParent != $nNextId) {
+ $new->setUnion($nParent);
+ }
+ $arPatterns[$nNextId] = $new;
+
+ if ($grandParent !== null) {
+ //dynamically adjust plan
+ $arPlan[$grandParent][$nNextId] = true;
+ }
+
+ $nNextId = $nChild;
+ }
+ //last one is not not needed anymore
+ unset($arPatterns[$nNextId]);
+ }
+ }//protected function executePlan(&$arPatterns, &$arPlan)
+
+
+
+ /**
+ * Returns an array of id-value pairs determining
+ * which pattern IDs (array id) are deepest nested
+ * (higher value).
+ * Array is sorted in reverse order, highest values
+ * first.
+ *
+ * @param array $arPatterns Array with GraphPatterns
+ * @return array Array with key-value pairs
+ */
+ protected function getNumbers(&$arPatterns)
+ {
+ $arNumbers = array();
+ foreach ($arPatterns as $nId => &$pattern) {
+ $nParent = $pattern->getSubpatternOf();
+ if ($nParent !== null) {
+ $arNumbers[$nId] = $arNumbers[$nParent] + 1;
+ } else {
+ $arNumbers[$nId] = 0;
+ }
+ }
+ //remove the not so interesting ones
+ foreach ($arNumbers as $nId => $nNumber) {
+ if ($nNumber == 0) {
+ unset($arNumbers[$nId]);
+ }
+ }
+
+ arsort($arNumbers);
+
+ return $arNumbers;
+ }//protected function getNumbers(&$arPatterns)
+
+
+
+ /**
+ * Removes all empty graph patterns from the array.
+ * Modifies it directly.
+ */
+ protected static function dropEmpty(&$arPatterns)
+ {
+ foreach ($arPatterns as $nId => &$pattern) {
+ if ($pattern->isEmpty()) {
+ unset($arPatterns[$nId]);
+ }
+ }
+
+ foreach ($arPatterns as $nId => &$pattern) {
+ $nParent = $pattern->getSubpatternOf();
+ if (!isset($arPatterns[$nParent])) {
+ $arPatterns[$nId]->setSubpatternOf(null);
+ }
+ }
+ //FIXME: continued indexes?
+ }//protected static function dropEmpty(&$arPatterns)
+
+}//class SparqlEngineDb_QuerySimplifier
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultConverter.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultConverter.php
new file mode 100755
index 00000000..93064098
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultConverter.php
@@ -0,0 +1,115 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlEngineDb_ResultConverter
+{
+ /**
+ * Determines the correct renderer and calls it.
+ *
+ * The $resultform may be:
+ * - false: The default renderer is taken then
+ * - an object that implements SparqlEngineDb_ResultRenderer interface
+ * - a string like "HTML" or "XML". The appropriate renderer is used then.
+ * - a full class name, e.g. SparqlEngineDb_ResultRenderer_XML
+ *
+ * @param array $arRecordSets Array of anything ADOConnection::Execute() can return
+ * @param SparqlEngineDb $engine Sparql database engine.
+ * @param mixed $resultform Which format the results shall be in (false or "xml")
+ *
+ * @return mixed Most likely an array or a boolean value,
+ * or anything else as determined by $resultform
+ */
+ public static function convertFromDbResults($arRecordSets, SparqlEngineDb $engine, $resultform = false)
+ {
+ if (is_object($resultform)) {
+ if ($resultform instanceof SparqlEngineDb_ResultRenderer) {
+ return $resultform->convertFromDbResults(
+ $arRecordSets,
+ $engine->getQuery(),
+ $engine
+ );
+ } else {
+ throw new Exception(
+ 'Result renderer object needs to implement'
+ . ' SparqlEngineDb_ResultRenderer interface'
+ );
+ }
+ }
+
+ if ($resultform === false) {
+ $resultform = 'Default';
+ } else if ($resultform == 'xml') {
+ //kept for BC reasons
+ $resultform = 'XML';
+ }
+
+ if ($strClass = self::loadClass($resultform)) {
+ $rrObj = new $strClass();
+ if ($rrObj instanceof SparqlEngineDb_ResultRenderer) {
+ return $rrObj->convertFromDbResults(
+ $arRecordSets,
+ $engine->getQuery(),
+ $engine
+ );
+ } else {
+ throw new Exception(
+ 'Result renderer class "' . $strClass . '" needs to implement'
+ . ' SparqlEngineDb_ResultRenderer interface'
+ );
+ }
+ } else {
+ throw new Exception(
+ 'Result renderer class "' . $resultform . '" could not be loaded.'
+ );
+ }
+ }//public static function convertFromDbResults($arRecordSets, SparqlEngineDb $engine, $resultform = false)
+
+
+
+ /**
+ * Tries to load a given class if it doesn't exist,
+ * and returns true if the class can be used.
+ *
+ * @param string $strClass Classname
+ * @return mixed Class name if the class is loaded and can be used, false if not.
+ */
+ protected static function loadClass($strClass)
+ {
+ if (class_exists($strClass, false)) {
+ return $strClass;
+ }
+
+ //RAP style, shortcut notation
+ $strFile = 'SparqlEngineDb/ResultRenderer/' . $strClass . '.php';
+ @include_once RDFAPI_INCLUDE_DIR . 'sparql/' . $strFile;
+ if (class_exists('SparqlEngineDb_ResultRenderer_' . $strClass, false)) {
+ return 'SparqlEngineDb_ResultRenderer_' . $strClass;
+ }
+
+ //RAP style
+ $strFile = str_replace('_', '/', $strClass) . '.php';
+ @include_once RDFAPI_INCLUDE_DIR . 'sparql/' . $strFile;
+ if (class_exists($strClass, false)) {
+ return $strClass;
+ }
+
+ //PEAR style
+ @include_once $strFile;
+ if (class_exists($strClass, false)) {
+ return $strClass;
+ }
+
+ return false;
+ }//protected static function loadClass($strClass)
+
+}//class SparqlEngineDb_ResultConverter
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer.php
new file mode 100755
index 00000000..2ff2c085
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer.php
@@ -0,0 +1,29 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+interface SparqlEngineDb_ResultRenderer
+{
+ /**
+ * Converts the database results into the desired output format
+ * and returns the result.
+ *
+ * @param array $arRecordSets Array of (possibly several) SQL query results.
+ * @param Query $query SPARQL query object
+ * @param SparqlEngineDb $engine Sparql Engine to query the database
+ * @return mixed The result as rendered by the result renderers.
+ */
+ public function convertFromDbResults($arRecordSets, Query $query, SparqlEngineDb $engine);
+
+}//interface SparqlEngineDb_ResultRenderer
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/.svn/all-wcprops b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/.svn/all-wcprops
new file mode 100755
index 00000000..dafb0daa
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/.svn/all-wcprops
@@ -0,0 +1,35 @@
+K 25
+svn:wc:ra_dav:version-url
+V 90
+/svnroot/rdfapi-php/!svn/ver/554/trunk/rdfapi-php/api/sparql/SparqlEngineDb/ResultRenderer
+END
+JSON.php
+K 25
+svn:wc:ra_dav:version-url
+V 99
+/svnroot/rdfapi-php/!svn/ver/553/trunk/rdfapi-php/api/sparql/SparqlEngineDb/ResultRenderer/JSON.php
+END
+XML.php
+K 25
+svn:wc:ra_dav:version-url
+V 98
+/svnroot/rdfapi-php/!svn/ver/554/trunk/rdfapi-php/api/sparql/SparqlEngineDb/ResultRenderer/XML.php
+END
+Default.php
+K 25
+svn:wc:ra_dav:version-url
+V 102
+/svnroot/rdfapi-php/!svn/ver/466/trunk/rdfapi-php/api/sparql/SparqlEngineDb/ResultRenderer/Default.php
+END
+HTML.php
+K 25
+svn:wc:ra_dav:version-url
+V 99
+/svnroot/rdfapi-php/!svn/ver/466/trunk/rdfapi-php/api/sparql/SparqlEngineDb/ResultRenderer/HTML.php
+END
+PlainText.php
+K 25
+svn:wc:ra_dav:version-url
+V 104
+/svnroot/rdfapi-php/!svn/ver/466/trunk/rdfapi-php/api/sparql/SparqlEngineDb/ResultRenderer/PlainText.php
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/.svn/entries b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/.svn/entries
new file mode 100755
index 00000000..8683e18b
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/.svn/entries
@@ -0,0 +1,91 @@
+8
+
+dir
+556
+https://rdfapi-php.svn.sourceforge.net/svnroot/rdfapi-php/trunk/rdfapi-php/api/sparql/SparqlEngineDb/ResultRenderer
+https://rdfapi-php.svn.sourceforge.net/svnroot/rdfapi-php
+
+
+
+2007-12-05T08:18:50.037887Z
+554
+fusel2k
+
+
+svn:special svn:externals svn:needs-lock
+
+
+
+
+
+
+
+
+
+
+
+b2ee660e-c932-0410-bdee-d8da4d8102f4
+
+JSON.php
+file
+
+
+
+
+2008-02-29T14:57:46.693985Z
+1ba0b132006310544d994987ef33ccad
+2007-11-27T13:06:14.820679Z
+553
+fusel2k
+
+XML.php
+file
+
+
+
+
+2008-02-29T14:57:46.709606Z
+cdaf2efc689c6109786fce0a55b6a635
+2007-12-05T08:18:50.037887Z
+554
+fusel2k
+has-props
+
+Default.php
+file
+
+
+
+
+2008-02-29T14:57:46.709606Z
+90ed777e9c50889887f9a23ee8b37670
+2007-07-04T08:44:01.466753Z
+466
+cweiske
+has-props
+
+HTML.php
+file
+
+
+
+
+2008-02-29T14:57:46.725226Z
+64816661ab11bf0bd18f686be7ce1ce2
+2007-07-04T08:44:01.466753Z
+466
+cweiske
+has-props
+
+PlainText.php
+file
+
+
+
+
+2008-02-29T14:57:46.725226Z
+7834bfe4e0037e013adcd7f7db9a22f1
+2007-07-04T08:44:01.466753Z
+466
+cweiske
+
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/.svn/format b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/.svn/format
new file mode 100755
index 00000000..45a4fb75
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/.svn/format
@@ -0,0 +1 @@
+8
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/.svn/prop-base/Default.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/.svn/prop-base/Default.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/.svn/prop-base/Default.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/.svn/prop-base/HTML.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/.svn/prop-base/HTML.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/.svn/prop-base/HTML.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/.svn/prop-base/XML.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/.svn/prop-base/XML.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/.svn/prop-base/XML.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/.svn/text-base/Default.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/.svn/text-base/Default.php.svn-base
new file mode 100755
index 00000000..b6916bb3
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/.svn/text-base/Default.php.svn-base
@@ -0,0 +1,339 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlEngineDb_ResultRenderer_Default implements SparqlEngineDb_ResultRenderer
+{
+
+ /**
+ * Defines the methods needed to create the types
+ * in $arVarAssignments.
+ * Key is the type (e.g. "s" for subject), and
+ * value the method's name.
+ *
+ * @see $arVarAssignments
+ *
+ * @var array
+ */
+ protected $arCreationMethods = array(
+ 's' => 'createSubjectFromDbRecordSetPart',
+ 'p' => 'createPredicateFromDbRecordSetPart',
+ 'o' => 'createObjectFromDbRecordSetPart'
+ );
+
+
+
+ /**
+ * Converts the database results into the desired output format
+ * and returns the result.
+ *
+ * @param array $arRecordSets Array of (possibly several) SQL query results.
+ * @param Query $query SPARQL query object
+ * @param SparqlEngineDb $engine Sparql Engine to query the database
+ * @return mixed The result as rendered by the result renderers.
+ */
+ public function convertFromDbResults($arRecordSets, Query $query, SparqlEngineDb $engine)
+ {
+ $this->query = $query;
+ $this->engine = $engine;
+ $this->sg = $engine->getSqlGenerator();
+
+ $strResultForm = $this->query->getResultForm();
+ switch ($strResultForm) {
+ case 'construct':
+ case 'select':
+ case 'select distinct':
+ $arResult = $this->getVariableArrayFromRecordSets($arRecordSets, $strResultForm);
+
+ //some result forms need more modification
+ switch ($strResultForm) {
+ case 'construct';
+ $arResult = $this->constructGraph(
+ $arResult,
+ $this->query->getConstructPattern()
+ );
+ break;
+ case 'describe';
+ $arResult = $this->describeGraph($arResult);
+ break;
+ }
+
+ return $arResult;
+ break;
+
+ case 'count':
+ case 'ask':
+ if (count($arRecordSets) > 1) {
+ throw new Exception(
+ 'More than one result set for a '
+ . $strResultForm . ' query!'
+ );
+ }
+
+ $nCount = 0;
+ $dbRecordSet = reset($arRecordSets);
+ foreach ($dbRecordSet as $row) {
+ $nCount += intval($row['count']);
+ break;
+ }
+
+ if ($strResultForm == 'ask') {
+ return $nCount > 0;
+ } else {
+ return $nCount;
+ }
+ break;
+
+ case 'describe':
+ default:
+ throw new Exception('Unsupported result form: ' . $strResultForm);
+ }
+
+ }//public function convertFromDbResults($arRecordSets, Query $query, SparqlEngineDb $engine)
+
+
+
+
+ protected function getVariableArrayFromRecordSets($arRecordSets, $strResultForm)
+ {
+ $arResult = array();
+ foreach ($arRecordSets as $dbRecordSet) {
+ $arResult = array_merge(
+ $arResult,
+ $this->getVariableArrayFromRecordSet($dbRecordSet, $strResultForm)
+ );
+ }
+ return $arResult;
+ }//protected function getVariableArrayFromRecordSets($arRecordSets, $strResultForm)
+
+
+
+ /**
+ * Converts a ADORecordSet object into an array of "rows" that
+ * are subarrays of variable => value pairs.
+ *
+ * @param ADORecordSet $dbRecordSet Anything ADOConnection::Execute() can return
+ * @return array
+ */
+ protected function getVariableArrayFromRecordSet(ADORecordSet $dbRecordSet, $strResultForm)
+ {
+ $arResult = array();
+ switch ($strResultForm) {
+ case 'construct':
+ $arResultVars = $this->query->getConstructPatternVariables();
+ break;
+ default:
+ $arResultVars = $this->query->getResultVars();
+ break;
+ }
+
+ if (in_array('*', $arResultVars)) {
+ $arResultVars = array_keys($this->sg->arVarAssignments);
+ }
+
+ //work around bug in adodb:
+ // ADORecordSet_empty does not implement php5 iterators
+ if ($dbRecordSet->RowCount() <= 0) {
+ return array();
+ }
+
+ foreach ($dbRecordSet as $row) {
+ $arResultRow = array();
+ foreach ($arResultVars as $strVar) {
+ $strVarName = (string)$strVar;
+ if (!isset($this->sg->arVarAssignments[$strVarName])) {
+ //variable is in select, but not in result (test: q-select-2)
+ $arResultRow[$strVarName] = '';
+ } else {
+ $arVarSettings = $this->sg->arVarAssignments[$strVarName];
+ $strMethod = $this->arCreationMethods[$arVarSettings[1]];
+ $arResultRow[$strVarName] = $this->$strMethod($dbRecordSet, $arVarSettings[0], $strVar);
+ }
+ }
+ $arResult[] = $arResultRow;
+ }
+ return $arResult;
+ }//function getVariableArrayFromRecordSet(ADORecordSet $dbRecordSet)
+
+
+
+ /**
+ * Creates an RDF Statement object for one of the variables
+ * contained in the given $dbRecordSet object.
+ *
+ * @see convertFromDbResult() to understand $strVarBase necessity
+ *
+ * @param ADORecordSet $dbRecordSet Record set returned from ADOConnection::Execute()
+ * @param string $strVarBase Prefix of the columns the recordset fields have.
+ *
+ * @return Statement RDF statement object
+ */
+ protected function createStatementFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase)
+ {
+ return new Statement(
+ $this->createSubjectFromDbRecordSetPart ($dbRecordSet, $strVarBase),
+ $this->createPredicateFromDbRecordSetPart($dbRecordSet, $strVarBase),
+ $this->createObjectFromDbRecordSetPart ($dbRecordSet, $strVarBase)
+ );
+ }//protected function createStatementFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase)
+
+
+
+ /**
+ * Creates an RDF subject object
+ * contained in the given $dbRecordSet object.
+ *
+ * @see convertFromDbResult() to understand $strVarBase necessity
+ *
+ * @param ADORecordSet $dbRecordSet Record set returned from ADOConnection::Execute()
+ * @param string $strVarBase Prefix of the columns the recordset fields have.
+ *
+ * @return Resource RDF triple subject resource object
+ */
+ protected function createSubjectFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+ {
+ $strVarName = (string)$strVar;
+ if ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']] === null) {
+ //FIXME: should be NULL, but doesn't pass test
+ return '';
+ }
+
+ if ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_is']] == 'r'
+ //null should be predicate which is always a resource
+ || $dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_is']] === null
+ ) {
+ $subject = new Resource ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ } else {
+ $subject = new BlankNode($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ }
+ return $subject;
+ }//protected function createSubjectFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVarName)
+
+
+
+ /**
+ * Creates an RDF predicate object
+ * contained in the given $dbRecordSet object.
+ *
+ * @see convertFromDbResult() to understand $strVarBase necessity
+ *
+ * @param ADORecordSet $dbRecordSet Record set returned from ADOConnection::Execute()
+ * @param string $strVarBase Prefix of the columns the recordset fields have.
+ *
+ * @return Resource RDF triple predicate resource object
+ */
+ protected function createPredicateFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+ {
+ $strVarName = (string)$strVar;
+ if ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']] === null) {
+ //FIXME: should be NULL, but doesn't pass test
+ return '';
+ }
+ $predicate = new Resource ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ return $predicate;
+ }//protected function createPredicateFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVarName)
+
+
+
+ /**
+ * Creates an RDF object object
+ * contained in the given $dbRecordSet object.
+ *
+ * @see convertFromDbResult() to understand $strVarBase necessity
+ *
+ * @param ADORecordSet $dbRecordSet Record set returned from ADOConnection::Execute()
+ * @param string $strVarBase Prefix of the columns the recordset fields have.
+ *
+ * @return Resource RDF triple object resource object
+ */
+ protected function createObjectFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+ {
+ $strVarName = (string)$strVar;
+ if ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']] === null) {
+ //FIXME: should be NULL, but doesn't pass test
+ return '';
+ }
+ switch ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_is']]) {
+ case 'r':
+ $object = new Resource ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ break;
+ case 'b':
+ $object = new BlankNode($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ break;
+ default:
+ $object = new Literal(
+ $dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']],
+ $dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_lang']]
+ );
+ if ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_type']]) {
+ $object->setDatatype($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_type']]);
+ }
+ }
+ return $object;
+ }//protected function createObjectFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVarName)
+
+
+
+ /**
+ * Constructs a result graph.
+ *
+ * @param array $arVartable A table containing the result vars and their bindings
+ * @param GraphPattern $constructPattern The CONSTRUCT pattern
+ * @return MemModel The result graph which matches the CONSTRUCT pattern
+ */
+ protected function constructGraph($arVartable, $constructPattern)
+ {
+ $resultGraph = new MemModel();
+
+ if (!$arVartable) {
+ return $resultGraph;
+ }
+
+ $tp = $constructPattern->getTriplePatterns();
+
+ $bnode = 0;
+ foreach ($arVartable as $value) {
+ foreach ($tp as $triple) {
+ $sub = $triple->getSubject();
+ $pred = $triple->getPredicate();
+ $obj = $triple->getObject();
+
+ if (is_string($sub) && $sub{1} == '_') {
+ $sub = new BlankNode("_bN".$bnode);
+ }
+ if (is_string($pred) && $pred{1} == '_') {
+ $pred = new BlankNode("_bN".$bnode);
+ }
+ if (is_string($obj) && $obj{1} == '_') {
+ $obj = new BlankNode("_bN".$bnode);
+ }
+
+
+ if (is_string($sub)) {
+ $sub = $value[$sub];
+ }
+ if (is_string($pred)) {
+ $pred = $value[$pred];
+ }
+ if (is_string($obj)) {
+ $obj = $value[$obj];
+ }
+
+ if ($sub !== "" && $pred !== "" && $obj !== "") {
+ $resultGraph->add(new Statement($sub,$pred,$obj));
+ }
+ }
+ $bnode++;
+ }
+ return $resultGraph;
+ }//protected function constructGraph($arVartable, $constructPattern)
+
+}//class SparqlEngineDb_ResultRenderer_Default implements SparqlEngineDb_ResultRenderer
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/.svn/text-base/HTML.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/.svn/text-base/HTML.php.svn-base
new file mode 100755
index 00000000..2d29c893
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/.svn/text-base/HTML.php.svn-base
@@ -0,0 +1,297 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlEngineDb_ResultRenderer_HTML implements SparqlEngineDb_ResultRenderer
+{
+ /**
+ * If the result HTML should be wrapped in a div
+ * @var boolean
+ */
+ protected $bWrap = true;
+
+ /**
+ * Defines the methods needed to create the types
+ * in $arVarAssignments.
+ * Key is the type (e.g. "s" for subject), and
+ * value the method's name.
+ *
+ * @see $arVarAssignments
+ *
+ * @var array
+ */
+ protected $arCreationMethods = array(
+ 's' => 'createSubjectFromDbRecordSetPart',
+ 'p' => 'createPredicateFromDbRecordSetPart',
+ 'o' => 'createObjectFromDbRecordSetPart'
+ );
+
+
+
+ /**
+ * Converts the database results into nice HTML.
+ *
+ * @param array $arRecordSets Array of (possibly several) SQL query results.
+ * @param Query $query SPARQL query object
+ * @param SparqlEngineDb $engine Sparql Engine to query the database
+ * @return mixed HTML code
+ */
+ public function convertFromDbResults($arRecordSets, Query $query, SparqlEngineDb $engine)
+ {
+ $this->query = $query;
+ $this->sg = $engine->getSqlGenerator();
+ $strCode = '';
+
+ $strResultForm = $query->getResultForm();
+ switch ($strResultForm) {
+ case 'select':
+ case 'select distinct':
+ $strCode = $this->createTableFromRecords($arRecordSets);
+ break;
+
+ case 'construct':
+ case 'describe':
+ throw new Exception(
+ 'Construct and describe are currently not supported by the'
+ . ' HTML renderer'
+ );
+
+ case 'count':
+ case 'ask':
+ if (count($arRecordSets) > 1) {
+ throw new Exception(
+ 'More than one result set for a '
+ . $strResultForm . ' query!'
+ );
+ }
+
+ $nCount = 0;
+ $dbRecordSet = reset($arRecordSets);
+ foreach ($dbRecordSet as $row) {
+ $nCount += intval($row['count']);
+ break;
+ }
+
+ if ($strResultForm == 'ask') {
+ $strCode = 'There were results.';
+ } else {
+ $strCode = 'There are ' . $nCount . ' results.';
+ }
+ break;
+
+ default:
+ throw new Exception('Unsupported result form: ' . $strResultForm);
+ }
+
+ return $this->wrapCode($strCode);
+ }//public function convertFromDbResults($arRecordSets, Query $query, SparqlEngineDb $engine)
+
+
+
+ protected function wrapCode($strCode)
+ {
+ if (!$this->bWrap) {
+ return $strCode;
+ }
+
+ return
+ '' . "\n"
+ . $strCode . "\n"
+ . "
\n";
+ }//protected function wrapCode($strCode)
+
+
+
+ protected function createTableFromRecords($arRecordSets)
+ {
+ $arResultVars = $this->query->getResultVars();
+
+ if (in_array('*', $arResultVars)) {
+ $arResultVars = array_keys($this->sg->arVarAssignments);
+ }
+
+ $arResult = array();
+ foreach ($arRecordSets as $dbRecordSet) {
+ //work around bug in adodb:
+ // ADORecordSet_empty does not implement php5 iterators
+ if ($dbRecordSet->RowCount() <= 0) {
+ return array();
+ }
+
+ foreach ($dbRecordSet as $row) {
+ $arResultRow = array();
+ foreach ($arResultVars as $strVar) {
+ $strVarName = (string)$strVar;
+ if (!isset($this->sg->arVarAssignments[$strVarName])) {
+ //variable is in select, but not in result (test: q-select-2)
+ $arResultRow[$strVarName] = '';
+ } else {
+ $arVarSettings = $this->sg->arVarAssignments[$strVarName];
+ $strMethod = $this->arCreationMethods[$arVarSettings[1]];
+ list($strCode, $strColor) = $this->$strMethod($dbRecordSet, $arVarSettings[0], $strVar);
+ $arResultRow[$strVarName] = '' . $strCode . ' | ';
+ }
+ }
+ $arResult[] = $arResultRow;
+ }
+ }
+
+ //I always wanted to to this :)
+ return
+ "\n"
+ . " SPARQL result with " . count($arResult) . " rows\n"
+ . " | "
+ . implode(' | ', array_keys(reset($arResult)))
+ . " | \n"
+ . " \n "
+ . implode(
+ "
\n ",
+ array_map(
+ create_function(
+ '$ar',
+ 'return implode("", $ar);'
+ ),
+ $arResult
+ )
+ )
+ . "
\n \n"
+ . "
\n";
+ }//protected function createTableFromRecords($arRecordSets)
+
+
+
+ /**
+ * Creates an RDF subject object
+ * contained in the given $dbRecordSet object.
+ *
+ * @see convertFromDbResult() to understand $strVarBase necessity
+ *
+ * @param ADORecordSet $dbRecordSet Record set returned from ADOConnection::Execute()
+ * @param string $strVarBase Prefix of the columns the recordset fields have.
+ *
+ * @return string HTML code
+ */
+ protected function createSubjectFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+ {
+ $strVarName = (string)$strVar;
+ if ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']] === null) {
+ return $this->getHtmlNull();
+ }
+ if ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_is']] == 'r'
+ //null should be predicate which is always a resource
+ || $dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_is']] === null
+ ) {
+ return $this->getHtmlResource($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ } else {
+ return $this->getHtmlBlank($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ }
+ }//protected function createSubjectFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+
+
+
+ /**
+ * Creates an RDF predicate object
+ * contained in the given $dbRecordSet object.
+ *
+ * @see convertFromDbResult() to understand $strVarBase necessity
+ *
+ * @param ADORecordSet $dbRecordSet Record set returned from ADOConnection::Execute()
+ * @param string $strVarBase Prefix of the columns the recordset fields have.
+ *
+ * @return string HTML code
+ */
+ protected function createPredicateFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+ {
+ $strVarName = (string)$strVar;
+ if ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']] === null) {
+ return $this->getHtmlNull();
+ }
+
+ return $this->getHtmlResource($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ }//protected function createPredicateFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+
+
+
+ /**
+ * Creates an RDF object object
+ * contained in the given $dbRecordSet object.
+ *
+ * @see convertFromDbResult() to understand $strVarBase necessity
+ *
+ * @param ADORecordSet $dbRecordSet Record set returned from ADOConnection::Execute()
+ * @param string $strVarBase Prefix of the columns the recordset fields have.
+ *
+ * @return string HTML code
+ */
+ protected function createObjectFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+ {
+ $strVarName = (string)$strVar;
+ if ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']] === null) {
+ return $this->getHtmlNull();
+ }
+ switch ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_is']]) {
+ case 'r':
+ return $this->getHtmlResource($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ break;
+ case 'b':
+ return $this->getHtmlBlank($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ break;
+ default:
+ return $this->getHtmlLiteral(
+ $dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']],
+ $dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_lang']],
+ $dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_type']]
+ );
+ }
+ }//protected function createObjectFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+
+
+
+ protected function getHtmlNull()
+ {
+ return array('NULL
', '#FFF');
+ }//protected function getHtmlNull()
+
+
+
+ protected function getHtmlBlank($value)
+ {
+ return array('Blank node', HTML_TABLE_BNODE_COLOR);
+ }//protected function getHtmlBlank($value)
+
+
+
+ protected function getHtmlResource($value)
+ {
+ return array(
+ htmlspecialchars($value),
+ HTML_TABLE_RESOURCE_COLOR
+ );
+ }//protected function getHtmlResource($value)
+
+
+
+ protected function getHtmlLiteral($value, $language, $datatype)
+ {
+ $strCode = htmlspecialchars($value);
+ if ($language) {
+ $strCode . ' xml:lang=' . $language;
+ }
+ if ($datatype) {
+ $strCode . ' rdf:type=' . $datatype;
+ }
+ return array($strCode, HTML_TABLE_LITERAL_COLOR);
+ }//protected function getHtmlLiteral($value, $language, $datatype)
+
+
+}//class SparqlEngineDb_ResultRenderer_HTML implements SparqlEngineDb_ResultRenderer
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/.svn/text-base/JSON.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/.svn/text-base/JSON.php.svn-base
new file mode 100755
index 00000000..16d6bea9
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/.svn/text-base/JSON.php.svn-base
@@ -0,0 +1,174 @@
+query = $query;
+ $this->sg = $engine->getSqlGenerator();
+ $strResultForm = $query->getResultForm();
+
+ foreach ($this->getResultVars() as $var)
+ $ResultVarsTemp[] = substr($var,1);
+
+ switch ($strResultForm) {
+ case 'select':
+ case 'select distinct':
+ $results = $this->createFromRecords($arRecordSets, $strResultForm);
+ $strCode = json_encode(array(
+ 'head' => array('vars'=>$ResultVarsTemp),
+ 'results'=>array('bindings'=>$results))
+ );
+ //$strCode = str_replace(',{',','.PHP_EOL.'{',$strCode);
+ break;
+ case 'construct':
+ case 'describe':
+ throw new Exception(
+ 'Construct and describe are not supported by the'
+ . ' JSON renderer'
+ );
+
+ case 'count':
+ case 'ask':
+ if (count($arRecordSets) > 1) {
+ throw new Exception(
+ 'More than one result set for a '
+ . $strResultForm . ' query not supported by JSON Renderer'
+ );
+ }
+
+ $nCount = 0;
+ $dbRecordSet = reset($arRecordSets);
+ foreach ($dbRecordSet as $row) {
+ $nCount += intval($row['count']);
+ break;
+ }
+
+ if ($strResultForm == 'ask') {
+ $strcode = json_encode(array('boolean' => ($nCount > 0)));
+ } else {
+ $strcode = json_encode(array('int' => $nCount ));
+ }
+ break;
+ default:
+ throw new Exception('Error');
+ }
+
+ return $strCode;
+
+
+ }
+ /**
+ * Method to create from record with specific resultform (not used yet)
+ *
+ * @param array $arRecordSets Array of (possibly several) SQL query results.
+ * @param unknown_type $strResultForm
+ * @return array ready for json conversion
+ */
+ protected function createFromRecords($arRecordSets, $strResultForm) {
+
+ $arVarAssignments = $this->sg->arVarAssignments;
+ $code = '';
+ $arResultVars = $this ->getResultVars();
+ $results = array();
+ foreach ($arRecordSets[0] as $value) {
+ $node = array();
+ foreach ($arResultVars as $ResultVar) {
+ $nodeType = $value[$arVarAssignments[$ResultVar][0].'.'.$arVarAssignments[$ResultVar]['sql_is']];
+ if ($nodeType == 'r') {
+ $node[substr($ResultVar,1)] = array('type'=> 'uri','value'=>$value[$arVarAssignments[$ResultVar][0].'.'.$arVarAssignments[$ResultVar]['sql_value']]);
+
+ }
+
+ if ($value[$arVarAssignments[$ResultVar][0].'.'.$arVarAssignments[$ResultVar]['sql_is']] == 'l') {
+ $literalType = $value[$arVarAssignments[$ResultVar][0] .
+ '.' . $arVarAssignments[$ResultVar]['sql_type']];
+ $literalLang = $value[$arVarAssignments[$ResultVar][0] .
+ '.' . $arVarAssignments[$ResultVar]['sql_lang']];
+ $literalValue = $value[$arVarAssignments[$ResultVar][0] .
+ '.' . $arVarAssignments[$ResultVar]['sql_value']];
+ $node[substr($ResultVar,1)] = $this->getLiteral($literalValue,$literalLang,$literalType);
+ }
+
+ if ($nodeType === 'b') {
+ $literalValue = $value[$arVarAssignments[$ResultVar][0].'.'.$arVarAssignments[$ResultVar]['sql_value']];
+ $node[substr($ResultVar,1)] = array ('type'=>'bnode' ,'value'=>$value[$arVarAssignments[$ResultVar][0].'.'.$arVarAssignments[$ResultVar]['sql_value']]);
+ }
+ }
+ $results[]=$node;
+
+
+ }
+ return $results;
+
+ }
+
+ /**
+ * COnverting Literals to array ready for json
+ *
+ * @param unknown_type $value
+ * @param unknown_type $lang
+ * @param unknown_type $type
+ * @return unknown
+ */
+ private function getLiteral($value, $lang , $type) {
+
+ $ret = array();
+
+ $type = 'literal';
+
+ if ($value != 'literal') {
+ $ret['value'] = $value;
+ }
+
+ if ($lang != '') {
+ $ret['lang'] = $lang;
+ }
+
+ if ($type != '') {
+ $ret['type'] = $type;
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Giving array of used Vars also resolves the all-quantifier *
+ *
+ * @return array of vars as strings
+ */
+ protected function getResultVars() {
+ $arResultVars = $this->query->getResultVars();
+ if (in_array('*', $arResultVars)) {
+ $arResultVars = array_keys($this->sg->arVarAssignments);
+ } else {
+ $arResultVars = array();
+ foreach ($this->query->getResultVars() as $Var) {
+ $arResultVars[] = (string) $Var;
+ }
+ }
+
+ return $arResultVars;
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/.svn/text-base/PlainText.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/.svn/text-base/PlainText.php.svn-base
new file mode 100755
index 00000000..d7d82315
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/.svn/text-base/PlainText.php.svn-base
@@ -0,0 +1,363 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlEngineDb_ResultRenderer_PlainText implements SparqlEngineDb_ResultRenderer
+{
+
+ /**
+ * Defines the methods needed to create the types
+ * in $arVarAssignments.
+ * Key is the type (e.g. "s" for subject), and
+ * value the method's name.
+ *
+ * @see $arVarAssignments
+ *
+ * @var array
+ */
+ protected $arCreationMethods = array(
+ 's' => 'createSubjectFromDbRecordSetPart',
+ 'p' => 'createPredicateFromDbRecordSetPart',
+ 'o' => 'createObjectFromDbRecordSetPart'
+ );
+
+
+
+ /**
+ * Converts the database results into the desired output format
+ * and returns the result.
+ *
+ * @param array $arRecordSets Array of (possibly several) SQL query results.
+ * @param Query $query SPARQL query object
+ * @param SparqlEngineDb $engine Sparql Engine to query the database
+ * @return mixed The result as rendered by the result renderers.
+ */
+ public function convertFromDbResults($arRecordSets, Query $query, SparqlEngineDb $engine)
+ {
+ $this->query = $query;
+ $this->engine = $engine;
+ $this->sg = $engine->getSqlGenerator();
+
+ $strResultForm = $this->query->getResultForm();
+ switch ($strResultForm) {
+ case 'construct':
+ case 'select':
+ case 'select distinct':
+ $arResult = $this->getVariableArrayFromRecordSets($arRecordSets, $strResultForm);
+
+ //some result forms need more modification
+ switch ($strResultForm) {
+ case 'construct';
+ $arResult = $this->constructGraph(
+ $arResult,
+ $this->query->getConstructPattern()
+ );
+ break;
+ case 'describe';
+ $arResult = $this->describeGraph($arResult);
+ break;
+ }
+
+ return $arResult;
+ break;
+
+ case 'count':
+ case 'ask':
+ if (count($arRecordSets) > 1) {
+ throw new Exception(
+ 'More than one result set for a '
+ . $strResultForm . ' query!'
+ );
+ }
+
+ $nCount = 0;
+ $dbRecordSet = reset($arRecordSets);
+ foreach ($dbRecordSet as $row) {
+ $nCount += intval($row['count']);
+ break;
+ }
+
+ if ($strResultForm == 'ask') {
+ return $nCount > 0;
+ } else {
+ return $nCount;
+ }
+ break;
+
+ case 'describe':
+ default:
+ throw new Exception('Unsupported result form: ' . $strResultForm);
+ }
+
+ }//public function convertFromDbResults($arRecordSets, Query $query, SparqlEngineDb $engine)
+
+
+
+
+ protected function getVariableArrayFromRecordSets($arRecordSets, $strResultForm)
+ {
+ $arResult = array();
+ foreach ($arRecordSets as $dbRecordSet) {
+ $arResult = array_merge(
+ $arResult,
+ $this->getVariableArrayFromRecordSet($dbRecordSet, $strResultForm)
+ );
+ }
+ return $arResult;
+ }//protected function getVariableArrayFromRecordSets($arRecordSets, $strResultForm)
+
+
+
+ /**
+ * Converts a ADORecordSet object into an array of "rows" that
+ * are subarrays of variable => value pairs.
+ *
+ * @param ADORecordSet $dbRecordSet Anything ADOConnection::Execute() can return
+ * @return array
+ */
+ protected function getVariableArrayFromRecordSet(ADORecordSet $dbRecordSet, $strResultForm)
+ {
+ $arResult = array();
+ switch ($strResultForm) {
+ case 'construct':
+ $arResultVars = $this->query->getConstructPatternVariables();
+ break;
+ default:
+ $arResultVars = $this->query->getResultVars();
+ break;
+ }
+
+ if (in_array('*', $arResultVars)) {
+ $arResultVars = array_keys($this->sg->arVarAssignments);
+ }
+
+ //work around bug in adodb:
+ // ADORecordSet_empty does not implement php5 iterators
+ if ($dbRecordSet->RowCount() <= 0) {
+ return array();
+ }
+
+ foreach ($dbRecordSet as $row) {
+ $arResultRow = array();
+ foreach ($arResultVars as $strVar) {
+ $strVarName = (string)$strVar;
+ if (!isset($this->sg->arVarAssignments[$strVarName])) {
+ //variable is in select, but not in result (test: q-select-2)
+ $arResultRow[$strVarName] = '';
+ } else {
+ $arVarSettings = $this->sg->arVarAssignments[$strVarName];
+ $strMethod = $this->arCreationMethods[$arVarSettings[1]];
+ $arResultRow[$strVarName] = $this->$strMethod($dbRecordSet, $arVarSettings[0], $strVar);
+ }
+ }
+ $arResult[] = $arResultRow;
+ }
+ return $arResult;
+ }//function getVariableArrayFromRecordSet(ADORecordSet $dbRecordSet)
+
+
+
+ /**
+ * Creates an RDF Statement object for one of the variables
+ * contained in the given $dbRecordSet object.
+ *
+ * @see convertFromDbResult() to understand $strVarBase necessity
+ *
+ * @param ADORecordSet $dbRecordSet Record set returned from ADOConnection::Execute()
+ * @param string $strVarBase Prefix of the columns the recordset fields have.
+ *
+ * @return Statement RDF statement object
+ */
+ protected function createStatementFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase)
+ {
+ return new Statement(
+ $this->createSubjectFromDbRecordSetPart ($dbRecordSet, $strVarBase),
+ $this->createPredicateFromDbRecordSetPart($dbRecordSet, $strVarBase),
+ $this->createObjectFromDbRecordSetPart ($dbRecordSet, $strVarBase)
+ );
+ }//protected function createStatementFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase)
+
+
+
+ /**
+ * Creates an RDF subject object
+ * contained in the given $dbRecordSet object.
+ *
+ * @see convertFromDbResult() to understand $strVarBase necessity
+ *
+ * @param ADORecordSet $dbRecordSet Record set returned from ADOConnection::Execute()
+ * @param string $strVarBase Prefix of the columns the recordset fields have.
+ *
+ * @return Resource RDF triple subject resource object
+ */
+ protected function createSubjectFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+ {
+ $strVarName = (string)$strVar;
+ if ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']] === null) {
+ //FIXME: should be NULL, but doesn't pass test
+ return '';
+ }
+
+ if ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_is']] == 'r'
+ //null should be predicate which is always a resource
+ || $dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_is']] === null
+ ) {
+ return $this->createResource($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ } else {
+ return $this->createBlankNode($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ }
+ return $subject;
+ }//protected function createSubjectFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+
+
+
+ /**
+ * Creates an RDF predicate object
+ * contained in the given $dbRecordSet object.
+ *
+ * @see convertFromDbResult() to understand $strVarBase necessity
+ *
+ * @param ADORecordSet $dbRecordSet Record set returned from ADOConnection::Execute()
+ * @param string $strVarBase Prefix of the columns the recordset fields have.
+ *
+ * @return Resource RDF triple predicate resource object
+ */
+ protected function createPredicateFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+ {
+ $strVarName = (string)$strVar;
+ if ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']] === null) {
+ //FIXME: should be NULL, but doesn't pass test
+ return '';
+ }
+ return $this->createResource($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ }//protected function createPredicateFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+
+
+
+ /**
+ * Creates an RDF object object
+ * contained in the given $dbRecordSet object.
+ *
+ * @see convertFromDbResult() to understand $strVarBase necessity
+ *
+ * @param ADORecordSet $dbRecordSet Record set returned from ADOConnection::Execute()
+ * @param string $strVarBase Prefix of the columns the recordset fields have.
+ *
+ * @return Resource RDF triple object resource object
+ */
+ protected function createObjectFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+ {
+ $strVarName = (string)$strVar;
+ if ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']] === null) {
+ //FIXME: should be NULL, but doesn't pass test
+ return '';
+ }
+ switch ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_is']]) {
+ case 'r':
+ return $this->createResource($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ break;
+ case 'b':
+ return $this->createBlankNode($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ break;
+ default:
+ return $this->createLiteral(
+ $dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']],
+ $dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_lang']],
+ $dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_type']]
+ );
+ }
+ }//protected function createObjectFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+
+
+
+ /**
+ * Constructs a result graph.
+ *
+ * @param array $arVartable A table containing the result vars and their bindings
+ * @param GraphPattern $constructPattern The CONSTRUCT pattern
+ * @return MemModel The result graph which matches the CONSTRUCT pattern
+ */
+ protected function constructGraph($arVartable, $constructPattern)
+ {
+ $resultGraph = new MemModel();
+
+ if (!$arVartable) {
+ return $resultGraph;
+ }
+
+ $tp = $constructPattern->getTriplePatterns();
+
+ $bnode = 0;
+ foreach ($arVartable as $value) {
+ foreach ($tp as $triple) {
+ $sub = $triple->getSubject();
+ $pred = $triple->getPredicate();
+ $obj = $triple->getObject();
+
+ if (is_string($sub) && $sub{1} == '_') {
+ $sub = new BlankNode("_bN".$bnode);
+ }
+ if (is_string($pred) && $pred{1} == '_') {
+ $pred = new BlankNode("_bN".$bnode);
+ }
+ if (is_string($obj) && $obj{1} == '_') {
+ $obj = new BlankNode("_bN".$bnode);
+ }
+
+
+ if (is_string($sub)) {
+ $sub = $value[$sub];
+ }
+ if (is_string($pred)) {
+ $pred = $value[$pred];
+ }
+ if (is_string($obj)) {
+ $obj = $value[$obj];
+ }
+
+ if ($sub !== "" && $pred !== "" && $obj !== "") {
+ $resultGraph->add(new Statement($sub,$pred,$obj));
+ }
+ }
+ $bnode++;
+ }
+ return $resultGraph;
+ }//protected function constructGraph($arVartable, $constructPattern)
+
+
+
+ protected function createResource($uri)
+ {
+ return 'R<' . $uri . '>';
+ }//protected function createResource($uri)
+
+
+
+ protected function createBlankNode($id)
+ {
+ return 'B(' . $id . ')';
+ }//protected function createBlankNode($id)
+
+
+
+ protected function createLiteral($value, $language, $datatype)
+ {
+ $v = 'L(' . $value;
+ if ($language != null) {
+ $v .= '@' . $language;
+ }
+ if ($datatype != null) {
+ $v .= '^^' . $datatype;
+ }
+ return $v . ')';
+ }//protected function createLiteral($value, $language, $datatype)
+
+}//class SparqlEngineDb_ResultRenderer_PlainText implements SparqlEngineDb_ResultRenderer
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/.svn/text-base/XML.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/.svn/text-base/XML.php.svn-base
new file mode 100755
index 00000000..6c24bb67
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/.svn/text-base/XML.php.svn-base
@@ -0,0 +1,336 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlEngineDb_ResultRenderer_XML implements SparqlEngineDb_ResultRenderer
+{
+
+ /**
+ * Defines the methods needed to create the types
+ * in $arVarAssignments.
+ * Key is the type (e.g. "s" for subject), and
+ * value the method's name.
+ *
+ * @see $arVarAssignments
+ *
+ * @var array
+ */
+ protected $arCreationMethods = array(
+ 's' => 'createSubjectFromDbRecordSetPart',
+ 'p' => 'createPredicateFromDbRecordSetPart',
+ 'o' => 'createObjectFromDbRecordSetPart'
+ );
+
+
+
+ /**
+ * Converts the database results into nice HTML.
+ *
+ * @param array $arRecordSets Array of (possibly several) SQL query results.
+ * @param Query $query SPARQL query object
+ * @param SparqlEngineDb $engine Sparql Engine to query the database
+ * @return mixed HTML code
+ */
+ public function convertFromDbResults($arRecordSets, Query $query, SparqlEngineDb $engine)
+ {
+ $this->query = $query;
+ $this->sg = $engine->getSqlGenerator();
+ $strCode = '';
+
+ $strResultForm = $query->getResultForm();
+ switch ($strResultForm) {
+ case 'select':
+ case 'select distinct':
+ $strCode = $this->createFromRecords($arRecordSets, $strResultForm);
+ break;
+
+ case 'construct':
+ case 'describe':
+ throw new Exception(
+ 'Construct and describe are not supported by the'
+ . ' XML renderer'
+ );
+
+ case 'count':
+ case 'ask':
+ if (count($arRecordSets) > 1) {
+ throw new Exception(
+ 'More than one result set for a '
+ . $strResultForm . ' query!'
+ );
+ }
+
+ $nCount = 0;
+ $dbRecordSet = reset($arRecordSets);
+ foreach ($dbRecordSet as $row) {
+ $nCount += intval($row['count']);
+ break;
+ }
+
+ if ($strResultForm == 'ask') {
+ $strCode = $this->getHead()
+ . ' '
+ . self::getSpokenBoolean($nCount > 0)
+ . '';
+ } else {
+ $strCode = $this->getHead()
+ . ' '
+ . $nCount
+ . '';
+ }
+ break;
+
+ default:
+ throw new Exception('Unsupported result form: ' . $strResultForm);
+ }
+
+ return $this->wrapCode($strCode);
+ }//public function convertFromDbResults($arRecordSets, Query $query, SparqlEngineDb $engine)
+
+
+
+ protected function wrapCode($strCode)
+ {
+ return <<
+
+
+EOT
+ . $strCode . "\n"
+ . "\n";
+ }//protected function wrapCode($strCode)
+
+
+
+ protected function getHead($strXml = '')
+ {
+ return " \n"
+ . $strXml
+ . " \n";
+ }//protected function getHead($strXml = '')
+
+
+
+ protected function createFromRecords($arRecordSets, $strResultForm)
+ {
+ $arResultVars = $this->query->getResultVars();
+
+ if (in_array('*', $arResultVars)) {
+ $arResultVars = array_keys($this->sg->arVarAssignments);
+ }
+
+ $strVarXML = '';
+ foreach ($arResultVars as $var) {
+ $strVarXML .= " \n";
+ }
+
+ $strHeadXml = $this->getHead($strVarXML);
+
+ $arResult = array();
+ foreach ($arRecordSets as $dbRecordSet) {
+ //work around bug in adodb:
+ // ADORecordSet_empty does not implement php5 iterators
+ if ($dbRecordSet->RowCount() <= 0) {
+
+ return
+ $strHeadXml
+ . ' ' . "\n"
+ . ' ' . PHP_EOL
+ . " \n";
+ }
+
+ foreach ($dbRecordSet as $row) {
+ $arResultRow = array();
+ foreach ($arResultVars as $strVar) {
+ $strVarName = (string)$strVar;
+ if (!isset($this->sg->arVarAssignments[$strVarName])) {
+ //variable is in select, but not in result (test: q-select-2)
+ $arResultRow[$strVarName] = '';
+ } else {
+ $arVarSettings = $this->sg->arVarAssignments[$strVarName];
+ $strMethod = $this->arCreationMethods[$arVarSettings[1]];
+ $arResultRow[$strVarName] = $this->$strMethod($dbRecordSet, $arVarSettings[0], $strVar);
+ }
+ }
+ $arResult[] = $arResultRow;
+ }
+ }
+
+
+ $arSM = $this->query->getSolutionModifier();
+
+ return
+ $strHeadXml
+ . ' ' . "\n"
+ . $this->getResultXml($arResult)
+ . " \n";
+ }//protected function createFromRecords($arRecordSets)
+
+
+
+ protected function getResultXml($arResult)
+ {
+ $strCode = '';
+ foreach ($arResult as $arSet) {
+ $strCode .= " \n";
+ foreach ($arSet as $strVarName => $strValue) {
+ if ($strValue !== null) {
+ $strCode .= ' '
+ . $strValue
+ . "\n";
+ }
+ }
+ $strCode .= " \n";
+ }
+ return $strCode;
+ }//protected function getResultXml($arResult)
+
+
+
+ protected static function getSpokenBoolean($b)
+ {
+ return $b ? 'true' : 'false';
+ }//protected static function getSpokenBoolean($b)
+
+
+
+ /**
+ * Creates an RDF subject object
+ * contained in the given $dbRecordSet object.
+ *
+ * @see convertFromDbResult() to understand $strVarBase necessity
+ *
+ * @param ADORecordSet $dbRecordSet Record set returned from ADOConnection::Execute()
+ * @param string $strVarBase Prefix of the columns the recordset fields have.
+ *
+ * @return string HTML code
+ */
+ protected function createSubjectFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+ {
+ $strVarName = (string)$strVar;
+ if ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']] === null) {
+ return $this->getXmlNull();
+ }
+ if ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_is']] == 'r'
+ //null should be predicate which is always a resource
+ || $dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_is']] === null
+ ) {
+ return $this->getXmlResource($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ } else {
+ return $this->getXmlBlank($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ }
+ }//protected function createSubjectFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+
+
+
+ /**
+ * Creates an RDF predicate object
+ * contained in the given $dbRecordSet object.
+ *
+ * @see convertFromDbResult() to understand $strVarBase necessity
+ *
+ * @param ADORecordSet $dbRecordSet Record set returned from ADOConnection::Execute()
+ * @param string $strVarBase Prefix of the columns the recordset fields have.
+ *
+ * @return string HTML code
+ */
+ protected function createPredicateFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+ {
+ $strVarName = (string)$strVar;
+ if ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']] === null) {
+ return $this->getXmlNull();
+ }
+
+ return $this->getXmlResource($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ }//protected function createPredicateFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+
+
+
+ /**
+ * Creates an RDF object object
+ * contained in the given $dbRecordSet object.
+ *
+ * @see convertFromDbResult() to understand $strVarBase necessity
+ *
+ * @param ADORecordSet $dbRecordSet Record set returned from ADOConnection::Execute()
+ * @param string $strVarBase Prefix of the columns the recordset fields have.
+ *
+ * @return string HTML code
+ */
+ protected function createObjectFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+ {
+ $strVarName = (string)$strVar;
+ if ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']] === null) {
+ return $this->getXmlNull();
+ }
+ switch ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_is']]) {
+ case 'r':
+ return $this->getXmlResource($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ break;
+ case 'b':
+ return $this->getXmlBlank($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ break;
+ default:
+ return $this->getXmlLiteral(
+ $dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']],
+ $dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_lang']],
+ $dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_type']]
+ );
+ }
+ }//protected function createObjectFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+
+
+
+ protected function getXmlNull()
+ {
+ return null;
+ }//protected function getHtmlNull()
+
+
+
+ protected function getXmlBlank($value)
+ {
+ return '' . $value . '';
+ }//protected function getHtmlBlank($value)
+
+
+
+ protected function getXmlResource($value)
+ {
+ return '' . htmlspecialchars($value) . '';
+ }//protected function getHtmlResource($value)
+
+
+
+ protected function getXmlLiteral($value, $language, $datatype)
+ {
+ $strCode = '';
+ return $strCode;
+ }//protected function getHtmlLiteral($value, $language, $datatype)
+
+}//class SparqlEngineDb_ResultRenderer_XML implements SparqlEngineDb_ResultRenderer
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/Default.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/Default.php
new file mode 100755
index 00000000..45276f36
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/Default.php
@@ -0,0 +1,339 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlEngineDb_ResultRenderer_Default implements SparqlEngineDb_ResultRenderer
+{
+
+ /**
+ * Defines the methods needed to create the types
+ * in $arVarAssignments.
+ * Key is the type (e.g. "s" for subject), and
+ * value the method's name.
+ *
+ * @see $arVarAssignments
+ *
+ * @var array
+ */
+ protected $arCreationMethods = array(
+ 's' => 'createSubjectFromDbRecordSetPart',
+ 'p' => 'createPredicateFromDbRecordSetPart',
+ 'o' => 'createObjectFromDbRecordSetPart'
+ );
+
+
+
+ /**
+ * Converts the database results into the desired output format
+ * and returns the result.
+ *
+ * @param array $arRecordSets Array of (possibly several) SQL query results.
+ * @param Query $query SPARQL query object
+ * @param SparqlEngineDb $engine Sparql Engine to query the database
+ * @return mixed The result as rendered by the result renderers.
+ */
+ public function convertFromDbResults($arRecordSets, Query $query, SparqlEngineDb $engine)
+ {
+ $this->query = $query;
+ $this->engine = $engine;
+ $this->sg = $engine->getSqlGenerator();
+
+ $strResultForm = $this->query->getResultForm();
+ switch ($strResultForm) {
+ case 'construct':
+ case 'select':
+ case 'select distinct':
+ $arResult = $this->getVariableArrayFromRecordSets($arRecordSets, $strResultForm);
+
+ //some result forms need more modification
+ switch ($strResultForm) {
+ case 'construct';
+ $arResult = $this->constructGraph(
+ $arResult,
+ $this->query->getConstructPattern()
+ );
+ break;
+ case 'describe';
+ $arResult = $this->describeGraph($arResult);
+ break;
+ }
+
+ return $arResult;
+ break;
+
+ case 'count':
+ case 'ask':
+ if (count($arRecordSets) > 1) {
+ throw new Exception(
+ 'More than one result set for a '
+ . $strResultForm . ' query!'
+ );
+ }
+
+ $nCount = 0;
+ $dbRecordSet = reset($arRecordSets);
+ foreach ($dbRecordSet as $row) {
+ $nCount += intval($row['count']);
+ break;
+ }
+
+ if ($strResultForm == 'ask') {
+ return $nCount > 0;
+ } else {
+ return $nCount;
+ }
+ break;
+
+ case 'describe':
+ default:
+ throw new Exception('Unsupported result form: ' . $strResultForm);
+ }
+
+ }//public function convertFromDbResults($arRecordSets, Query $query, SparqlEngineDb $engine)
+
+
+
+
+ protected function getVariableArrayFromRecordSets($arRecordSets, $strResultForm)
+ {
+ $arResult = array();
+ foreach ($arRecordSets as $dbRecordSet) {
+ $arResult = array_merge(
+ $arResult,
+ $this->getVariableArrayFromRecordSet($dbRecordSet, $strResultForm)
+ );
+ }
+ return $arResult;
+ }//protected function getVariableArrayFromRecordSets($arRecordSets, $strResultForm)
+
+
+
+ /**
+ * Converts a ADORecordSet object into an array of "rows" that
+ * are subarrays of variable => value pairs.
+ *
+ * @param ADORecordSet $dbRecordSet Anything ADOConnection::Execute() can return
+ * @return array
+ */
+ protected function getVariableArrayFromRecordSet(ADORecordSet $dbRecordSet, $strResultForm)
+ {
+ $arResult = array();
+ switch ($strResultForm) {
+ case 'construct':
+ $arResultVars = $this->query->getConstructPatternVariables();
+ break;
+ default:
+ $arResultVars = $this->query->getResultVars();
+ break;
+ }
+
+ if (in_array('*', $arResultVars)) {
+ $arResultVars = array_keys($this->sg->arVarAssignments);
+ }
+
+ //work around bug in adodb:
+ // ADORecordSet_empty does not implement php5 iterators
+ if ($dbRecordSet->RowCount() <= 0) {
+ return array();
+ }
+
+ foreach ($dbRecordSet as $row) {
+ $arResultRow = array();
+ foreach ($arResultVars as $strVar) {
+ $strVarName = (string)$strVar;
+ if (!isset($this->sg->arVarAssignments[$strVarName])) {
+ //variable is in select, but not in result (test: q-select-2)
+ $arResultRow[$strVarName] = '';
+ } else {
+ $arVarSettings = $this->sg->arVarAssignments[$strVarName];
+ $strMethod = $this->arCreationMethods[$arVarSettings[1]];
+ $arResultRow[$strVarName] = $this->$strMethod($dbRecordSet, $arVarSettings[0], $strVar);
+ }
+ }
+ $arResult[] = $arResultRow;
+ }
+ return $arResult;
+ }//function getVariableArrayFromRecordSet(ADORecordSet $dbRecordSet)
+
+
+
+ /**
+ * Creates an RDF Statement object for one of the variables
+ * contained in the given $dbRecordSet object.
+ *
+ * @see convertFromDbResult() to understand $strVarBase necessity
+ *
+ * @param ADORecordSet $dbRecordSet Record set returned from ADOConnection::Execute()
+ * @param string $strVarBase Prefix of the columns the recordset fields have.
+ *
+ * @return Statement RDF statement object
+ */
+ protected function createStatementFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase)
+ {
+ return new Statement(
+ $this->createSubjectFromDbRecordSetPart ($dbRecordSet, $strVarBase),
+ $this->createPredicateFromDbRecordSetPart($dbRecordSet, $strVarBase),
+ $this->createObjectFromDbRecordSetPart ($dbRecordSet, $strVarBase)
+ );
+ }//protected function createStatementFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase)
+
+
+
+ /**
+ * Creates an RDF subject object
+ * contained in the given $dbRecordSet object.
+ *
+ * @see convertFromDbResult() to understand $strVarBase necessity
+ *
+ * @param ADORecordSet $dbRecordSet Record set returned from ADOConnection::Execute()
+ * @param string $strVarBase Prefix of the columns the recordset fields have.
+ *
+ * @return Resource RDF triple subject resource object
+ */
+ protected function createSubjectFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+ {
+ $strVarName = (string)$strVar;
+ if ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']] === null) {
+ //FIXME: should be NULL, but doesn't pass test
+ return '';
+ }
+
+ if ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_is']] == 'r'
+ //null should be predicate which is always a resource
+ || $dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_is']] === null
+ ) {
+ $subject = new Resource ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ } else {
+ $subject = new BlankNode($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ }
+ return $subject;
+ }//protected function createSubjectFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVarName)
+
+
+
+ /**
+ * Creates an RDF predicate object
+ * contained in the given $dbRecordSet object.
+ *
+ * @see convertFromDbResult() to understand $strVarBase necessity
+ *
+ * @param ADORecordSet $dbRecordSet Record set returned from ADOConnection::Execute()
+ * @param string $strVarBase Prefix of the columns the recordset fields have.
+ *
+ * @return Resource RDF triple predicate resource object
+ */
+ protected function createPredicateFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+ {
+ $strVarName = (string)$strVar;
+ if ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']] === null) {
+ //FIXME: should be NULL, but doesn't pass test
+ return '';
+ }
+ $predicate = new Resource ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ return $predicate;
+ }//protected function createPredicateFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVarName)
+
+
+
+ /**
+ * Creates an RDF object object
+ * contained in the given $dbRecordSet object.
+ *
+ * @see convertFromDbResult() to understand $strVarBase necessity
+ *
+ * @param ADORecordSet $dbRecordSet Record set returned from ADOConnection::Execute()
+ * @param string $strVarBase Prefix of the columns the recordset fields have.
+ *
+ * @return Resource RDF triple object resource object
+ */
+ protected function createObjectFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+ {
+ $strVarName = (string)$strVar;
+ if ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']] === null) {
+ //FIXME: should be NULL, but doesn't pass test
+ return '';
+ }
+ switch ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_is']]) {
+ case 'r':
+ $object = new Resource ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ break;
+ case 'b':
+ $object = new BlankNode($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ break;
+ default:
+ $object = new Literal(
+ $dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']],
+ $dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_lang']]
+ );
+ if ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_type']]) {
+ $object->setDatatype($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_type']]);
+ }
+ }
+ return $object;
+ }//protected function createObjectFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVarName)
+
+
+
+ /**
+ * Constructs a result graph.
+ *
+ * @param array $arVartable A table containing the result vars and their bindings
+ * @param GraphPattern $constructPattern The CONSTRUCT pattern
+ * @return MemModel The result graph which matches the CONSTRUCT pattern
+ */
+ protected function constructGraph($arVartable, $constructPattern)
+ {
+ $resultGraph = new MemModel();
+
+ if (!$arVartable) {
+ return $resultGraph;
+ }
+
+ $tp = $constructPattern->getTriplePatterns();
+
+ $bnode = 0;
+ foreach ($arVartable as $value) {
+ foreach ($tp as $triple) {
+ $sub = $triple->getSubject();
+ $pred = $triple->getPredicate();
+ $obj = $triple->getObject();
+
+ if (is_string($sub) && $sub{1} == '_') {
+ $sub = new BlankNode("_bN".$bnode);
+ }
+ if (is_string($pred) && $pred{1} == '_') {
+ $pred = new BlankNode("_bN".$bnode);
+ }
+ if (is_string($obj) && $obj{1} == '_') {
+ $obj = new BlankNode("_bN".$bnode);
+ }
+
+
+ if (is_string($sub)) {
+ $sub = $value[$sub];
+ }
+ if (is_string($pred)) {
+ $pred = $value[$pred];
+ }
+ if (is_string($obj)) {
+ $obj = $value[$obj];
+ }
+
+ if ($sub !== "" && $pred !== "" && $obj !== "") {
+ $resultGraph->add(new Statement($sub,$pred,$obj));
+ }
+ }
+ $bnode++;
+ }
+ return $resultGraph;
+ }//protected function constructGraph($arVartable, $constructPattern)
+
+}//class SparqlEngineDb_ResultRenderer_Default implements SparqlEngineDb_ResultRenderer
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/HTML.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/HTML.php
new file mode 100755
index 00000000..34dce3b0
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/HTML.php
@@ -0,0 +1,297 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlEngineDb_ResultRenderer_HTML implements SparqlEngineDb_ResultRenderer
+{
+ /**
+ * If the result HTML should be wrapped in a div
+ * @var boolean
+ */
+ protected $bWrap = true;
+
+ /**
+ * Defines the methods needed to create the types
+ * in $arVarAssignments.
+ * Key is the type (e.g. "s" for subject), and
+ * value the method's name.
+ *
+ * @see $arVarAssignments
+ *
+ * @var array
+ */
+ protected $arCreationMethods = array(
+ 's' => 'createSubjectFromDbRecordSetPart',
+ 'p' => 'createPredicateFromDbRecordSetPart',
+ 'o' => 'createObjectFromDbRecordSetPart'
+ );
+
+
+
+ /**
+ * Converts the database results into nice HTML.
+ *
+ * @param array $arRecordSets Array of (possibly several) SQL query results.
+ * @param Query $query SPARQL query object
+ * @param SparqlEngineDb $engine Sparql Engine to query the database
+ * @return mixed HTML code
+ */
+ public function convertFromDbResults($arRecordSets, Query $query, SparqlEngineDb $engine)
+ {
+ $this->query = $query;
+ $this->sg = $engine->getSqlGenerator();
+ $strCode = '';
+
+ $strResultForm = $query->getResultForm();
+ switch ($strResultForm) {
+ case 'select':
+ case 'select distinct':
+ $strCode = $this->createTableFromRecords($arRecordSets);
+ break;
+
+ case 'construct':
+ case 'describe':
+ throw new Exception(
+ 'Construct and describe are currently not supported by the'
+ . ' HTML renderer'
+ );
+
+ case 'count':
+ case 'ask':
+ if (count($arRecordSets) > 1) {
+ throw new Exception(
+ 'More than one result set for a '
+ . $strResultForm . ' query!'
+ );
+ }
+
+ $nCount = 0;
+ $dbRecordSet = reset($arRecordSets);
+ foreach ($dbRecordSet as $row) {
+ $nCount += intval($row['count']);
+ break;
+ }
+
+ if ($strResultForm == 'ask') {
+ $strCode = 'There were results.';
+ } else {
+ $strCode = 'There are ' . $nCount . ' results.';
+ }
+ break;
+
+ default:
+ throw new Exception('Unsupported result form: ' . $strResultForm);
+ }
+
+ return $this->wrapCode($strCode);
+ }//public function convertFromDbResults($arRecordSets, Query $query, SparqlEngineDb $engine)
+
+
+
+ protected function wrapCode($strCode)
+ {
+ if (!$this->bWrap) {
+ return $strCode;
+ }
+
+ return
+ '' . "\n"
+ . $strCode . "\n"
+ . "
\n";
+ }//protected function wrapCode($strCode)
+
+
+
+ protected function createTableFromRecords($arRecordSets)
+ {
+ $arResultVars = $this->query->getResultVars();
+
+ if (in_array('*', $arResultVars)) {
+ $arResultVars = array_keys($this->sg->arVarAssignments);
+ }
+
+ $arResult = array();
+ foreach ($arRecordSets as $dbRecordSet) {
+ //work around bug in adodb:
+ // ADORecordSet_empty does not implement php5 iterators
+ if ($dbRecordSet->RowCount() <= 0) {
+ return array();
+ }
+
+ foreach ($dbRecordSet as $row) {
+ $arResultRow = array();
+ foreach ($arResultVars as $strVar) {
+ $strVarName = (string)$strVar;
+ if (!isset($this->sg->arVarAssignments[$strVarName])) {
+ //variable is in select, but not in result (test: q-select-2)
+ $arResultRow[$strVarName] = '';
+ } else {
+ $arVarSettings = $this->sg->arVarAssignments[$strVarName];
+ $strMethod = $this->arCreationMethods[$arVarSettings[1]];
+ list($strCode, $strColor) = $this->$strMethod($dbRecordSet, $arVarSettings[0], $strVar);
+ $arResultRow[$strVarName] = '' . $strCode . ' | ';
+ }
+ }
+ $arResult[] = $arResultRow;
+ }
+ }
+
+ //I always wanted to to this :)
+ return
+ "\n"
+ . " SPARQL result with " . count($arResult) . " rows\n"
+ . " | "
+ . implode(' | ', array_keys(reset($arResult)))
+ . " | \n"
+ . " \n "
+ . implode(
+ "
\n ",
+ array_map(
+ create_function(
+ '$ar',
+ 'return implode("", $ar);'
+ ),
+ $arResult
+ )
+ )
+ . "
\n \n"
+ . "
\n";
+ }//protected function createTableFromRecords($arRecordSets)
+
+
+
+ /**
+ * Creates an RDF subject object
+ * contained in the given $dbRecordSet object.
+ *
+ * @see convertFromDbResult() to understand $strVarBase necessity
+ *
+ * @param ADORecordSet $dbRecordSet Record set returned from ADOConnection::Execute()
+ * @param string $strVarBase Prefix of the columns the recordset fields have.
+ *
+ * @return string HTML code
+ */
+ protected function createSubjectFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+ {
+ $strVarName = (string)$strVar;
+ if ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']] === null) {
+ return $this->getHtmlNull();
+ }
+ if ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_is']] == 'r'
+ //null should be predicate which is always a resource
+ || $dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_is']] === null
+ ) {
+ return $this->getHtmlResource($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ } else {
+ return $this->getHtmlBlank($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ }
+ }//protected function createSubjectFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+
+
+
+ /**
+ * Creates an RDF predicate object
+ * contained in the given $dbRecordSet object.
+ *
+ * @see convertFromDbResult() to understand $strVarBase necessity
+ *
+ * @param ADORecordSet $dbRecordSet Record set returned from ADOConnection::Execute()
+ * @param string $strVarBase Prefix of the columns the recordset fields have.
+ *
+ * @return string HTML code
+ */
+ protected function createPredicateFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+ {
+ $strVarName = (string)$strVar;
+ if ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']] === null) {
+ return $this->getHtmlNull();
+ }
+
+ return $this->getHtmlResource($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ }//protected function createPredicateFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+
+
+
+ /**
+ * Creates an RDF object object
+ * contained in the given $dbRecordSet object.
+ *
+ * @see convertFromDbResult() to understand $strVarBase necessity
+ *
+ * @param ADORecordSet $dbRecordSet Record set returned from ADOConnection::Execute()
+ * @param string $strVarBase Prefix of the columns the recordset fields have.
+ *
+ * @return string HTML code
+ */
+ protected function createObjectFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+ {
+ $strVarName = (string)$strVar;
+ if ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']] === null) {
+ return $this->getHtmlNull();
+ }
+ switch ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_is']]) {
+ case 'r':
+ return $this->getHtmlResource($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ break;
+ case 'b':
+ return $this->getHtmlBlank($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ break;
+ default:
+ return $this->getHtmlLiteral(
+ $dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']],
+ $dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_lang']],
+ $dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_type']]
+ );
+ }
+ }//protected function createObjectFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+
+
+
+ protected function getHtmlNull()
+ {
+ return array('NULL
', '#FFF');
+ }//protected function getHtmlNull()
+
+
+
+ protected function getHtmlBlank($value)
+ {
+ return array('Blank node', HTML_TABLE_BNODE_COLOR);
+ }//protected function getHtmlBlank($value)
+
+
+
+ protected function getHtmlResource($value)
+ {
+ return array(
+ htmlspecialchars($value),
+ HTML_TABLE_RESOURCE_COLOR
+ );
+ }//protected function getHtmlResource($value)
+
+
+
+ protected function getHtmlLiteral($value, $language, $datatype)
+ {
+ $strCode = htmlspecialchars($value);
+ if ($language) {
+ $strCode . ' xml:lang=' . $language;
+ }
+ if ($datatype) {
+ $strCode . ' rdf:type=' . $datatype;
+ }
+ return array($strCode, HTML_TABLE_LITERAL_COLOR);
+ }//protected function getHtmlLiteral($value, $language, $datatype)
+
+
+}//class SparqlEngineDb_ResultRenderer_HTML implements SparqlEngineDb_ResultRenderer
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/JSON.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/JSON.php
new file mode 100755
index 00000000..16d6bea9
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/JSON.php
@@ -0,0 +1,174 @@
+query = $query;
+ $this->sg = $engine->getSqlGenerator();
+ $strResultForm = $query->getResultForm();
+
+ foreach ($this->getResultVars() as $var)
+ $ResultVarsTemp[] = substr($var,1);
+
+ switch ($strResultForm) {
+ case 'select':
+ case 'select distinct':
+ $results = $this->createFromRecords($arRecordSets, $strResultForm);
+ $strCode = json_encode(array(
+ 'head' => array('vars'=>$ResultVarsTemp),
+ 'results'=>array('bindings'=>$results))
+ );
+ //$strCode = str_replace(',{',','.PHP_EOL.'{',$strCode);
+ break;
+ case 'construct':
+ case 'describe':
+ throw new Exception(
+ 'Construct and describe are not supported by the'
+ . ' JSON renderer'
+ );
+
+ case 'count':
+ case 'ask':
+ if (count($arRecordSets) > 1) {
+ throw new Exception(
+ 'More than one result set for a '
+ . $strResultForm . ' query not supported by JSON Renderer'
+ );
+ }
+
+ $nCount = 0;
+ $dbRecordSet = reset($arRecordSets);
+ foreach ($dbRecordSet as $row) {
+ $nCount += intval($row['count']);
+ break;
+ }
+
+ if ($strResultForm == 'ask') {
+ $strcode = json_encode(array('boolean' => ($nCount > 0)));
+ } else {
+ $strcode = json_encode(array('int' => $nCount ));
+ }
+ break;
+ default:
+ throw new Exception('Error');
+ }
+
+ return $strCode;
+
+
+ }
+ /**
+ * Method to create from record with specific resultform (not used yet)
+ *
+ * @param array $arRecordSets Array of (possibly several) SQL query results.
+ * @param unknown_type $strResultForm
+ * @return array ready for json conversion
+ */
+ protected function createFromRecords($arRecordSets, $strResultForm) {
+
+ $arVarAssignments = $this->sg->arVarAssignments;
+ $code = '';
+ $arResultVars = $this ->getResultVars();
+ $results = array();
+ foreach ($arRecordSets[0] as $value) {
+ $node = array();
+ foreach ($arResultVars as $ResultVar) {
+ $nodeType = $value[$arVarAssignments[$ResultVar][0].'.'.$arVarAssignments[$ResultVar]['sql_is']];
+ if ($nodeType == 'r') {
+ $node[substr($ResultVar,1)] = array('type'=> 'uri','value'=>$value[$arVarAssignments[$ResultVar][0].'.'.$arVarAssignments[$ResultVar]['sql_value']]);
+
+ }
+
+ if ($value[$arVarAssignments[$ResultVar][0].'.'.$arVarAssignments[$ResultVar]['sql_is']] == 'l') {
+ $literalType = $value[$arVarAssignments[$ResultVar][0] .
+ '.' . $arVarAssignments[$ResultVar]['sql_type']];
+ $literalLang = $value[$arVarAssignments[$ResultVar][0] .
+ '.' . $arVarAssignments[$ResultVar]['sql_lang']];
+ $literalValue = $value[$arVarAssignments[$ResultVar][0] .
+ '.' . $arVarAssignments[$ResultVar]['sql_value']];
+ $node[substr($ResultVar,1)] = $this->getLiteral($literalValue,$literalLang,$literalType);
+ }
+
+ if ($nodeType === 'b') {
+ $literalValue = $value[$arVarAssignments[$ResultVar][0].'.'.$arVarAssignments[$ResultVar]['sql_value']];
+ $node[substr($ResultVar,1)] = array ('type'=>'bnode' ,'value'=>$value[$arVarAssignments[$ResultVar][0].'.'.$arVarAssignments[$ResultVar]['sql_value']]);
+ }
+ }
+ $results[]=$node;
+
+
+ }
+ return $results;
+
+ }
+
+ /**
+ * COnverting Literals to array ready for json
+ *
+ * @param unknown_type $value
+ * @param unknown_type $lang
+ * @param unknown_type $type
+ * @return unknown
+ */
+ private function getLiteral($value, $lang , $type) {
+
+ $ret = array();
+
+ $type = 'literal';
+
+ if ($value != 'literal') {
+ $ret['value'] = $value;
+ }
+
+ if ($lang != '') {
+ $ret['lang'] = $lang;
+ }
+
+ if ($type != '') {
+ $ret['type'] = $type;
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Giving array of used Vars also resolves the all-quantifier *
+ *
+ * @return array of vars as strings
+ */
+ protected function getResultVars() {
+ $arResultVars = $this->query->getResultVars();
+ if (in_array('*', $arResultVars)) {
+ $arResultVars = array_keys($this->sg->arVarAssignments);
+ } else {
+ $arResultVars = array();
+ foreach ($this->query->getResultVars() as $Var) {
+ $arResultVars[] = (string) $Var;
+ }
+ }
+
+ return $arResultVars;
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/PlainText.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/PlainText.php
new file mode 100755
index 00000000..d7d82315
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/PlainText.php
@@ -0,0 +1,363 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlEngineDb_ResultRenderer_PlainText implements SparqlEngineDb_ResultRenderer
+{
+
+ /**
+ * Defines the methods needed to create the types
+ * in $arVarAssignments.
+ * Key is the type (e.g. "s" for subject), and
+ * value the method's name.
+ *
+ * @see $arVarAssignments
+ *
+ * @var array
+ */
+ protected $arCreationMethods = array(
+ 's' => 'createSubjectFromDbRecordSetPart',
+ 'p' => 'createPredicateFromDbRecordSetPart',
+ 'o' => 'createObjectFromDbRecordSetPart'
+ );
+
+
+
+ /**
+ * Converts the database results into the desired output format
+ * and returns the result.
+ *
+ * @param array $arRecordSets Array of (possibly several) SQL query results.
+ * @param Query $query SPARQL query object
+ * @param SparqlEngineDb $engine Sparql Engine to query the database
+ * @return mixed The result as rendered by the result renderers.
+ */
+ public function convertFromDbResults($arRecordSets, Query $query, SparqlEngineDb $engine)
+ {
+ $this->query = $query;
+ $this->engine = $engine;
+ $this->sg = $engine->getSqlGenerator();
+
+ $strResultForm = $this->query->getResultForm();
+ switch ($strResultForm) {
+ case 'construct':
+ case 'select':
+ case 'select distinct':
+ $arResult = $this->getVariableArrayFromRecordSets($arRecordSets, $strResultForm);
+
+ //some result forms need more modification
+ switch ($strResultForm) {
+ case 'construct';
+ $arResult = $this->constructGraph(
+ $arResult,
+ $this->query->getConstructPattern()
+ );
+ break;
+ case 'describe';
+ $arResult = $this->describeGraph($arResult);
+ break;
+ }
+
+ return $arResult;
+ break;
+
+ case 'count':
+ case 'ask':
+ if (count($arRecordSets) > 1) {
+ throw new Exception(
+ 'More than one result set for a '
+ . $strResultForm . ' query!'
+ );
+ }
+
+ $nCount = 0;
+ $dbRecordSet = reset($arRecordSets);
+ foreach ($dbRecordSet as $row) {
+ $nCount += intval($row['count']);
+ break;
+ }
+
+ if ($strResultForm == 'ask') {
+ return $nCount > 0;
+ } else {
+ return $nCount;
+ }
+ break;
+
+ case 'describe':
+ default:
+ throw new Exception('Unsupported result form: ' . $strResultForm);
+ }
+
+ }//public function convertFromDbResults($arRecordSets, Query $query, SparqlEngineDb $engine)
+
+
+
+
+ protected function getVariableArrayFromRecordSets($arRecordSets, $strResultForm)
+ {
+ $arResult = array();
+ foreach ($arRecordSets as $dbRecordSet) {
+ $arResult = array_merge(
+ $arResult,
+ $this->getVariableArrayFromRecordSet($dbRecordSet, $strResultForm)
+ );
+ }
+ return $arResult;
+ }//protected function getVariableArrayFromRecordSets($arRecordSets, $strResultForm)
+
+
+
+ /**
+ * Converts a ADORecordSet object into an array of "rows" that
+ * are subarrays of variable => value pairs.
+ *
+ * @param ADORecordSet $dbRecordSet Anything ADOConnection::Execute() can return
+ * @return array
+ */
+ protected function getVariableArrayFromRecordSet(ADORecordSet $dbRecordSet, $strResultForm)
+ {
+ $arResult = array();
+ switch ($strResultForm) {
+ case 'construct':
+ $arResultVars = $this->query->getConstructPatternVariables();
+ break;
+ default:
+ $arResultVars = $this->query->getResultVars();
+ break;
+ }
+
+ if (in_array('*', $arResultVars)) {
+ $arResultVars = array_keys($this->sg->arVarAssignments);
+ }
+
+ //work around bug in adodb:
+ // ADORecordSet_empty does not implement php5 iterators
+ if ($dbRecordSet->RowCount() <= 0) {
+ return array();
+ }
+
+ foreach ($dbRecordSet as $row) {
+ $arResultRow = array();
+ foreach ($arResultVars as $strVar) {
+ $strVarName = (string)$strVar;
+ if (!isset($this->sg->arVarAssignments[$strVarName])) {
+ //variable is in select, but not in result (test: q-select-2)
+ $arResultRow[$strVarName] = '';
+ } else {
+ $arVarSettings = $this->sg->arVarAssignments[$strVarName];
+ $strMethod = $this->arCreationMethods[$arVarSettings[1]];
+ $arResultRow[$strVarName] = $this->$strMethod($dbRecordSet, $arVarSettings[0], $strVar);
+ }
+ }
+ $arResult[] = $arResultRow;
+ }
+ return $arResult;
+ }//function getVariableArrayFromRecordSet(ADORecordSet $dbRecordSet)
+
+
+
+ /**
+ * Creates an RDF Statement object for one of the variables
+ * contained in the given $dbRecordSet object.
+ *
+ * @see convertFromDbResult() to understand $strVarBase necessity
+ *
+ * @param ADORecordSet $dbRecordSet Record set returned from ADOConnection::Execute()
+ * @param string $strVarBase Prefix of the columns the recordset fields have.
+ *
+ * @return Statement RDF statement object
+ */
+ protected function createStatementFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase)
+ {
+ return new Statement(
+ $this->createSubjectFromDbRecordSetPart ($dbRecordSet, $strVarBase),
+ $this->createPredicateFromDbRecordSetPart($dbRecordSet, $strVarBase),
+ $this->createObjectFromDbRecordSetPart ($dbRecordSet, $strVarBase)
+ );
+ }//protected function createStatementFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase)
+
+
+
+ /**
+ * Creates an RDF subject object
+ * contained in the given $dbRecordSet object.
+ *
+ * @see convertFromDbResult() to understand $strVarBase necessity
+ *
+ * @param ADORecordSet $dbRecordSet Record set returned from ADOConnection::Execute()
+ * @param string $strVarBase Prefix of the columns the recordset fields have.
+ *
+ * @return Resource RDF triple subject resource object
+ */
+ protected function createSubjectFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+ {
+ $strVarName = (string)$strVar;
+ if ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']] === null) {
+ //FIXME: should be NULL, but doesn't pass test
+ return '';
+ }
+
+ if ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_is']] == 'r'
+ //null should be predicate which is always a resource
+ || $dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_is']] === null
+ ) {
+ return $this->createResource($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ } else {
+ return $this->createBlankNode($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ }
+ return $subject;
+ }//protected function createSubjectFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+
+
+
+ /**
+ * Creates an RDF predicate object
+ * contained in the given $dbRecordSet object.
+ *
+ * @see convertFromDbResult() to understand $strVarBase necessity
+ *
+ * @param ADORecordSet $dbRecordSet Record set returned from ADOConnection::Execute()
+ * @param string $strVarBase Prefix of the columns the recordset fields have.
+ *
+ * @return Resource RDF triple predicate resource object
+ */
+ protected function createPredicateFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+ {
+ $strVarName = (string)$strVar;
+ if ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']] === null) {
+ //FIXME: should be NULL, but doesn't pass test
+ return '';
+ }
+ return $this->createResource($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ }//protected function createPredicateFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+
+
+
+ /**
+ * Creates an RDF object object
+ * contained in the given $dbRecordSet object.
+ *
+ * @see convertFromDbResult() to understand $strVarBase necessity
+ *
+ * @param ADORecordSet $dbRecordSet Record set returned from ADOConnection::Execute()
+ * @param string $strVarBase Prefix of the columns the recordset fields have.
+ *
+ * @return Resource RDF triple object resource object
+ */
+ protected function createObjectFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+ {
+ $strVarName = (string)$strVar;
+ if ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']] === null) {
+ //FIXME: should be NULL, but doesn't pass test
+ return '';
+ }
+ switch ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_is']]) {
+ case 'r':
+ return $this->createResource($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ break;
+ case 'b':
+ return $this->createBlankNode($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ break;
+ default:
+ return $this->createLiteral(
+ $dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']],
+ $dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_lang']],
+ $dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_type']]
+ );
+ }
+ }//protected function createObjectFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+
+
+
+ /**
+ * Constructs a result graph.
+ *
+ * @param array $arVartable A table containing the result vars and their bindings
+ * @param GraphPattern $constructPattern The CONSTRUCT pattern
+ * @return MemModel The result graph which matches the CONSTRUCT pattern
+ */
+ protected function constructGraph($arVartable, $constructPattern)
+ {
+ $resultGraph = new MemModel();
+
+ if (!$arVartable) {
+ return $resultGraph;
+ }
+
+ $tp = $constructPattern->getTriplePatterns();
+
+ $bnode = 0;
+ foreach ($arVartable as $value) {
+ foreach ($tp as $triple) {
+ $sub = $triple->getSubject();
+ $pred = $triple->getPredicate();
+ $obj = $triple->getObject();
+
+ if (is_string($sub) && $sub{1} == '_') {
+ $sub = new BlankNode("_bN".$bnode);
+ }
+ if (is_string($pred) && $pred{1} == '_') {
+ $pred = new BlankNode("_bN".$bnode);
+ }
+ if (is_string($obj) && $obj{1} == '_') {
+ $obj = new BlankNode("_bN".$bnode);
+ }
+
+
+ if (is_string($sub)) {
+ $sub = $value[$sub];
+ }
+ if (is_string($pred)) {
+ $pred = $value[$pred];
+ }
+ if (is_string($obj)) {
+ $obj = $value[$obj];
+ }
+
+ if ($sub !== "" && $pred !== "" && $obj !== "") {
+ $resultGraph->add(new Statement($sub,$pred,$obj));
+ }
+ }
+ $bnode++;
+ }
+ return $resultGraph;
+ }//protected function constructGraph($arVartable, $constructPattern)
+
+
+
+ protected function createResource($uri)
+ {
+ return 'R<' . $uri . '>';
+ }//protected function createResource($uri)
+
+
+
+ protected function createBlankNode($id)
+ {
+ return 'B(' . $id . ')';
+ }//protected function createBlankNode($id)
+
+
+
+ protected function createLiteral($value, $language, $datatype)
+ {
+ $v = 'L(' . $value;
+ if ($language != null) {
+ $v .= '@' . $language;
+ }
+ if ($datatype != null) {
+ $v .= '^^' . $datatype;
+ }
+ return $v . ')';
+ }//protected function createLiteral($value, $language, $datatype)
+
+}//class SparqlEngineDb_ResultRenderer_PlainText implements SparqlEngineDb_ResultRenderer
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/XML.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/XML.php
new file mode 100755
index 00000000..d98714aa
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/ResultRenderer/XML.php
@@ -0,0 +1,336 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlEngineDb_ResultRenderer_XML implements SparqlEngineDb_ResultRenderer
+{
+
+ /**
+ * Defines the methods needed to create the types
+ * in $arVarAssignments.
+ * Key is the type (e.g. "s" for subject), and
+ * value the method's name.
+ *
+ * @see $arVarAssignments
+ *
+ * @var array
+ */
+ protected $arCreationMethods = array(
+ 's' => 'createSubjectFromDbRecordSetPart',
+ 'p' => 'createPredicateFromDbRecordSetPart',
+ 'o' => 'createObjectFromDbRecordSetPart'
+ );
+
+
+
+ /**
+ * Converts the database results into nice HTML.
+ *
+ * @param array $arRecordSets Array of (possibly several) SQL query results.
+ * @param Query $query SPARQL query object
+ * @param SparqlEngineDb $engine Sparql Engine to query the database
+ * @return mixed HTML code
+ */
+ public function convertFromDbResults($arRecordSets, Query $query, SparqlEngineDb $engine)
+ {
+ $this->query = $query;
+ $this->sg = $engine->getSqlGenerator();
+ $strCode = '';
+
+ $strResultForm = $query->getResultForm();
+ switch ($strResultForm) {
+ case 'select':
+ case 'select distinct':
+ $strCode = $this->createFromRecords($arRecordSets, $strResultForm);
+ break;
+
+ case 'construct':
+ case 'describe':
+ throw new Exception(
+ 'Construct and describe are not supported by the'
+ . ' XML renderer'
+ );
+
+ case 'count':
+ case 'ask':
+ if (count($arRecordSets) > 1) {
+ throw new Exception(
+ 'More than one result set for a '
+ . $strResultForm . ' query!'
+ );
+ }
+
+ $nCount = 0;
+ $dbRecordSet = reset($arRecordSets);
+ foreach ($dbRecordSet as $row) {
+ $nCount += intval($row['count']);
+ break;
+ }
+
+ if ($strResultForm == 'ask') {
+ $strCode = $this->getHead()
+ . ' '
+ . self::getSpokenBoolean($nCount > 0)
+ . '';
+ } else {
+ $strCode = $this->getHead()
+ . ' '
+ . $nCount
+ . '';
+ }
+ break;
+
+ default:
+ throw new Exception('Unsupported result form: ' . $strResultForm);
+ }
+
+ return $this->wrapCode($strCode);
+ }//public function convertFromDbResults($arRecordSets, Query $query, SparqlEngineDb $engine)
+
+
+
+ protected function wrapCode($strCode)
+ {
+ return <<
+
+
+EOT
+ . $strCode . "\n"
+ . "\n";
+ }//protected function wrapCode($strCode)
+
+
+
+ protected function getHead($strXml = '')
+ {
+ return " \n"
+ . $strXml
+ . " \n";
+ }//protected function getHead($strXml = '')
+
+
+
+ protected function createFromRecords($arRecordSets, $strResultForm)
+ {
+ $arResultVars = $this->query->getResultVars();
+
+ if (in_array('*', $arResultVars)) {
+ $arResultVars = array_keys($this->sg->arVarAssignments);
+ }
+
+ $strVarXML = '';
+ foreach ($arResultVars as $var) {
+ $strVarXML .= " \n";
+ }
+
+ $strHeadXml = $this->getHead($strVarXML);
+
+ $arResult = array();
+ foreach ($arRecordSets as $dbRecordSet) {
+ //work around bug in adodb:
+ // ADORecordSet_empty does not implement php5 iterators
+ if ($dbRecordSet->RowCount() <= 0) {
+
+ return
+ $strHeadXml
+ . ' ' . "\n"
+ . ' ' . PHP_EOL
+ . " \n";
+ }
+
+ foreach ($dbRecordSet as $row) {
+ $arResultRow = array();
+ foreach ($arResultVars as $strVar) {
+ $strVarName = (string)$strVar;
+ if (!isset($this->sg->arVarAssignments[$strVarName])) {
+ //variable is in select, but not in result (test: q-select-2)
+ $arResultRow[$strVarName] = '';
+ } else {
+ $arVarSettings = $this->sg->arVarAssignments[$strVarName];
+ $strMethod = $this->arCreationMethods[$arVarSettings[1]];
+ $arResultRow[$strVarName] = $this->$strMethod($dbRecordSet, $arVarSettings[0], $strVar);
+ }
+ }
+ $arResult[] = $arResultRow;
+ }
+ }
+
+
+ $arSM = $this->query->getSolutionModifier();
+
+ return
+ $strHeadXml
+ . ' ' . "\n"
+ . $this->getResultXml($arResult)
+ . " \n";
+ }//protected function createFromRecords($arRecordSets)
+
+
+
+ protected function getResultXml($arResult)
+ {
+ $strCode = '';
+ foreach ($arResult as $arSet) {
+ $strCode .= " \n";
+ foreach ($arSet as $strVarName => $strValue) {
+ if ($strValue !== null) {
+ $strCode .= ' '
+ . $strValue
+ . "\n";
+ }
+ }
+ $strCode .= " \n";
+ }
+ return $strCode;
+ }//protected function getResultXml($arResult)
+
+
+
+ protected static function getSpokenBoolean($b)
+ {
+ return $b ? 'true' : 'false';
+ }//protected static function getSpokenBoolean($b)
+
+
+
+ /**
+ * Creates an RDF subject object
+ * contained in the given $dbRecordSet object.
+ *
+ * @see convertFromDbResult() to understand $strVarBase necessity
+ *
+ * @param ADORecordSet $dbRecordSet Record set returned from ADOConnection::Execute()
+ * @param string $strVarBase Prefix of the columns the recordset fields have.
+ *
+ * @return string HTML code
+ */
+ protected function createSubjectFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+ {
+ $strVarName = (string)$strVar;
+ if ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']] === null) {
+ return $this->getXmlNull();
+ }
+ if ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_is']] == 'r'
+ //null should be predicate which is always a resource
+ || $dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_is']] === null
+ ) {
+ return $this->getXmlResource($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ } else {
+ return $this->getXmlBlank($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ }
+ }//protected function createSubjectFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+
+
+
+ /**
+ * Creates an RDF predicate object
+ * contained in the given $dbRecordSet object.
+ *
+ * @see convertFromDbResult() to understand $strVarBase necessity
+ *
+ * @param ADORecordSet $dbRecordSet Record set returned from ADOConnection::Execute()
+ * @param string $strVarBase Prefix of the columns the recordset fields have.
+ *
+ * @return string HTML code
+ */
+ protected function createPredicateFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+ {
+ $strVarName = (string)$strVar;
+ if ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']] === null) {
+ return $this->getXmlNull();
+ }
+
+ return $this->getXmlResource($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ }//protected function createPredicateFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+
+
+
+ /**
+ * Creates an RDF object object
+ * contained in the given $dbRecordSet object.
+ *
+ * @see convertFromDbResult() to understand $strVarBase necessity
+ *
+ * @param ADORecordSet $dbRecordSet Record set returned from ADOConnection::Execute()
+ * @param string $strVarBase Prefix of the columns the recordset fields have.
+ *
+ * @return string HTML code
+ */
+ protected function createObjectFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+ {
+ $strVarName = (string)$strVar;
+ if ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']] === null) {
+ return $this->getXmlNull();
+ }
+ switch ($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_is']]) {
+ case 'r':
+ return $this->getXmlResource($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ break;
+ case 'b':
+ return $this->getXmlBlank($dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']]);
+ break;
+ default:
+ return $this->getXmlLiteral(
+ $dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_value']],
+ $dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_lang']],
+ $dbRecordSet->fields[$strVarBase . '.' . $this->sg->arVarAssignments[$strVarName]['sql_type']]
+ );
+ }
+ }//protected function createObjectFromDbRecordSetPart(ADORecordSet $dbRecordSet, $strVarBase, $strVar)
+
+
+
+ protected function getXmlNull()
+ {
+ return null;
+ }//protected function getHtmlNull()
+
+
+
+ protected function getXmlBlank($value)
+ {
+ return '' . $value . '';
+ }//protected function getHtmlBlank($value)
+
+
+
+ protected function getXmlResource($value)
+ {
+ return '' . htmlspecialchars($value) . '';
+ }//protected function getHtmlResource($value)
+
+
+
+ protected function getXmlLiteral($value, $language, $datatype)
+ {
+ $strCode = '';
+ return $strCode;
+ }//protected function getHtmlLiteral($value, $language, $datatype)
+
+}//class SparqlEngineDb_ResultRenderer_XML implements SparqlEngineDb_ResultRenderer
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/SqlGenerator.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/SqlGenerator.php
new file mode 100755
index 00000000..d8fc46c1
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/SqlGenerator.php
@@ -0,0 +1,999 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlEngineDb_SqlGenerator
+{
+ public $query = null;
+
+ /**
+ * Determines which variables can be found
+ * in which SQL result column.
+ * @example
+ * array(
+ * '?person' => array('t1', 's'),
+ ' '?p' => array('t1', 'p'),
+ * '?mbox' => array('t2', 'o')
+ * )
+ * Would express that variable ?person is the subject
+ * in result table t1, and ?mbox is the object in
+ * table t2.
+ *
+ * @see $arCreationMethods
+ *
+ * @internal The array is created in createSql()
+ * and used in convertFromDbResult().
+ *
+ * @var array
+ */
+ public $arVarAssignments = array();
+
+ /**
+ * Array of variable name => table.col assignments
+ * for all variables used in the query not only
+ * the ones that shall be returned.
+ *
+ * @example
+ * array(
+ * '?person' => 't0.subject'
+ * )
+ *
+ * @var array
+ */
+ public $arUsedVarAssignments = array();
+
+ /**
+ * Array of arrays that contain all variable names
+ * which are to be found in the result of
+ * an sql statement in a union.
+ *
+ * @example
+ * array(
+ * 0 => array(
+ * '?person' => 's',
+ * '?p' => 'o'
+ * ),
+ * 1 => array(
+ * '?person' => 's',
+ * '?mbox' => 'o'
+ * )
+ * )
+ *
+ * @var array
+ */
+ public $arUnionVarAssignments = array();
+
+ /**
+ * Which variables have been used as which type?
+ * key is variable name, value is an array of
+ * max. three keys (s, p, o)
+ *
+ * @example
+ * array(
+ * '?person' => array(
+ * 's' => true
+ * ),
+ * '?mbox' => array(
+ * 'o' => true
+ * )
+ * )
+ *
+ * @var array
+ */
+ protected $arUsedVarTypes = array();
+
+ /**
+ * Array with placeholders of prepared statements variables.
+ * key is the variable name (without "??"), value is the
+ * placeholder.
+ * @var array
+ */
+ protected $arPlaceholders = array();
+
+ /**
+ * Column names for subjects, predicates and
+ * objects for easy access via their character
+ * names (spo).
+ *
+ * @var array
+ */
+ public static $arTableColumnNames = array(
+ 's' => array(
+ 'value' => 'subject',
+ 'is' => 'subject_is'
+ ),
+ 'p' => array(
+ 'value' => 'predicate'
+ ),
+ 'o' => array(
+ 'value' => 'object',
+ 'is' => 'object_is'
+ )
+ );
+
+ /**
+ * Current UNION part number
+ * @var int
+ */
+ protected $nUnionCount = 0;
+
+ protected $nSqlVariableNameCount = 0;
+
+ /**
+ * Name of the statements table
+ */
+ protected $tblStatements = 'statements';
+
+
+
+ public function __construct(Query $query, ADOConnection $dbConn, $arModelIds)
+ {
+ $this->query = $query;
+ $this->dbConn = $dbConn;
+ $this->arModelIds = $arModelIds;
+ }//public function __construct(Query $query, ADOConnection $dbConn, $arModelIds)
+
+
+
+ /**
+ * Creates an SQL query string from the given Sparql query object.
+ *
+ * @internal uses $query variable
+ *
+ * @return array Array of arrays of SQL query string parts: select, from and where
+ *
+ * @throws SparqlEngineDb_SqlGeneratorException If there is no variable in the result set.
+ */
+ function createSql()
+ {
+//var_dump($this->query);
+ $arSelect = array();
+ $arFrom = array();
+ $arWhere = array();
+
+ $strResultForm = $this->query->getResultForm();
+ $filterGen = new SparqlEngineDb_FilterGenerator($this);
+ switch ($strResultForm) {
+ case 'construct':
+ $arResultVars = $this->query->getConstructPatternVariables();
+ break;
+ default:
+ $arResultVars = $this->query->getResultVars();
+ break;
+ }
+
+ $this->nTableId = 0;
+ $this->nGraphPatternCount = 0;
+ $this->nUnionCount = 0;
+ $this->nUnionTriplePatternCount = 0;
+ $this->arUnionVarAssignments[0] = array();
+
+ foreach ($this->query->getResultPart() as $graphPattern) {
+ if ($graphPattern->isEmpty()) {
+ continue;
+ }
+ if ($graphPattern->getUnion() !== null) {
+ ++$this->nUnionCount;
+ $this->nTableId = 0;
+ $this->nUnionTriplePatternCount = 0;
+ $this->nGraphPatternCount = 0;
+ $this->arUnionVarAssignments[$this->nUnionCount] = array();
+ }
+ $this->nTriplePatternCount = 0;
+ $arTriplePattern = $graphPattern->getTriplePatterns();
+ if ($arTriplePattern != null) {
+ foreach ($arTriplePattern as $triplePattern) {
+ list (
+ $arSelect[$this->nUnionCount][],
+ $arFrom [$this->nUnionCount][],
+ $arWhere [$this->nUnionCount][]
+ ) =
+ $this->getTripleSql(
+ $triplePattern,
+ $graphPattern,
+ $arResultVars
+ );
+ ++$this->nTableId;
+ ++$this->nTriplePatternCount;
+ ++$this->nUnionTriplePatternCount;
+ }
+ }
+ ++$this->nGraphPatternCount;
+
+ }
+
+ //constraints extra. needed, since OPTIONAL parts are put after
+ // the current pattern while the constraint already refers to variables
+ // defined in there
+ $this->nGraphPatternCount = 0;
+ $this->nUnionCount = 0;
+ foreach ($this->query->getResultPart() as $graphPattern) {
+ if ($graphPattern->getUnion() !== null) {
+ ++$this->nUnionCount;
+ }
+ $arConstraints = $graphPattern->getConstraints();
+ if ($arConstraints != null) {
+ foreach ($arConstraints as $constraint) {
+ $arWhere[$this->nUnionCount][count($arWhere[$this->nUnionCount]) - 1]
+ .= $filterGen->createFilterSql(
+ $constraint->getTree(),
+ $graphPattern->getOptional() !== null,
+ $this->nUnionCount
+ );
+ }
+ }
+ ++$this->nGraphPatternCount;
+ }
+
+ $arSelect = $this->createEqualSelects($arSelect);
+ $arStrSelect = array();
+
+ switch ($strResultForm) {
+ case 'construct':
+ case 'describe':
+ $strSelectType = 'SELECT';
+ case 'select':
+ case 'select distinct':
+ if (!isset($strSelectType)) {
+ $strSelectType = $strResultForm;
+ }
+ foreach ($arSelect as $nUnionCount => $arSelectPart) {
+ $arSelectPart = self::removeNull($arSelectPart);
+ if (count($arSelectPart) == 0
+ || (count($arSelectPart) == 1 && $arSelectPart[0] == '')) {
+ //test "test-1-07" suggests we return no rows in this case
+ //throw new SparqlEngineDb_SqlGeneratorException('No variable that could be returned.');
+ } else {
+ $arStrSelect[$nUnionCount] = strtoupper($strSelectType) . ' ' . implode(', ' , $arSelectPart);
+ }
+ }
+ break;
+
+ case 'ask':
+ case 'count':
+ $arStrSelect = array('SELECT COUNT(*) as count');
+ break;
+
+ default:
+ throw new SparqlEngineDb_SqlGeneratorException('Unsupported query type "' . $strResultForm . '"');
+ break;
+ }
+
+ $arSqls = array();
+ foreach ($arStrSelect as $nUnionCount => $arSelectPart) {
+ $arSqls[] = array(
+ 'select' => $arStrSelect[$nUnionCount],
+ 'from' => ' FROM ' . implode(' ' , self::removeNull($arFrom[$nUnionCount])),
+ 'where' => ' WHERE ' . self::fixWhere(
+ implode(' ' , self::removeNull($arWhere[$nUnionCount]))
+ )
+ );
+ }
+ return $arSqls;
+ }//function createSql()
+
+
+
+ /**
+ * Creates some SQL statements from the given triple pattern
+ * array.
+ *
+ * @param QueryTriple $triple Array containing subject, predicate and object
+ * @param GraphPattern $graphPattern Graph pattern object
+ *
+ * @return array Array consisting of on array and two string values:
+ * SELECT, FROM and WHERE part
+ */
+ function getTripleSql(QueryTriple $triple, GraphPattern $graphPattern, $arResultVars)
+ {
+ $arSelect = array();
+ $strFrom = null;
+ $strWhere = null;
+ $strWhereEquality = '';
+ $bWhereEqualitySubject = false;
+ $bWhereEqualityPredicate = false;
+ $bWhereEqualityObject = false;
+
+ $subject = $triple->getSubject();
+ $predicate = $triple->getPredicate();
+ $object = $triple->getObject();
+
+ $arRefVars = array();
+ $strTablePrefix = 't' . $this->nTableId;
+
+ /**
+ * SELECT part
+ * We do select only the columns we need for variables
+ */
+ if (SparqlVariable::isVariable($subject)) {
+ if (isset($this->arUnionVarAssignments[$this->nUnionCount][$subject])) {
+ //already selected -> add equality check
+ $bWhereEqualitySubject = true;
+ $this->arUsedVarTypes[$subject]['s'] = true;
+ } else {
+ if (isset($this->arVarAssignments[$subject][0])) {
+ $strTablePrefix = $this->arVarAssignments[$subject][0];
+ }
+ $this->arVarAssignments[$subject] = array($strTablePrefix, 's');
+ $this->arUnionVarAssignments[$this->nUnionCount][$subject] = array($strTablePrefix, 's');
+ $this->arUsedVarTypes[$subject]['s'] = true;
+ if (self::isResultVar($subject, $arResultVars)) {
+ //new variable that needs to be selected
+ $arSelect[$subject] = $this->createVariableSelectArray(
+ 's', $subject, $strTablePrefix
+ );
+ if (isset($this->arUsedVarAssignments[$subject])) {
+ $arRefVars[$subject] = $strTablePrefix . '.subject';
+ } else {
+ $this->arUsedVarAssignments[$subject] = $strTablePrefix . '.subject';
+ }
+ }
+ }
+ }
+
+ if (SparqlVariable::isVariable($predicate)) {
+ if (isset($this->arUnionVarAssignments[$this->nUnionCount][$predicate])) {
+ //already selected -> add equality check
+ $bWhereEqualityPredicate = true;
+ $this->arUsedVarTypes[$predicate]['p'] = true;
+ } else {
+ if (isset($this->arVarAssignments[$predicate][0])) {
+ $strTablePrefix = $this->arVarAssignments[$predicate][0];
+ }
+ $this->arVarAssignments[$predicate] = array($strTablePrefix, 'p');
+ $this->arUnionVarAssignments[$this->nUnionCount][$predicate] = array($strTablePrefix, 'p');
+ $this->arUsedVarTypes[$predicate]['p'] = true;
+ if (self::isResultVar($predicate, $arResultVars)) {
+ $arSelect[$predicate] = $this->createVariableSelectArray(
+ 'p', $predicate, $strTablePrefix
+ );
+ if (isset($this->arUsedVarAssignments[$predicate])) {
+ $arRefVars[$predicate] = $strTablePrefix . '.predicate';
+ } else {
+ $this->arUsedVarAssignments[$predicate] = $strTablePrefix . '.predicate';
+ }
+ }
+ }
+ }
+
+ if (SparqlVariable::isVariable($object)) {
+ if (isset($this->arUnionVarAssignments[$this->nUnionCount][$object])) {
+ //already selected -> add equality check
+ $bWhereEqualityObject = true;
+ $this->arUsedVarTypes[$object]['o'] = true;
+ } else {
+ if (isset($this->arVarAssignments[$object][0])) {
+ $strTablePrefix = $this->arVarAssignments[$object][0];
+ }
+ $this->arVarAssignments[$object] = array($strTablePrefix, 'o');
+ $this->arUnionVarAssignments[$this->nUnionCount][$object] = array($strTablePrefix, 'o');
+ $this->arUsedVarTypes[$object]['o'] = true;
+ if (self::isResultVar($object, $arResultVars)) {
+ $arSelect[$object] = $this->createVariableSelectArray(
+ 'o', $object, $strTablePrefix
+ );
+ if (isset($this->arUsedVarAssignments[$object])) {
+ $arRefVars[$object] = $strTablePrefix . '.object';
+ } else {
+ $this->arUsedVarAssignments[$object] = $strTablePrefix . '.object';
+ }
+ }
+ if (isset($this->query->varLanguages[$object])
+ && $this->query->varLanguages[$object] !== null
+ ) {
+ $strWhereEquality .=
+ ' AND ' . $strTablePrefix . '.l_language = "'
+ . addslashes($this->query->varLanguages[$object]) . '"';
+ }
+ if (isset($this->query->varDatatypes[$object])
+ && $this->query->varDatatypes[$object] !== null
+ ) {
+ $strWhereEquality .=
+ ' AND ' . $strTablePrefix . '.l_datatype = "'
+ . addslashes($this->query->varDatatypes[$object]) . '"';
+ }
+ }
+ }
+
+ /**
+ * WhereEquality - needs to be done now because strTablePrefix may change
+ */
+ if ($bWhereEqualitySubject) {
+ $strWhereEquality .= ' AND ' . self::getSqlEqualityCondition(
+ array($strTablePrefix, 's'),
+ $this->arVarAssignments[$subject]
+ );
+ }
+ if ($bWhereEqualityPredicate) {
+ $strWhereEquality .= ' AND ' . self::getSqlEqualityCondition(
+ array($strTablePrefix, 'p'),
+ $this->arVarAssignments[$predicate]
+ );
+ }
+ if ($bWhereEqualityObject) {
+ $strWhereEquality .= ' AND ' . self::getSqlEqualityCondition(
+ array($strTablePrefix, 'o'),
+ $this->arVarAssignments[$object]
+ );
+ }
+
+
+ /**
+ * FROM part
+ */
+ if ($this->nUnionTriplePatternCount == 0) {
+ //first FROM
+ $strFrom = $this->tblStatements . ' as ' . $strTablePrefix;
+ } else {
+ //normal join
+ if (count($this->arModelIds) == 1) {
+ $strFrom = 'LEFT JOIN ' . $this->tblStatements . ' as ' . $strTablePrefix
+ . ' ON t0.modelID = ' . $strTablePrefix . '.modelID';
+ } else if (count($this->arModelIds) > 1) {
+ $arIDs = array();
+ foreach ($this->arModelIds as $nId) {
+ $arIDs[] = $strTablePrefix . '.modelID = ' . intval($nId);
+ }
+ $strFrom = 'LEFT JOIN ' . $this->tblStatements . ' as ' . $strTablePrefix
+ . ' ON (' . implode(' OR ', $arIDs) . ')';
+ } else {
+ $strFrom = 'LEFT JOIN ' . $this->tblStatements . ' as ' . $strTablePrefix
+ . ' ON t0.modelID = ' . $strTablePrefix . '.modelID';
+ }
+
+ foreach ($arRefVars as $strRefVar => $strSqlVar) {
+ $strFrom .= ' AND ' . $this->arUsedVarAssignments[$strRefVar] . ' = ' . $strSqlVar;
+ }
+
+ if ($graphPattern->getOptional() !== null) {
+ $strFrom .= $this->getSqlCondition($subject , $strTablePrefix, 'subject')
+ . $this->getSqlCondition($predicate, $strTablePrefix, 'predicate')
+ . $this->getSqlCondition($object , $strTablePrefix, 'object')
+ . $strWhereEquality;
+ }
+ }
+
+
+ /**
+ * WHERE part
+ */
+ if ($this->nUnionTriplePatternCount == 0) {
+ if (count($this->arModelIds) == 1) {
+ $strWhere = $strTablePrefix . '.modelID = ' . intval(reset($this->arModelIds));
+ } else if (count($this->arModelIds) > 1) {
+ $arIDs = array();
+ foreach ($this->arModelIds as $nId) {
+ $arIDs[] = $strTablePrefix . '.modelID = ' . intval($nId);
+ }
+ $strWhere = '(' . implode(' OR ', $arIDs) . ')';
+ } else {
+ //so that we can append an AND
+ $strWhere = '1';
+ }
+ }
+ if ($graphPattern->getOptional() === null || $this->nGraphPatternCount == 0) {
+ $strWhere .= $this->getSqlCondition($subject , $strTablePrefix, 'subject')
+ . $this->getSqlCondition($predicate, $strTablePrefix, 'predicate')
+ . $this->getSqlCondition($object , $strTablePrefix, 'object')
+ . $strWhereEquality;
+ }
+
+ return array($arSelect, $strFrom, $strWhere);
+ }//function getTripleSql(QueryTriple $triple)
+
+
+
+
+ protected function createVariableSelectArray($chType, $varname, $strTablePrefix)
+ {
+ $var = $this->query->getResultVar($varname);
+ if ($var !== false) {
+ if ((string)$var != $varname) {
+ //copy over var assignments
+ $this->arVarAssignments[(string)$var] = $this->arVarAssignments[$varname];
+ }
+
+ //works on non-* only
+ $func = $var->getFunc();
+ if ($func != null) {
+ if ($func == 'datatype') {
+ if ($chType != 'o') {
+ throw new SparqlEngineDb_SqlGeneratorException(
+ 'datatype() works on objects only'
+ );
+ }
+ return array(
+ $strTablePrefix . '.l_datatype as "' . $strTablePrefix . '.' . $this->getSqlVariableNameValue($var) . '"',
+ '"r"' . ' as "' . $strTablePrefix . '.' . $this->getSqlVariableNameIs($var) . '"',
+ '""' . ' as "' . $strTablePrefix . '.' . $this->getSqlVariableNameLanguage($var) . '"',
+ '""' . ' as "' . $strTablePrefix . '.' . $this->getSqlVariableNameDatatype($var) . '"',
+ );
+ } else if ($func == 'lang') {
+ if ($chType != 'o') {
+ throw new SparqlEngineDb_SqlGeneratorException(
+ 'lang() works on objects only'
+ );
+ }
+ return array(
+ $strTablePrefix . '.l_language as "' . $strTablePrefix . '.' . $this->getSqlVariableNameValue($var) . '"',
+ '"l"' . ' as "' . $strTablePrefix . '.' . $this->getSqlVariableNameIs($var) . '"',
+ '""' . ' as "' . $strTablePrefix . '.' . $this->getSqlVariableNameLanguage($var) . '"',
+ '""' . ' as "' . $strTablePrefix . '.' . $this->getSqlVariableNameDatatype($var) . '"',
+ );
+ } else {
+ throw new SparqlEngineDb_SqlGeneratorException(
+ 'Unsupported function for select "' . $func . '"'
+ );
+ }
+ }
+ }
+
+ switch ($chType) {
+ case 's':
+ return array(
+ $strTablePrefix . '.subject as "' . $strTablePrefix . '.' . $this->getSqlVariableNameValue($varname) . '"',
+ $strTablePrefix . '.subject_is as "' . $strTablePrefix . '.' . $this->getSqlVariableNameIs($varname) . '"'
+ );
+ case 'p':
+ return array(
+ $strTablePrefix . '.predicate as "' . $strTablePrefix . '.' . $this->getSqlVariableNameValue($varname) . '"'
+ );
+ case 'o':
+ return array(
+ $strTablePrefix . '.object as "' . $strTablePrefix . '.' . $this->getSqlVariableNameValue($varname) . '"',
+ $strTablePrefix . '.object_is as "' . $strTablePrefix . '.' . $this->getSqlVariableNameIs($varname) . '"',
+ $strTablePrefix . '.l_language as "' . $strTablePrefix . '.' . $this->getSqlVariableNameLanguage($varname) . '"',
+ $strTablePrefix . '.l_datatype as "' . $strTablePrefix . '.' . $this->getSqlVariableNameDatatype($varname) . '"',
+ );
+ default:
+ throw new SparqlEngineDb_SqlGeneratorException(
+ 'Unknown sentence type "' . $chType . "', one of (s,p,o) expected"
+ );
+ }
+ }//protected function createVariableSelectArray($chType, $value, $strTablePrefix)
+
+
+
+ /**
+ * Creates SELECT statements that have the same number of columns.
+ * Needed for UNIONs.
+ *
+ * @param array $arSelect Array of arrays.
+ * array(
+ * //for each union part one
+ * 0 => array(
+ * //foreach triple pattern
+ * 0 => array(
+ * '?person' => array(
+ * 't0.subject as "t0.subject"'
+ * )
+ * )
+ * )
+ * )
+ * @return array Array of SELECT strings
+ */
+ protected function createEqualSelects($arSelect)
+ {
+ $arNewSelect = array();
+ if (count($arSelect) == 1) {
+ if ($arSelect[0] == array(array())) {
+ //ASK and COUNT
+ return array(array(''));
+ }
+
+ foreach ($arSelect[0] as $arTripleVars) {
+ $ar = array();
+ foreach ($arTripleVars as $arVarParts) {
+ $ar[] = implode(', ', $arVarParts);
+ }
+ if (count($ar) > 0) {
+ $arNewSelect[0][] = implode(', ', $ar);
+ }
+ }
+ return $arNewSelect;
+ }
+
+ $arVars = array();
+ foreach ($arSelect as $arUnionVars) {
+ foreach ($arUnionVars as $arTripleVars) {
+ $arVars = array_merge($arVars, array_keys($arTripleVars));
+ }
+ }
+ $arVars = array_unique($arVars);
+
+ foreach ($arSelect as $nUnionCount => $arUnionVars) {
+ $arSelectVars = array();
+ foreach ($arUnionVars as $arTripleVars) {
+ foreach ($arTripleVars as $strVar => $arVarParts) {
+ $arSelectVars[$strVar] = $arVarParts;
+ }
+ }
+
+ $ars = array();
+ foreach ($arVars as $strVar) {
+ if (isset($arSelectVars[$strVar])) {
+ $ar = $arSelectVars[$strVar];
+ $nCount = count($arSelectVars[$strVar]);
+ } else {
+ $ar = array();
+ $nCount = 0;
+ }
+
+ if ($nCount == 0) {
+ //nothing of this variable in this union part
+ $ar[] = 'NULL as '
+ . '"' . $this->arVarAssignments[$strVar][0] . '.' . $this->arVarAssignments[$strVar]['sql_value'] . '"';
+ }
+ if ((
+ isset($this->arUsedVarTypes[$strVar]['o'])
+ || isset($this->arUsedVarTypes[$strVar]['s'])
+ ) && $nCount < 2
+ ) {
+ //it's a subject or object, but we don't want the type
+ $ar[] = 'NULL as '
+ . '"' . $this->arVarAssignments[$strVar][0] . '.' . $this->arVarAssignments[$strVar]['sql_is'] . '"';
+ }
+ if (isset($this->arUsedVarTypes[$strVar]['o']) && $nCount < 4) {
+ //it's a subject or object, but we don't want the type
+ if (isset($this->arVarAssignments[$strVar]['sql_lang'])) {
+ $strColLanguage = $this->arVarAssignments[$strVar]['sql_lang'];
+ } else {
+ $strColLanguage = 'dummyLang';
+ }
+ if (isset($this->arVarAssignments[$strVar]['sql_type'])) {
+ $strColDatatype = $this->arVarAssignments[$strVar]['sql_type'];
+ } else {
+ $strColDatatype = 'dummyType';
+ }
+ $ar[] = 'NULL as '
+ . '"' . $this->arVarAssignments[$strVar][0] . '.' . $strColLanguage . '"';
+ $ar[] = 'NULL as '
+ . '"' . $this->arVarAssignments[$strVar][0] . '.' . $strColDatatype . '"';
+ }
+ $ars[] = implode(', ', $ar);
+ }
+ $arNewSelect[$nUnionCount] = $ars;
+ }
+
+ return $arNewSelect;
+ }//protected function createEqualSelects($arSelect)
+
+
+
+ /**
+ * Creates an SQL statement that checks for the value
+ * of some subject/predicate/object
+ *
+ * @param mixed $bject subject|predicate|object
+ * @param string $strTablePrefix Table prefix (e.g. "t0")
+ * @param string $strType Type of $bject ('subject'|'predicate'|'object')
+ * @return string Part of the SQL query (prefixed with AND)
+ */
+ function getSqlCondition($bject, $strTablePrefix, $strType)
+ {
+ if (is_string($bject)) {
+ if (SparqlVariable::isVariable($bject)) {
+ //variable?
+ if (self::isPreparedVariable($bject)) {
+ //no, not really
+ $value = $this->getPreparedVariablePlaceholder($bject);
+ } else {
+ //yes
+ return null;
+ }
+ } else {
+ $value = $this->dbConn->qstr($bject);
+ }
+ //literal
+ return ' AND ' . $strTablePrefix . '.' . $strType . ' = ' . $value;
+ }
+
+ if ($bject instanceof BlankNode) {
+ //Blank node
+ throw new SparqlEngineDb_SqlGeneratorException(
+ 'FIXME: Querying for blank nodes not supported'
+ );
+
+ } else if ($bject instanceof Resource) {
+ //Resource
+ $r = ' AND ' . $strTablePrefix . '.' . $strType . ' = '
+ . $this->dbConn->qstr($bject->getURI());
+ if ($strType !== 'predicate') {
+ $r .= ' AND ' . $strTablePrefix . '.' . $strType . '_is ='
+ . ' "r"';
+ }
+ return $r;
+
+ } else if ($bject instanceof Literal) {
+ //Literal
+ //I'm doubling Filter code here, but what the hell
+ $strColDatatype = $strTablePrefix . '.l_datatype';
+ if ($bject->dtype == 'http://www.w3.org/2001/XMLSchema#integer'
+ || $bject->dtype == 'http://www.w3.org/2001/XMLSchema#double'
+ ) {
+ $strVariable = 'CAST(' . $strTablePrefix . '.' . $strType . ' AS DECIMAL(15,10))';
+ $strValue = $bject->getLabel();
+ } else {
+ $strVariable = $strTablePrefix . '.' . $strType;
+ $strValue = $this->dbConn->qstr($bject->getLabel());
+ }
+ $r = ' AND ' . $strVariable . ' = ' . $strValue;
+ if ($strType !== 'predicate') {
+ $r .= ' AND ' . $strTablePrefix . '.' . $strType . '_is ='
+ . ' "l"';
+ }
+
+ if ($strType == 'object') {
+ if ($bject->dtype == '' || $bject->dtype == 'http://www.w3.org/2001/XMLSchema#string') {
+ //string
+ $r .= ' AND ('
+ . $strColDatatype . ' = ""'
+ . ' OR ' . $strColDatatype . ' = "http://www.w3.org/2001/XMLSchema#string"'
+ . ')';
+ } else {
+ $r .= ' AND ' . $strColDatatype . ' = "'
+ . $bject->dtype
+ . '"';
+ }
+ }
+
+ if ($bject->lang != '') {
+ $strColLanguage = $strTablePrefix . '.l_language';
+ $r .= ' AND ' . $strColLanguage . ' = '
+ . $this->dbConn->qstr($bject->lang);
+ }
+ return $r;
+
+ } else {
+ throw new SparqlEngineDb_SqlGeneratorException(
+ 'Unsupported sentence part: ' . get_class($bject)
+ );
+ }
+ }//function getSqlCondition($bject, $strTablePrefix, $strType)
+
+
+
+ /**
+ * Checks if the sentence part (subject, predicate or object) in
+ * $arNew has the same content as $arOld.
+ * Required for queries like ":x ?a ?a" where predicate and object
+ * need to have the same value
+ *
+ * @param array $arNew array($strTablePrefix, $strType = s|p|o)
+ * @param array $arOld array($strTablePrefix, $strType = s|p|o)
+ * @return string
+ */
+ protected static function getSqlEqualityCondition($arNew, $arOld)
+ {
+ $chTypeNew = $arNew[1]; $chTypeOld = $arOld[1];
+ $strTablePrefixNew = $arNew[0]; $strTablePrefixOld = $arOld[0];
+
+ if ($chTypeNew == 'p' || $chTypeOld == 'p') {
+ //just check value
+ //FIXME: it might be I need to check for resource type in object and subject
+ return
+ $strTablePrefixNew . '.' . self::$arTableColumnNames[$chTypeNew]['value']
+ . ' = '
+ . $strTablePrefixOld . '.' . self::$arTableColumnNames[$chTypeOld]['value']
+ ;
+ } else if ($chTypeNew == 's' || $chTypeOld == 's') {
+ //check value and type
+ return
+ $strTablePrefixNew . '.' . self::$arTableColumnNames[$chTypeNew]['value']
+ . ' = '
+ . $strTablePrefixOld . '.' . self::$arTableColumnNames[$chTypeOld]['value']
+ . ' AND '
+ . $strTablePrefixNew . '.' . self::$arTableColumnNames[$chTypeNew]['is']
+ . ' = '
+ . $strTablePrefixOld . '.' . self::$arTableColumnNames[$chTypeOld]['is']
+ ;
+ } else {
+ //two objects -> check everything
+ return
+ $strTablePrefixNew . '.object = ' . $strTablePrefixOld . '.object'
+ . ' AND '
+ . $strTablePrefixNew . '.object_is = ' . $strTablePrefixOld . '.object_is'
+ . ' AND '
+ . $strTablePrefixNew . '.l_language = ' . $strTablePrefixOld . '.l_language'
+ . ' AND '
+ . $strTablePrefixNew . '.l_datatype = ' . $strTablePrefixOld . '.l_datatype'
+ ;
+ }
+ }//protected static function getSqlEqualityCondition($arNew, $arOld)
+
+
+
+ /**
+ * Checks if the given variable name is part of the result
+ * variables list.
+ * Needed since $arResultVars may contain "*" that captures all variables.
+ *
+ * @param string $strVar Variable name (e.g. "?p")
+ * @param array $arResultVars Array with result variables
+ * @return boolean true if it is a result variable
+ */
+ protected static function isResultVar($strVar, &$arResultVars)
+ {
+ foreach ($arResultVars as $var) {
+ if ($var == '*') {
+ return true;
+ } else if ((is_string($var) && $var == $strVar)
+ || (is_object($var) && $var->getVariable() == $strVar)) {
+ return true;
+ }
+ }
+ return false;
+ }//protected static function isResultVar($strVar, &$arResultVars)
+
+
+
+ /**
+ * Checks if the given variable is a replacement
+ * for a prepared statement.
+ *
+ * @return boolean
+ */
+ public static function isPreparedVariable($bject)
+ {
+ return is_string($bject) && strlen($bject) >= 3
+ && ($bject[0] == '?' || $bject[0] == '$')
+ && ($bject[1] == '?' || $bject[1] == '$')
+ ;
+ }//public static function isPreparedVariable($bject)
+
+
+
+ /**
+ * Returns a placeholder to be included in the sql statement.
+ * It will be replaced with a real prepared statement variable later on.
+ * Also adds it to the internal placeholder array.
+ *
+ * @param string $strVariable The variable to get a placeholder for
+ * @return string placeholder
+ */
+ protected function getPreparedVariablePlaceholder($strVariable)
+ {
+ $strName = substr($strVariable, 2);
+ if (!isset($this->arPlaceholders[$strName])) {
+ $this->arPlaceholders[$strName] = '@$%_PLACEHOLDER_'
+ . count($this->arPlaceholders) . '_%$@';
+ }
+ return $this->arPlaceholders[$strName];
+ }//protected function getPreparedVariablePlaceholder($strVariable)
+
+
+
+ public function getPlaceholders()
+ {
+ return $this->arPlaceholders;
+ }//public function getPlaceholders()
+
+
+
+ public function getVarAssignments()
+ {
+ return $this->arVarAssignments;
+ }//public function getVarAssignments()
+
+
+
+ public function getUsedVarAssignments()
+ {
+ return $this->arUsedVarAssignments;
+ }//public function getUsedVarAssignments()
+
+
+
+ public function getUsedVarTypes()
+ {
+ return $this->arUsedVarTypes;
+ }//public function getUsedVarTypes()
+
+
+
+ /**
+ * Removes all NULL values from an array and returns it.
+ *
+ * @param array $array Some array
+ * @return array $array without the NULL values.
+ */
+ protected static function removeNull($array)
+ {
+ foreach ($array as $key => &$value) {
+ if ($value === null) {
+ unset($array[$key]);
+ }
+ }
+ return $array;
+ }//protected static function removeNull($array)
+
+
+
+ /**
+ * Removes a leading AND from the where clause which would render
+ * the sql illegal.
+ */
+ protected function fixWhere($strWhere)
+ {
+ $strWhere = ltrim($strWhere);
+ if (substr($strWhere, 0, 4) == 'AND ') {
+ $strWhere = substr($strWhere, 4);
+ }
+ return $strWhere;
+ }//protected function fixWhere($strWhere)
+
+
+
+ protected function getSqlVariableName($var)
+ {
+ $strSparqlVar = (string)$var;
+ if (!isset($this->arVarAssignments[$strSparqlVar]['sqlname'])) {
+ if (preg_match('/[a-zA-Z0-9]+/', substr($strSparqlVar, 1))) {
+ $strName = 'v_' . substr($strSparqlVar, 1);
+ } else {
+ $strName = 'va_' . $this->nSqlVariableNameCount++;
+ }
+ $this->arVarAssignments[$strSparqlVar]['sqlname'] = $strName;
+ }
+ return $this->arVarAssignments[$strSparqlVar]['sqlname'];
+ }//protected function getSqlVariableName($var)
+
+
+
+ protected function getSqlVariableNameValue($var)
+ {
+ $strSparqlVar = (string)$var;
+ $this->arVarAssignments[$strSparqlVar]['sql_value'] =
+ 'value_' . $this->getSqlVariableName($var);
+ return $this->arVarAssignments[$strSparqlVar]['sql_value'];
+ }//protected function getSqlVariableNameValue($var)
+
+
+
+ protected function getSqlVariableNameIs($var)
+ {
+ $strSparqlVar = (string)$var;
+ $this->arVarAssignments[$strSparqlVar]['sql_is'] =
+ 'is_' . $this->getSqlVariableName($var);
+ return $this->arVarAssignments[$strSparqlVar]['sql_is'];
+ }//protected function getSqlVariableNameIs($var)
+
+
+
+ protected function getSqlVariableNameLanguage($var)
+ {
+ $strSparqlVar = (string)$var;
+ $this->arVarAssignments[$strSparqlVar]['sql_lang'] =
+ 'lang_' . $this->getSqlVariableName($var);
+ return $this->arVarAssignments[$strSparqlVar]['sql_lang'];
+ }//protected function getSqlVariableNameLanguage($var)
+
+
+
+ protected function getSqlVariableNameDatatype($var)
+ {
+ $strSparqlVar = (string)$var;
+ $this->arVarAssignments[$strSparqlVar]['sql_type'] =
+ 'type_' . $this->getSqlVariableName($var);
+ return $this->arVarAssignments[$strSparqlVar]['sql_type'];
+ }//protected function getSqlVariableNameDatatype($var)
+
+
+
+ public function setStatementsTable($tblStatements)
+ {
+ $this->tblStatements = $tblStatements;
+ }//public function setStatementsTable($tblStatements)
+
+}//class SparqlEngineDb_SqlGenerator
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/SqlGeneratorException.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/SqlGeneratorException.php
new file mode 100755
index 00000000..1d98a3b7
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/SqlGeneratorException.php
@@ -0,0 +1,14 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlEngineDb_SqlGeneratorException extends Exception
+{
+}
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/SqlMerger.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/SqlMerger.php
new file mode 100755
index 00000000..d53137f3
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/SqlMerger.php
@@ -0,0 +1,46 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlEngineDb_SqlMerger
+{
+ public static function getSelect(Query $query, $arSqls, $strAdditional = '')
+ {
+ if (count($arSqls) == 1) {
+ return implode('', $arSqls[0]) . $strAdditional;
+ }
+
+ //union
+ $strUnion = 'UNION' .
+ ($query->getResultForm() == 'select distinct' ? '' : ' ALL');
+ $ar = array();
+ foreach ($arSqls as $arSql) {
+ $ar[] = implode('', $arSql) . $strAdditional;
+ }
+ return '(' . implode(') ' . $strUnion . ' (', $ar) . ')';
+ }//public static function getSelect(Query $query, $arSqls, $strAdditional = '')
+
+
+
+ public static function getCount(Query $query, $arSqls, $strAdditional = '')
+ {
+ if (count($arSqls) == 1) {
+ return 'SELECT COUNT(*) as count ' . $arSqls[0]['from'] . $arSqls[0]['where'] . $strAdditional;
+ }
+
+ $ar = array();
+ foreach ($arSqls as $arSql) {
+ $ar[] = implode('', $arSql) . $strAdditional;
+ }
+ return 'SELECT (' . implode(') + (', $ar) . ') as count';
+ }//public static function getCount(Query $query, $arSqls, $strAdditional = '')
+
+}//class SparqlEngineDb_SqlMerger
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/TypeSorter.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/TypeSorter.php
new file mode 100755
index 00000000..5b92d540
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlEngineDb/TypeSorter.php
@@ -0,0 +1,450 @@
+
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlEngineDb_TypeSorter
+{
+ /**
+ * Defines the sort order for value types in the database,
+ * so that they get sorted correctly as the specs want it.
+ * @var array
+ */
+ public static $arTypeNumbers = array(
+ null => 0,//empty
+ 'b' => 1,//blank
+ 'r' => 2,//resource
+ 'l' => 3,//literal
+ );
+
+ /**
+ * SQL types to cast XSD schema types to, so that they will get
+ * sorted correctly.
+ * @var array
+ */
+ public static $arCastTypes = array(
+ 'http://www.w3.org/2001/XMLSchema#integer' => 'SIGNED INTEGER',
+ 'http://www.w3.org/2001/XMLSchema#decimal' => 'DECIMAL',
+ //yes, this does not work with multiple time zones.
+ 'http://www.w3.org/2001/XMLSchema#dateTime' => 'CHAR',
+ 'http://www.w3.org/2001/XMLSchema#date' => 'CHAR',
+ );
+
+
+
+ public function __construct(Query $query, ADOConnection $dbConn)
+ {
+ $this->dbConn = $dbConn;
+ $this->query = $query;
+ }
+
+
+ /**
+ * Needs to be executed before getOrderifiedSqls and willBeDataDependent
+ *
+ * @param SparqlEngineDb_SqlGenerator $sg SQL generator object
+ */
+ public function setData(SparqlEngineDb_SqlGenerator $sg)
+ {
+ $this->arUsedVarTypes = $sg->getUsedVarTypes();
+ $this->arUsedVarAssignments = $sg->getUsedVarAssignments();
+ $this->arVarAssignments = $sg->getVarAssignments();
+ }//public function setData(SparqlEngineDb_SqlGenerator $sg)
+
+
+
+ /**
+ * Returns an array of sql statements that need to be executed
+ * and deliver the full result set when combined.
+ *
+ * Execute setData() before this.
+ *
+ * @internal It is not possible (ok, it is - but it would really complicate
+ * the queries and the code here) to use UNION to combine the sqls to
+ * a single one - UNION merges the results and does not keep the order
+ * of the rows. Citing the mysql manual:
+ * Use of ORDER BY for individual SELECT statements implies nothing
+ * about the order in which the rows appear in the final result because
+ * UNION by default produces an unordered set of rows. If ORDER BY
+ * appears with LIMIT, it is used to determine the subset of the
+ * selected rows to retrieve for the SELECT, but does not necessarily
+ * affect the order of those rows in the final UNION result.
+ * If ORDER BY appears without LIMIT in a SELECT, it is
+ * optimized away because it will have no effect anyway.
+ *
+ * @param string $strSelect SELECT clause
+ * @param string $strFrom FROM clause
+ * @param string $strWhere WHERE clause
+ * @return array Array of arrays. Imploding an array will give
+ * a complete sql statement. The array will have the keys
+ * select/from/where/order.
+ */
+ public function getOrderifiedSqls($arSqls)
+ {
+ if (count($arSqls) == 0) {
+ return $arSqls;
+ }
+
+ $strSelect = $arSqls[0]['select'];
+ $strFrom = $arSqls[0]['from'];
+ $strWhere = $arSqls[0]['where'];
+
+ $strResultForm = $this->query->getResultForm();
+ if ($strResultForm == 'ask' || $strResultForm == 'count') {
+ return array(
+ $arSqls
+ );
+ }
+
+ $arSpecial = $this->getSpecialOrderVariables();
+ if (count($arSpecial) == 0) {
+ $strOrder = $this->getSqlOrderBy();
+ foreach ($arSqls as &$arSql) {
+ $arSql['order'] = $strOrder;
+ }
+ return array(
+ $arSqls
+ );
+ }
+
+ $arTypeSets = $this->orderTypeSets(
+ $this->getTypeSets($arSpecial, $strFrom, $strWhere)
+ );
+
+ $arNewSqls = array();
+ foreach ($arTypeSets as $arTypeSet) {
+ $arSqlParts = array();
+ foreach ($arSqls as $arSql) {
+ $arSql['where'] .= $this->getTypesetWhereClause($arTypeSet);
+ $arSql['order'] = $this->getSqlOrderBy($arTypeSet);
+ $arSqlParts[] = $arSql;
+ }
+ $arNewSqls[] = $arSqlParts;
+ }
+
+ return $arNewSqls;
+ }//public function getOrderifiedSqls($arUsedVarAssignments, $strSelect, $strFrom, $strWhere)
+
+
+
+ /**
+ * Returns wether the returned queries will depend on the data or not.
+ * If the queries depend on the data, they cannot be prepare()d and
+ * thus won't be that fast when executing.
+ *
+ * Execute setData() before this.
+ *
+ * @return boolean
+ */
+ public function willBeDataDependent()
+ {
+ $strResultForm = $this->query->getResultForm();
+ return !(
+ $strResultForm == 'ask' || $strResultForm == 'count'
+ || count($this->getSpecialOrderVariables()) == 0
+ );
+ }//public function willBeDataDependent()
+
+
+
+ /**
+ * Returns an array of variables that the result is going to be
+ * ordered by and that need to be sorted multiple times
+ * (because they may contain different data types)
+ *
+ * @return array Array of sparql variable names
+ */
+ protected function getSpecialOrderVariables()
+ {
+ $arSM = $this->query->getSolutionModifier();
+ if ($arSM['order by'] === null) {
+ return array();
+ }
+
+ $arSpecial = array();
+ foreach ($arSM['order by'] as $arVar) {
+ if ($this->isSpecialOrderVariable($arVar['val'])) {
+ $arSpecial[] = $arVar['val'];
+ }
+ }
+ return $arSpecial;
+ }//protected function getSpecialOrderVariables()
+
+
+
+ /**
+ * Checks if a given variable name is a variable that
+ * needs special care when used in ORDER BY statements.
+ *
+ * @param string $strVar SPARQL variable name
+ * @return boolean true if the variable needs special care
+ */
+ protected function isSpecialOrderVariable($strVar)
+ {
+ return !isset($this->arUsedVarTypes[$strVar]['s'])
+ && !isset($this->arUsedVarTypes[$strVar]['p']);
+ }//protected function isSpecialOrderVariable($arVar)
+
+
+
+ /**
+ * Determines the type sets in the query results.
+ * A type set is a distinct set of variables and their types,
+ * e.g. the variable and its type (r/b/l) and its datatype
+ * if its an object.
+ *
+ * @param array $arSpecialVars Special variables as returned by
+ * getSpecialOrderVariables()
+ * @param string $strFrom FROM part of the sql query
+ * @param string $strWhere WHERE part of the sql query
+ *
+ * @return array Key is the sparql variable name, value is an
+ * array. This one has one key 'type' with a
+ * value of b/l/r. It might have another key
+ * 'datatype' with the resource's datatype.
+ */
+ protected function getTypeSets($arSpecialVars, $strFrom, $strWhere)
+ {
+ $arSel = array();
+ foreach ($arSpecialVars as $strSparqlVar) {
+ if ($this->arVarAssignments[$strSparqlVar][1] == 'o') {
+ $arSel[] = $this->arVarAssignments[$strSparqlVar][0] . '.l_datatype'
+ . ' as "' . $strSparqlVar . '-datatype"';
+ }
+ $strTypeCol = $this->arVarAssignments[$strSparqlVar][1] == 'o'
+ ? 'object_is' : 'subject_is';
+ $this->arVarAssignments[$strSparqlVar][2] = $strTypeCol;
+ $arSel[] = $this->arVarAssignments[$strSparqlVar][0] . '.' . $strTypeCol
+ . ' as "' . $strSparqlVar . '-type"';
+ }
+
+ $oldmode = $this->dbConn->SetFetchMode(ADODB_FETCH_ASSOC);
+ $sql = 'SELECT DISTINCT ' . implode(', ', $arSel) . ' ' . $strFrom . $strWhere;
+ $arResult = $this->dbConn->execute($sql);
+ $this->dbConn->SetFetchMode($oldmode);
+
+ if ($arResult === false) {
+ throw new SparqlEngineDb_SqlGeneratorException(
+ 'Error reading typesets: ' . $sql
+ );
+ }
+
+ $arTypes = array();
+ foreach ($arResult as $arRow) {
+ $nLine = count($arTypes);
+ foreach ($arRow as $key => $value) {
+ list($strSparqlVar, $strType) = explode('-', $key);
+ $arTypes[$nLine][$strSparqlVar][$strType] = $value;
+ }
+ }
+
+ return $arTypes;
+ }//protected function getTypeSets($arSpecialVars, $strFrom, $strWhere)
+
+
+
+ /**
+ * Takes an array of type sets (as returned by getTypeSets()) and
+ * sorts the variables according to the SPARQL specs.
+ *
+ * @param array $arTypes Array of type sets
+ * @return array Ordered array of type sets
+ */
+ protected function orderTypeSets($arTypes)
+ {
+ $arSM = $this->query->getSolutionModifier();
+ if ($arSM['order by'] !== null) {
+ $this->arDirection = array();
+ foreach ($arSM['order by'] as $arVar) {
+ $this->arDirection[$arVar['val']] =
+ (strtoupper($arVar['type']) == 'ASC' ? 1 : -1);
+ }
+ }
+
+ usort($arTypes, array($this, 'compareTypeSet'));
+
+ return $arTypes;
+ }//protected function orderTypeSets($arTypes)
+
+
+
+ /**
+ * Compares two type sets. Works like a normal comparision
+ * method that returns -1/0/1 for use in usort()
+ *
+ * @param array $arTs1 First typeset
+ * @param array $arTs2 Second typeset
+ * @return int Comparison value
+ */
+ public function compareTypeSet($arTs1, $arTs2)
+ {
+ foreach ($arTs1 as $strSparqlVar => $arType1) {
+ //compare types
+ $n = self::$arTypeNumbers[$arType1['type']]
+ - self::$arTypeNumbers[$arTs2[$strSparqlVar]['type']];
+ if ($n != 0) {
+ //and take ASC/DESC into account
+ return $n * $this->arDirection[$strSparqlVar];
+ }
+
+ //compare the datatypes
+ $n = self::compareXsdType(
+ $arType1['datatype'],
+ $arTs2[$strSparqlVar]['datatype']
+ );
+ //if they are not equal, return the value
+ if ($n != 0) {
+ //and take ASC/DESC into account
+ return $n * $this->arDirection[$strSparqlVar];
+ }
+ }
+
+ //they are equal
+ return 0;
+ }//public function compareTypeSet($arTs1, $arTs2)
+
+
+
+ /**
+ * Compares two XSD data types and returns the comparison number.
+ *
+ * @param string $strType1 First data type
+ * @param string $strType2 Second data type
+ * @return int Comparison number (<0 if $strType1 is less than
+ * $strType2, 0 if equal, >0 if type2 is greater)
+ */
+ public static function compareXsdType($strType1, $strType2)
+ {
+ return self::getXsdTypeNumber($strType1) - self::getXsdTypeNumber($strType2);
+ }//public static function compareXsdType($strType1, $strType2)
+
+
+
+ /**
+ * Returns the type number for an xsd data type.
+ *
+ * @param string $strType XSD data type
+ * @return int Some integer to compare two types.
+ */
+ public static function getXsdTypeNumber($strType)
+ {
+ if ($strType === null) {
+ return 0;
+ } else if ($strType == '') {
+ return 1;
+ } else {
+ return 2;
+ }
+ }//public static function getXsdTypeNumber($strType)
+
+
+
+ /**
+ * Returns the ORDER BY sql query string
+ * if neccessary for the query. The returned string
+ * already has ORDER BY prefixed.
+ *
+ * @internal Also takes care of casting the data if the type
+ * is listed in $arCastTypes. See getCastMethod() for more info.
+ *
+ * @param arrray $arTypeSet Single typeset
+ * @return string ORDER BY ... string or empty string
+ */
+ function getSqlOrderBy($arTypeSet = array())
+ {
+ $arSM = $this->query->getSolutionModifier();
+ if ($arSM['order by'] === null) {
+ return '';
+ }
+
+ $sqlOrder = array();
+ foreach ($arSM['order by'] as $arVar) {
+ $strSparqlVar = $arVar['val'];
+ if (isset($this->arUsedVarAssignments[$strSparqlVar])) {
+ if (!isset($arTypeSet[$strSparqlVar]['datatype'])
+ || $arTypeSet[$strSparqlVar]['datatype'] == '') {
+ $sqlOrder[] = $this->arUsedVarAssignments[$strSparqlVar] . ' ' . strtoupper($arVar['type']);
+ } else {
+ $sqlOrder[] = self::getCastMethod(
+ $arTypeSet[$strSparqlVar]['datatype'],
+ $this->arUsedVarAssignments[$strSparqlVar]
+ ) . ' ' . strtoupper($arVar['type']);
+ }
+ }
+ }
+
+ return ' ORDER BY ' . implode(', ', $sqlOrder);
+ }//function getSqlOrderBy($arTypeSet = array())
+
+
+
+ /**
+ * Returns the SQL statement needed to case the given variable to
+ * the given type.
+ *
+ * @param string $strType XML data type
+ * @param string $strSqlVar SQL variable name
+ * @return string SQL command to cast the variable
+ */
+ protected static function getCastMethod($strType, $strSqlVar)
+ {
+ if (isset(self::$arCastTypes[$strType])) {
+ return 'CAST(' . $strSqlVar . ' as ' . self::$arCastTypes[$strType] . ')';
+ } else {
+ //unsupported type!
+ throw new Exception('Unsupported cast type in order by: ' . $strType);
+ return $strSqlVar;
+ }
+ }//protected static function getCastMethod($strType, $strSqlVar)
+
+
+
+ /**
+ * Creates and returns the SQL WHERE clauses needed to get only
+ * data in the given typeset.
+ *
+ * @param array $arTypeSet Typeset
+ * @return string Clauses for the WHERE part in an SQL query
+ */
+ protected function getTypesetWhereClause($arTypeSet)
+ {
+ $strWhereTypes = '';
+ foreach ($arTypeSet as $strSparqlVar => $arType) {
+ //check type
+ $strWhereTypes .= ' AND ' . $this->arVarAssignments[$strSparqlVar][0]
+ . '.' . $this->arVarAssignments[$strSparqlVar][2]
+ . $this->getStringNullComparison($arType['type']);
+ //check datatype
+ if (isset($arType['datatype'])) {
+ $strWhereTypes .= ' AND ' . $this->arVarAssignments[$strSparqlVar][0]
+ . '.l_datatype '
+ . $this->getStringNullComparison($arType['datatype']);
+ }
+ }
+ return $strWhereTypes;
+ }//protected function getTypesetWhereClause($arTypeSet)
+
+
+
+ /**
+ * Returns the correct sql string comparison method.
+ *
+ * @internal If the string is NULL, an "IS NULL" sql statment
+ * will be returned, and a normal "= 'something'" if it is
+ * a normal string.
+ */
+ protected function getStringNullComparison($str)
+ {
+ if ($str === null) {
+ return ' IS NULL';
+ } else {
+ return ' = ' . $this->dbConn->qstr($str) . '';
+ }
+ }//protected function getStringNullComparison($str)
+
+}//class SparqlEngineDb_TypeSorter
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlParser.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlParser.php
new file mode 100755
index 00000000..f0e2c8c6
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlParser.php
@@ -0,0 +1,1551 @@
+
+* @author Christian Weiske
+* @version $Id$
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+class SparqlParser extends Object
+{
+
+ /**
+ * The query Object
+ * @var Query
+ */
+ protected $query;
+
+ /**
+ * The Querystring
+ * @var string
+ */
+ protected $queryString;
+
+ /**
+ * The tokenized Query
+ * @var array
+ */
+ protected $tokens = array();
+
+ /**
+ * Last parsed graphPattern
+ * @var int
+ */
+ protected $tmp;
+
+ /**
+ * Operators introduced by sparql
+ * @var array
+ */
+ protected static $sops = array(
+ 'regex',
+ 'bound',
+ 'isuri',
+ 'isblank',
+ 'isliteral',
+ 'str',
+ 'lang',
+ 'datatype',
+ 'langmatches'
+ );
+
+ /**
+ * Which order operators are to be treated.
+ * (11.3 Operator Mapping)
+ * @var array
+ */
+ protected static $operatorPrecedence = array(
+ '||' => 0,
+ '&&' => 1,
+ '=' => 2,
+ '!=' => 3,
+ '<' => 4,
+ '>' => 5,
+ '<=' => 6,
+ '>=' => 7,
+ '*' => 0,
+ '/' => 0,
+ '+' => 0,
+ '-' => 0,
+ );
+
+
+
+ /**
+ * Constructor of SparqlParser
+ */
+ public function SparqlParser()
+ {
+ }
+
+
+
+ /**
+ * Main function of SparqlParser. Parses a query string.
+ *
+ * @param String $queryString The SPARQL query
+ * @return Query The query object
+ * @throws SparqlParserException
+ */
+ public function parse($queryString = false)
+ {
+ $this->prepare();
+
+ if ($queryString) {
+ $this->query->setQueryString($queryString);
+ $uncommentedQuery = $this->uncomment($queryString);
+ $this->queryString = $uncommentedQuery;
+ $this->tokens = self::tokenize($uncommentedQuery);
+ $this->parseQuery();
+ if (!$this->query->isComplete()) {
+ throw new SparqlParserException(
+ "Query is incomplete.",
+ null,
+ $queryString
+ );
+ }
+ } else {
+ throw new SparqlParserException(
+ "Querystring is empty.",
+ null,
+ key($this->tokens)
+ );
+ $this->query->isEmpty = true;
+ }
+ return $this->query;
+ }//public function parse($queryString = false)
+
+
+
+ /**
+ * Set all internal variables to a clear state
+ * before we start parsing.
+ */
+ protected function prepare()
+ {
+ $this->query = new Query();
+ $this->queryString = null;
+ $this->tokens = array();
+ $this->tmp = null;
+ // add the default prefixes defined in constants.php
+ global $default_prefixes;
+ $this->query->prefixes = $default_prefixes;
+ }//protected function prepare()
+
+
+
+ /**
+ * Tokenizes the query string into $tokens.
+ * The query may not contain any comments.
+ *
+ * @param string $queryString Query to split into tokens
+ *
+ * @return array Tokens
+ */
+ public static function tokenize($queryString)
+ {
+ $queryString = trim($queryString);
+ $specialChars = array(' ', "\t", "\r", "\n", ',', '\\', '(', ')','{','}','"',"'",';','[',']');
+ $len = strlen($queryString);
+ $tokens = array('');
+ $n = 0;
+
+ for ($i = 0; $i < $len; ++$i) {
+ if (!in_array($queryString{$i}, $specialChars)) {
+ $tokens[$n] .= $queryString{$i};
+ } else {
+ if ($tokens[$n] != '') {
+ ++$n;
+ if (!isset($tokens[$n])) {
+ $tokens[$n] = '';
+ }
+ }
+ if ($queryString{$i} == "'" && $n > 1
+ && $tokens[$n - 2] == "'" && $tokens[$n - 1] == "'"
+ ) {
+ //special ''' quotation
+ $tokens[$n - 2] = "'''";
+ $tokens[$n - 1] = '';
+ unset($tokens[$n]);
+ --$n;
+ continue;
+ } else if ($queryString{$i} == '"' && $n > 1
+ && $tokens[$n - 2] == '"' && $tokens[$n - 1] == '"'
+ ) {
+ //special """ quotation
+ $tokens[$n - 2] = '"""';
+ $tokens[$n - 1] = '';
+ unset($tokens[$n]);
+ --$n;
+ continue;
+ } else if ($queryString{$i} == '\\') {
+ $tokens[$n] .= substr($queryString, $i, 2);
+ ++$i;
+ continue;
+ }
+ $tokens[$n] = $queryString{$i};
+ $tokens[++$n] = '';
+ }
+ }
+//var_dump($tokens);
+ return $tokens;
+ }//public static function tokenize($queryString)
+
+
+
+ /**
+ * Removes comments in the query string. Comments are
+ * indicated by '#'.
+ *
+ * @param String $queryString
+ * @return String The uncommented query string
+ */
+ protected function uncomment($queryString)
+ {
+ $regex ="/((\"[^\"]*\")|(\'[^\']*\')|(\<[^\>]*\>))|(#.*)/";
+ return preg_replace($regex,'\1',$queryString);
+ }//protected function uncomment($queryString)
+
+
+
+ /**
+ * Starts parsing the tokenized SPARQL Query.
+ *
+ * @return void
+ */
+ protected function parseQuery()
+ {
+ do {
+ switch (strtolower(current($this->tokens))) {
+ case "base":
+ $this->parseBase();
+ break;
+ case "prefix":
+ $this->parsePrefix();
+ break;
+ case "select":
+ $this->parseSelect();
+ break;
+ case "describe":
+ $this->parseDescribe();
+ break;
+ case "ask":
+ $this->parseAsk('ask');
+ break;
+ case "count":
+ $this->parseAsk('count');
+ break;
+ case "from":
+ $this->parseFrom();
+ break;
+ case "construct":
+ $this->parseConstruct();
+ break;
+ case "where":
+ $this->parseWhere();
+ $this->parseModifier();
+ break;
+ case "{":
+ prev($this->tokens);
+ $this->parseWhere();
+ $this->parseModifier();
+ break;
+ }
+ } while (next($this->tokens));
+
+ }//protected function parseQuery()
+
+
+
+ /**
+ * Parses the BASE part of the query.
+ *
+ * @return void
+ * @throws SparqlParserException
+ */
+ protected function parseBase()
+ {
+ $this->_fastForward();
+ if ($this->iriCheck(current($this->tokens))) {
+ $this->query->setBase(current($this->tokens));
+ } else {
+ $msg = current($this->tokens);
+ $msg = preg_replace('/', '<', $msg);
+ throw new SparqlParserException(
+ "IRI expected",
+ null,
+ key($this->tokens)
+ );
+ }
+ }
+
+
+
+ /**
+ * Adds a new namespace prefix to the query object.
+ *
+ * @return void
+ * @throws SparqlParserException
+ */
+ protected function parsePrefix()
+ {
+ $this->_fastForward();
+ $prefix = substr(current($this->tokens), 0, -1);
+ $this->_fastForward();
+ if ($this->iriCheck(current($this->tokens))) {
+ $uri = substr(current($this->tokens), 1, -1);
+ $this->query->addPrefix($prefix, $uri);
+ } else {
+ $msg = current($this->tokens);
+ $msg = preg_replace('/', '<', $msg);
+ throw new SparqlParserException(
+ "IRI expected",
+ null,
+ key($this->tokens)
+ );
+ }
+ }
+
+
+
+ /**
+ * Parses the SELECT part of a query.
+ *
+ * @return void
+ * @throws SparqlParserException
+ */
+ protected function parseSelect()
+ {
+ $this->_fastForward();
+ $curLow = strtolower(current($this->tokens));
+ prev($this->tokens);
+ if ($curLow == 'distinct') {
+ $this->query->setResultForm('select distinct');
+ } else {
+ $this->query->setResultForm('select');
+ }
+
+ $currentVar = null;
+ $currentFunc = null;
+ $bWaitForRenaming = false;
+ while ($curLow != 'from' && $curLow != 'where' &&
+ $curLow != "{"
+ ){
+ $this->_fastForward();
+ $curTok = current($this->tokens);
+ $curLow = strtolower($curTok);
+
+ if ($this->varCheck($curTok) || $curLow == '*') {
+ if ($bWaitForRenaming) {
+ $bWaitForRenaming = false;
+ $currentVar->setAlias($curTok);
+ if ($currentFunc != null) {
+ $currentVar->setFunc($currentFunc);
+ }
+ $this->query->addResultVar($currentVar);
+ $currentVar = null;
+ } else {
+ if ($currentVar != null) {
+ $this->query->addResultVar($currentVar);
+ $currentVar = null;
+ }
+ $currentVar = new Query_ResultVariable($curTok);
+ if ($currentFunc != null) {
+ $currentVar->setFunc($currentFunc);
+ }
+ }
+ $currentFunc = null;
+ } else if ($curLow == 'as') {
+ if ($currentVar === null) {
+ throw new SparqlParserException(
+ 'AS requires a variable left and right',
+ null,
+ key($this->tokens)
+ );
+ }
+ $bWaitForRenaming = true;
+ } else if (in_array($curLow, self::$sops)) {
+ $currentFunc = $curLow;
+ }
+
+ if (!current($this->tokens)) {
+ throw new SparqlParserException(
+ "Unexpected end of File.",
+ null,
+ key($this->tokens)
+ );
+ }
+ }
+
+ if ($currentVar != null) {
+ $this->query->addResultVar($currentVar);
+ }
+ prev($this->tokens);
+
+ if (count($this->query->getResultVars()) == 0) {
+ throw new SparqlParserException(
+ "Variable or '*' expected.",
+ null,
+ key($this->tokens)
+ );
+ }
+ }//protected function parseSelect()
+
+
+ /**
+ * Adds a new variable to the query and sets result form to 'DESCRIBE'.
+ *
+ * @return void
+ */
+ protected function parseDescribe()
+ {
+ while(strtolower(current($this->tokens))!='from'& strtolower(current($this->tokens))!='where'){
+ $this->_fastForward();
+ if($this->varCheck(current($this->tokens))|$this->iriCheck(current($this->tokens))){
+ $this->query->addResultVar(current($this->tokens));
+ if(!$this->query->getResultForm())
+ $this->query->setResultForm('describe');
+ }
+ if(!current($this->tokens))
+ break;
+ }
+ prev($this->tokens);
+ }
+
+ /**
+ * Sets result form to 'ASK' and 'COUNT'.
+ *
+ * @param string $form if it's an ASK or COUNT query
+ * @return void
+ */
+ protected function parseAsk($form){
+ $this->query->setResultForm($form);
+ $this->_fastForward();
+ if(current($this->tokens)=="{")
+ $this->_rewind();
+ $this->parseWhere();
+ $this->parseModifier();
+ }
+
+ /**
+ * Parses the FROM clause.
+ *
+ * @return void
+ * @throws SparqlParserException
+ */
+ protected function parseFrom(){
+ $this->_fastForward();
+ if(strtolower(current($this->tokens))!='named'){
+ if($this->iriCheck(current($this->tokens))||$this->qnameCheck(current($this->tokens))){
+ $this->query->addFrom(new Resource(substr(current($this->tokens),1,-1)));
+ }else if($this->varCheck(current($this->tokens))){
+ $this->query->addFrom(current($this->tokens));
+ }else{
+ throw new SparqlParserException("Variable, Iri or qname expected in FROM ",null,key($this->tokens));
+ }
+ $this->query->addFrom(current($this->tokens));
+ }else{
+ $this->_fastForward();
+ if($this->iriCheck(current($this->tokens))||$this->qnameCheck(current($this->tokens))){
+ $this->query->addFromNamed(new Resource(substr(current($this->tokens),1,-1)));
+ }else if($this->varCheck(current($this->tokens))){
+ $this->query->addFromNamed(current($this->tokens));
+ }else{
+ throw new SparqlParserException("Variable, Iri or qname expected in FROM NAMED ",null,key($this->tokens));
+ }
+ }
+ }
+
+
+ /**
+ * Parses the CONSTRUCT clause.
+ *
+ * @return void
+ * @throws SparqlParserException
+ */
+ protected function parseConstruct(){
+ $this->_fastForward();
+ $this->query->setResultForm('construct');
+ if(current($this->tokens)=="{"){
+ $this->parseGraphPattern(false,false,false,true);
+ }else{
+ throw new SparqlParserException("Unable to parse CONSTRUCT part. '{' expected. ",null,key($this->tokens));
+ }
+ $this->parseWhere();
+ $this->parseModifier();
+ }
+
+
+ /**
+ * Parses the WHERE clause.
+ *
+ * @return void
+ * @throws SparqlParserException
+ */
+ protected function parseWhere(){
+ $this->_fastForward();
+ if(current($this->tokens)=="{"){
+ $this->parseGraphPattern();
+ }else{
+ throw new SparqlParserException("Unable to parse WHERE part. '{' expected in Query. ",null,key($this->tokens));
+ }
+ }
+
+
+
+ /**
+ * Checks if $token is a variable.
+ *
+ * @param String $token The token
+ * @return boolean TRUE if the token is a variable false if not
+ */
+ protected function varCheck($token)
+ {
+ if (isset($token[0]) && ($token{0} == '$' || $token{0} == '?')) {
+ $this->query->addUsedVar($token);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Checks if $token is an IRI.
+ *
+ * @param String $token The token
+ * @return boolean TRUE if the token is an IRI false if not
+ */
+ protected function iriCheck($token){
+ $pattern="/^<[^>]*>\.?$/";
+ if(preg_match($pattern,$token)>0)
+ return true;
+ return false;
+ }
+
+
+ /**
+ * Checks if $token is a Blanknode.
+ *
+ * @param String $token The token
+ * @return boolean TRUE if the token is BNode false if not
+ */
+ protected function bNodeCheck($token){
+ if($token{0} == "_")
+ return true;
+ else
+ return false;
+ }
+
+
+ /**
+ * Checks if $token is a qname.
+ *
+ * @param String $token The token
+ * @return boolean TRUE if the token is a qname false if not
+ * @throws SparqlParserException
+ */
+ protected function qnameCheck($token)
+ {
+ $pattern="/^([^:^\<]*):([^:]*)$/";
+ if (preg_match($pattern,$token,$hits)>0) {
+ $prefs = $this->query->getPrefixes();
+ if (isset($prefs{$hits{1}})) {
+ return true;
+ }
+ if ($hits{1} == "_") {
+ return true;
+ }
+ throw new SparqlParserException("Unbound Prefix: ".$hits{1}."",null,key($this->tokens));
+ } else {
+ return false;
+ }
+ }
+
+
+
+ /**
+ * Checks if $token is a Literal.
+ *
+ * @param string $token The token
+ *
+ * @return boolean TRUE if the token is a Literal false if not
+ */
+ protected function literalCheck($token)
+ {
+ $pattern = "/^[\"\'].*$/";
+ if (preg_match($pattern,$token) > 0) {
+ return true;
+ }
+ return false;
+ }//protected function literalCheck($token)
+
+
+
+ /**
+ * FastForward until next token which is not blank.
+ *
+ * @return void
+ */
+ protected function _fastForward()
+ {
+ next($this->tokens);
+ while(current($this->tokens)==" "|current($this->tokens)==chr(10)|current($this->tokens)==chr(13)|current($this->tokens)==chr(9)){
+ next($this->tokens);
+ }
+ }//protected function _fastForward()
+
+
+
+ /**
+ * Rewind until next token which is not blank.
+ *
+ * @return void
+ */
+ protected function _rewind()
+ {
+ prev($this->tokens);
+ while(current($this->tokens)==" "|current($this->tokens)==chr(10)|current($this->tokens)==chr(13)|current($this->tokens)==chr(9)){
+ prev($this->tokens);
+ }
+ return;
+ }//protected function _rewind()
+
+
+
+ /**
+ * Parses a graph pattern.
+ *
+ * @param int $optional Optional graph pattern
+ * @param int $union Union graph pattern
+ * @param string $graph Graphname
+ * @param boolean $constr TRUE if the pattern is a construct pattern
+ * @param boolean $external If the parsed pattern shall be returned
+ * @param int $subpattern If the new pattern is subpattern of the
+ * pattern with the given id
+ * @return void
+ */
+ protected function parseGraphPattern(
+ $optional = false, $union = false, $graph = false,
+ $constr = false, $external = false, $subpattern = false
+ ){
+ $pattern = $this->query->getNewPattern($constr);
+ if (is_int($optional)) {
+ $pattern->setOptional($optional);
+ } else {
+ $this->tmp = $pattern->getId();
+ }
+ if (is_int($union)) {
+ $pattern->setUnion($union);
+ }
+ if (is_int($subpattern)) {
+ $pattern->setSubpatternOf($subpattern);
+ }
+ if ($graph != false) {
+ $pattern->setGraphname($graph);
+ }
+
+ $this->_fastForward();
+
+ do {
+ switch (strtolower(current($this->tokens))) {
+ case "graph":
+ $this->parseGraph();
+ break;
+ case "union":
+ $this->_fastForward();
+ $this->parseGraphPattern(
+ false, $this->tmp, false, false, false, $subpattern
+ );
+ break;
+ case "optional":
+ $this->_fastForward();
+ $this->parseGraphPattern(
+ $this->tmp, false, false, false, false, $subpattern
+ );
+ break;
+ case "filter":
+ $this->parseConstraint(
+ $pattern, true, false, false, false, $subpattern
+ );
+ $this->_fastForward();
+ break;
+ case ".":
+ $this->_fastForward();
+ break;
+ case "{":
+ if (!is_int($subpattern)) {
+ $subpattern = $pattern->getId();
+ }
+
+ $this->parseGraphPattern(
+ false, false, false, false, false, $subpattern
+ );
+ break;
+ case "}":
+ $pattern->open = false;
+ break;
+ default:
+ $this->parseTriplePattern($pattern);
+ break;
+ }
+ } while ($pattern->open);
+
+ if ($external) {
+ return $pattern;
+ }
+ $this->_fastForward();
+ }
+
+ /**
+ * Parses a triple pattern.
+ *
+ * @param GraphPattern $pattern
+ * @return void
+ */
+ protected function parseTriplePattern(&$pattern)
+ {
+ $trp = array();
+ $prev = false;
+ $prevPred = false;
+ $cont = true;
+ $sub = "";
+ $pre = "";
+ $tmp = "";
+ $tmpPred = "";
+ $obj = "";
+ do {
+//echo strtolower(current($this->tokens)) . "\n";
+ switch (strtolower(current($this->tokens))) {
+ case false:
+ $cont = false;
+ $pattern->open = false;
+ break;
+ case "filter":
+ $this->parseConstraint($pattern,false);
+ $this->_fastForward();
+ break;
+ case "optional":
+ $this->_fastForward();
+ $this->parseGraphPattern($pattern->getId(),false);
+ $cont = false;
+ break;
+ case "union":
+ $this->_fastForward();
+ $this->parseGraphPattern(
+ false, $this->tmp, false, false, false, $pattern->getId()
+ );
+ break;
+ case ";":
+ $prev = true;
+ $this->_fastForward();
+ break;
+ case ".":
+ $prev = false;
+ $this->_fastForward();
+ break;
+ case "graph":
+ $this->parseGraph();
+ break;
+ case ",":
+ $prev = true;
+ $prevPred = true;
+ $this->_fastForward();
+ break;
+ case "}":
+ $prev = false;
+ $pattern->open = false;
+ $cont = false;
+ break;
+ case '{':
+ //subpatterns opens
+ $this->parseGraphPattern(
+ false, false, false, false, false, $pattern->getId()
+ );
+ break;
+ case "[":
+ $prev = true;
+ $tmp = $this->parseNode($this->query->getBlanknodeLabel());
+ $this->_fastForward();
+ break;
+ case "]":
+ $prev = true;
+ $this->_fastForward();
+ break;
+ case "(":
+ $prev = true;
+ $tmp = $this->parseCollection($trp);
+ $this->_fastForward();
+ break;
+ case false:
+ $cont = false;
+ $pattern->open = false;
+ break;
+ default:
+ if ($prev) {
+ $sub = $tmp;
+ } else {
+ $sub = $this->parseNode();
+ $this->_fastForward();
+ $tmp = $sub;
+ }
+ if ($prevPred) {
+ $pre = $tmpPred;
+ } else {
+ $pre = $this->parseNode();
+ $this->_fastForward();
+ $tmpPred = $pre;
+ }
+ if (current($this->tokens)=="[") {
+ $tmp = $this->parseNode($this->query->getBlanknodeLabel());
+ $prev = true;
+ $obj = $tmp;
+ } else if (current($this->tokens)=="(") {
+ $obj = $this->parseCollection($trp);
+ } else {
+ $obj = $this->parseNode();
+ }
+ $trp[] = new QueryTriple($sub,$pre,$obj);
+ $this->_fastForward();
+ break;
+
+ }
+ } while ($cont);
+
+ if (count($trp) > 0) {
+ $pattern->addTriplePatterns($trp);
+ }
+ }
+
+
+
+ /**
+ * Parses a value constraint.
+ *
+ * @param GraphPattern $pattern
+ * @param boolean $outer If the constraint is an outer one.
+ * @return void
+ */
+ protected function parseConstraint(&$pattern, $outer)
+ {
+ $constraint = new Constraint();
+ $constraint->setOuterFilter($outer);
+ $this->_fastForward();
+ $this->_rewind();
+ $nBeginKey = key($this->tokens);
+ $constraint->setTree(
+ $t = $this->parseConstraintTree()
+ );
+
+ $nEndKey = key($this->tokens);
+ if (current($this->tokens) == '}') {
+ prev($this->tokens);
+ }
+
+ //for backwards compatibility with the normal sparql engine
+ // which does not use the tree array currently
+ $expression = trim(implode(
+ '',
+ array_slice(
+ $this->tokens,
+ $nBeginKey + 1,
+ $nEndKey - $nBeginKey - 1
+ )
+ ));
+ if ($expression[0] == '(' && substr($expression, -1) == ')') {
+ $expression = trim(substr($expression, 1, -1));
+ }
+ $constraint->addExpression($expression);
+
+ $pattern->addConstraint($constraint);
+ }//protected function parseConstraint(&$pattern, $outer)
+
+
+
+ /**
+ * Parses a constraint string recursively.
+ *
+ * The result array is one "element" which may contain subelements.
+ * All elements have one key "type" that determines which other
+ * array keys the element array has. Valid types are:
+ * - "value":
+ * Just a plain value with a value key, nothing else
+ * - "function"
+ * A function has a name and an array of parameter(s). Each parameter
+ * is an element.
+ * - "equation"
+ * An equation has an operator, and operand1 and operand2 which
+ * are elements themselves
+ * Any element may have the "negated" value set to true, which means
+ * that is is - negated (!).
+ *
+ * @internal The functionality of this method is being unit-tested
+ * in testSparqlParserTests::testParseFilter()
+ * "equation'-elements have another key "level" which is to be used
+ * internally only.
+ *
+ * @return array Nested tree array representing the filter
+ */
+ protected function parseConstraintTree($nLevel = 0, $bParameter = false)
+ {
+ $tree = array();
+ $part = array();
+ $chQuotes = null;
+ $litQuotes = null;
+ $strQuoted = '';
+
+ while ($tok = next($this->tokens)) {
+//var_dump(array($tok, $tok[strlen($tok) - 1]));
+ if ($chQuotes !== null && $tok != $chQuotes) {
+ $strQuoted .= $tok;
+ continue;
+ } else if ($litQuotes !== null) {
+ $strQuoted .= $tok;
+ if ($tok[strlen($tok) - 1] == '>') {
+ $tok = '>';
+ } else {
+ continue;
+ }
+ } else if ($tok == ')' || $tok == '}' || $tok == '.') {
+ break;
+ }
+
+ switch ($tok) {
+ case '"':
+ case '\'':
+ if ($chQuotes === null) {
+ $chQuotes = $tok;
+ $strQuoted = '';
+ } else {
+ $chQuotes = null;
+ $part[] = array(
+ 'type' => 'value',
+ 'value' => $strQuoted,
+ 'quoted'=> true
+ );
+ }
+ continue 2;
+ break;
+
+ case '>':
+ $litQuotes = null;
+ $part[] = array(
+ 'type' => 'value',
+ 'value' => $strQuoted,
+ 'quoted'=> false
+ );
+ continue 2;
+ break;
+
+ case '(':
+ $bFunc1 = isset($part[0]['type']) && $part[0]['type'] == 'value';
+ $bFunc2 = isset($tree['type']) && $tree['type'] == 'equation'
+ && isset($tree['operand2']) && isset($tree['operand2']['value']);
+ $part[] = $this->parseConstraintTree(
+ $nLevel + 1,
+ $bFunc1 || $bFunc2
+ );
+
+ if ($bFunc1) {
+ $tree['type'] = 'function';
+ $tree['name'] = $part[0]['value'];
+ self::fixNegationInFuncName($tree);
+ if (isset($part[1]['type'])) {
+ $part[1] = array($part[1]);
+ }
+ $tree['parameter'] = $part[1];
+ $part = array();
+ } else if ($bFunc2) {
+ $tree['operand2']['type'] = 'function';
+ $tree['operand2']['name'] = $tree['operand2']['value'];
+ self::fixNegationInFuncName($tree['operand2']);
+ $tree['operand2']['parameter'] = $part[0];
+ unset($tree['operand2']['value']);
+ unset($tree['operand2']['quoted']);
+ $part = array();
+ }
+ continue 2;
+ break;
+
+ case ' ':
+ case "\t":
+ continue 2;
+
+ case '=':
+ case '>':
+ case '<':
+ case '<=':
+ case '>=':
+ case '!=':
+ case '&&':
+ case '||':
+ if (isset($tree['type']) && $tree['type'] == 'equation'
+ && isset($tree['operand2'])) {
+ //previous equation open
+ $part = array($tree);
+ } else if (isset($tree['type']) && $tree['type'] != 'equation') {
+ $part = array($tree);
+ $tree = array();
+ }
+ $tree['type'] = 'equation';
+ $tree['level'] = $nLevel;
+ $tree['operator'] = $tok;
+ $tree['operand1'] = $part[0];
+ unset($tree['operand2']);
+ $part = array();
+ continue 2;
+ break;
+
+ case '!':
+ if ($tree != array()) {
+ throw new SparqlParserException(
+ 'Unexpected "!" negation in constraint.'
+ );
+ }
+ $tree['negated'] = true;
+ continue 2;
+
+ case ',':
+ //parameter separator
+ if (count($part) == 0 && !isset($tree['type'])) {
+ throw new SparqlParserException(
+ 'Unexpected comma'
+ );
+ }
+ $bParameter = true;
+ if (count($part) == 0) {
+ $part[] = $tree;
+ $tree = array();
+ }
+ continue 2;
+
+ default:
+ break;
+ }
+
+ if ($this->varCheck($tok)) {
+ $part[] = array(
+ 'type' => 'value',
+ 'value' => $tok,
+ 'quoted' => false
+ );
+ } else if (substr($tok, 0, 2) == '^^') {
+ $part[count($part) - 1]['datatype']
+ = $this->query->getFullUri(substr($tok, 2));
+ } else if ($tok[0] == '@') {
+ $part[count($part) - 1]['language'] = substr($tok, 1);
+ } else if ($tok[0] == '<') {
+ if ($tok[strlen($tok) - 1] == '>') {
+ //single-tokenized <> uris
+ $part[] = array(
+ 'type' => 'value',
+ 'value' => $tok,
+ 'quoted' => false
+ );
+ } else {
+ //iris split over several tokens
+ $strQuoted = $tok;
+ $litQuotes = true;
+ }
+ } else if ($tok == 'true' || $tok == 'false') {
+ $part[] = array(
+ 'type' => 'value',
+ 'value' => $tok,
+ 'quoted' => false,
+ 'datatype' => 'http://www.w3.org/2001/XMLSchema#boolean'
+ );
+ } else {
+ $part[] = array(
+ 'type' => 'value',
+ 'value' => $tok,
+ 'quoted' => false
+ );
+ }
+
+ if (isset($tree['type']) && $tree['type'] == 'equation' && isset($part[0])) {
+ $tree['operand2'] = $part[0];
+ self::balanceTree($tree);
+ $part = array();
+ }
+ }
+
+ if (!isset($tree['type']) && $bParameter) {
+ return $part;
+ } else if (isset($tree['type']) && $tree['type'] == 'equation'
+ && isset($tree['operand1']) && !isset($tree['operand2'])
+ && isset($part[0])) {
+ $tree['operand2'] = $part[0];
+ self::balanceTree($tree);
+ }
+
+ if (!isset($tree['type']) && isset($part[0])) {
+ if (isset($tree['negated'])) {
+ $part[0]['negated'] = true;
+ }
+ return $part[0];
+ }
+
+ return $tree;
+ }//protected function parseConstraintTree($nLevel = 0, $bParameter = false)
+
+
+
+ /**
+ * "Balances" the filter tree in the way that operators on the same
+ * level are nested according to their precedence defined in
+ * $operatorPrecedence array.
+ *
+ * @param array $tree Tree to be modified
+ */
+ protected static function balanceTree(&$tree)
+ {
+ if (
+ isset($tree['type']) && $tree['type'] == 'equation'
+ && isset($tree['operand1']['type']) && $tree['operand1']['type'] == 'equation'
+ && $tree['level'] == $tree['operand1']['level']
+ && self::$operatorPrecedence[$tree['operator']] > self::$operatorPrecedence[$tree['operand1']['operator']]
+ ) {
+ $op2 = array(
+ 'type' => 'equation',
+ 'level' => $tree['level'],
+ 'operator' => $tree['operator'],
+ 'operand1' => $tree['operand1']['operand2'],
+ 'operand2' => $tree['operand2']
+ );
+ $tree['operator'] = $tree['operand1']['operator'];
+ $tree['operand1'] = $tree['operand1']['operand1'];
+ $tree['operand2'] = $op2;
+ }
+ }//protected static function balanceTree(&$tree)
+
+
+
+ protected static function fixNegationInFuncName(&$tree)
+ {
+ if ($tree['type'] == 'function' && $tree['name'][0] == '!') {
+ $tree['name'] = substr($tree['name'], 1);
+ if (!isset($tree['negated'])) {
+ $tree['negated'] = true;
+ } else {
+ unset($tree['negated']);
+ }
+ //perhaps more !!
+ self::fixNegationInFuncName($tree);
+ }
+ }//protected static function fixNegationInFuncName(&$tree)
+
+
+
+ /**
+ * Parses a bracketted expression.
+ *
+ * @param Constraint $constraint
+ * @return void
+ * @throws SparqlParserException
+ */
+ protected function parseBrackettedExpression(&$constraint)
+ {
+ $open = 1;
+ $exp = "";
+ $this->_fastForward();
+ while ($open != 0 && current($this->tokens)!= false) {
+ switch (current($this->tokens)) {
+ case "(":
+ $open++;
+ $exp = $exp . current($this->tokens);
+ break;
+ case ")":
+ $open--;
+ if($open != 0){
+ $exp = $exp . current($this->tokens);
+ }
+ break;
+ case false:
+ throw new SparqlParserException(
+ "Unexpected end of query.",
+ null,
+ key($this->tokens)
+ );
+ default:
+ $exp = $exp . current($this->tokens);
+ break;
+ }
+ next($this->tokens);
+ }
+ $constraint->addExpression($exp);
+ }
+
+
+ /**
+ * Parses an expression.
+ *
+ * @param Constraint $constrain
+ * @return void
+ * @throws SparqlParserException
+ */
+ protected function parseExpression(&$constraint)
+ {
+ $exp = "";
+ while (current($this->tokens) != false && current($this->tokens) != "}") {
+ switch (current($this->tokens)) {
+ case false:
+ throw new SparqlParserException(
+ "Unexpected end of query.",
+ null,
+ key($this->tokens)
+ );
+ case ".":
+ break;
+ break;
+ default:
+ $exp = $exp . current($this->tokens);
+ break;
+ }
+ next($this->tokens);
+ }
+ $constraint->addExpression($exp);
+ }
+
+ /**
+ * Parses a GRAPH clause.
+ *
+ * @param GraphPattern $pattern
+ * @return void
+ * @throws SparqlParserException
+ */
+ protected function parseGraph(){
+ $this->_fastForward();
+ $name = current($this->tokens);
+ if(!$this->varCheck($name)&!$this->iriCheck($name)&&!$this->qnameCheck($name)){
+ $msg = $name;
+ $msg = preg_replace('/', '<', $msg);
+ throw new SparqlParserException(" IRI or Var expected. ",null,key($this->tokens));
+ }
+ $this->_fastForward();
+
+ if($this->iriCheck($name)){
+ $name = new Resource(substr($name,1,-1));
+ }else if($this->qnameCheck($name)){
+ $name = new Resource($this->query->getFullUri($name));
+ }
+ $this->parseGraphPattern(false,false,$name);
+ if(current($this->tokens)=='.')
+ $this->_fastForward();
+ }
+
+ /**
+ * Parses the solution modifiers of a query.
+ *
+ * @return void
+ * @throws SparqlParserException
+ */
+ protected function parseModifier(){
+ do{
+ switch(strtolower(current($this->tokens))){
+ case "order":
+ $this->_fastForward();
+ if(strtolower(current($this->tokens))=='by'){
+ $this->_fastForward();
+ $this->parseOrderCondition();
+ }else{
+ throw new SparqlParserException("'BY' expected.",null,key($this->tokens));
+ }
+ break;
+ case "limit":
+ $this->_fastForward();
+ $val = current($this->tokens);
+ $this->query->setSolutionModifier('limit',$val);
+ break;
+ case "offset":
+ $this->_fastForward();
+ $val = current($this->tokens);
+ $this->query->setSolutionModifier('offset',$val);
+ break;
+ default:
+ break;
+ }
+ }while(next($this->tokens));
+ }
+
+ /**
+ * Parses order conditions of a query.
+ *
+ * @return void
+ * @throws SparqlParserException
+ */
+ protected function parseOrderCondition(){
+ $valList = array();
+ $val = array();
+ while(strtolower(current($this->tokens))!='limit'
+ & strtolower(current($this->tokens))!= false
+ & strtolower(current($this->tokens))!= 'offset'){
+ switch (strtolower(current($this->tokens))){
+ case "desc":
+ $this->_fastForward();
+ $this->_fastForward();
+ if($this->varCheck(current($this->tokens))){
+ $val['val'] = current($this->tokens);
+ }else{
+ throw new SparqlParserException("Variable expected in ORDER BY clause. ",null,key($this->tokens));
+ }
+ $this->_fastForward();
+ if(current($this->tokens)!=')')
+ throw new SparqlParserException("missing ')' in ORDER BY clause.",null,key($this->tokens));
+ $val['type'] = 'desc';
+ $this->_fastForward();
+ break;
+ case "asc" :
+ $this->_fastForward();
+ $this->_fastForward();
+ if($this->varCheck(current($this->tokens))){
+ $val['val'] = current($this->tokens);
+ }else{
+ throw new SparqlParserException("Variable expected in ORDER BY clause. ",null,key($this->tokens));
+ }
+ $this->_fastForward();
+ if(current($this->tokens)!=')')
+ throw new SparqlParserException("missing ')' in ORDER BY clause.",null,key($this->tokens));
+ $val['type'] = 'asc';
+ $this->_fastForward();
+ break;
+ default:
+ if($this->varCheck(current($this->tokens))){
+ $val['val'] = current($this->tokens);
+ $val['type'] = 'asc';
+ }else{
+ throw new SparqlParserException("Variable expected in ORDER BY clause. ",null,key($this->tokens));
+ }
+ $this->_fastForward();
+ break;
+ }
+ $valList[] = $val;
+ }
+ prev($this->tokens);
+ $this->query->setSolutionModifier('order by',$valList);
+ }
+
+ /**
+ * Parses a String to an RDF node.
+ *
+ * @param String $node
+ *
+ * @return Node The parsed RDF node
+ * @throws SparqlParserException
+ */
+ protected function parseNode($node = false)
+ {
+ //$eon = false;
+ if ($node) {
+ $node = $node;
+ } else {
+ $node = current($this->tokens);
+ }
+ if ($node{strlen($node)-1} == '.') {
+ $node = substr($node,0,-1);
+ }
+ if ($this->dtypeCheck($node)) {
+ return $node;
+ }
+ if ($this->bNodeCheck($node)) {
+ $node = '?'.$node;
+ $this->query->addUsedVar($node);
+ return $node;
+ }
+ if ($node == '[') {
+ $node = '?' . substr($this->query->getBlanknodeLabel(), 1);
+ $this->query->addUsedVar($node);
+ $this->_fastForward();
+ if(current($this->tokens)!=']') {
+ prev($this->tokens);
+ }
+ return $node;
+ }
+ if ($this->iriCheck($node)){
+ $base = $this->query->getBase();
+ if ($base!=null) {
+ $node = new Resource(substr(substr($base,0,-1).substr($node,1),1,-1));
+ } else {
+ $node = new Resource(substr($node,1,-1));
+ }
+ return $node;
+ } else if ($this->qnameCheck($node)) {
+ $node = $this->query->getFullUri($node);
+ $node = new Resource($node);
+ return $node;
+ } else if ($this->literalCheck($node)) {
+ $ch = substr($node, 0, 1);
+ $chLong = str_repeat($ch, 3);
+ if (substr($node, 0, 3) == $chLong) {
+ $ch = $chLong;
+ }
+ $this->parseLiteral($node, $ch);
+ } else if ($this->varCheck($node)) {
+ $pos = strpos($node,'.');
+ if ($pos) {
+ return substr($node,0,$pos);
+ } else {
+ return $node;
+ }
+ } else if ($node[0] == '<') {
+ //partial IRI? loop tokens until we find a closing >
+ while (next($this->tokens)) {
+ $node .= current($this->tokens);
+ if (substr($node, -1) == '>') {
+ break;
+ }
+ }
+ if (substr($node, -1) != '>') {
+ throw new SparqlParserException(
+ "Unclosed IRI: " . $node,
+ null,
+ key($this->tokens)
+ );
+ }
+ return $this->parseNode($node);
+ } else {
+ throw new SparqlParserException(
+ '"' . $node . '" is neither a valid rdf- node nor a variable.',
+ null,
+ key($this->tokens)
+ );
+ }
+ return $node;
+ }//protected function parseNode($node = false)
+
+
+
+ /**
+ * Checks if there is a datatype given and appends it to the node.
+ *
+ * @param string $node Node to check
+ *
+ * @return void
+ */
+ protected function checkDtypeLang(&$node, $nSubstrLength = 1)
+ {
+ $this->_fastForward();
+ switch (substr(current($this->tokens), 0, 1)) {
+ case '^':
+ if (substr(current($this->tokens),0,2)=='^^') {
+ $node = new Literal(substr($node,1,-1));
+ $node->setDatatype(
+ $this->query->getFullUri(
+ substr(current($this->tokens), 2)
+ )
+ );
+ }
+ break;
+ case '@':
+ $node = new Literal(
+ substr($node, $nSubstrLength, -$nSubstrLength),
+ substr(current($this->tokens), $nSubstrLength)
+ );
+ break;
+ default:
+ prev($this->tokens);
+ $node = new Literal(substr($node, $nSubstrLength, -$nSubstrLength));
+ break;
+
+ }
+ }//protected function checkDtypeLang(&$node, $nSubstrLength = 1)
+
+
+
+ /**
+ * Parses a literal.
+ *
+ * @param String $node
+ * @param String $sep used separator " or '
+ *
+ * @return void
+ */
+ protected function parseLiteral(&$node, $sep)
+ {
+ do {
+ next($this->tokens);
+ $node = $node.current($this->tokens);
+ } while (current($this->tokens) != $sep);
+ $this->checkDtypeLang($node, strlen($sep));
+ }//protected function parseLiteral(&$node, $sep)
+
+
+
+ /**
+ * Checks if the Node is a typed Literal.
+ *
+ * @param String $node
+ *
+ * @return boolean TRUE if typed FALSE if not
+ */
+ protected function dtypeCheck(&$node)
+ {
+ $patternInt = "/^-?[0-9]+$/";
+ $match = preg_match($patternInt,$node,$hits);
+ if($match>0){
+ $node = new Literal($hits[0]);
+ $node->setDatatype(XML_SCHEMA.'integer');
+ return true;
+ }
+ $patternBool = "/^(true|false)$/";
+ $match = preg_match($patternBool,$node,$hits);
+ if($match>0){
+ $node = new Literal($hits[0]);
+ $node->setDatatype(XML_SCHEMA.'boolean');
+ return true;
+ }
+ $patternType = "/^a$/";
+ $match = preg_match($patternType,$node,$hits);
+ if($match>0){
+ $node = new Resource(RDF_NAMESPACE_URI.'type');
+ return true;
+ }
+ $patternDouble = "/^-?[0-9]+.[0-9]+[e|E]?-?[0-9]*/";
+ $match = preg_match($patternDouble,$node,$hits);
+ if($match>0){
+ $node = new Literal($hits[0]);
+ $node->setDatatype(XML_SCHEMA.'double');
+ return true;
+ }
+ return false;
+ }//protected function dtypeCheck(&$node)
+
+
+
+ /**
+ * Parses an RDF collection.
+ *
+ * @param TriplePattern $trp
+ *
+ * @return Node The first parsed label
+ */
+ protected function parseCollection(&$trp)
+ {
+ $tmpLabel = $this->query->getBlanknodeLabel();
+ $firstLabel = $this->parseNode($tmpLabel);
+ $this->_fastForward();
+ $i = 0;
+ while (current($this->tokens)!=")") {
+ if($i>0)
+ $trp[] = new QueryTriple($this->parseNode($tmpLabel),new Resource("http://www.w3.org/1999/02/22-rdf-syntax-ns#rest"),$this->parseNode($tmpLabel = $this->query->getBlanknodeLabel()));
+ $trp[] = new QueryTriple($this->parseNode($tmpLabel),new Resource("http://www.w3.org/1999/02/22-rdf-syntax-ns#first"),$this->parseNode());
+ $this->_fastForward();
+ $i++;
+ }
+ $trp[] = new QueryTriple($this->parseNode($tmpLabel),new Resource("http://www.w3.org/1999/02/22-rdf-syntax-ns#rest"),new Resource("http://www.w3.org/1999/02/22-rdf-syntax-ns#nil"));
+ return $firstLabel;
+ }//protected function parseCollection(&$trp)
+
+}// end class: SparqlParser.php
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlParserException.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlParserException.php
new file mode 100755
index 00000000..9151ce84
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlParserException.php
@@ -0,0 +1,33 @@
+
+* @version $Id$
+* @license http://www.gnu.org/licenses/lgpl.html LGPL
+*
+* @package sparql
+*/
+Class SparqlParserException extends Exception{
+
+ private $tokenPointer;
+
+ public function __construct($message, $code = 0, $pointer){
+
+ $this->tokenPointer = $pointer;
+ parent::__construct($message, $code);
+ }
+
+ /**
+ * Returns a pointer to the token which caused the exception.
+ * @return int
+ */
+ public function getPointer(){
+ return $this->tokenPointer;
+ }
+
+}
+?>
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlVariable.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlVariable.php
new file mode 100755
index 00000000..5db6e665
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/sparql/SparqlVariable.php
@@ -0,0 +1,40 @@
+name = $name;
+ }
+
+
+
+ public function __toString()
+ {
+ return $this->name;
+ }
+
+
+
+ /**
+ * Checks if the given subject/predicate/object
+ * is a variable name.
+ *
+ * @return boolean
+ */
+ public static function isVariable($bject)
+ {
+ return is_string($bject) && strlen($bject) >= 2
+ && ($bject[0] == '?' || $bject[0] == '$');
+ }//public static function isVariable($bject)
+
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/all-wcprops b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/all-wcprops
new file mode 100755
index 00000000..214ebffe
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/all-wcprops
@@ -0,0 +1,113 @@
+K 25
+svn:wc:ra_dav:version-url
+V 60
+/svnroot/rdfapi-php/!svn/ver/556/trunk/rdfapi-php/api/syntax
+END
+N3Parser.php
+K 25
+svn:wc:ra_dav:version-url
+V 73
+/svnroot/rdfapi-php/!svn/ver/517/trunk/rdfapi-php/api/syntax/N3Parser.php
+END
+TriXParser.php
+K 25
+svn:wc:ra_dav:version-url
+V 75
+/svnroot/rdfapi-php/!svn/ver/268/trunk/rdfapi-php/api/syntax/TriXParser.php
+END
+JsonSerializer.php
+K 25
+svn:wc:ra_dav:version-url
+V 79
+/svnroot/rdfapi-php/!svn/ver/555/trunk/rdfapi-php/api/syntax/JsonSerializer.php
+END
+SyntaxGRDDL.php
+K 25
+svn:wc:ra_dav:version-url
+V 76
+/svnroot/rdfapi-php/!svn/ver/320/trunk/rdfapi-php/api/syntax/SyntaxGRDDL.php
+END
+RdfSerializer.php
+K 25
+svn:wc:ra_dav:version-url
+V 78
+/svnroot/rdfapi-php/!svn/ver/316/trunk/rdfapi-php/api/syntax/RdfSerializer.php
+END
+NTripleSerializer.php
+K 25
+svn:wc:ra_dav:version-url
+V 82
+/svnroot/rdfapi-php/!svn/ver/268/trunk/rdfapi-php/api/syntax/NTripleSerializer.php
+END
+GRDDLParser.php
+K 25
+svn:wc:ra_dav:version-url
+V 76
+/svnroot/rdfapi-php/!svn/ver/320/trunk/rdfapi-php/api/syntax/GRDDLParser.php
+END
+N3Serializer.php
+K 25
+svn:wc:ra_dav:version-url
+V 77
+/svnroot/rdfapi-php/!svn/ver/556/trunk/rdfapi-php/api/syntax/N3Serializer.php
+END
+SparqlResultParser.php
+K 25
+svn:wc:ra_dav:version-url
+V 83
+/svnroot/rdfapi-php/!svn/ver/442/trunk/rdfapi-php/api/syntax/SparqlResultParser.php
+END
+SyntaxRSS.php
+K 25
+svn:wc:ra_dav:version-url
+V 74
+/svnroot/rdfapi-php/!svn/ver/320/trunk/rdfapi-php/api/syntax/SyntaxRSS.php
+END
+TriXSerializer.php
+K 25
+svn:wc:ra_dav:version-url
+V 79
+/svnroot/rdfapi-php/!svn/ver/268/trunk/rdfapi-php/api/syntax/TriXSerializer.php
+END
+SyntaxJSON.php
+K 25
+svn:wc:ra_dav:version-url
+V 75
+/svnroot/rdfapi-php/!svn/ver/552/trunk/rdfapi-php/api/syntax/SyntaxJSON.php
+END
+SyntaxRDF.php
+K 25
+svn:wc:ra_dav:version-url
+V 74
+/svnroot/rdfapi-php/!svn/ver/320/trunk/rdfapi-php/api/syntax/SyntaxRDF.php
+END
+SyntaxSparqlRes.php
+K 25
+svn:wc:ra_dav:version-url
+V 80
+/svnroot/rdfapi-php/!svn/ver/320/trunk/rdfapi-php/api/syntax/SyntaxSparqlRes.php
+END
+RssParser.php
+K 25
+svn:wc:ra_dav:version-url
+V 74
+/svnroot/rdfapi-php/!svn/ver/301/trunk/rdfapi-php/api/syntax/RssParser.php
+END
+JsonParser.php
+K 25
+svn:wc:ra_dav:version-url
+V 75
+/svnroot/rdfapi-php/!svn/ver/555/trunk/rdfapi-php/api/syntax/JsonParser.php
+END
+SyntaxN3.php
+K 25
+svn:wc:ra_dav:version-url
+V 73
+/svnroot/rdfapi-php/!svn/ver/320/trunk/rdfapi-php/api/syntax/SyntaxN3.php
+END
+RdfParser.php
+K 25
+svn:wc:ra_dav:version-url
+V 74
+/svnroot/rdfapi-php/!svn/ver/493/trunk/rdfapi-php/api/syntax/RdfParser.php
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/entries b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/entries
new file mode 100755
index 00000000..008b678a
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/entries
@@ -0,0 +1,262 @@
+8
+
+dir
+556
+https://rdfapi-php.svn.sourceforge.net/svnroot/rdfapi-php/trunk/rdfapi-php/api/syntax
+https://rdfapi-php.svn.sourceforge.net/svnroot/rdfapi-php
+
+
+
+2008-01-22T10:52:48.041272Z
+556
+fusel2k
+
+
+svn:special svn:externals svn:needs-lock
+
+
+
+
+
+
+
+
+
+
+
+b2ee660e-c932-0410-bdee-d8da4d8102f4
+
+N3Parser.php
+file
+
+
+
+
+2008-02-29T14:57:47.865530Z
+112f9ffb3eecb8f3889f1b7924f638b9
+2007-08-13T16:14:17.763656Z
+517
+cweiske
+has-props
+
+TriXParser.php
+file
+
+
+
+
+2008-02-29T14:57:47.896771Z
+1eb40f115840fcd2c5067931dd90d9b3
+2006-05-15T05:28:09.000000Z
+268
+tgauss
+has-props
+
+JsonSerializer.php
+file
+
+
+
+
+2008-02-29T14:57:47.881151Z
+7e382932ad24a6eb9fbfbd43a3bdf586
+2007-12-11T20:27:34.710933Z
+555
+p_frischmuth
+has-props
+
+SyntaxGRDDL.php
+file
+
+
+
+
+2008-02-29T14:57:47.881151Z
+035b206f45692cb49acaf5211b43f4ff
+2006-11-21T09:38:51.000000Z
+320
+tgauss
+has-props
+
+RdfSerializer.php
+file
+
+
+
+
+2008-02-29T14:57:47.896771Z
+8182d432e5d53187b4ed144b4e92a5b8
+2006-08-24T07:55:29.000000Z
+316
+tgauss
+has-props
+
+NTripleSerializer.php
+file
+
+
+
+
+2008-02-29T14:57:47.912392Z
+d80d6ba00ff0cd324384a34a40c831ab
+2006-05-15T05:28:09.000000Z
+268
+tgauss
+has-props
+
+GRDDLParser.php
+file
+
+
+
+
+2008-02-29T14:57:47.912392Z
+b3c7c8b3e0fa482c12f511683772c4ea
+2006-11-21T09:38:51.000000Z
+320
+tgauss
+has-props
+
+N3Serializer.php
+file
+
+
+
+
+2008-02-29T14:57:47.928013Z
+30157ef08631eef25957a56e3542d284
+2008-01-22T10:52:48.041272Z
+556
+fusel2k
+has-props
+
+SparqlResultParser.php
+file
+
+
+
+
+2008-02-29T14:57:47.943633Z
+5c7a1a5a7e925334256ce0b12354c20f
+2007-06-01T16:19:26.000000Z
+442
+cax
+has-props
+
+SyntaxRSS.php
+file
+
+
+
+
+2008-02-29T14:57:47.928013Z
+8b422e251e0ba0658d541ecbc9541aea
+2006-11-21T09:38:51.000000Z
+320
+tgauss
+has-props
+
+TriXSerializer.php
+file
+
+
+
+
+2008-02-29T14:57:47.943633Z
+adb9be4b413f8b2a9055bcfb4d2eff53
+2006-05-15T05:28:09.000000Z
+268
+tgauss
+has-props
+
+SyntaxJSON.php
+file
+
+
+
+
+2008-02-29T14:57:47.943633Z
+754f114a67a5ba7da4deea1ab439c990
+2007-11-23T09:12:11.140388Z
+552
+p_frischmuth
+has-props
+
+SyntaxRDF.php
+file
+
+
+
+
+2008-02-29T14:57:47.959254Z
+e7c898c17d52c5dc6308a71ea547ce6f
+2006-11-21T09:38:51.000000Z
+320
+tgauss
+has-props
+
+SyntaxSparqlRes.php
+file
+
+
+
+
+2008-02-29T14:57:47.959254Z
+b2493bd4cee875db558b5d708181b2a7
+2006-11-21T09:38:51.000000Z
+320
+tgauss
+has-props
+
+RssParser.php
+file
+
+
+
+
+2008-02-29T14:57:47.974874Z
+325cb7dcfb103295a7f5974384e312ab
+2006-06-26T10:22:25.000000Z
+301
+tgauss
+has-props
+
+JsonParser.php
+file
+
+
+
+
+2008-02-29T14:57:47.974874Z
+54244ff3c37bf47b4e9b914d2b50d1e0
+2007-12-11T20:27:34.710933Z
+555
+p_frischmuth
+has-props
+
+SyntaxN3.php
+file
+
+
+
+
+2008-02-29T14:57:47.990495Z
+f31fb3eceb8ca23be83648f5e7b1909d
+2006-11-21T09:38:51.000000Z
+320
+tgauss
+has-props
+
+RdfParser.php
+file
+
+
+
+
+2008-02-29T14:57:47.990495Z
+89eba3f0656c075f28c178b4a678dc05
+2007-08-12T17:43:07.694190Z
+493
+cweiske
+has-props
+
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/format b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/format
new file mode 100755
index 00000000..45a4fb75
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/format
@@ -0,0 +1 @@
+8
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/GRDDLParser.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/GRDDLParser.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/GRDDLParser.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/JsonParser.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/JsonParser.php.svn-base
new file mode 100755
index 00000000..92c8ad74
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/JsonParser.php.svn-base
@@ -0,0 +1,5 @@
+K 12
+svn:keywords
+V 2
+Id
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/JsonSerializer.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/JsonSerializer.php.svn-base
new file mode 100755
index 00000000..92c8ad74
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/JsonSerializer.php.svn-base
@@ -0,0 +1,5 @@
+K 12
+svn:keywords
+V 2
+Id
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/N3Parser.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/N3Parser.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/N3Parser.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/N3Serializer.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/N3Serializer.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/N3Serializer.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/NTripleSerializer.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/NTripleSerializer.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/NTripleSerializer.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/RdfParser.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/RdfParser.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/RdfParser.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/RdfSerializer.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/RdfSerializer.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/RdfSerializer.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/RssParser.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/RssParser.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/RssParser.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/SparqlResultParser.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/SparqlResultParser.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/SparqlResultParser.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/SyntaxGRDDL.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/SyntaxGRDDL.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/SyntaxGRDDL.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/SyntaxJSON.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/SyntaxJSON.php.svn-base
new file mode 100755
index 00000000..92c8ad74
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/SyntaxJSON.php.svn-base
@@ -0,0 +1,5 @@
+K 12
+svn:keywords
+V 2
+Id
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/SyntaxN3.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/SyntaxN3.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/SyntaxN3.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/SyntaxRDF.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/SyntaxRDF.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/SyntaxRDF.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/SyntaxRSS.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/SyntaxRSS.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/SyntaxRSS.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/SyntaxSparqlRes.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/SyntaxSparqlRes.php.svn-base
new file mode 100755
index 00000000..7b57b302
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/SyntaxSparqlRes.php.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/TriXParser.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/TriXParser.php.svn-base
new file mode 100755
index 00000000..bdbd3051
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/TriXParser.php.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:eol-style
+V 6
+native
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/TriXSerializer.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/TriXSerializer.php.svn-base
new file mode 100755
index 00000000..bdbd3051
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/prop-base/TriXSerializer.php.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:eol-style
+V 6
+native
+END
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/GRDDLParser.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/GRDDLParser.php.svn-base
new file mode 100755
index 00000000..988927d4
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/GRDDLParser.php.svn-base
@@ -0,0 +1,120 @@
+,
+ *
+ * @package syntax
+ * @access public
+ *
+ */
+class GRDDLParser extends Object{
+
+
+ /**
+ * Document link
+ *
+ *
+ * @var String
+ * @access private
+ */
+ var $doclink;
+
+
+ /**
+ * Stylesheet link
+ *
+ *
+ * @var String[]
+ * @access private
+ */
+ var $stylelinks;
+
+
+ /**
+ * DomDocument
+ *
+ * @var DomDocument
+ * @access private
+ */
+ var $domdoc;
+
+
+ /**
+ * generates a MemModel and creates the DomDocument.
+ *
+ * @param String $doc
+ * @access public
+ * @return MemModel $model
+ */
+ function generateModel($doc){
+ $model = new MemModel();
+ $this->doclink=$doc;
+ $this->domdoc = new DomDocument;
+ $this->domdoc->load($doc);
+ $this->_getStyles();
+ $model = $this->_generateRDF();
+ return $model;
+ }
+
+
+ /**
+ * gets the used xsl stylesheets.
+ *
+ * @access private
+ */
+ function _getStyles(){
+ $link=$this->domdoc->getElementsByTagName('link');
+ $i=0;
+ while($link->item($i)!=''){
+ $item = $link->item($i);
+ if($item->getAttributeNode('rel')->value=='transformation'){
+ $temp = $item->getAttributeNode('href')->value;
+ if(substr($temp,0,1)=='/'){
+ $pos = strrpos($this->doclink,'/');
+ $part = substr($this->doclink,0,$pos);
+ $this->stylelink[]=$part.$temp;
+ }else{
+ $this->stylelink[]=$temp;
+ }
+ }
+ $i++;
+ }
+ }
+
+ /*
+ * uses the PHP build in xslt processor to
+ * generate the RDF statements and uses the
+ * RDF- Parser to generate the model
+ *
+ * @access private
+ * @return MemModel $model
+ */
+ function _generateRDF(){
+ $model=new MemModel();
+ $model->setBaseURI($this->doclink);
+ $proc = new xsltprocessor;
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_RDF);
+ $pars=new RdfParser();
+ foreach($this->stylelink as $key => $value){
+ $xsl = new DomDocument;
+ $xsl->load($value);
+ $proc->importStyleSheet($xsl);
+ $model->addModel($pars->generateModel($proc->transformToXML($this->domdoc),$this->doclink));
+ }
+ return $model;
+ }
+
+
+
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/JsonParser.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/JsonParser.php.svn-base
new file mode 100755
index 00000000..61dc2781
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/JsonParser.php.svn-base
@@ -0,0 +1,54 @@
+
+ * @version $Id$
+ */
+class JsonParser extends Object {
+
+ /**
+ * This method takes a json encoded rdf-model and a reference to aa (usually empty) MemModel, parses the json
+ * string and adds the statements to the given MemModel.
+ *
+ * @param string $jsonString The string that contains the rdf model, encoded as a json-string.
+ * @param MemModel $model A reference to the model, where to add the statements, usually an empty MemModel.
+ */
+ public function generateModelFromString($jsonString, $model) {
+
+ $jsonModel = array();
+ $jsonModel = json_decode($jsonString, true);
+
+ // throws an excpetion if json model was corrupt
+ if (!is_array($jsonModel)) {
+ throw new Exception('error in json string');
+ }
+
+ foreach ($jsonModel as $subject=>$remain) {
+ foreach ($remain as $predicate=>$object) {
+ $s = (strpos($subject, '_') === 0) ? new BlankNode(substr($subject, 2)) : new Resource($subject);
+ $p = new Resource($predicate);
+
+ foreach ($object as $obj) {
+ if ($obj['type'] === 'uri') {
+ $o = new Resource($obj['value']);
+ } else if ($obj['type'] === 'bnode') {
+ $o = new BlankNode(substr($obj['value'], 2));
+ } else {
+ $dtype = (isset($obj['datatype'])) ? $obj['datatype'] : '';
+ $lang = (isset($obj['lang'])) ? $obj['lang'] : '';
+
+ $oVal = $obj['value'];
+
+ $o = new Literal($oVal, $lang);
+ $o->setDatatype($dtype);
+ }
+
+ $model->add(new Statement($s, $p, $o));
+ }
+ }
+ }
+ }
+}
+?>
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/JsonSerializer.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/JsonSerializer.php.svn-base
new file mode 100755
index 00000000..8e1c867e
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/JsonSerializer.php.svn-base
@@ -0,0 +1,163 @@
+
+ * @version $Id$
+ */
+class JsonSerializer extends Object {
+
+ /**
+ * This method takes a MemModel object ad parameter and serializes all contained triples to rdf/json format.
+ *
+ * @see http://n2.talis.com/wiki/RDF_JSON_Specification#rdf.2Fjson
+ * @param MemModel $model
+ * @return string Returns a string containing the serialized model.
+ */
+ public function serialize(MemModel $model) {
+
+ // create the root json object (root object)
+ $jsonString = '{';
+ $subjects = array();
+
+ // sort triples by subject
+ foreach ($model->triples as $triple) {
+ $subjects[$triple->toStringSubject()][] = $triple;
+ }
+
+ // sort alphabetically
+ ksort($subjects);
+
+ // triples are sorted by subject now, each key is a subject uri, containing all triples with this subject uri
+ $i = 0;
+ foreach ($subjects as $predicatesArray) {
+ $predicates = array();
+
+ if ($i > 0) {
+ $jsonString .= ',';
+ }
+ $i++;
+
+ $subj = $predicatesArray[0]->getSubject();
+
+ // add special _: sequence for blank node only
+ if ($subj instanceof BlankNode) {
+ $jsonString .= '"_:' . $this->_escapeValue($subj->getLabel()) . '":';
+ } else {
+ $jsonString .= '"' . $this->_escapeValue($subj->getLabel()) . '":';
+ }
+
+
+
+ // create a json object for each subject (subject object)
+ $jsonString .= '{';
+
+ // sort triples with current subject by predicate
+ foreach ($predicatesArray as $triple) {
+ $predicates[$triple->toStringPredicate()][] = $triple;
+ }
+
+ // sort alphabetically
+ ksort($predicates);
+
+ $j = 0;
+ foreach ($predicates as $valueArray) {
+
+ if ($j > 0) {
+ $jsonString .= ',';
+ }
+ $j++;
+
+ $jsonString .= '"' . $this->_escapeValue($valueArray[0]->getLabelPredicate()) . '":';
+
+ // create a json array (value array)
+ $jsonString .= '[';
+
+ $k = 0;
+ foreach ($valueArray as $triple) {
+ if ($k > 0) {
+ $jsonString .= ',';
+ }
+ $k++;
+
+ // create json value object (value object)
+ $jsonString .= '{';
+
+ $obj = $triple->getObject();
+
+ // add special _: sequence for blank nodes only
+ if ($obj instanceof BlankNode) {
+ $jsonString .= '"value":"_:' . $this->_escapeValue($obj->getLabel()) . '",';
+ } else if ($obj instanceof Literal) {
+ $jsonString .= '"value":"' . $this->_escapeValue($obj->getLabel()) . '",';
+ } else {
+ $jsonString .= '"value":"' . $this->_escapeValue($obj->getLabel()) . '",';
+ }
+
+ // add type of object
+ if ($obj instanceof Literal) {
+ $jsonString .= '"type":"literal"';
+ } else if ($obj instanceof BlankNode) {
+ $jsonString .= '"type":"bnode"';
+ } else {
+ $jsonString .= '"type":"uri"';
+ }
+
+ if ($obj instanceof Literal) {
+ if ($obj->getLanguage() != '') {
+ $jsonString .= ',"lang":"' . $this->_escapeValue($obj->getLanguage()) . '"';
+ }
+ if ($obj->getDatatype() != '') {
+ $jsonString .= ',"datatype":"' . $this->_escapeValue($obj->getDatatype()) . '"';
+ }
+
+ }
+
+ // close value object
+ $jsonString .= '}';
+ }
+
+ // close the value array
+ $jsonString .= ']';
+ }
+
+ // close the json object (for the subject) (subject object)
+ $jsonString .= '}';
+ }
+
+ // close root json object (root object)
+ $jsonString .= '}';
+
+ return $jsonString;
+ }
+
+ /*
+ * Escapes the following chars as specified at json.org:
+ *
+ * " -> \"
+ * \ -> \\
+ * / -> \/
+ * \b -> \\b
+ * \f -> \\f
+ * \n -> \\n
+ * \r -> \\r
+ * \t -> \\t
+ * \uXXXX -> \\uXXXX
+ */
+ protected function _escapeValue($value) {
+
+
+ $value = str_replace("\\", '\\\\', $value);
+ #$value = str_replace("/", '\/', $value);
+ $value = str_replace("\n", '\\n', $value);
+ $value = str_replace("\t", '\\t', $value);
+ $value = str_replace("\r", '\\r', $value);
+ $value = str_replace("\b", '\\b', $value);
+ $value = str_replace("\f", '\\f', $value);
+ $value = str_replace('"', '\"', $value);
+
+ return $value;
+ }
+}
+?>
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/N3Parser.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/N3Parser.php.svn-base
new file mode 100755
index 00000000..bbbfe2a5
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/N3Parser.php.svn-base
@@ -0,0 +1,1137 @@
+
+ * Standard things, repeated triples ( ; and , ), blank nodes using [ ], self-reference ('<>')
+ * @prefix mappings
+ * = maps to owl#sameAs
+ * a maps to rdf-syntax-ns#type
+ * Literal datytype- and xmlLanguageTag support
+ *
+ * Un-supported N3 Features include:
+ *
+ * - Reification using { }
+ * - . and ^ operators for tree traversal
+ * - Any log operators, like log:forAll etc.
+ *
+ *
+ * This parser is based on n3.py from Epp released 2nd March, 2002.
+ * by Sean B. Palmer
+ * ( http://infomesh.net/2002/eep/20020302-013802/n3.py )
+ *
+ * This parser is released under the GNU GPL license.
+ * ( http://www.gnu.org/licenses/gpl.txt )
+ *
+ *
+ *
+ * @author Sean B. Palmer
+ * @author Gunnar AA. Grimnes
+ * @author Daniel Westphal
+ * @version $Id$
+ * @license GPL http://www.gnu.org/licenses/gpl.txt
+ * @package syntax
+ * @access public
+ **/
+
+class N3Parser extends Object {
+
+
+ /* ==================== Variables ==================== */
+
+ var $Tokens;
+ var $bNode;
+ var $RDF_NS, $DAML_NS, $OWL_NS;
+ var $debug;
+ var $parseError;
+ var $parsedNamespaces = array();
+
+ /* ==================== Public Methods ==================== */
+
+ /**
+ * Constructor
+ * @access public
+ **/
+ function N3Parser() {
+ //Regular expressions:
+ $Name = '[A-Za-z0-9_@\.]+[^\.,;\[\]\s\) ]*';
+ $URI = '<[^> ]*>';
+ $bNode = '_:'.$Name;
+ $Univar = '\?'.$Name;
+ $QName = '(?:[A-Za-z][A-Za-z0-9_@\.]*)?:'.$Name;
+ $Literal = '(?:'
+ . '"(\\\"|[^"])*"'
+ . '|'
+ . "'(\\\'|[^'])*'"
+ . ')';
+ # '"(?:\\"|[^"])*"'
+ $Number = '[-+]?[0-9]+(\\.[0-9]+)?([eE][-+]?[0-9]+)?';
+ $Boolean = '@(?:true|false)';
+// $Literal = '"[^"\\\\]*(?:\\.\\[^"\\]*)*"'; # '"(?:\\"|[^"])*"'
+ $LangTag = '@[A-Za-z\-]*[^ \^\.\;\,]';
+ $Datatype = '(\^\^)[^ ,\.;)]+';
+ $Datatype_URI = '(\^\^)'.$URI;
+ // $LLiteral = '"""[^"\\\\]*(?:(?:.|"(?!""))[^"\\\\]*)*"""';
+ $LLiteral = '(?:'
+ . '"""[^"\\\\]*(?:(?:\\\\.|"(?!""))[^"\\\\]*)*"""'
+ . '|'
+ . "'''[^'\\\\]*(?:(?:\\\\.|'(?!''))[^\"\\\\]*)*'''"
+ . ')';
+ // '"""[^"\\]*(?:(?:\\.|"(?!""))[^"\\]*)*"""'
+ $Comment = '#.*$';
+ $Prefix = '(?:[A-Za-z][A-Za-z0-9_]*)?:';
+ $PrefixDecl = '@prefix';
+ $WS = '[ \t]';
+ $this->RDF_NS = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'; # for 'a' keyword
+ $this->DAML_NS = 'http://www.daml.org/2001/03/daml+oil#'; # for '=' keyword
+ $this->OWL_NS = 'http://www.w3.org/2002/07/owl#';
+
+ // $t = array( $LLiteral, $URI); //, $Literal, $PrefixDecl, $QName, $bNode, $Prefix,
+ // $Univar, 'a', '{', '}', '\(', '\)', '\[', '\]', ',', ';', '\.', $WS, $Comment);
+ $t = array(
+ $Datatype_URI, $Datatype, $LLiteral, $URI, $Literal,
+ $PrefixDecl, $QName, $Number, $Boolean, $bNode,
+ $Prefix, $Univar, 'a','=',
+ '{', '}', '\(', '\)', '\[', '\]', ',', ';', '\.',
+ $WS, $Comment,$LangTag
+ );
+ $this->Tokens = "/(".join($t,"|").")/m";
+
+ $this->bNode = 0;
+ $this->debug = 0;
+ $this->bNodeMap = array();
+ $this->FixBnodes = FIX_BLANKNODES;
+ $this->parseError =false;
+ }
+
+
+ /**
+ * Sets, if BlankNode labels should be replaced by the generic label from the constants.php file
+ * default is "false" -> the used label in n3 is parsed to the model
+ * @param boolean
+ * @access public
+ **/
+ function setFixBnodes($set) {
+
+ if (($set===true) OR ($set===false)) $this->FixBnodes = $set;
+ }
+
+
+ /**
+ * This parses a N3 string and prints out the triples
+ * @param string $s
+ * @access public
+ **/
+ function parse($s) {
+ // """Get a string, tokenize, create list, convert to Eep store."""
+ $stat=$this->n3tolist($s);
+ foreach ( $stat as $t) {
+
+ if (count($t)>3) {
+ $object=$t[2];
+
+ for ($i = 3; $i < 5; $i++){
+ if ($t[$i][0]=='@')$object.=$t[$i];
+ if (substr($t[$i],0,2)=='^^')$object.=$t[$i];
+ };
+ } else {$object=$t[2];};
+
+ print '('.$t[0].', '.$t[1].', '.$object.")\n";
+
+ }
+ // return [[eep.Article(t[0]), eep.Article(t[1]), eep.Article(t[2])]
+ // for t in n3tolist(s)]
+ }
+
+
+ /**
+ * This parses a N3 string and calls func($subject, $predicate, $object) with each triple
+ * @param string $s
+ * @param string $func
+ * @access public
+ **/
+ function uparse($s,$func) {
+ // """Get a string, tokenize, create list, convert to Eep store."""
+ $stat=$this->n3tolist($s);
+ foreach ( $stat as $t) {
+
+ if (count($t)>3) {
+ $object=$t[2];
+
+ for ($i = 3; $i < 5; $i++){
+ if ($t[$i][0]=='@')$object.=$t[$i];
+ if (substr($t[$i],0,2)=='^^')$object.=$t[$i];
+ };
+ } else {$object=$t[2];};
+ // print "(".$t[0].", ".$t[1].", ".$t[2].")";
+
+ $func($t[0],$t[1],$object);
+ }
+ // return [[eep.Article(t[0]), eep.Article(t[1]), eep.Article(t[2])]
+ // for t in n3tolist(s)]
+ }
+
+
+ /**
+ * This parses a N3 string and returns a memmodel
+ * @param string $s
+ * @access public
+ * @return object Model
+ **/
+
+ function parse2model($s,$model = false) {
+ if($model == false){
+ $m=new MemModel();
+ }else{
+ $m=$model;
+ }
+ // """Get a string, tokenize, create list, convert to Eep store."""
+ $stat=$this->n3tolist($s);
+
+ foreach ( $stat as $t) {
+ $s=$this->toRDFNode($t[0],$t);
+ $p=$this->toRDFNode($t[1],$t);
+ $o=$this->toRDFNode($t[2],$t);
+
+ $new_statement= new Statement($s,$p,$o);
+
+ $m->add($new_statement);
+ // print "(".$t[0].", ".$t[1].", ".$t[2].")";
+ }
+ // return [[eep.Article(t[0]), eep.Article(t[1]), eep.Article(t[2])]
+ // for t in n3tolist(s)]
+ $m->addParsedNamespaces($this->parsedNamespaces);
+ return $m;
+ }
+
+/**
+ * Generate a new MemModel from an URI or file.
+ *
+ * @access public
+ * @param $path
+ * @throws PhpError
+ * @return object MemModel
+ */
+ function & generateModel($path,$dummy=false,$model=false) {
+
+ $handle = fopen($path,'r') or die("N3 Parser: Could not open File: '$path' - Stopped parsing.");
+ $done=false;
+ $input="";
+ while(!$done)
+ {
+ $input .= fread( $handle, 512 );
+ $done = feof($handle);
+
+ };
+
+
+ fclose($handle);
+
+ $m = $this->parse2model($input,$model);
+ return $m;
+ }
+
+
+ /* ==================== Private Methods from here ==================== */
+
+ // General list processing functions
+
+/**
+ * Returns FALSE if argument is a whitespace character
+ * @access private
+ * @param string $s
+ **/
+ function isWS($s) {
+ return !preg_match('/^(#.*|\s*)$/', $s);
+ }
+
+
+
+ /**
+ * Returns true if the string is not a comment
+ * @access private
+ * @param string $s
+ * @returns boolean
+ **/
+ function notComment($s) {
+ if ($s=="") return false;
+ $N3Comment = '^[ \t]*\#';
+
+ if (ereg($N3Comment,$s)) return false;
+ else return true;
+ }
+
+ /**
+ * Removes all whitespace tokens from list
+ * @access private
+ * @param array $list
+ **/
+ function filterWs($list) {
+ // var_dump($list);
+ // """Filter whitespace from a list."""
+
+ return array_filter($list, array($this,"isWS"));
+ }
+
+/**
+* converts a string to its unicode NFC form (e.g. \uHHHH or \UHHHHHHHH).
+*
+* @param String $str
+* @return String
+* @access private
+*
+*/
+function str2unicode_nfc($str=""){
+ $result="";
+ /* try to detect encoding */
+ $tmp=str_replace("?", "", $str);
+ if(strpos(utf8_decode($tmp), "?")===false){
+ $str=utf8_decode($str);
+ }
+ for($i=0,$i_max=strlen($str);$i<$i_max;$i++){
+ $nr=0;/* unicode dec nr */
+ /* char */
+ $char=$str[$i];
+ /* utf8 binary */
+ $utf8_char=utf8_encode($char);
+ $bytes=strlen($utf8_char);
+ if($bytes==1){
+ /* 0####### (0-127) */
+ $nr=ord($utf8_char);
+ }
+ elseif($bytes==2){
+ /* 110##### 10###### = 192+x 128+x */
+ $nr=((ord($utf8_char[0])-192)*64) + (ord($utf8_char[1])-128);
+ }
+ elseif($bytes==3){
+ /* 1110#### 10###### 10###### = 224+x 128+x 128+x */
+ $nr=((ord($utf8_char[0])-224)*4096) + ((ord($utf8_char[1])-128)*64) + (ord($utf8_char[2])-128);
+ }
+ elseif($bytes==4){
+ /* 1111#### 10###### 10###### 10###### = 240+x 128+x 128+x 128+x */
+ $nr=((ord($utf8_char[0])-240)*262144) + ((ord($utf8_char[1])-128)*4096) + ((ord($utf8_char[2])-128)*64) + (ord($utf8_char[3])-128);
+ }
+ /* result (see http://www.w3.org/TR/rdf-testcases/#ntrip_strings) */
+ if($nr<9){/* #x0-#x8 (0-8) */
+ $result.="\\u".sprintf("%04X",$nr);
+ }
+ elseif($nr==9){/* #x9 (9) */
+ $result.='\t';
+ }
+ elseif($nr==10){/* #xA (10) */
+ $result.='\n';
+ }
+ elseif($nr<13){/* #xB-#xC (11-12) */
+ $result.="\\u".sprintf("%04X",$nr);
+ }
+ elseif($nr==13){/* #xD (13) */
+ $result.='\t';
+ }
+ elseif($nr<32){/* #xE-#x1F (14-31) */
+ $result.="\\u".sprintf("%04X",$nr);
+ }
+ elseif($nr<34){/* #x20-#x21 (32-33) */
+ $result.=$char;
+ }
+ elseif($nr==34){/* #x22 (34) */
+ $result.='\"';
+ }
+ elseif($nr<92){/* #x23-#x5B (35-91) */
+ $result.=$char;
+ }
+ elseif($nr==92){/* #x5C (92) */
+ $result.='\\';
+ }
+ elseif($nr<127){/* #x5D-#x7E (93-126) */
+ $result.=$char;
+ }
+ elseif($nr<65536){/* #x7F-#xFFFF (128-65535) */
+ $result.="\\u".sprintf("%04X",$nr);
+ }
+ elseif($nr<1114112){/* #x10000-#x10FFFF (65536-1114111) */
+ $result.="\\U".sprintf("%08X",$nr);
+ }
+ else{
+ /* other chars are not defined => ignore */
+ }
+ }
+ return $result;
+}
+
+
+
+ /**
+ * Gets a slice of an array.
+ * Returns the wanted slice, as well as the remainder of the array.
+ * e.g. getSpan(['p', 'q', 'r'], 1, 2) gives (['q'], ['p', 'r'])
+ * @return array
+ * @access private
+ * @param array $list
+ * @param integer $start
+ * @param integer $end
+ **/
+ function getSpan($list, $start, $end) {
+
+ $pre=array_slice($list, 0, $start);
+ $post=array_slice($list, $end);
+
+ return array(array_slice($list, $start,$end-$start),$this->array_concat($pre,$post));
+ }
+
+
+ /**
+ * Concatenates two arrays
+ * @param array $a
+ * @param array $b
+ * @returns array
+ * @access private
+ **/
+ function array_concat($a, $b) {
+ array_splice($a,count($a),0,$b);
+ return $a;
+ }
+
+ /**
+ * Returns an array with all indexes where item appears in list
+ * @param array $list
+ * @param string $item
+ * @returns array
+ * @access private
+ **/
+ function posns($list, $item) {
+ $res=array();
+ $i=0;
+ foreach ( $list as $k=>$v) {
+ if ($v === $item ) $res[]=$i;
+ $i++;
+ }
+ $res[]=$i;
+ return $res;
+ }
+
+
+ /* More N3 specific functions */
+
+ /**
+ * Returns a list of tokens
+ * @param string $s
+ * @returns array
+ * @access private
+ **/
+ function toke($s) {
+
+ // print "$s\n";
+ // """Notation3 tokenizer. Takes in a string, returns a raw token list."""
+ if (strlen($s) == 0) die('Document has no content!');
+
+ $s=str_replace("\r\n","\n",$s);
+ $s=str_replace("\r","\n",$s);
+
+
+ //$lines=explode("\n",$s);
+
+ //$reallines=array_filter($lines, array($this, "notComment"));
+ // print "LINES: ".join($reallines, " ")." :LINES\n";
+ //array_walk($reallines, array($this, "trimLine"));
+ //$res=array();
+
+ // foreach ($reallines as $l) {
+ //preg_match_all($this->Tokens, $l, $newres);
+ //$res=$this->array_concat($res,$newres[0]);
+ //}
+
+ $res=array();
+ preg_match_all($this->Tokens, $s, $newres);
+ $res=$this->array_concat($res, array_map('trim', $newres[0]));
+//var_dump($newres[0]);
+ return $res;
+ }
+
+ /**
+ * Returns a list with the elements between start and end as one quoted string
+ * e.g. listify(["a","b","c","d"],1,2) => ["a","b c", "d"]
+ * @param array $list
+ * @param integer $start
+ * @param integer $end
+ * @returns array
+ * @access private
+ **/
+ function listify($list, $start, $end) {
+
+ //Re-form a list, merge elements start->end into one quoted element
+ //Start and end are offsets...
+
+ $l=$end-$start;
+
+ $s=array_slice($list, 0, $start);
+ $m=array_slice($list, $start,$l);
+ $e=array_slice($list, $end);
+
+ // array_push($s,"\"".join($m," ")."\"");
+ array_push($s,$m);
+
+ return $this->array_concat($s,$e);
+ }
+
+ /**
+ * Returns an array with prefixes=>namespace mappings
+ * @param array $list
+ * @access private
+ * @returns array
+ **/
+ function getPrefixes($list) {
+
+ $prefixes=array();
+ $ns=1;
+ $name=2;
+ foreach ($list as $l) {
+ if ($l=='@prefix') {
+ // while '@prefix' in list {
+
+ $pos=current($list);
+ //pos = list.index('@prefix')
+ $r = $this->getSpan($list, $pos, ($pos+4)); # processes the prefix tokens
+ $binding=$r[0];
+ $list=$r[1];
+ $prefixes[$binding[$ns]] = substr($binding[$name],1,-1);
+ $this->parsedNamespaces[substr($binding[$name],1,-1)] = substr($binding[$ns],0,-1);
+ }
+ }
+
+ if (count($prefixes)<1) $list= array_slice($list,0);
+
+ return array($prefixes, $list);
+ }
+
+ /**
+ * Callback function for replacing "a" elements with the right RDF uri.
+ * @param string $l
+ * @access private
+ **/
+ function replace_a_type(&$l,$p) {
+ if ($l=='a') $l='<'.$this->RDF_NS.'type>';
+ }
+
+ /**
+ * Callback function for replacing "=" elements with the right DAML+OIL uri.
+ * @param string $l
+ * @access private
+ **/
+ function replace_equal(&$l,$p) {
+ if ($l=='=') $l='<'.$this->OWL_NS.'sameAs>';
+ }
+
+ /**
+ * Callback function for replacing "this" elements with the right RDF uri.
+ * @param string $l
+ * @access private
+ **/
+ function replace_this($l,$p) {
+ if ($l=='this') $l='';
+ }
+
+ /**
+ * Applies stuff :)
+ * Expands namespace prefixes etc.
+ * @param array $prefixes
+ * @param array $list
+ * @returns $list
+ * @access private
+ **/
+ function applyStuff($prefixes, $list)
+ {
+ array_walk($list, array($this, 'replace_a_type'));
+ array_walk($list, array($this, 'replace_equal'));
+ array_walk($list, array($this, 'replace_this'));
+
+ for ($i = 0; $i < count($list); $i++) {
+
+ if ($list[$i]=='<>') {
+ if (!isset($path)) {
+ if (!isset($_SERVER['SERVER_ADDR'])) {
+ $_SERVER['SERVER_ADDR'] = 'localhost';
+ }
+ if (!isset($_SERVER['REQUEST_URI'])) {
+ $_SERVER['REQUEST_URI'] = '/rdfapi-php';
+ }
+ $list[$i] = '';
+ } else {
+ $list[$i] = '<'.$path.'>';
+ };
+ };
+
+
+ if (preg_match('/^[-+]?[0-9]+$/', $list[$i])) {
+ //integer
+ $list[$i] = intval($list[$i]);
+ } else if (is_numeric($list[$i])) {
+ //float or decimal
+ // After conversion we cannot distinguish between both
+ $list[$i] = floatval($list[$i]);
+ } else if ((!strstr('<_"\'?.;,{}[]()@', $list[$i]{0}))
+ && (substr($list[$i],0,3) != '^^<')
+ ) {
+ //prefix or unknown
+ $_r = explode(':', $list[$i]);
+ $ns = $_r[0] . ':';
+ $name = $_r[1];
+
+ if (isset($prefixes[$ns])) {
+ $list[$i] = '<'.$prefixes[$ns].$name.'>';
+ } else if (isset($prefixes[substr($ns, 2)])) {
+ $list[$i] = '^^' . $prefixes[substr($ns, 2)] . $name . '';
+ } else {
+ //die('Prefix not declared:'.$ns);
+ $this->parseError = true;
+ trigger_error('Prefix not declared: '.$ns, E_USER_ERROR);
+ break;
+ }
+
+ } else {
+ if ($list[$i]{0} == '"') {
+ $bLiteral = true;
+ $chBase = '"';
+ } else if ($list[$i]{0} == '\'') {
+ $bLiteral = true;
+ $chBase = '\'';
+ } else {
+ $bLiteral = false;
+ }
+ if ($bLiteral) {
+ $tripleBase = $chBase . $chBase . $chBase;
+ // Congratulations - it's a literal!
+ if (substr($list[$i], 0, 3) == $tripleBase) {
+ if (substr($list[$i],-3,3) == $tripleBase) {
+ // A big literal...
+ $lit = substr($list[$i],3,-3);
+ // print "++$lit++";
+ $lit=str_replace('\n', '\\n',$lit);
+
+ //$lit=ereg_replace("[^\\]" . $chBase, "\\" . $chBase, $lit);
+ $lit = stripslashes($lit);
+
+ $list[$i] = $chBase . $lit . $chBase;
+ } else {
+ die ('Incorrect string formatting: '.substr($list[$i],-3,3));
+ }
+ } else {
+ if (strstr($list[$i],"\n")) {
+ die('Newline in literal: ' . $list[$i]);
+ }
+ $list[$i] = stripslashes($list[$i]);
+ }
+ }
+ }
+
+ if (substr($list[$i],0,2)=='^^') {
+ if ($list[$i][2]!='<') {
+ $list[$i] = '^^<' . substr($list[$i], 2) . '>';
+ }
+ };
+
+ }//foreach list item
+
+ return $list;
+ }//function applyStuff($prefixes, $list)
+
+
+
+ /**
+ * Returns an array of triples extracted from the list of n3 tokens
+ * @param array $list
+ * @returns array
+ * @access private
+ **/
+ function getStatements($list) {
+
+
+ $statements = array();
+
+ while (in_array('.', $list)) {
+ // for($i=0;$igetSpan($list, 0, $pos+1);
+
+ $statement=$r[0];
+ $list = $r[1];
+
+ array_pop($statement);
+ $statements[]=$statement;
+ }
+
+ return $statements;
+ }
+
+ /**
+ * Gets a list of triples with same subject
+ * e.g. :Gunnar :firstname "Gunnar" ; :lastname "Grimnes.
+ * @param array $list
+ * @returns array
+ * @acces private
+ **/
+ function getPovs($list) {
+ $povs = array();
+ while (in_array(';', $list)) {
+ $r=$this->posns($list,';');
+ $pos=array_slice($r,0,2);
+ $r = $this->getSpan($list, $pos[0], $pos[1]);
+ $pov=$r[0];
+ $list=$r[1];
+
+ // skip lone semicolons, e.g. " ; ."
+ if (count($pov) == 1) continue;
+
+ $povs[]=array_slice($pov,1);
+ }
+
+ return array($list, $povs);
+ }
+
+ /**
+ * Gets a list of triples with same predicate
+ * e.g. :Gunnar :likes "Cheese", "Wine".
+ * @access private
+ * @param array $list
+ * @returns array
+ **/
+ function getObjs($list) {
+
+
+ $objs = array();
+ while (in_array(",",$list)) {
+ $pos=array_search(",",$list);
+ // for($i=0;$igetSpan($list, $pos, ($pos+$get_array_fields));
+
+ $obj=$r[0];
+ if (!isset($obj[2])) $obj[2]=' ';
+ if (!isset($obj[3])) $obj[3]=' ';
+
+ $list=$r[1];
+
+
+ $objs[]=$obj;
+
+
+ }
+
+ return array($list, $objs);
+ }
+
+ /**
+ * Does the real work, returns a list of subject, predicate, object triples.
+ * @param array $list
+ * @returns array
+ * @access private
+ **/
+ function statementize($list) {
+
+ if (count($list) == 1 && preg_match("/_".BNODE_PREFIX."[0-9]+_/",$list[0])) {
+ if ($this->debug) print "Ignored bNode exists statement. $list\n";
+ return array();
+ }
+
+
+
+ if (count($list) == 3) return array($list);
+ if (count($list) < 3) {
+ throw new Exception(
+ 'N3 statement too short,'
+ . ' only ' . count($list) . ' elements instead of 3:' . "\n"
+ . implode("\n", $list)
+ );
+ }
+
+ //Get all ;
+ $r=$this->getPovs($list);
+ $spo=$r[0];
+ $po=$r[1];
+ $all=array();
+
+
+
+ // (spo, po), all = getPovs(list), []
+ $subject = $spo[0];
+ foreach ($po as $pop) {
+ // for pop in po {
+ $r=$this->getObjs($pop);
+
+ $myPo=$r[0];
+ $obj=$r[1];
+ //myPo, obj = getObjs(pop)
+
+ if (!isset($myPo[2])) $myPo[2]=' ';
+ if (!isset($myPo[3])) $myPo[3]=' ';
+
+
+ $predicate = $myPo[0];
+ $all[]=array($subject,$predicate,$myPo[1],$myPo[2],$myPo[3]);
+ // all.append([subject, predicate, myPo[1]])
+
+
+
+ foreach ($obj as $o) $all[]=array($subject,$predicate, $o[1],$o[2],$o[3]);
+ // for x in obj: all.append([subject, predicate, x])
+
+ }
+
+
+
+ $r = $this->getObjs($spo);
+ $spo=$r[0];
+
+ $objs=$r[1];
+
+ //spo, objs = getObjs(spo)
+ $subject=$spo[0];
+ $predicate=$spo[1];
+
+
+ if(!isset($spo[3])) $spo[3]=' ';
+ if(!isset($spo[4])) $spo[4]=' ';
+
+ $all[]=array($subject, $predicate, $spo[2],$spo[3],$spo[4]);
+
+ foreach ($objs as $obj) $all[]=array($subject, $predicate, $obj[1],$obj[2],$obj[3]);
+
+ return $all;
+ }
+
+ /**
+ * Makes lists of elements in list into a seperate array element.
+ * e.g. doLists(["a","b","[","c","]","d"], "[","]")=> ["a","b", ["c"], "d"]
+ * @param array $list
+ * @param string $schar
+ * @param string $echar
+ * @returns array
+ * @access private
+ **/
+ function doLists($list, $schar, $echar) {
+
+ while (in_array($schar, $list)) {
+ // while schar in list {
+ $ndict = array();
+ $nestingLevel = 0;
+ $biggest = 0;
+ for ($i = 0; $i < count($list); $i++) {
+ if ($list[$i] == $schar) {
+ $nestingLevel += 1;
+ if (!in_array($nestingLevel, array_keys($ndict))) {
+ $ndict[$nestingLevel] = array(array($i));
+ } else {
+ $ndict[$nestingLevel][]=array($i);
+ }
+ }
+ if ($list[$i] == $echar) {
+ if (!in_array($nestingLevel, array_keys($ndict))) {
+ $ndict[$nestingLevel]=array(array($i));
+ } else {
+ $ndict[$nestingLevel][count($ndict[$nestingLevel])-1][]=$i;
+ $nestingLevel-= 1;
+# elif type(list[i]) == type([]) {
+# list[i] = doLists(list[i], schar, echar)
+ }
+ }
+ }
+ foreach (array_keys($ndict) as $key) {
+ if ($key > $biggest) $biggest = $key;
+ }
+
+ $tol = $ndict[$biggest][0];
+ $list = $this->listify($list, $tol[0], ($tol[1]+1));
+ }
+ return $list;
+ }
+
+ /**
+ * Apply doLists for all different types of list.
+ * @param array
+ * @returns array
+ * @access private
+ **/
+ function listStuff($list) {
+# y, z = zip(['[', ']'], ['{', '}'], ['(', ')'])
+# return map(doLists, [list, list, list], y, z).pop()
+ $list = $this->doLists($list, '[', ']');
+ $list = $this->doLists($list, '{', '}');
+ return $this->doLists($list, '(', ')');
+ }
+
+ /**
+ * Generates a new node id.
+ * @access private
+ * @returns string
+ **/
+ function bnodeID() {
+
+ $this->bNode++;
+ return "_".BNODE_PREFIX.$this->bNode."_";
+ }
+
+ /**
+ * This makes bNodes out of variables like _:a etc.
+ * @access private
+ * @param array $list
+ * @returns array
+ **/
+ function fixAnon($list) {
+// $map=array();
+ for($i=0;$ibNodeMap[$l])) {
+ $a=$this->bnodeID();
+ $this->bNodeMap[$l]=$a;
+ } else $a=$this->bNodeMap[$l];
+ $list[$i]=$a;
+ }
+ }
+ return $list;
+ }
+
+ /**
+ * This makes [ ] lists into bnodes.
+ * @access private
+ * @param array $list
+ * @return array
+ **/
+ function expandLists($list) {
+
+ for($i=0;$ibnodeID();
+ $prop=$list[$i];
+ $list[$i]=$bnode;
+ $list[]=$bnode;
+ $list=$this->array_concat($list, array_slice($prop,1,-1));
+ $list[]='.';
+ }elseif($list[$i][0]=='(') {
+
+ $rdfNil = '<'. RDF_NAMESPACE_URI . RDF_NIL .'>';
+ $rdfFirst = '<'. RDF_NAMESPACE_URI . RDF_FIRST .'>';
+ $rdfRest = '<'. RDF_NAMESPACE_URI . RDF_REST .'>';
+
+ // local copy of list without "(" and ")"
+ $t_list = array_slice($list[$i], 1, -1);
+
+ //prepare bnodes
+ $fromBnode = $this->bnodeID();
+ $toBnode = $this->bnodeID();
+
+ //link first bnode into graph
+ $list[$i] = $fromBnode;
+
+ $count = count($t_list);
+
+ //loop through list, convert to RDF linked list
+ for ($idx = 0; $idx < $count; $idx++){
+
+ // set rdf:first
+ $list[] = $fromBnode;
+ $list[] = $rdfFirst;
+ $list[] = $t_list[$idx];
+ $list[] = '.';
+
+ // set rdf:rest (nil or next bnode)
+ if ($idx == $count - 1) {
+ $list[] = $fromBnode;
+ $list[] = $rdfRest;
+ $list[] = $rdfNil;
+ $list[] = '.';
+ }
+ else {
+ $list[] = $fromBnode;
+ $list[] = $rdfRest;
+ $list[] = $toBnode;
+ $list[] = '.';
+
+ $fromBnode = $toBnode;
+ $toBnode = $this->bnodeID();
+ }
+ }
+ }
+ else {
+ die('Only [ ] and () lists are supported!');
+ }
+ }
+
+
+ }
+ return $list;
+ }
+
+ /**
+ * Main work-horse function. This converts a N3 string to a list of statements
+ * @param string $s
+ * @returns array
+ * @access private
+ **/
+ function n3tolist($s) {
+
+ // """Convert an N3 string into a list of triples as strings."""
+ $result = array();
+
+ $t = $this->filterWs($this->toke($s)); # tokenize the stream, and filter whitespace tokens
+
+ if ($this->debug) {
+ print "Filter WS:\n";
+ var_dump($t);
+ }
+ $r=$this->getPrefixes($t); # get the prefix directives, and add to a dict
+ $prefixes=$r[0];
+ $t=$r[1];
+ if ($this->debug) {
+ print "Prefixes:\n";
+ var_dump($prefixes);
+ print "***\n";
+ var_dump($t);
+ }
+ $t=$this->applyStuff($prefixes, $t);#apply prefixes, keywords, and string formatting
+ if ($this->debug) {
+ print "Stuff applied:\n";
+ var_dump($t);
+ }
+
+ $t=$this->fixAnon($t); # fix _:a anons
+ if ($this->debug) {
+ print "Fix anon:\n";
+ var_dump($t);
+ }
+
+ $t = $this->listStuff($t); # apply list stuff: todo
+ if ($this->debug) {
+ print "Lists done:\n";
+ var_dump($t);
+ }
+ $t=$this->expandLists($t);
+ if ($this->debug) {
+ print "Lists applied:\n";
+ var_dump($t);
+ }
+ $t = $this->getStatements($t); # get all of the "statements" from the stream
+
+ foreach ($t as $stat) {
+ $stats = $this->statementize($stat);
+
+ foreach ($stats as $y) {
+ $result[]=$y;
+ }
+ }
+
+ // for x in [statementize(stat) for stat in t] {
+ // for y in x: result.append(y)
+ return $result;
+ }
+
+
+
+ /**
+ * Constructs a RAP RDFNode from URI/Literal/Bnode
+ * @access private
+ * @param string $s
+ * @returns object RDFNode
+ **/
+ function toRDFNode($s, $state)
+ {
+ $ins = substr($s, 1, -1);
+ if ($s{0} == '"' || $s{0} == '\'') {
+ $lang = NULL;
+
+ if (count($state)>3) {
+ for ($i = 3; $i < count($state); $i++) {
+ if ($state[$i][0]=='@') {
+ $lang = substr($state[3], 1);
+ }
+ if (substr($state[$i],0,2) == '^^') {
+ $dtype = substr($state[$i],2);
+ if ($dtype[0]=='<') {
+ $dtype = substr($dtype,1,-1);
+ }
+ }
+ }
+ }
+
+
+ if (UNIC_RDF) {
+ $ins = $this->str2unicode_nfc($ins);
+ }
+ $new_Literal = new Literal($ins, $lang);
+ if (isset($dtype)) {
+ $new_Literal->setDatatype($dtype);
+ }
+ return $new_Literal;
+ } else if (is_int($s)) {
+ $value = new Literal($s);
+ $value->setDatatype(XML_SCHEMA . 'integer');
+ return $value;
+ } else if (is_float($s)) {
+ $value = new Literal($s);
+ $value->setDatatype(XML_SCHEMA . 'double');
+ return $value;
+ } else if ($s == '@true') {
+ $value = new Literal(true);
+ $value->setDatatype(XML_SCHEMA . 'boolean');
+ return $value;
+ } else if ($s == '@false') {
+ $value = new Literal(false);
+ $value->setDatatype(XML_SCHEMA . 'boolean');
+ return $value;
+ }
+
+ if (strstr($s, '_' . BNODE_PREFIX)) {
+ if (($this->FixBnodes) || (!array_search($s,$this->bNodeMap))) {
+ return new BlankNode($ins);
+ } else {
+ return new BlankNode(
+ trim(
+ substr(
+ array_search($s, $this->bNodeMap),
+ 2
+ )
+ )
+ );
+ };
+ }
+
+ return new Resource($ins);
+ }//function toRDFNode($s, $state)
+
+
+
+
+} //end: N3Parser
+
+?>
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/N3Serializer.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/N3Serializer.php.svn-base
new file mode 100755
index 00000000..91540d2e
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/N3Serializer.php.svn-base
@@ -0,0 +1,526 @@
+
+ * Using [ ] for blank nodes, or _: if necessary
+ * Literal datatype- and xmlLanguageTag support
+ *
+ *
+ * Un-supported N3 Features include:
+ *
+ *
+ *
+ * @author Gunnar AA. Grimnes
+ * @author Daniel Westphal
+ * @author Christian Weiske
+ * @version $Id$
+ * @package syntax
+ * @access public
+ **/
+
+define('MAGIC_STRING', '~~~');
+
+class N3Serializer extends Object
+{
+
+ var $debug = false;
+
+ var $prefixes = array();
+ var $noPrefixes = array();
+
+ var $done; // keeps track of already serialized resources
+ var $resourcetext;
+ var $resourcetext_taken;
+ var $model;
+ var $res;
+ var $anon;
+
+ var $styleCompress = false;
+ var $stylePretty = false;
+ var $styleNest = false;
+
+ /**
+ * Constructor
+ *
+ * @access public
+ */
+ function N3Serializer()
+ {
+ $this->debug = false;
+ }
+
+
+ /**
+ * Adds a new namespace prefix to use.
+ * Unknown namespaces will become ns0, ns1 etc.
+ * @access public
+ * @param string $s
+ * @returns void
+ **/
+ function addNSPrefix($ns, $prefix)
+ {
+ $this->prefixes[$ns] = $prefix;
+ }
+
+
+
+ /**
+ * Clears all previously set namespace prefixes
+ */
+ function clearNSPrefixes()
+ {
+ $this->prefixes = array();
+ }
+
+
+
+ /**
+ * Add a namespace that shall not get shortened by using a prefix.
+ *
+ * @param string $ns Namespace URI like "http://example.com/"
+ */
+ function addNoNSPrefix($ns)
+ {
+ $this->noPrefixes[$ns] = true;
+ }
+
+
+
+ /**
+ * Clears all previously set noNamespace prefixes
+ */
+ function clearNoNSPrefixes()
+ {
+ $this->noPrefixes = array();
+ }
+
+
+
+ /**
+ * Serializes a model to N3 syntax.
+ *
+ * @param object Model $model
+ * @return string
+ * @access public
+ */
+ function &serialize(&$m)
+ {
+ if (is_a($m, 'DbModel')) {
+ $m=$m->getMemModel();
+ }
+
+ $this->reset();
+ $this->model = $m;
+ $this->res = "";
+
+ // copy default namespaces
+ global $default_prefixes;
+ foreach($default_prefixes as $prefix => $namespace) {
+ $this->addNSPrefix($namespace,$prefix);
+ }
+
+ $nps= $this->model->getParsedNamespaces();
+ if ($nps!=false) {
+ foreach ($nps as $uri => $prefix){
+ $this->addNSPrefix($uri,$prefix);
+ }
+ }
+
+ $namespaces = array();
+ $count = array();
+ $resources = array();
+ foreach ($this->model->triples as $t) {
+ $s = $t->getSubject();
+ if (is_a($s, 'Resource')) {
+ $namespaces[$s->getNamespace()] = 1;
+ }
+ $p = $t->getPredicate();
+ if (is_a($p, 'Resource')) {
+ $namespaces[$p->getNamespace()] = 1;
+ }
+ $o = $t->getObject();
+ if (is_a($o, 'Resource')) {
+ $namespaces[$o->getNamespace()] = 1;
+ }
+ $uri = $s->getURI();
+
+ if (isset($count[$uri])) {
+ $count[$uri]++;
+ } else {
+ $count[$uri] = 0;
+ $resources[$uri] = $s;
+ }
+
+ if ($this->styleNest && is_a($s, 'BlankNode')) {
+ //make sure blank nodes are sorted *after* normal nodes
+ //so that they can be included
+ $count[$uri] -= 0.00001;
+ }
+ }
+
+ if (!HIDE_ADVERTISE) {
+ $this->res .= '# Generated by N3Serializer.php from RDF RAP.'.LINEFEED
+ .'# http://www.wiwiss.fu-berlin.de/suhl/bizer/rdfapi/index.html'
+ .LINEFEED.LINEFEED;
+ }
+
+ $this->doNamespaces($namespaces);
+
+ $this->res .= LINEFEED.LINEFEED;
+
+ arsort($count);
+
+ foreach ( $count as $k => $v) {
+ $this->doResource($resources[$k]);
+ // $this->res.=" .\n";
+ }
+
+ //make all replacements
+ do {
+ $bReplacements = false;
+ foreach ($this->resourcetext as $r => $t) {
+ if (preg_match_all('/'.MAGIC_STRING.'([^ ]+)'.MAGIC_STRING.'/', $t, $ms, PREG_SET_ORDER)) {
+ foreach ($ms as $mseach) {
+ $rp = $this->resourcetext[$mseach[1]];
+ $this->resourcetext[$r] = preg_replace('/'.MAGIC_STRING.$mseach[1].MAGIC_STRING.'/', $rp, $t);
+ $bReplacements = true;
+ }
+ }
+
+ }
+ } while ($bReplacements);
+
+ //after all replacements took place, put the lines out
+ $c = 0;
+ foreach ($this->resourcetext as $r => $t) {
+ if ($this->debug) {
+ $this->res .= $c . ': ';
+ }
+ if (!(isset($this->resourcetext_taken[$r]) && $this->resourcetext_taken[$r]>0)) {
+ $this->res .= $t . ' .' . LINEFEED;
+ if ($this->stylePretty) {
+ $this->res .= LINEFEED;
+ }
+ } else if ($this->debug ) {
+ $this->res.=' Skipping : '.$t.LINEFEED;
+ }
+ $c++;
+ }
+
+ // $max=-1111;
+ // $maxkey="";
+ // foreach ($count as $k=>$c) {
+ // if ( $c>$max) { $maxkey=$k; $max=$c; }
+ // }
+
+ // if ($this->debug) {
+ // print "$maxkey is subject of most triples! ($max) \n";
+ // }
+
+ return $this->res;
+ }//function &serialize(&$m)
+
+
+
+ /**
+ * Serializes a model and saves it into a file.
+ * Returns FALSE if the model couldn't be saved to the file.
+ *
+ * @param object MemModel $model
+ * @param string $filename
+ * @return boolean
+ * @access public
+ */
+ function saveAs(&$model, $filename)
+ {
+ // serialize model
+ $n3 = $this->serialize($model);
+
+ // write serialized model to file
+ $file_handle = @fopen($filename, 'w');
+ if ($file_handle) {
+ fwrite($file_handle, $n3);
+ fclose($file_handle);
+ return true;
+ } else {
+ return false;
+ };
+ }
+
+
+
+ /**
+ * Set to true, if the N3 serializer should try to compress the blank node
+ * syntax using [] whereever possible.
+ */
+ function setCompress($compress)
+ {
+ $this->styleCompress = $compress;
+ }
+
+
+
+ /**
+ * Enables pretty printing in semicolon delimited sentences.
+ */
+ function setPrettyPrint($prettyPrint)
+ {
+ $this->stylePretty = $prettyPrint;
+ }
+
+
+
+ /**
+ * Enables nesting of blank nodes with [] if
+ * compression is activated via @see setCompress
+ */
+ function setNest($nest)
+ {
+ $this->styleNest = $nest;
+ }
+
+ /* ==================== Private Methods from here ==================== */
+
+
+ /**
+ * Readies this object for serializing another model
+ * @access private
+ * @param void
+ * @returns void
+ **/
+ function reset()
+ {
+ $this->anon = 0;
+ $this->done = array();
+ $this->resourcetext_taken = array();
+ $this->resourcetext = array();
+ $this->res = '';
+ $this->model = null;
+ }
+
+
+
+ /**
+ * Makes ns0, ns1 etc. prefixes for unknown prefixes.
+ * Outputs @prefix lines.
+ * @access private
+ * @param array $n
+ * @returns void
+ **/
+ function doNamespaces(&$n)
+ {
+ $c = 0;
+ foreach ($n as $ns => $nonsense) {
+ if (!$ns || isset($this->noPrefixes[$ns])) {
+ continue;
+ }
+ if (isset($this->prefixes[$ns])) {
+ $p = $this->prefixes[$ns];
+ } else {
+ $p = 'ns' . $c;
+ $this->prefixes[$ns] = $p;
+ $c++;
+ }
+ $this->res .= "@prefix $p: <".$ns.'> .'.LINEFEED;
+ }
+ }
+
+
+
+ /**
+ * Fill in $resourcetext for a single resource.
+ * Will recurse into Objects of triples, but should never look ? (really?)
+ * @param object Resource $r
+ * @returns boolean
+ * @access private
+ **/
+ function doResource(&$r, $bEmbedded = false, $strIndent = ' ')
+ {
+ //var_dump($r->getURI());
+
+ $ts = $this->model->find($r, null, null);
+ if (count($ts->triples) == 0) {
+ if ($bEmbedded) {
+ $this->resourcetext[$r->getURI()] = '_:' . $r->getLabel();
+ }
+ return;
+ }
+
+ $out = '';
+
+ if (isset($this->done[$r->getURI()]) && $this->done[$r->getURI()]) {
+ if (!$this->styleNest && is_a($r, 'BlankNode')) {
+ if ($this->resourcetext_taken[$r->getURI()] == 1) {
+ //Oh bother, we must use the _:blah construct.
+ $a = $this->resourcetext[$r->getURI()];
+ $this->resourcetext[$r->getURI()]='_:anon'.$this->anon;
+ $this->resourcetext['_:anon'.$this->anon]=$this->fixAnon($a, '_:anon'.$this->anon);
+ $this->resourcetext_taken[$r->getURI()]=2;
+ $this->anon++;
+ }
+ }
+ return false;
+ }
+
+ $this->done[$r->getURI()] = true;
+ $compress = false;
+
+ if (is_a($r, 'Resource')) {
+ if (is_a($r, 'BlankNode')) {
+ //test if this blanknode is referenced somewhere
+ $rbn = $this->model->find(null, null, $r);
+ $compress = (N3SER_BNODE_SHORT || $this->styleCompress)
+ && (
+ count($rbn->triples) == 0
+ || (count($rbn->triples) == 1 && $bEmbedded)
+ );
+ if ($compress) {
+ $out.='[';
+ } else {
+ $out.='_:'.$r->getLabel();
+ }
+ } else {
+ $this->doURI($r, $out);
+ }
+ }
+
+ usort($ts->triples, 'statementsorter');
+ $lastp = '';
+ $out .= ' ';
+
+ foreach ($ts->triples as $t) {
+ $p = $t->getPredicate();
+
+ if ($p === $lastp) {
+ $out .= ' , ';
+ } else {
+ if ($lastp!='') {
+ if ($this->stylePretty) {
+ $out .= ";\n" . $strIndent;
+ } else {
+ $out .= ' ; ';
+ }
+ }
+ $this->doURI($p, $out);
+ $lastp = $p;
+ }
+
+ $out .= ' ';
+
+ $o = $t->getObject();
+
+ if (is_a($o, 'Literal')) {
+ $l = $o->getLabel();
+ if (strpos($l, LINEFEED) === false) {
+ $long = false;
+ } else {
+ $long = true;
+ }
+
+ //try to be intelligent
+ $quoteSingle = strpos($l, '\'') !== false;
+ $quoteDouble = strpos($l, '"') !== false;
+ if ($quoteSingle && !$quoteDouble) {
+ $quoteChar = $long ? '"""' : '"';
+ } else if ($quoteDouble && !$quoteSingle) {
+ $quoteChar = $long ? '\'\'\'' : '\'';
+ } else if ($quoteDouble && $quoteSingle) {
+ //both quotation chars inside
+ $quoteChar = $long ? '"""' : '"';
+ $l = addslashes($l);
+ } else {
+ //no quotation chars
+ $quoteChar = $long ? '"""' : '"';
+ }
+ $out .= $quoteChar . $l . $quoteChar;
+
+ if ( $o->getLanguage()!='' ) {
+ $out.='@'.$o->getLanguage();
+ }
+ if ( $o->getDatatype()!='' ) {
+ $out.='^^<'.$o->getDatatype().'>';
+ }
+ }
+
+ if (is_a($o, 'Resource')) {
+ if ($this->debug) {
+ print 'Doing object: '.$o->getURI().LINEFEED;
+ }
+ if (is_a($o, 'BlankNode')) {
+ if ($this->styleNest && $this->styleCompress
+ && !isset($this->done[$o->getURI()])
+ ) {
+ $this->doResource($o, true, $strIndent . ' ');
+ $out .= MAGIC_STRING . $o->getURI() . MAGIC_STRING;
+ //$out .= $this->resourcetext[$o->getURI()];
+ $this->resourcetext_taken[$o->getURI()] = 1;
+ } else {
+ $out .= '_:'.$o->getLabel();
+ }
+ } else {
+ $this->doURI($o, $out);
+ }
+ }
+ }
+
+ if ($compress) {
+ $out .= ' ]';
+ };
+
+ $this->resourcetext[$r->getURI()]=$out;
+
+ return true;
+ }//function doResource(&$r)
+
+
+
+ /**
+ * Format a single URI
+ * @param string $s
+ * @return void
+ * @access private
+ **/
+ function doURI(&$r, &$out)
+ {
+ if ($r->getURI() == 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type') {
+ $out .= 'a';
+ return;
+ }
+ $ns = $r->getNamespace();
+ if ($ns != '' && !isset($this->noPrefixes[$ns])) {
+ $out .= $this->prefixes[$ns].':'.$r->getLocalName();
+ } else {
+ //Will this ever happen? It does, now.
+ $out .= '<' . $r->getURI() . '>';
+ }
+ }
+
+
+
+ /**
+ * Fix the resourcetext for a blanknode where the _: construct was used
+ * @param string $s
+ * @param string $a
+ * @access private
+ * @return void
+ **/
+ function fixAnon($t,$a)
+ {
+ $t = preg_replace("/( \] $|^\[ )/", '', $t);
+ return $a . $t;
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/NTripleSerializer.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/NTripleSerializer.php.svn-base
new file mode 100755
index 00000000..1f4c7c6d
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/NTripleSerializer.php.svn-base
@@ -0,0 +1,133 @@
+
+ * @version $Id$
+ * @package syntax
+ * @access public
+ **/
+
+
+
+class NTripleSerializer extends Object {
+
+ var $debug;
+ var $model;
+ var $res;
+
+
+
+
+
+ /**
+ * Constructor
+ *
+ * @access public
+ */
+ function NTripleSerializer() {
+ $this->debug=FALSE;
+ }
+
+ /**
+ * Serializes a model to N Triple syntax.
+ *
+ * @param object Model $model
+ * @return string
+ * @access public
+ */
+ function & serialize(&$m) {
+
+ if (is_a($m, 'DbModel')) $m = $m->getMemModel();
+
+ $this->reset();
+ if (!HIDE_ADVERTISE) {
+ $this->res .= '# Generated by NTripleSerializer.php from RDF RAP.' .
+ LINEFEED . '# http://www.wiwiss.fu-berlin.de/suhl/bizer/rdfapi/index.html'.
+ LINEFEED . LINEFEED;
+ }
+
+ foreach ($m->triples as $t) {
+
+ $s=$t->getSubject();
+ if (is_a($s, 'Blanknode')) {
+ $subject='_:'.$s->getURI();
+ } else {
+ $subject = '<' . ereg_replace(' ', '', $s->getURI()) . '>';
+ }
+
+ $p=$t->getPredicate();
+ $predicate='<'.ereg_replace(' ', '', $p->getURI()).'>';
+
+ $o=$t->getObject();
+ if (is_a($o, 'literal')) {
+ $object='"'.$o->getLabel().'"';
+ if ($o->getLanguage()!='') $object.='@'.$o->getLanguage();
+ if ($o->getDatatype()!='') $object.='^^<'.$o->getDatatype().">";
+ } elseif (is_a($o, 'Blanknode')) {
+ $object='_:'.$o->getURI();
+ } else {$object='<'.ereg_replace(' ', '', $o->getURI()).'>';};
+
+ $this->res.=$subject.' '.$predicate.' '.$object.' .';
+ $this->res.=LINEFEED.LINEFEED;
+ }
+
+ return $this->res;
+ }
+
+
+/**
+ * Serializes a model and saves it into a file.
+ * Returns FALSE if the model couldn't be saved to the file.
+ *
+ * @access public
+ * @param object MemModel $model
+ * @param string $filename
+ * @return boolean
+ * @access public
+ */
+ function saveAs(&$model, $filename) {
+
+ // serialize model
+ $n3 = $this->serialize($model);
+
+ // write serialized model to file
+ $file_handle = @fopen($filename, 'w');
+ if ($file_handle) {
+ fwrite($file_handle, $n3);
+ fclose($file_handle);
+ return TRUE;
+ }else{
+ return FALSE;
+ };
+ }
+
+
+ /* ==================== Private Methods from here ==================== */
+
+
+/**
+ * Readies this object for serializing another model
+ * @access private
+ * @param void
+ * @returns void
+ **/
+ function reset() {
+ $this->res="";
+ $this->model=NULL;
+ }
+
+}
+
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/RdfParser.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/RdfParser.php.svn-base
new file mode 100755
index 00000000..46008cac
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/RdfParser.php.svn-base
@@ -0,0 +1,2365 @@
+,
+ * Chris Bizer ,
+ * Radoslaw Oldakowski
+ * Daniel Westphal
+ * @package syntax
+ * @access public
+ *
+ */
+
+class RdfParser extends Object {
+
+var $rdf_parser;
+var $model;
+
+/* Private Methods */
+
+
+/**
+* converts a string to its unicode NFC form (e.g. \uHHHH or \UHHHHHHHH).
+*
+* @param String $str
+* @return String
+* @access private
+*
+*/
+function str2unicode_nfc($str=""){
+ $result="";
+ /* try to detect encoding */
+ $tmp=str_replace("?", "", $str);
+ if(strpos(utf8_decode($tmp), "?")===false){
+ $str=utf8_decode($str);
+ }
+ for($i=0,$i_max=strlen($str);$i<$i_max;$i++){
+ $nr=0;/* unicode dec nr */
+ /* char */
+ $char=$str[$i];
+ /* utf8 binary */
+ $utf8_char=utf8_encode($char);
+ $bytes=strlen($utf8_char);
+ if($bytes==1){
+ /* 0####### (0-127) */
+ $nr=ord($utf8_char);
+ }
+ elseif($bytes==2){
+ /* 110##### 10###### = 192+x 128+x */
+ $nr=((ord($utf8_char[0])-192)*64) + (ord($utf8_char[1])-128);
+ }
+ elseif($bytes==3){
+ /* 1110#### 10###### 10###### = 224+x 128+x 128+x */
+ $nr=((ord($utf8_char[0])-224)*4096) + ((ord($utf8_char[1])-128)*64) + (ord($utf8_char[2])-128);
+ }
+ elseif($bytes==4){
+ /* 1111#### 10###### 10###### 10###### = 240+x 128+x 128+x 128+x */
+ $nr=((ord($utf8_char[0])-240)*262144) + ((ord($utf8_char[1])-128)*4096) + ((ord($utf8_char[2])-128)*64) + (ord($utf8_char[3])-128);
+ }
+ /* result (see http://www.w3.org/TR/rdf-testcases/#ntrip_strings) */
+ if($nr<9){/* #x0-#x8 (0-8) */
+ $result.="\\u".sprintf("%04X",$nr);
+ }
+ elseif($nr==9){/* #x9 (9) */
+ $result.='\t';
+ }
+ elseif($nr==10){/* #xA (10) */
+ $result.='\n';
+ }
+ elseif($nr<13){/* #xB-#xC (11-12) */
+ $result.="\\u".sprintf("%04X",$nr);
+ }
+ elseif($nr==13){/* #xD (13) */
+ $result.='\t';
+ }
+ elseif($nr<32){/* #xE-#x1F (14-31) */
+ $result.="\\u".sprintf("%04X",$nr);
+ }
+ elseif($nr<34){/* #x20-#x21 (32-33) */
+ $result.=$char;
+ }
+ elseif($nr==34){/* #x22 (34) */
+ $result.='\"';
+ }
+ elseif($nr<92){/* #x23-#x5B (35-91) */
+ $result.=$char;
+ }
+ elseif($nr==92){/* #x5C (92) */
+ $result.='\\';
+ }
+ elseif($nr<127){/* #x5D-#x7E (93-126) */
+ $result.=$char;
+ }
+ elseif($nr<65536){/* #x7F-#xFFFF (128-65535) */
+ $result.="\\u".sprintf("%04X",$nr);
+ }
+ elseif($nr<1114112){/* #x10000-#x10FFFF (65536-1114111) */
+ $result.="\\U".sprintf("%08X",$nr);
+ }
+ else{
+ /* other chars are not defined => ignore */
+ }
+ }
+ return $result;
+}
+
+
+
+
+/**
+ * @access private
+ */
+function _new_element()
+{
+ $e['parent']=Array(); // Parent is a blank Array
+ $e['state']=0;
+ $e['has_property_atributes']=0;
+ $e['has_member_attributes']=0;
+ $e['subject_type']=0;
+ $e['subject']='';
+ $e['predicate']='';
+ $e['ordinal']=0;
+ $e['members']=0;
+ $e['data']='';
+ $e['xml_lang']='';
+ $e['bag_id']='';
+ $e['statements']=0;
+ $e['statement_id']='';
+ $e['datatype']='';
+ $e['element_base_uri'] = '';
+
+ return $e;
+}
+
+/**
+
+ * @param string $source
+ * @param string &$destination
+ *
+ * @access private
+ */
+function _copy_element($source, &$destination )
+{
+ if( $source )
+ {
+ $destination['parent'] = $source;
+ $destination['state'] = $source['state'];
+ $destination['xml_lang'] = $source['xml_lang'];
+ $destination['element_base_uri'] = $source['element_base_uri'];
+ }
+}
+
+ /**
+ * @param string &$e
+ * @access private
+ */
+function _clear_element(&$e)
+{
+ $e['subject']='';
+ $e['predicate']='';
+ $e['data']='';
+ $e['bag_id']='';
+ $e['statement_id']='';
+
+ if(isset($e['parent'])) {
+ if( $e['parent'] )
+ {
+ if( $e['parent']['xml_lang'] != $e['xml_lang'] )
+ {
+ $e['xml_lang']='';
+ }
+ }
+ else
+ {
+ $e['xml_lang']='';
+ }
+ } else {
+ $e['xml_lang']='';
+ }
+
+ $e['parent']=Array();
+ $e['state']=0;
+ $e['has_property_attributes']=0;
+ $e['has_member_attributes']=0;
+ $e['subject_type']=0;
+ $e['subject']='';
+ $e['predicate']='';
+ $e['ordinal']=0;
+ $e['members']=0;
+ $e['data']='';
+ $e['xml_lang']='';
+ $e['bag_id']='';
+ $e['statements']=0;
+ $e['statement_id']='';
+ $e['datatype']='';
+ $e['element_base_uri'] = '';
+}
+
+ /**
+ * @access private
+ */
+function _push_element()
+{
+ if(!isset($this->rdf_parser['free'])) {
+ $this->rdf_parser['free']=Array();
+ }
+ if(count($this->rdf_parser['free'])>0)
+ {
+ $e = $this->rdf_parser['free'];
+ if(isset($e['parent'])) {
+ $this->rdf_parser['free'] = $e['parent'];
+ } else {
+ $this->rdf_parser['free']=$this->_new_element();
+ }
+ }
+ else
+ {
+ $e = $this->_new_element();
+ }
+ if(!isset($this->rdf_parser['top'])) {
+ $this->rdf_parser['top']=Array();
+ }
+ $this->_copy_element( $this->rdf_parser['top'], $e );
+ $this->rdf_parser['top'] = $e;
+}
+
+ /**
+ * @access private
+ */
+function _pop_element()
+{
+ $e = $this->rdf_parser['top'];
+ $this->rdf_parser['top'] = $e['parent'];
+ $this->_clear_element( $e );
+ $this->rdf_parser['free'] = $e;
+}
+
+ /**
+ * @param string $local_name
+ * @access private
+ */
+function _is_rdf_property_attribute_resource($local_name )
+{
+ return ( $local_name == RDF_TYPE );
+}
+
+ /**
+ * @param string $local_name
+ * @access private
+ */
+function _is_rdf_property_attribute_literal($local_name )
+{
+ return ( $local_name == RDF_VALUE )
+ || ( $local_name == RDF_BAG )
+ || ( $local_name == RDF_SEQ )
+ || ( $local_name == RDF_ALT )
+ || ( $local_name == RDF_STATEMENT )
+ || ( $local_name == RDF_PROPERTY )
+ || ( $local_name == RDF_LIST );
+}
+
+ /**
+ * @param string $local_name
+ * @access private
+ */
+function _is_rdf_ordinal( $local_name )
+{
+ $ordinal = -1;
+
+ if( $local_name{0} == '_' )
+ {
+ $ordinal = substr($local_name,1) + 1 ;
+ }
+
+ return ( $ordinal > 0 ) ? $ordinal : 0;
+}
+
+ /**
+ * @param string $local_name
+ * @access private
+ */
+function _is_rdf_property_attribute( $local_name )
+{
+ return $this->_is_rdf_property_attribute_resource( $local_name )
+ || $this->_is_rdf_property_attribute_literal( $local_name );
+}
+
+function _is_forbidden_rdf_property_attribute($local_name)
+{
+ return ( $local_name == RDF_RDF )
+ || ( $local_name == RDF_DESCRIPTION)
+ || ( $local_name == RDF_ID)
+ || ( $local_name == RDF_ABOUT )
+ || ( $local_name == RDF_BAG_ID )
+ || ( $local_name == RDF_PARSE_TYPE )
+ || ( $local_name == RDF_RESOURCE )
+ || ( $local_name == RDF_NODEID )
+ || ( $local_name == RDF_LI )
+ || ( $local_name == RDF_ABOUT_EACH )
+ || ( $local_name == RDF_ABOUT_EACH_PREFIX )
+ || ( $local_name == RDF_DATATYPE );
+}
+
+ /**
+ * @param string $local_name
+ * @access private
+ */
+function _is_rdf_property_element( $local_name )
+{
+ return ( $local_name == RDF_TYPE )
+ || ( $local_name == RDF_SUBJECT )
+ || ( $local_name == RDF_PREDICATE )
+ || ( $local_name == RDF_OBJECT )
+ || ( $local_name == RDF_VALUE )
+ || ( $local_name == RDF_LI )
+ || ( $local_name == RDF_SEEALSO )
+ || ( $local_name == RDF_BAG )
+ || ( $local_name == RDF_SEQ )
+ || ( $local_name == RDF_ALT )
+ || ( $local_name == RDF_STATEMENT )
+ || ( $local_name == RDF_PROPERTY )
+ || ( $local_name == RDF_LIST )
+ || ( $local_name == RDF_FIRST )
+ || ( $local_name == RDF_REST )
+ || ( $local_name{0} == '_' );
+}
+
+ /**
+ * @param string $local_name
+ * @access private
+ */
+function _is_forbidden_rdf_property_element ($local_name)
+{
+ return ( $local_name == RDF_RDF )
+ || ( $local_name == RDF_DESCRIPTION)
+ || ( $local_name == RDF_ID)
+ || ( $local_name == RDF_ABOUT )
+ || ( $local_name == RDF_BAG_ID )
+ || ( $local_name == RDF_PARSE_TYPE )
+ || ( $local_name == RDF_RESOURCE )
+ || ( $local_name == RDF_NODEID )
+ || ( $local_name == RDF_ABOUT_EACH )
+ || ( $local_name == RDF_ABOUT_EACH_PREFIX )
+ || ( $local_name == RDF_DATATYPE );
+}
+
+
+ /**
+ * @param string $local_name
+ * @access private
+ */
+function _is_rdf_node_element( $local_name )
+{
+ return ( $local_name == RDF_DESCRIPTION )
+ || ( $local_name == RDF_STATEMENT )
+ || ( $local_name == RDF_SUBJECT )
+ || ( $local_name == RDF_PREDICATE )
+ || ( $local_name == RDF_OBJECT )
+ || ( $local_name == RDF_PROPERTY )
+ || ( $local_name == RDF_TYPE )
+ || ( $local_name == RDF_VALUE )
+ || ( $local_name == RDF_BAG )
+ || ( $local_name == RDF_SEQ )
+ || ( $local_name == RDF_ALT )
+ || ( $local_name == RDF_SEEALSO )
+ || ( $local_name == RDF_LIST )
+ || ( $local_name == RDF_FIRST )
+ || ( $local_name == RDF_REST )
+ || ( $local_name == RDF_NIL )
+ || ( $local_name{0} == '_' );
+}
+
+ /**
+ * @param string $local_name
+ * @access private
+ */
+function _is_forbidden_rdf_node_element ($local_name)
+{
+ return ( $local_name == RDF_RDF )
+ || ( $local_name == RDF_ID)
+ || ( $local_name == RDF_ABOUT )
+ || ( $local_name == RDF_BAG_ID )
+ || ( $local_name == RDF_PARSE_TYPE )
+ || ( $local_name == RDF_RESOURCE )
+ || ( $local_name == RDF_NODEID )
+ || ( $local_name == RDF_LI )
+ || ( $local_name == RDF_ABOUT_EACH )
+ || ( $local_name == RDF_ABOUT_EACH_PREFIX )
+ || ( $local_name == RDF_DATATYPE );
+}
+
+ /**
+ * @param string $val
+ * @access private
+ */
+function _istalnum($val) {
+ return ereg("[A-Za-z0-9]",$val);
+}
+ /**
+ * @param string $val
+ * @access private
+ */
+function _istalpha($val) {
+ return ereg("[A-Za-z]",$val);
+}
+
+ /**
+ * @param string $uri
+ * @access private
+ */
+function _is_absolute_uri($uri )
+{
+ $result = false;
+ $uri_p=0;
+ if( $uri && $this->_istalpha( $uri{$uri_p} ) )
+ {
+ ++$uri_p;
+
+ while( ($uri_p_istalnum( $uri{$uri_p} )
+ || ( $uri{$uri_p} == '+' )
+ || ( $uri{$uri_p} == '-' )
+ || ( $uri{$uri_p} == '.' ) ) )
+ {
+ ++$uri_p;
+ }
+
+ $result = ( $uri{$uri_p} == ':' );
+ }
+ return $result;
+}
+
+
+/*
+ * This function returns an associative array returning any of the various components of the URL that are present. This includes the
+ * $arr=parse_url($url)
+ * scheme - e.g. http
+ * host
+ * port
+ * user
+ * pass
+ * path
+ * query - after the question mark ?
+ * fragment - after the hashmark #
+ *
+ * @param string $uri
+ * @param string $buffer
+ * @param string &$scheme
+ * @param string &$authority
+ * @param string &$path
+ * @param string &$query
+ * @param string &$fragment
+ * @access private
+*/
+function _parse_uri($uri,$buffer,&$scheme,&$authority,&$path,&$query,&$fragment ) {
+
+ $parsed=parse_url($uri);
+ if(isset($parsed['scheme'])) {
+ $scheme=$parsed['scheme'];
+ } else {
+ $scheme='';
+ }
+ if(isset($parsed['host'])) {
+ $host=$parsed['host'];
+ } else {
+ $host='';
+ }
+ if(isset($parsed['host'])) {
+ $authority=$parsed['host'];
+ } else {
+ $authority='';
+ }
+ if(isset($parsed['path'])) {
+ $path=$parsed['path'];
+ } else {
+ $path='';
+ }
+ if(isset($parsed['query'])) {
+ $query=$parsed['query'];
+ } else {
+ $query='';
+ }
+ if(isset($parsed['fragment'])) {
+ $fragment=$parsed['fragment'];
+ } else {
+ $fragment='';
+ }
+
+}
+
+/**
+ * @param string $base_uri
+ * @param string $reference_uri
+ * @param string &$buffer
+ * @access private
+*/
+function _resolve_uri_reference($base_uri,$reference_uri,&$buffer )
+{
+ if ($reference_uri == '')
+ return ($buffer = preg_replace("/\#[^\/\\\]*$/", '', $base_uri));
+
+ $base_buffer='';
+ $reference_buffer='';
+ $path_buffer='';
+
+ $buffer = '';
+
+ $this->_parse_uri($reference_uri,
+ $reference_buffer,
+ $reference_scheme,
+ $reference_authority,
+ $reference_path,
+ $reference_query,
+ $reference_fragment );
+
+ $this->_parse_uri($base_uri,
+ $base_buffer,
+ $base_scheme,
+ $base_authority,
+ $base_path,
+ $base_query,
+ $base_fragment );
+
+ if( $reference_scheme == ''
+ && $reference_authority == ''
+ && $reference_path == ''
+ && $reference_query == '' )
+ {
+ $buffer=$base_uri;
+
+ if( $reference_fragment != '' )
+ {
+ if ($base_path == '' || $base_path == '/' || $base_path == "\\") {
+ $buffer = $this->rdf_parser['document_base_uri'];
+ }
+ else
+ {
+ $buffer = preg_replace("/\#[^\/\\\]*$/", '', $base_uri);
+ }
+
+ // CB: Changed for base URI
+ $c = substr($buffer, strlen($buffer)-1 ,1);
+ if (!($c=='#' || $c==':' || $c=='/' || $c=="\\"))
+ $buffer.= '#' ;
+ $buffer.=$reference_fragment;
+
+ }
+ }
+ else if( $reference_scheme != '' )
+ {
+ $buffer=$reference_uri;
+ }
+ else
+ {
+ $result_scheme = $base_scheme;
+ $result_path = '';
+
+ if( $reference_authority != '' )
+ {
+ $result_authority = $reference_authority;
+ }
+ else
+ {
+ $result_authority = $base_authority;
+
+ if ($reference_path != '')
+ {
+ if ($reference_path{0} == '/' || $reference_path{0} == "\\")
+ {
+ if ($reference_path{1} == '/' || $reference_path{1} == "\\")
+ {
+ $result_authority = '';
+ $result_path = $reference_path;
+ }
+ else
+ $result_path = $reference_path;
+ }
+ elseif (substr($reference_path, 0, 3) == '../' ||
+ substr($reference_path, 0, 3) == '..\\')
+ {
+ $slash = $reference_path{2};
+ while($base_path != '' && ( substr($reference_path, 0, 3) == '../'
+ || substr($reference_path, 0, 3) == '..\\'))
+ {
+ $base_path = preg_replace("/((\/)|(\\\))[^\/\\\]*$/", '', $base_path);
+ if ($base_path != '') {
+ $base_path = preg_replace("/((\/)|(\\\))[^\/\\\]*$/", '', $base_path);
+ $reference_path = substr($reference_path, 3);
+ }
+ }
+
+ $result_path = $base_path .$slash .$reference_path;
+ }
+ else
+ {
+ if ($base_path)
+ $result_path = preg_replace("/[^\/\\\]*$/", $reference_path, $base_path, 1);
+ else
+ $result_path = '/' .$reference_path;
+ }
+ }
+
+ }
+
+ if( $result_scheme != '' )
+ {
+ $buffer=$result_scheme;
+ $buffer.=':';
+ }
+
+ if( $result_authority != '' )
+ {
+ $buffer.="//";
+ $buffer.=$result_authority;
+ }
+
+ if( $result_path != '' )
+ {
+ $buffer.=$result_path;
+ }
+
+ if( $reference_query != '' )
+ {
+ $buffer.='?';
+ $buffer.=$reference_query;
+ }
+
+ if( $reference_fragment != '' )
+ {
+ $buffer.='#';
+ $buffer.=$reference_fragment;
+ }
+ }
+}
+
+
+/**
+ * IDs which contain CombiningChars or Extenders
+ * (see http://www.w3.org/TR/REC-xml-names/#NT-NCName) are assumed to be invalid.
+ * If you want to use IDs containing these characters you can turn off
+ * the validating by setting the constant VALIDATE_IDS to FALSE (see constants.php).
+ *
+ * @param string $id
+ * @access private
+*/
+function is_valid_id($id )
+{
+ if (!VALIDATE_IDS)
+ return TRUE;
+
+ $result = FALSE;
+
+ if( $id )
+ {
+ if( $this->_istalpha($id{0}) || $id{0} == '_')
+ {
+ $result = TRUE;
+ $i=0;
+ $len = strlen($id);
+ while( $result != FALSE && ++$i < $len )
+ {
+ if( !($this->_istalnum( $id{$i})
+ || $id{$i} == '.'
+ || $id{$i} == '-'
+ || $id{$i} == '_'))
+ {
+ $result = FALSE;
+ }
+ }
+ }
+ }
+
+ if (!$result)
+ $this->_report_error('illegal ID, nodeID or bagID attribute value');
+ else
+ return TRUE;
+}
+
+/**
+ * @param string $id
+ * @param string &$buffer
+ * @access private
+*/
+function _resolve_id($id,&$buffer )
+{
+ $id_buffer='';
+
+ if( $this->is_valid_id($id) )
+ {
+ $id_buffer="#$id";
+ }
+
+ $this->_resolve_uri_reference( $this->rdf_get_base(), $id_buffer, $buffer );
+
+}
+
+/**
+ * @param string $name
+ * @param string &$buffer
+ * @param string &$namespace_uri
+ * @param string &$local_name
+ * @access private
+*/
+function _split_name($name, &$buffer, &$namespace_uri, &$local_name )
+{
+ static $nul = 0;
+ $buffer=$name;
+
+ if( strstr( $buffer, NAMESPACE_SEPARATOR_CHAR ) )
+ {
+ $cosas=explode(NAMESPACE_SEPARATOR_CHAR,$buffer);
+ $namespace_uri = $cosas[0];
+ $local_name = $cosas[1];
+ }
+ else
+ {
+ if( ( $buffer{ 0 } == 'x' )
+ && ( $buffer{ 1 } == 'm' )
+ && ( $buffer{ 2 } == 'l' )
+ && ( $buffer{ 3 } == ':' ) )
+ {
+ $namespace_uri = XML_NAMESPACE_URI;
+ $local_name = substr($buffer,4);
+ }
+ else
+ {
+ $namespace_uri = '';
+ $local_name = $buffer;
+ }
+ }
+}
+/**
+ * @param string &$buf
+ * @access private
+*/
+function _generate_anonymous_uri(&$buf )
+{
+ $id='';
+ if(!isset($this->rdf_parser['anonymous_id'])) {
+ $this->rdf_parser['anonymous_id']=0;
+ }
+ $this->rdf_parser['anonymous_id']++;
+
+ $buf= BNODE_PREFIX . $this->rdf_parser['anonymous_id'];
+
+}
+/**
+ * @param string $subject_type
+ * @param string $subject
+ * @param string $predicate
+ * @param string $ordinal
+ * @param string $object_type
+ * @param string $object
+ * @param string $xml_lang
+ * @param string $bag_id
+ * @param string $statements
+ * @param string $statement_id
+ * @access private
+*/
+function _report_statement( $subject_type, $subject, $predicate, $ordinal, $object_type, $object, $xml_lang, $bag_id, $statements, $statement_id, $datatype )
+{
+ $statement_id_type = RDF_SUBJECT_TYPE_URI;
+ $statement_id_buffer='';
+ $predicate_buffer='';
+ if (!$xml_lang && $object_type == RDF_OBJECT_TYPE_LITERAL && isset($this->rdf_parser['document_xml_lang']))
+ $xml_lang = $this->rdf_parser['document_xml_lang'];
+
+ // call add statement
+ $this->add_statement_to_model($this->rdf_parser['user_data'],$subject_type,$subject,$predicate,$ordinal,$object_type,$object,$xml_lang, $datatype );
+
+ if( $bag_id )
+ {
+ if( $statements == '' )
+ {
+ $this->_report_statement(RDF_SUBJECT_TYPE_URI,
+ $bag_id,
+ RDF_NAMESPACE_URI.RDF_TYPE,
+ 0,
+ RDF_OBJECT_TYPE_RESOURCE,
+ RDF_NAMESPACE_URI.RDF_BAG,
+ '',
+ '',
+ '',
+ '',
+ $datatype );
+ }
+
+ if( ! $statement_id )
+ {
+ $statement_id_type = RDF_SUBJECT_TYPE_BNODE;
+ $this->_generate_anonymous_uri( $statement_id_buffer );
+ $statement_id = $statement_id_buffer;
+ }
+ $statements++;
+ $predicate_buffer='RDF_NAMESPACE_URI_'.$statements;
+
+ $this->_report_statement(
+ RDF_SUBJECT_TYPE_URI,
+ $bag_id,
+ $predicate_buffer,
+ $statements,
+ RDF_OBJECT_TYPE_BNODE,
+ $statement_id,
+ '',
+ '',
+ '',
+ '',
+ $datatype );
+ }
+
+ if( $statement_id )
+ {
+ // rdf:type = rdf:Statement
+ $this->_report_statement(
+ $statement_id_type,
+ $statement_id,
+ RDF_NAMESPACE_URI.RDF_TYPE,
+ 0,
+ RDF_OBJECT_TYPE_RESOURCE,
+ RDF_NAMESPACE_URI.RDF_STATEMENT,
+ '',
+ '',
+ '',
+ '',
+ $datatype );
+
+ if ($subject_type == RDF_SUBJECT_TYPE_BNODE)
+ $obj_type = RDF_OBJECT_TYPE_BNODE;
+ else
+ $obj_type = RDF_OBJECT_TYPE_RESOURCE;
+
+
+ // rdf:subject
+ $this->_report_statement(
+ $statement_id_type,
+ $statement_id,
+ RDF_NAMESPACE_URI.RDF_SUBJECT,
+ 0,
+ $obj_type,
+ $subject,
+ '',
+ '',
+ '',
+ '',
+ $datatype );
+
+ // rdf:predicate
+ $this->_report_statement(
+ $statement_id_type,
+ $statement_id,
+ RDF_NAMESPACE_URI.RDF_PREDICATE,
+ 0,
+ RDF_OBJECT_TYPE_RESOURCE,
+ $predicate,
+ '',
+ '',
+ '',
+ '',
+ $datatype );
+
+ // rdf:object
+ $this->_report_statement(
+ $statement_id_type,
+ $statement_id,
+ RDF_NAMESPACE_URI.RDF_OBJECT,
+ 0,
+ $object_type,
+ $object,
+ '',
+ '',
+ '',
+ '',
+ $datatype );
+ }
+}
+/**
+ * @param string $subject_type
+ * @param string $subject
+ * @param string $attributes
+ * @param string $xml_lang
+ * @param string $bag_id
+ * @param string $statements
+ * @access private
+*/
+function _handle_property_attributes($subject_type, $subject, $attributes, $xml_lang, $bag_id, $statements )
+{
+ $i=0;
+
+ $attribute='';
+ $predicate='';
+
+ $attribute_namespace_uri='';
+ $attribute_local_name='';
+ $attribute_value='';
+
+ $ordinal=0;
+
+ for( $i = 0; isset($attributes[ $i ]); $i += 2 )
+ {
+ $this->_split_name(
+ $attributes[ $i ],
+ $attribute,
+ $attribute_namespace_uri,
+ $attribute_local_name );
+
+ $attribute_value = $attributes[ $i + 1 ];
+
+ $predicate=$attribute_namespace_uri;
+ $predicate.=$attribute_local_name;
+
+ if( RDF_NAMESPACE_URI == $attribute_namespace_uri )
+ {
+ if( $this->_is_rdf_property_attribute_literal( $attribute_local_name ) )
+ {
+ $this->_report_statement(
+ $subject_type,
+ $subject,
+ $predicate,
+ 0,
+ RDF_OBJECT_TYPE_LITERAL,
+ $attribute_value,
+ $xml_lang,
+ $bag_id,
+ $statements,
+ '',
+ '');
+ }
+ else if( $this->_is_rdf_property_attribute_resource( $attribute_local_name ) )
+ {
+ $this->_report_statement(
+ $subject_type,
+ $subject,
+ $predicate,
+ 0,
+ RDF_OBJECT_TYPE_RESOURCE,
+ $attribute_value,
+ '',
+ $bag_id,
+ $statements,
+ '',
+ '');
+ }
+ else if( ( $ordinal = $this->_is_rdf_ordinal( $attribute_local_name ) ) != 0 )
+ {
+ $this->_report_statement(
+ $subject_type,
+ $subject,
+ $predicate,
+ $ordinal,
+ RDF_OBJECT_TYPE_LITERAL,
+ $attribute_value,
+ $xml_lang,
+ $bag_id,
+ $statements,
+ '',
+ '' );
+ }
+ else if ( ($attribute_local_name != RDF_ABOUT)
+ && ($attribute_local_name != RDF_RDF)
+ && ($attribute_local_name != RDF_DESCRIPTION)
+ && ($attribute_local_name != RDF_ID)
+ && ($attribute_local_name != RDF_ABOUT_EACH)
+ && ($attribute_local_name != RDF_ABOUT_EACH_PREFIX)
+ && ($attribute_local_name != RDF_BAG_ID)
+ && ($attribute_local_name != RDF_RESOURCE)
+ && ($attribute_local_name != RDF_PARSE_TYPE)
+ && ($attribute_local_name != RDF_PARSE_TYPE_LITERAL)
+ && ($attribute_local_name != RDF_PARSE_TYPE_RESOURCE)
+ && ($attribute_local_name != RDF_LI)
+ && ($attribute_local_name != RDF_SUBJECT)
+ && ($attribute_local_name != RDF_PREDICATE)
+ && ($attribute_local_name != RDF_OBJECT)
+ && ($attribute_local_name != RDF_NODEID)
+ && ($attribute_local_name != RDF_DATATYPE)
+ && ($attribute_local_name != RDF_SEEALSO)
+ && ($attribute_local_name != RDF_NIL)
+ && ($attribute_local_name != RDF_REST)
+ && ($attribute_local_name != RDF_FIRST)
+ )
+ {
+ $this->_report_statement(
+ $subject_type,
+ $subject,
+ $predicate,
+ 0,
+ RDF_OBJECT_TYPE_LITERAL,
+ $attribute_value,
+ $xml_lang,
+ $bag_id,
+ $statements,
+ '',
+ '' );
+ }
+ }
+ else if( XML_NAMESPACE_URI == $attribute_namespace_uri )
+ {
+ if ($attribute_local_name == 'base')
+ {
+ $this->rdf_parser['top']['element_base_uri'] = $attribute_value;
+ }
+ }
+ else if( $attribute_namespace_uri )
+ {
+ // is it required that property attributes be in an explicit namespace?
+
+ $this->_report_statement(
+ $subject_type,
+ $subject,
+ $predicate,
+ 0,
+ RDF_OBJECT_TYPE_LITERAL,
+ $attribute_value,
+ $xml_lang,
+ $bag_id,
+ $statements,
+ '',
+ '' );
+ }
+ }
+}
+
+
+
+/**
+ * @param string $warning
+ * @access private
+*/
+function _report_warning($warning)
+{
+ $errmsg = RDFAPI_ERROR . '(class: parser): ' . $warning .'.';
+ trigger_error($errmsg, E_USER_WARNING);
+}
+
+
+function _report_error($error)
+{
+ $errmsg = RDFAPI_ERROR . '(class: parser): ' . $error .'.';
+ trigger_error($errmsg, E_USER_ERROR);
+}
+
+
+/**
+ * @param string $namespace_uri
+ * @param string $local_name
+ * @param string $attributes
+ * @param string $parent
+ * @access private
+*/
+function _handle_resource_element( $namespace_uri, $local_name, $attributes, $parent )
+{
+ $subjects_found = 0;
+ $aux=$attributes;
+ $aux2=Array();
+ foreach($attributes as $atkey=>$atvalue) {
+ $aux2[]=$atkey;
+ $aux2[]=$atvalue;
+ }
+ $attributes=$aux2;
+ $id = '';
+ $about = '';
+
+ $bag_id = '';
+ $node_id = '';
+ $datatype = '';
+
+ $i=0;
+
+ $attribute='';
+
+ $attribute_namespace_uri='';
+ $attribute_local_name='';
+ $attribute_value='';
+
+ $id_buffer='';
+
+ $type='';
+
+ $this->rdf_parser['top']['has_property_attributes'] = false;
+ $this->rdf_parser['top']['has_member_attributes'] = false;
+
+
+ if( $namespace_uri == RDF_NAMESPACE_URI )
+ {
+ if( ! $this->_is_rdf_node_element( $local_name ) )
+ {
+ $msg = 'unknown or out of context rdf node element: '.$local_name;
+
+ if ($this->_is_forbidden_rdf_node_element($local_name))
+ $this->_report_error($msg);
+ else
+ $this->_report_warning($msg);
+ }
+ }
+
+ // examine each attribute for the standard RDF "keywords"
+ for( $i = 0; isset($attributes[$i]); $i += 2 )
+ {
+ $this->_split_name(
+ $attributes[ $i ],
+ $attribute,
+ $attribute_namespace_uri,
+ $attribute_local_name );
+
+ $attribute_value = $attributes[ $i + 1 ];
+
+ // if the attribute is not in any namespace
+ // or the attribute is in the RDF namespace
+ if( ( $attribute_namespace_uri == '' )
+ || ( $attribute_namespace_uri == RDF_NAMESPACE_URI ))
+ {
+ if( $attribute_local_name == RDF_ID )
+ {
+ $id = $attribute_value;
+ ++$subjects_found;
+ } else if( $attribute_local_name == RDF_ABOUT ) {
+ $about = '_'.$attribute_value;
+ ++$subjects_found;
+ } else if( $attribute_local_name == RDF_NODEID) {
+ $node_id = $attribute_value;
+ ++$subjects_found;
+ } else if( $attribute_local_name == RDF_ABOUT_EACH ) {
+ $error = 'aboutEach has been removed from the RDF specifications';
+ $this->_report_error($error);
+ } else if( $attribute_local_name == RDF_ABOUT_EACH_PREFIX ) {
+ $error = 'aboutEachPrefix has been removed from the RDF specifications';
+ $this->_report_error($error);
+ } else if( $attribute_local_name == RDF_BAG_ID) {
+ $bag_id = $attribute_value;
+ } else if( $attribute_local_name == RDF_DATATYPE) {
+ $datatype = $attribute_value;
+ } else if( $this->_is_rdf_property_attribute( $attribute_local_name )) {
+ $this->rdf_parser['top']['has_property_attributes'] = true;
+ } else if( $this->_is_rdf_ordinal( $attribute_local_name )) {
+ $this->rdf_parser['top']['has_property_attributes'] = true;
+ $this->rdf_parser['top']['has_member_attributes'] = true;
+ } else {
+ $this->rdf_parser['top']['has_property_attributes'] = true;
+ $msg = 'unknown or out of context rdf attribute: '.$attribute_local_name;
+
+ if ($this->_is_forbidden_rdf_property_attribute($attribute_local_name))
+ $this->_report_error($msg);
+ else
+ $this->_report_warning($msg);
+ }
+ }
+ else if( $attribute_namespace_uri == XML_NAMESPACE_URI )
+ {
+ if( $attribute_local_name == XML_LANG )
+ {
+ $this->rdf_parser['top']['xml_lang'] = $attribute_value;
+ }
+ elseif ($attribute_local_name == 'base')
+ {
+ $this->rdf_parser['top']['element_base_uri'] = $attribute_value;
+ }
+ }
+ else if( $attribute_namespace_uri )
+ {
+ $this->rdf_parser['top']['has_property_attributes'] = true;
+ }
+ }
+
+ // if no subjects were found, generate one.
+ if( $subjects_found == 0 )
+ {
+ $this->_generate_anonymous_uri( $id_buffer );
+ $this->rdf_parser['top']['subject']=$id_buffer;
+ $this->rdf_parser['top']['subject_type'] = RDF_SUBJECT_TYPE_BNODE;
+ }
+ else if( $subjects_found > 1 )
+ {
+ $this->_report_error('ID, about and nodeID are mutually exclusive');
+ }
+ else if( $id )
+ {
+ $this->_resolve_id( $id, $id_buffer );
+ $this->rdf_parser['top']['subject_type'] = RDF_SUBJECT_TYPE_URI;
+ $this->rdf_parser['top']['subject']=$id_buffer;
+ }
+ else if( $about )
+ {
+ $this->_resolve_uri_reference( $this->rdf_get_base(), substr($about,1), $id_buffer );
+ $this->rdf_parser['top']['subject_type'] = RDF_SUBJECT_TYPE_URI;
+ $this->rdf_parser['top']['subject']=$id_buffer;
+ }
+ else if( $node_id )
+ {
+ $this->is_valid_id($node_id);
+ $this->rdf_parser['top']['subject_type'] = RDF_SUBJECT_TYPE_BNODE;
+ $this->rdf_parser['top']['subject']=$node_id;
+ }
+
+ // if the subject is empty, assign it the document uri
+ if( $this->rdf_parser['top']['subject'] == '' )
+ {
+ $this->rdf_parser['top']['subject']=$this->rdf_get_base();
+ }
+
+ if( $bag_id )
+ {
+ $this->_resolve_id( $bag_id, $id_buffer );
+ $this->rdf_parser['top']['bag_id']=$id_buffer;
+ }
+
+ // only report the type for non-rdf:Description elements.
+ if( ($local_name != RDF_DESCRIPTION )
+ || ( $namespace_uri != RDF_NAMESPACE_URI ) )
+ {
+ $type=$namespace_uri;
+ $type.=$local_name;
+
+ $this->_report_statement(
+ $this->rdf_parser['top']['subject_type'],
+ $this->rdf_parser['top']['subject'],
+ RDF_NAMESPACE_URI.RDF_TYPE,
+ 0,
+ RDF_OBJECT_TYPE_RESOURCE,
+ $type,
+ '',
+ $this->rdf_parser['top']['bag_id'],
+ $this->rdf_parser['top']['statements'],
+ '',
+ $datatype);
+
+ }
+
+ // if this element is the child of some property,
+ // report the appropriate statement.
+ if( $parent )
+ {
+ if ($this->rdf_parser['top']['subject_type'] == RDF_SUBJECT_TYPE_BNODE)
+ $objtype = RDF_OBJECT_TYPE_BNODE;
+ else
+ $objtype = RDF_OBJECT_TYPE_RESOURCE;
+
+ $this->_report_statement(
+ $parent['parent']['subject_type'],
+ $parent['parent']['subject'],
+ $parent['predicate'],
+ $parent['ordinal'],
+ $objtype,
+ $this->rdf_parser['top']['subject'],
+ '',
+ $parent['parent']['bag_id'],
+ $parent['parent']['statements'],
+ $parent['statement_id'],
+ $parent['datatype']);
+
+ }
+
+ if( $this->rdf_parser['top']['has_property_attributes'] )
+ {
+ $this->_handle_property_attributes(
+ $this->rdf_parser['top']['subject_type'],
+ $this->rdf_parser['top']['subject'],
+ $attributes,
+ $this->rdf_parser['top']['xml_lang'],
+ $this->rdf_parser['top']['bag_id'],
+ $this->rdf_parser['top']['statements'] );
+ }
+}
+
+/**
+ * @param string &$namespace_uri
+ * @param string &$local_name
+ * @param string &$attributes
+ * @access private
+*/
+function _handle_property_element( &$namespace_uri, &$local_name, &$attributes )
+{
+ $buffer='';
+
+ $i=0;
+
+ $aux=$attributes;
+ $aux2=Array();
+ foreach($attributes as $atkey=>$atvalue) {
+ $aux2[]=$atkey;
+ $aux2[]=$atvalue;
+ }
+ $attributes=$aux2;
+
+ $attribute_namespace_uri='';
+ $attribute_local_name='';
+ $attribute_value = '';
+
+ $resource = NULL;
+ $statement_id = '';
+ $bag_id = '';
+ $parse_type = '';
+ $node_id = '';
+ $datatype = '';
+
+ $this->rdf_parser['top']['ordinal'] = 0;
+
+ if( $namespace_uri == RDF_NAMESPACE_URI )
+ {
+ if( ! $this->_is_rdf_property_element( $local_name ) )
+ {
+ $msg = 'unknown or out of context rdf property element: '.$local_name;
+
+ if ($this->_is_forbidden_rdf_property_element($local_name))
+ $this->_report_error($msg);
+ else
+ $this->_report_warning($msg);
+ }
+
+ }
+
+ $buffer=$namespace_uri;
+
+ if( ( $namespace_uri == RDF_NAMESPACE_URI )
+ && ( $local_name == RDF_LI ) )
+ {
+ $this->rdf_parser['top']['parent']['members']++;
+ $this->rdf_parser['top']['ordinal'] = $this->rdf_parser['top']['parent']['members'];
+
+ $this->rdf_parser['top']['ordinal']=$this->rdf_parser['top']['ordinal'];
+
+ $buffer.='_'.$this->rdf_parser['top']['ordinal'];
+
+ }
+ else
+ {
+ $buffer.=$local_name;
+ }
+
+ $this->rdf_parser['top']['predicate']=$buffer;
+
+ $this->rdf_parser['top']['has_property_attributes'] = false;
+ $this->rdf_parser['top']['has_member_attributes'] = false;
+
+
+ for( $i = 0; isset($attributes[$i]); $i += 2 )
+ {
+ $this->_split_name(
+ $attributes[$i],
+ $buffer,
+ $attribute_namespace_uri,
+ $attribute_local_name );
+
+ $attribute_value = $attributes[$i + 1];
+
+ // if the attribute is not in any namespace
+ // or the attribute is in the RDF namespace
+ if( ( $attribute_namespace_uri == '' )
+ || ( $attribute_namespace_uri == RDF_NAMESPACE_URI ) )
+ {
+ if( ( $attribute_local_name == RDF_ID ) )
+ {
+ $statement_id = $attribute_value;
+ }
+ else if( $attribute_local_name == RDF_PARSE_TYPE )
+ {
+ $parse_type = $attribute_value;
+ }
+ else if( $attribute_local_name == RDF_RESOURCE )
+ {
+ $resource = $attribute_value;
+ }
+ else if( $attribute_local_name == RDF_NODEID )
+ {
+ $node_id = $attribute_value;
+ }
+ else if( $attribute_local_name == RDF_BAG_ID )
+ {
+ $bag_id = $attribute_value;
+ }
+ else if( $attribute_local_name == RDF_DATATYPE )
+ {
+ $datatype = $attribute_value;
+ $this->rdf_parser['top']['datatype'] = $attribute_value;
+ }
+ else if( $this->_is_rdf_property_attribute( $attribute_local_name ) )
+ {
+ $this->rdf_parser['top']['has_property_attributes'] = true;
+ }
+ else
+ {
+ $this->_report_warning('unknown rdf attribute: '.$attribute_local_name );
+ return;
+ }
+ }
+ else if( $attribute_namespace_uri == XML_NAMESPACE_URI )
+ {
+ if( $attribute_local_name == XML_LANG )
+ {
+ $this->rdf_parser['top']['xml_lang'] = $attribute_value;
+ }
+ elseif ($attribute_local_name == 'base')
+ {
+ $this->rdf_parser['top']['element_base_uri'] = $attribute_value;
+ }
+ }
+ else if( $attribute_namespace_uri )
+ {
+ $this->rdf_parser['top']['has_property_attributes'] = true;
+ }
+ }
+
+ if( $statement_id )
+ {
+ $this->_resolve_id($statement_id, $buffer );
+ $this->rdf_parser['top']['statement_id']=$buffer;
+ }
+
+ if ($node_id)
+ {
+ $this->is_valid_id($node_id);
+
+ if ($resource)
+ {
+ $this->_report_error('nodeID and resource are mutually exclusive');
+ }
+ if ($statement_id)
+ {
+ // reify statement
+ $this->_report_statement(
+ $this->rdf_parser['top']['parent']['subject_type'],
+ $this->rdf_parser['top']['parent']['subject'],
+ $this->rdf_parser['top']['predicate'],
+ $this->rdf_parser['top']['ordinal'],
+ RDF_OBJECT_TYPE_BNODE,
+ $node_id,
+ '',
+ $this->rdf_parser['top']['parent']['bag_id'],
+ $this->rdf_parser['top']['parent']['statements'],
+ $this->rdf_parser['top']['statement_id'],
+ '');
+ $statement_id = '';
+ }
+ else
+ {
+ $this->_report_statement(
+ $this->rdf_parser['top']['parent']['subject_type'],
+ $this->rdf_parser['top']['parent']['subject'],
+ $this->rdf_parser['top']['predicate'],
+ $this->rdf_parser['top']['ordinal'],
+ RDF_OBJECT_TYPE_BNODE,
+ $node_id,
+ '',
+ $this->rdf_parser['top']['parent']['bag_id'],
+ $this->rdf_parser['top']['parent']['statements'],
+ '',
+ $datatype );
+ }
+
+ $this->rdf_parser['top']['state'] = IN_PROPERTY_EMPTY_RESOURCE;
+ }
+
+ if( $parse_type )
+ {
+ if( $resource ) {
+ $this->_report_error('property elements with rdf:parseType do not allow rdf:resource' );
+ }
+
+ if( $bag_id ) {
+ $this->_report_warning('property elements with rdf:parseType do not allow rdf:bagID' );
+ return;
+ }
+
+ if( $this->rdf_parser['top']['has_property_attributes'] )
+ {
+ $this->_report_error('property elements with rdf:parseType do not allow property attributes');
+ return;
+ }
+
+ if( $attribute_value == RDF_PARSE_TYPE_RESOURCE )
+ {
+ $this->_generate_anonymous_uri( $buffer );
+ // since we are sure that this is now a resource property we can report it
+ $this->_report_statement(
+ $this->rdf_parser['top']['parent']['subject_type'],
+ $this->rdf_parser['top']['parent']['subject'],
+ $this->rdf_parser['top']['predicate'],
+ 0,
+ RDF_OBJECT_TYPE_BNODE,
+ $buffer,
+ '',
+ $this->rdf_parser['top']['parent']['bag_id'],
+ $this->rdf_parser['top']['parent']['statements'],
+ $this->rdf_parser['top']['statement_id'],
+ $datatype );
+
+ $this->_push_element( );
+
+ $this->rdf_parser['top']['state'] = IN_PROPERTY_PARSE_TYPE_RESOURCE;
+ $this->rdf_parser['top']['subject_type'] = RDF_SUBJECT_TYPE_BNODE;
+ $this->rdf_parser['top']['subject']=$buffer;
+ $this->rdf_parser['top']['bag_id']='';
+ $this->rdf_parser['top']['datatype']= $datatype;
+
+ }
+ elseif ( $attribute_value == RDF_PARSE_TYPE_LITERAL )
+ {
+ $this->rdf_parser['top']['state'] = IN_PROPERTY_PARSE_TYPE_LITERAL;
+ $this->rdf_parser['top']['datatype']= RDF_NAMESPACE_URI .RDF_XMLLITERAL;
+ $this->rdf_parser['xml_literal']['buffer'] = '';
+ $this->rdf_parser['xml_literal']['depth'] = 0;
+ }
+ elseif ($attribute_value == RDF_PARSE_TYPE_COLLECTION)
+ {
+ $this->_generate_anonymous_uri( $buffer );
+ $this->_report_statement(
+ $this->rdf_parser['top']['parent']['subject_type'],
+ $this->rdf_parser['top']['parent']['subject'],
+ $this->rdf_parser['top']['predicate'],
+ 0,
+ RDF_OBJECT_TYPE_BNODE,
+ $buffer,
+ '',
+ $this->rdf_parser['top']['parent']['bag_id'],
+ $this->rdf_parser['top']['parent']['statements'],
+ $this->rdf_parser['top']['statement_id'],
+ $datatype );
+
+ $this->rdf_parser['top']['state'] = IN_PROPERTY_PARSE_TYPE_COLLECTION;
+ $this->rdf_parser['top']['collection']['first_blank_node_id'] = $buffer;
+ }
+
+ else
+ {
+
+ $this->_report_statement(
+ $this->rdf_parser['top']['parent']['subject_type'],
+ $this->rdf_parser['top']['parent']['subject'],
+ $this->rdf_parser['top']['predicate'],
+ 0,
+ RDF_OBJECT_TYPE_XML,
+ '',
+ '',
+ $this->rdf_parser['top']['parent']['bag_id'],
+ $this->rdf_parser['top']['parent']['statements'],
+ $this->rdf_parser['top']['statement_id'],
+ $datatype );
+
+ $this->rdf_parser['top']['state'] = IN_PROPERTY_PARSE_TYPE_LITERAL;
+ }
+ }
+ else if( $resource !== NULL || $bag_id || $this->rdf_parser['top']['has_property_attributes'] )
+ {
+ if( $resource !== NULL )
+ {
+ $subject_type = RDF_SUBJECT_TYPE_URI;
+ $this->_resolve_uri_reference( $this->rdf_get_base(), $resource, $buffer );
+ $object_type=RDF_OBJECT_TYPE_RESOURCE;
+ }
+ else
+ {
+ $subject_type = RDF_SUBJECT_TYPE_BNODE;
+ $this->_generate_anonymous_uri( $buffer );
+ $object_type=RDF_OBJECT_TYPE_BNODE;
+ }
+ $this->rdf_parser['top']['state'] = IN_PROPERTY_EMPTY_RESOURCE;
+
+ // since we are sure that this is now a resource property we can report it.
+ $this->_report_statement(
+ $this->rdf_parser['top']['parent']['subject_type'],
+ $this->rdf_parser['top']['parent']['subject'],
+ $this->rdf_parser['top']['predicate'],
+ $this->rdf_parser['top']['ordinal'],
+ $object_type,
+ $buffer,
+ '',
+ $this->rdf_parser['top']['parent']['bag_id'],
+ $this->rdf_parser['top']['parent']['statements'],
+ $this->rdf_parser['top']['statement_id'],
+ $datatype ); // should we allow IDs?
+
+ if( $bag_id )
+ {
+ $this->_resolve_id( $bag_id, $buffer );
+ $this->rdf_parser['top']['bag_id']=$buffer;
+ }
+
+ if( $this->rdf_parser['top']['has_property_attributes'] )
+ {
+ $this->_handle_property_attributes(
+ $subject_type,
+ $buffer,
+ $attributes,
+ $this->rdf_parser['top']['xml_lang'],
+ $this->rdf_parser['top']['bag_id'],
+ $this->rdf_parser['top']['statements'] );
+ }
+ }
+}
+
+/**
+ * @param string &$namespace_uri
+ * @param string &$local_name
+ * @param string &$attributes
+ * @access private
+*/
+function _handle_collection_element(&$namespace_uri, &$local_name, &$attributes)
+{
+ $aux2=Array();
+ foreach($attributes as $atkey=>$atvalue) {
+ $aux2[]=$atkey;
+ $aux2[]=$atvalue;
+ }
+ $attributes=$aux2;
+/* collection construction site
+// old:
+ if ( ($namespace_uri == RDF_NAMESPACE_URI || $namespace_uri == '')
+ && ($local_name == RDF_DESCRIPTION || $local_name == RDF_LI) )
+ {
+ for( $i = 0; isset($attributes[$i]); $i += 2 )
+ {
+ $this->_split_name(
+ $attributes[ $i ],
+ $attribute,
+ $attribute_namespace_uri,
+ $attribute_local_name );
+
+ $attribute_value = $attributes[ $i + 1 ];
+
+ if( $attribute_namespace_uri == '' || $attribute_namespace_uri == RDF_NAMESPACE_URI )
+ {
+ if( $attribute_local_name == RDF_ABOUT ||
+ $attribute_local_name == RDF_RESOURCE)
+ {
+ $this->rdf_parser['top']['parent']['collection']['object_type'][] = RDF_OBJECT_TYPE_RESOURCE;
+ }
+ elseif ( $attribute_local_name == RDF_NODEID ) {
+ $this->rdf_parser['top']['parent']['collection']['object_type'][] = RDF_OBJECT_TYPE_BNODE;
+ }
+ $this->rdf_parser['top']['parent']['collection']['object_label'][] = $attribute_value;
+ }
+ }
+ }
+*/
+// new
+
+ for( $i = 0; isset($attributes[$i]); $i += 2 )
+ {
+ $this->_split_name(
+ $attributes[ $i ],
+ $attribute,
+ $attribute_namespace_uri,
+ $attribute_local_name );
+
+ $attribute_value = $attributes[ $i + 1 ];
+
+ if( $attribute_namespace_uri == '' || $attribute_namespace_uri == RDF_NAMESPACE_URI )
+ {
+ $tmp_subject_type = RDF_SUBJECT_TYPE_URI;
+ if( $attribute_local_name == RDF_ABOUT ||
+ $attribute_local_name == RDF_RESOURCE)
+ {
+ $this->rdf_parser['top']['parent']['collection']['object_type'][] = RDF_OBJECT_TYPE_RESOURCE;
+ }
+ elseif ( $attribute_local_name == RDF_NODEID ) {
+ $this->rdf_parser['top']['parent']['collection']['object_type'][] = RDF_OBJECT_TYPE_BNODE;
+ $tmp_subject_type = RDF_SUBJECT_TYPE_BNODE;
+ }
+ $id_buffer = '';
+ $this->_resolve_uri_reference( $this->rdf_get_base(), $attribute_value, $id_buffer );
+ $this->rdf_parser['top']['parent']['collection']['object_label'][] = $id_buffer;
+
+ if (!( ($namespace_uri == RDF_NAMESPACE_URI || $namespace_uri == '')
+ && ($local_name == RDF_DESCRIPTION || $local_name == RDF_LI) ))
+ {
+ $this->_report_statement(
+ $tmp_subject_type,
+ $id_buffer,
+ RDF_NAMESPACE_URI.RDF_TYPE,
+ '',
+ RDF_OBJECT_TYPE_RESOURCE,
+ $namespace_uri.$local_name,
+ '',
+ '',
+ '',
+ '',
+ '');
+ }
+ }
+ }
+
+
+// collection construction site
+}
+
+/**
+ * @param string &$namespace_uri
+ * @param string &$local_name
+ * @param string &$attributes
+ * @access private
+*/
+function _handle_xml_start_element(&$namespace_uri, &$local_name, &$attributes)
+{
+ $aux2=Array();
+ foreach($attributes as $atkey=>$atvalue) {
+ $aux2[]=$atkey;
+ $aux2[]=$atvalue;
+ }
+ $attributes=$aux2;
+
+ $element = '<' .$this->_join_name_and_declare_prefix($namespace_uri, $local_name);
+
+ for( $i = 0; isset($attributes[$i]); $i += 2 )
+ {
+ $this->_split_name(
+ $attributes[ $i ],
+ $attribute,
+ $attribute_namespace_uri,
+ $attribute_local_name );
+
+ $attribute_value = $attributes[ $i + 1 ];
+
+ $element .= ' ' .$this->_join_name_and_declare_prefix($attribute_namespace_uri, $attribute_local_name);
+ $element .= '=\"' .$attribute_value .'\"';
+ }
+ $element .= '>';
+
+ $this->rdf_parser['xml_literal']['buffer'] .= $element;
+}
+
+/**
+ * @param string $name
+ * @access private
+*/
+function _handle_xml_end_element($name)
+{
+ $buffer='';
+ $namespace_uri='';
+ $local_name='';
+
+ $this->_split_name(
+ $name,
+ $buffer,
+ $namespace_uri,
+ $local_name );
+
+ $element = '';
+
+ if ($namespace_uri && isset($this->rdf_parser['default_namespace'])
+ &&$namespace_uri != $this->rdf_parser['default_namespace'])
+ {
+ $element .= $this->rdf_parser['namespaces'][$namespace_uri] .':';
+ }
+
+ $element .= $local_name .'>';
+
+ $this->rdf_parser['xml_literal']['buffer'] .= $element;
+ $depth = $this->rdf_parser['xml_literal']['depth']--;
+
+ if (isset($this->rdf_parser['xml_literal']['declared_ns']))
+ foreach ($this->rdf_parser['xml_literal']['declared_ns'] as $prefix => $_depth)
+ {
+ if ($depth == $_depth)
+ unset($this->rdf_parser['xml_literal']['declared_ns'][$prefix]);
+ }
+}
+
+/**
+ * @param string $namespace_uri
+ * @param string $local_name
+ * @access private
+*/
+function _join_name_and_declare_prefix($namespace_uri, $local_name) {
+
+ $name = '';
+
+ if ($namespace_uri)
+ {
+ if (isset($this->rdf_parser['default_namespace'])
+ && $namespace_uri == $this->rdf_parser['default_namespace'])
+ {
+ $name .= $local_name;
+
+ if (!isset($this->rdf_parser['xml_literal']['declared_ns']['_DEFAULT_'])
+ && $namespace_uri != XML_NAMESPACE_URI)
+ {
+ $name .= ' xmlns=' . '\"' .$namespace_uri .'\"';
+
+ $this->rdf_parser['xml_literal']['declared_ns']['_DEFAULT_']
+ = $this->rdf_parser['xml_literal']['depth'];
+ }
+ }
+ else
+ {
+ $ns_prefix = $this->rdf_parser['namespaces'][$namespace_uri];
+ $name .= $ns_prefix .':' .$local_name;
+
+ if (!isset($this->rdf_parser['xml_literal']['declared_ns'][$ns_prefix])
+ && $namespace_uri != XML_NAMESPACE_URI)
+ {
+ $name .= " xmlns:$ns_prefix=" . '\"' .$namespace_uri .'\"';
+
+ $this->rdf_parser['xml_literal']['declared_ns'][$ns_prefix]
+ = $this->rdf_parser['xml_literal']['depth'];
+ }
+ }
+
+ }
+ else
+ $name .= $local_name;
+
+ return $name;
+
+}
+
+/**
+ * @access private
+*/
+function _end_collection() {
+
+ if (isset($this->rdf_parser['top']['collection']))
+ {
+
+ $subject = $this->rdf_parser['top']['collection']['first_blank_node_id'];
+
+ for ($i=0; isset($this->rdf_parser['top']['collection']['object_label'][$i]); $i++)
+ {
+
+ $this->_report_statement(
+ RDF_SUBJECT_TYPE_BNODE,
+ $subject,
+ RDF_NAMESPACE_URI.RDF_FIRST,
+ '',
+ $this->rdf_parser['top']['collection']['object_type'][$i],
+ $this->rdf_parser['top']['collection']['object_label'][$i],
+ '',
+ '',
+ '',
+ '',
+ '');
+
+ if (!isset($this->rdf_parser['top']['collection']['object_label'][$i+1]))
+ {
+ $obj_type_2 = RDF_OBJECT_TYPE_RESOURCE;
+ $object_2 = RDF_NAMESPACE_URI.RDF_NIL;
+ }
+ else
+ {
+ $obj_type_2= RDF_OBJECT_TYPE_BNODE;
+ $this->_generate_anonymous_uri($object_2);
+ }
+
+
+ $this->_report_statement(
+ RDF_SUBJECT_TYPE_BNODE,
+ $subject,
+ RDF_NAMESPACE_URI.RDF_REST,
+ '',
+ $obj_type_2,
+ $object_2,
+ '',
+ '',
+ '',
+ '',
+ '');
+
+ $subject = $object_2;
+ }
+ }
+}
+
+/**
+ * @param string $parser
+ * @param string $name
+ * @param string $attributes
+ * @access private
+*/
+function _start_element_handler($parser, $name, $attributes )
+{
+ $buffer='';
+
+ $namespace_uri='';
+ $local_name='';
+
+ $this->_push_element();
+
+
+ $this->_split_name(
+ $name,
+ $buffer,
+ $namespace_uri,
+ $local_name );
+
+ switch( $this->rdf_parser['top']['state'] )
+ {
+ case IN_TOP_LEVEL:
+ // set base_uri, if possible
+ foreach ($attributes as $key => $value) {
+ if($key == XML_NAMESPACE_URI . NAMESPACE_SEPARATOR_CHAR . 'base') {
+ $this->rdf_parser['base_uri'] = $value;
+ $this->rdf_parser['document_base_uri'] = $value;
+
+ $c = substr($value, strlen($value)-1 ,1);
+ if (!($c=='#' || $c==':' || $c=='/' || $c=="\\"))
+ $this->rdf_parser['normalized_base_uri'] = $value . '#';
+ else
+ $this->rdf_parser['normalized_base_uri'] = $value;
+
+ }
+ elseif ($key == XML_NAMESPACE_URI . NAMESPACE_SEPARATOR_CHAR .'lang')
+ $this->rdf_parser['document_xml_lang'] = $value;
+echo "";
+ }
+
+
+ if( RDF_NAMESPACE_URI.NAMESPACE_SEPARATOR_STRING.RDF_RDF == $name )
+ {
+ $this->rdf_parser['top']['state'] = IN_RDF;
+
+ break;
+ }
+ case IN_RDF:
+ $this->rdf_parser['top']['state'] = IN_DESCRIPTION;
+ $this->_handle_resource_element( $namespace_uri, $local_name, $attributes, '' );
+ break;
+ case IN_DESCRIPTION:
+ case IN_PROPERTY_PARSE_TYPE_RESOURCE:
+ $this->rdf_parser['top']['state'] = IN_PROPERTY_UNKNOWN_OBJECT;
+ $this->_handle_property_element( $namespace_uri, $local_name, $attributes );
+ break;
+ case IN_PROPERTY_PARSE_TYPE_COLLECTION:
+ $this->_handle_collection_element($namespace_uri, $local_name, $attributes);
+ break;
+ case IN_PROPERTY_UNKNOWN_OBJECT:
+ /* if we're in a property with an unknown object type and we encounter
+ an element, the object must be a resource, */
+ $this->rdf_parser['top']['data']='';
+ $this->rdf_parser['top']['parent']['state'] = IN_PROPERTY_RESOURCE;
+ $this->rdf_parser['top']['state'] = IN_DESCRIPTION;
+ $this->_handle_resource_element(
+ $namespace_uri,
+ $local_name,
+ $attributes,
+ $this->rdf_parser['top']['parent'] );
+ break;
+ case IN_PROPERTY_LITERAL:
+ $this->_report_warning( 'no markup allowed in literals' );
+ break;
+ case IN_PROPERTY_PARSE_TYPE_LITERAL:
+ $this->rdf_parser['top']['state'] = IN_XML;
+ /* fall through */
+ case IN_XML:
+ $this->rdf_parser['xml_literal']['depth']++;
+ $this->_handle_xml_start_element($namespace_uri, $local_name, $attributes);
+ break;
+ case IN_PROPERTY_RESOURCE:
+ $this->_report_warning(
+ 'only one element allowed inside a property element' );
+ break;
+ case IN_PROPERTY_EMPTY_RESOURCE:
+ $this->_report_warning(
+ 'no content allowed in property with rdf:resource, rdf:bagID, or property attributes' );
+ break;
+ case IN_UNKNOWN:
+ break;
+ }
+}
+
+/**
+ property elements with text only as content set the state to
+ IN_PROPERTY_LITERAL. as character data is received from expat,
+ it is saved in a buffer and reported when the end tag is
+ received.
+ * @access private
+*/
+function _end_literal_property()
+{
+ if(!isset($this->rdf_parser['top']['statement_id'])) {
+ $this->rdf_parser['top']['statement_id']='';
+ }
+ if(!isset($this->rdf_parser['top']['parent']['subject_type'])) {
+ $this->rdf_parser['top']['parent']['subject_type']='';
+ }
+ if(!isset($this->rdf_parser['top']['parent']['subject'])) {
+ $this->rdf_parser['top']['parent']['subject']='';
+ }
+ if(!isset($this->rdf_parser['top']['parent']['bag_id'])) {
+ $this->rdf_parser['top']['parent']['bag_id']='';
+ }
+ if(!isset($this->rdf_parser['top']['parent']['statements'])) {
+ $this->rdf_parser['top']['parent']['statements']=0;
+ }
+ if(!isset($this->rdf_parser['top']['predicate'])) {
+ $this->rdf_parser['top']['predicate']='';
+ }
+ if(!isset($this->rdf_parser['top']['datatype'])) {
+ $this->rdf_parser['top']['datatype']='';
+ }
+ if(!isset($this->rdf_parser['top']['ordinal'])) {
+ $this->rdf_parser['top']['ordinal']=0;
+ }
+ $this->_report_statement(
+ $this->rdf_parser['top']['parent']['subject_type'],
+ $this->rdf_parser['top']['parent']['subject'],
+ $this->rdf_parser['top']['predicate'],
+ $this->rdf_parser['top']['ordinal'],
+ RDF_OBJECT_TYPE_LITERAL,
+ $this->rdf_parser['top']['data'],
+ $this->rdf_parser['top']['xml_lang'],
+ $this->rdf_parser['top']['parent']['bag_id'],
+ $this->rdf_parser['top']['parent']['statements'],
+ $this->rdf_parser['top']['statement_id'],
+ $this->rdf_parser['top']['datatype']);
+
+}
+
+/**
+ * @param string $parser
+ * @param string $name
+ * @access private
+*/
+function _end_element_handler( $parser, $name )
+{
+ switch( $this->rdf_parser['top']['state'] )
+ {
+ case IN_TOP_LEVEL:
+ break;
+ case IN_XML:
+ $this->_handle_xml_end_element($name);
+ break;
+ case IN_PROPERTY_UNKNOWN_OBJECT:
+ case IN_PROPERTY_LITERAL:
+ $this->_end_literal_property( );
+ break;
+ case IN_PROPERTY_PARSE_TYPE_RESOURCE:
+ $this->_pop_element( );
+ break;
+ case IN_PROPERTY_PARSE_TYPE_LITERAL:
+// $search = array((0) => chr(10), (1) => chr(13), (2) => chr(9));
+// $replace = array((0) => '\n' , (1) => '\r' , (2) => '\t');
+// $this->rdf_parser["xml_literal"]["buffer"]
+// = str_replace($search, $replace, $this->rdf_parser["xml_literal"]["buffer"]);
+
+ $this->rdf_parser['top']['data'] = $this->rdf_parser['xml_literal']['buffer'];
+ $this->_end_literal_property();
+ $this->rdf_parser['xml_literal']['buffer'] = '';
+
+ break;
+ case IN_PROPERTY_PARSE_TYPE_COLLECTION:
+ $this->_end_collection();
+ break;
+ case IN_RDF:
+ case IN_DESCRIPTION:
+ case IN_PROPERTY_RESOURCE:
+ case IN_PROPERTY_EMPTY_RESOURCE:
+ case IN_UNKNOWN:
+ break;
+ }
+
+ $this->_pop_element();
+}
+
+/**
+ * @param string $parser
+ * @param string $s
+ * @access private
+*/
+function _character_data_handler( $parser,$s)
+{
+ $len=strlen($s);
+ switch( $this->rdf_parser['top']['state'] )
+ {
+ case IN_PROPERTY_LITERAL:
+ case IN_PROPERTY_UNKNOWN_OBJECT:
+ if( isset($this->rdf_parser['top']['data']) )
+ {
+ $n = strlen( $this->rdf_parser['top']['data'] );
+ $this->rdf_parser['top']['data'].= $s;
+
+ }
+ else
+ {
+ $this->rdf_parser['top']['data']=$s;
+ }
+
+ if( $this->rdf_parser['top']['state'] == IN_PROPERTY_UNKNOWN_OBJECT )
+ {
+ /* look for non-whitespace */
+ for( $i = 0; (( $i < $len ) && ( ereg(" |\n|\t",$s{ $i }) )); $i++ );
+ /* if we found non-whitespace, this is a literal */
+ if( $i < $len )
+ {
+ $this->rdf_parser['top']['state'] = IN_PROPERTY_LITERAL;
+ }
+ }
+
+ break;
+ case IN_TOP_LEVEL:
+ break;
+ case IN_PROPERTY_PARSE_TYPE_LITERAL:
+ case IN_XML:
+ $this->rdf_parser['xml_literal']['buffer'] .= $s;
+ break;
+ case IN_RDF:
+ case IN_DESCRIPTION:
+ case IN_PROPERTY_RESOURCE:
+ case IN_PROPERTY_EMPTY_RESOURCE:
+ case IN_PROPERTY_PARSE_TYPE_RESOURCE:
+ case IN_UNKNOWN:
+ break;
+ }
+}
+
+
+ /**
+ * Adds a new statement to the model
+ * This method is called by generateModel().
+ *
+ * @access private
+ * @param string &$user_data
+ * @param string $subject_type
+ * @param string $subject
+ * @param string $predicate
+ * @param string $ordinal
+ * @param string $object_type
+ * @param string $object
+ * @param string $xml_lang )
+ * @return object MemModel
+ */
+function add_statement_to_model(
+ &$user_data,
+ $subject_type,
+ $subject,
+ $predicate,
+ $ordinal,
+ $object_type,
+ $object,
+ $xml_lang,
+ $datatype )
+{
+
+ // ParseUnicode
+ if(UNIC_RDF){
+ $subject=$this->str2unicode_nfc($subject);
+ $predicate=$this->str2unicode_nfc($predicate);
+ $object=$this->str2unicode_nfc($object);
+ }
+
+ //create subject
+ if ($subject_type == RDF_SUBJECT_TYPE_BNODE)
+ $objsub = new BlankNode($subject);
+ else
+ $objsub = new Resource($subject);
+
+ // create predicate
+ $objpred = new Resource($predicate);
+
+ // create object
+ if (($object_type == RDF_OBJECT_TYPE_RESOURCE) || ($object_type == RDF_OBJECT_TYPE_BNODE)) {
+ if ($object_type == RDF_OBJECT_TYPE_BNODE)
+ $objobj = new BlankNode($object);
+ else
+ $objobj = new Resource($object);
+ } else {
+
+ $objobj = new Literal($object);
+ if ($datatype != '') {
+ $objobj->setDatatype($datatype);
+ }
+ elseif ($xml_lang !='') {
+ $objobj->setLanguage($xml_lang);
+ }
+ }
+
+ // create statement
+ $statement = new Statement($objsub, $objpred, $objobj);
+
+ // add statement to model
+ if(CREATE_MODEL_WITHOUT_DUPLICATES == TRUE){
+ $this->model->addWithoutDuplicates($statement);
+ }else
+ $this->model->add($statement);
+ }
+
+
+/* public functions */
+
+ /**
+ * Generates a new MemModel from a URI, a file or from memory.
+ * If you want to parse an RDF document, pass the URI or location in the filesystem
+ * of the RDF document. You can also pass RDF code direct to the function. If you pass
+ * RDF code directly to the parser and there is no xml:base included, you should set
+ * the base URI manually using the optional second parameter $rdfBaseURI.
+ * Make sure that here are proper namespace declarations in your input document.
+ *
+ * @access public
+ * @param string $base
+ * @param boolean $rdfBaseURI
+ * @return object MemModel
+ */
+function & generateModel($base,$rdfBaseURI = false, $model = false) {
+
+ // Check if $base is a URI or filename or a string containing RDF code.
+ if (substr(ltrim($base),0 ,1) != '<') {
+
+ // $base is URL or filename
+ $this->model = $model?$model:new MemModel($base);
+
+ $input = fopen($base,'r') or die("RDF Parser: Could not open File: $base. Stopped parsing.");
+ $this->rdf_parser_create( NULL );
+ $this->rdf_set_base($base);
+ $done=false;
+ while(!$done)
+ {
+ $buf = fread( $input, 512 );
+ $done = feof($input);
+
+ if ( ! $this->rdf_parse( $buf, feof($input) ) )
+ {
+ $err_code = xml_get_error_code( $this->rdf_get_xml_parser());
+ $line = xml_get_current_line_number($this->rdf_get_xml_parser() );
+ $errmsg = RDFAPI_ERROR . '(class: parser; method: generateModel): XML-parser-error ' . $err_code .' in Line ' . $line .' of input document.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+ }
+ /* close file. */
+ fclose( $input );
+
+ } else {
+ // $base is RDF string
+ $this->model = $model?$model:new MemModel($base);
+
+ $this->rdf_parser_create( NULL );
+
+ if ($rdfBaseURI!==false)
+ {
+ $this->rdf_set_base($rdfBaseURI);
+ } else
+ {
+ $this->rdf_set_base( NULL );
+ }
+
+ if ( ! $this->rdf_parse( $base, TRUE ) )
+ {
+ $err_code = xml_get_error_code( $this->rdf_get_xml_parser());
+ $line = xml_get_current_line_number($this->rdf_get_xml_parser() );
+ $errmsg = RDFAPI_ERROR . '(class: parser; method: generateModel): XML-parser-error ' . $err_code .' in Line ' . $line .' of input document.';
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+ }
+ // base_uri could have changed while parsing
+ $this->model->setBaseURI($this->rdf_parser['base_uri']);
+
+ if(isset($this->rdf_parser['namespaces'])){
+ $this->model->addParsedNamespaces($this->rdf_parser['namespaces']);
+ }
+
+ $this->rdf_parser_free();
+
+ return $this->model;
+
+}
+
+/**
+ * @param string $encoding
+
+ * @access private
+*/
+function rdf_parser_create( $encoding )
+{
+
+ $parser = xml_parser_create_ns( $encoding, NAMESPACE_SEPARATOR_CHAR );
+
+ xml_parser_set_option($parser,XML_OPTION_CASE_FOLDING,0);
+ $this->rdf_parser['xml_parser'] = $parser;
+
+ xml_set_object($this->rdf_parser['xml_parser'], $this);
+ xml_set_element_handler( $this->rdf_parser['xml_parser'], '_start_element_handler', '_end_element_handler' );
+ xml_set_character_data_handler( $this->rdf_parser['xml_parser'], '_character_data_handler' );
+ xml_set_start_namespace_decl_handler($this->rdf_parser['xml_parser'], '_start_ns_declaration_handler');
+
+ return $this->rdf_parser;
+}
+
+/**
+ * @param resource &$parser
+ * @param string $ns_prefix
+ * @param string $ns_uri
+ * @access private
+*/
+function _start_ns_declaration_handler(&$parser, $ns_prefix, $ns_uri)
+{
+ if (!$ns_prefix)
+ $this->rdf_parser['default_namespace'] = $ns_uri;
+ else
+ $this->rdf_parser['namespaces'][$ns_uri] = $ns_prefix;
+}
+
+
+/**
+ * @access private
+*/
+function rdf_parser_free( )
+{
+ $z=3;
+
+ $this->rdf_parser['base_uri']='';
+ $this->rdf_parser['document_base_uri'] = '';
+
+ unset( $this->rdf_parser );
+}
+
+/**
+ * @param string $s
+ * @param string $is_final
+ * @access private
+*/
+function rdf_parse( $s, $is_final )
+{
+ return XML_Parse( $this->rdf_parser['xml_parser'], $s, $is_final );
+}
+
+/**
+ * @access private
+*/
+function rdf_get_xml_parser()
+{
+ return ( $this->rdf_parser['xml_parser']);
+}
+
+/**
+ * @param string $base
+ * @access private
+*/
+function rdf_set_base($base )
+{
+
+ $this->rdf_parser['base_uri']=$base;
+
+ $c = substr($base, strlen($base)-1 ,1);
+ if (!($c=='#' || $c==':' || $c=='/' || $c=="\\"))
+ $this->rdf_parser['normalized_base_uri'] = $base . '#';
+ else
+ $this->rdf_parser['normalized_base_uri'] = $base;
+
+ return 0;
+}
+
+/**
+ * @access private
+*/
+function rdf_get_base()
+{
+ if ($this->rdf_parser['top']['element_base_uri'])
+ return $this->rdf_parser['top']['element_base_uri'];
+ else
+ return $this->rdf_parser['base_uri'];
+}
+
+
+} // end: rdf_parser
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/RdfSerializer.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/RdfSerializer.php.svn-base
new file mode 100755
index 00000000..45333d9a
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/RdfSerializer.php.svn-base
@@ -0,0 +1,719 @@
+, Boris Motik , Daniel Westphal , Leandro Mariano Lopez
+*
+* @package syntax
+* @access public
+*
+*/
+class RdfSerializer extends Object {
+
+ // configuration
+ var $use_entities;
+ var $use_attributes;
+ var $sort_model;
+ var $rdf_qnames;
+ var $use_xml_declaration;
+
+ // properties
+ var $m_defaultNamespaces = array();
+ var $m_namespaces = array();
+ var $m_nextAutomaticPrefixIndex;
+ var $m_out;
+ var $m_baseURI;
+ var $m_statements = array();
+ var $m_currentSubject;
+ var $m_rdfIDElementText;
+ var $m_rdfAboutElementText;
+ var $m_rdfResourceElementText;
+ var $m_groupTypeStatement;
+ var $m_attributeStatements = array();
+ var $m_contentStatements = array();
+ var $rdf_qname_prefix;
+
+ /**
+ * Constructor
+ *
+ * @access public
+ */
+ function RdfSerializer() {
+
+ // default serializer configuration
+ $this->use_entities = SER_USE_ENTITIES;
+ $this->use_attributes = SER_USE_ATTRIBUTES;
+ $this->sort_model = SER_SORT_MODEL;
+ $this->rdf_qnames = SER_RDF_QNAMES;
+ $this->use_xml_declaration = SER_XML_DECLARATION;
+
+ global $default_prefixes;
+ foreach($default_prefixes as $key => $value){
+ $this->addNamespacePrefix($key,$value);
+ }
+
+ require_once(RDFAPI_INCLUDE_DIR.PACKAGE_UTILITY);
+ }
+
+ /**
+ * Serializer congiguration: Sort Model
+ * Flag if the serializer should sort the model by subject before serializing.
+ * TRUE makes the RDF code more compact.
+ * TRUE is default. Default can be changed in constants.php.
+ *
+ * @param boolean
+ * @access public
+ */
+ function configSortModel($bool) {
+ $this->sort_model = $bool;
+ }
+
+ /**
+ * Serializer congiguration: Use Entities
+ * Flag if the serializer should use entities for URIs.
+ * TRUE makes the RDF code more compact.
+ * FALSE is default. Default can be changed in constants.php.
+ *
+ * @param boolean
+ * @access public
+ */
+ function configUseEntities($bool) {
+ $this->use_entities = $bool;
+ }
+
+ /**
+ * Serializer congiguration: Use Attributes
+ * Flag if the serializer should serialize triples as XML attributes where possible.
+ * TRUE makes the RDF code more compact.
+ * FALSE is default. Default can be changed in constants.php.
+ *
+ * @param boolean
+ * @access public
+ */
+ function configUseAttributes($bool) {
+ $this->use_attributes = $bool;
+ }
+
+ /**
+ * Serializer congiguration: Use Qnames
+ * Flag if the serializer should use qualified names for RDF reserved words.
+ * TRUE makes the RDF code more compact.
+ * TRUE is default. Default can be changed in constants.php.
+ *
+ * @param boolean
+ * @access public
+ */
+ function configUseQnames($bool) {
+ $this->rdf_qnames = $bool;
+ }
+
+ /**
+ * Serializer congiguration: Use XML Declaration
+ * Flag if the serializer should start documents with the xml declaration
+ * .
+ * TRUE is default. Default can be changed in constants.php.
+ *
+ * @param boolean
+ * @access public
+ */
+ function configUseXmlDeclaration($bool) {
+ $this->use_xml_declaration = $bool;
+ }
+
+
+ /**
+ * Adds a new prefix/namespace combination.
+ *
+ * @param String $prefix
+ * @param String $namespace
+ * @access public
+ */
+ function addNamespacePrefix($prefix, $namespace) {
+ $this->m_defaultNamespaces[$prefix] = $namespace;
+ }
+
+ /**
+ * Serializes a model to RDF syntax.
+ * RDF syntax can be changed by config_use_attributes($boolean), config_use_entities($boolean),
+ * config_sort_model($boolean).
+ * NOTE: There is only one default namespace allowed within an XML document.
+ * Therefore if SER_RDF_QNAMES in constants.php is set to FALSE and you pass
+ * another $xml_default_namespace as parameter, the model will be serialized
+ * as if SER_RDF_QNAMES were set to TRUE.
+ *
+ * @param object MemModel $model
+ * @param String $encoding
+ * @return string
+ * @access public
+ */
+ function & serialize(&$model, $xml_default_namespace = NULL, $encoding = DEFAULT_ENCODING) {
+
+ if ($xml_default_namespace) {
+
+ if ($xml_default_namespace == RDF_NAMESPACE_URI) {
+ $this->rdf_qnames = FALSE;
+ unset($this->m_defaultNamespaces[RDF_NAMESPACE_PREFIX]);
+ }
+ elseif ($xml_default_namespace == RDF_SCHEMA_URI) {
+ unset($this->m_defaultNamespaces[RDF_SCHEMA_PREFIX]);
+ }
+ elseif (!SER_RDF_QNAMES)
+ $this->rdf_qnames = TRUE;
+
+ $this->addNamespacePrefix(NULL, $xml_default_namespace);
+ }
+
+ //copy parsed namespaces
+ $nsps = array();
+ $nsps = $model->getParsedNamespaces();
+ foreach($this->m_defaultNamespaces as $prefix => $namespace){
+ if(!isset ($nsps[$namespace]))
+ $nsps[$namespace] = $prefix;
+ }
+
+ // define rdf prefix (qname or not)
+ if ($this->rdf_qnames){
+ if(isset($nsps[RDF_NAMESPACE_URI])){
+ $this->rdf_qname_prefix = $nsps[RDF_NAMESPACE_URI].':';
+ }else{
+ $this->rdf_qname_prefix = RDF_NAMESPACE_PREFIX . ':';
+ }
+
+ }else{
+ $this->rdf_qname_prefix = '';
+ }
+ // check if model is empty
+ if ($model->size() == 0) return "<". $this->rdf_qname_prefix . RDF_RDF ." xmlns:rdf='".RDF_NAMESPACE_URI."' />";
+
+ foreach($nsps as $ns => $pre){
+ $this->m_namespaces[$pre] = $ns;
+ }
+
+
+ // set base URI
+ if ($model->getBaseURI()==NULL)
+ $this->m_baseURI="opaque:uri";
+ else
+ $this->m_baseURI=$model->getBaseURI();
+
+
+ if ($this->sort_model) {
+ // sort the array of statements
+
+ foreach($model->triples as $key => $statement) {
+ $stmkey = $statement->subj->getURI() .
+ $statement->pred->getURI() .
+ (is_a($statement->obj,'Literal')?'"'.$statement->obj->getLabel().'"@'.$statement->obj->getLanguage().'^^'.$statement->obj->getDatatype():$statement->obj->getURI());
+ $this->m_statements[$stmkey] = $statement;
+ }
+ ksort($this->m_statements);
+
+ /*
+ // Sort using the PHP usort() function. Slower :-(
+ $this->m_statements = $model->triples;
+ usort($this->m_statements, "statementsorter");
+ */
+ } else {
+ $this->m_statements = $model->triples;
+ }
+ // collects namespaces
+ $this->m_nextAutomaticPrefixIndex=0;
+ $this->collectNamespaces($model);
+
+ // start writing the contents
+ $this->m_out="";
+ if ($this->use_xml_declaration)
+ $this->m_out .= '' . LINEFEED;
+ if (!HIDE_ADVERTISE)
+ $this->m_out.="".LINEFEED.LINEFEED ;
+
+ // write entitie declarations
+ if($this->use_entities) {
+ $this->m_out .= 'rdf_qname_prefix .
+ RDF_RDF.' [' . LINEFEED;
+ $this->writeEntityDeclarations();
+ $this->m_out .= LINEFEED . ']>' . LINEFEED;
+ }
+
+ // start the RDF text
+ $this->m_out .= '<' . $this->rdf_qname_prefix . RDF_RDF;
+
+ // write the xml:base
+ if ($model->getBaseURI() != NULL)
+ $this->m_out .= LINEFEED. INDENTATION .'xml:base="'.$model->getBaseURI().'"';
+
+ // write namespaces declarations
+ $this->writeNamespaceDeclarations();
+ $this->m_out .='>'. LINEFEED;
+
+ // write triples
+ $this->writeDescriptions();
+
+ $this->m_out .= LINEFEED;
+ $this->m_out .='' . $this->rdf_qname_prefix . RDF_RDF .'>';
+
+ $this->m_namespaces=null;
+ $this->m_statements=null;
+ $this->m_currentSubject=null;
+ $this->m_groupTypeStatement=null;
+ $this->m_attributeStatements=null;
+ $this->m_contentStatements=null;
+ $this->m_rdfResourceElementText=null;
+
+ return $this->m_out;
+ }
+
+ /**
+ * Serializes a model and saves it into a file.
+ * Returns FALSE if the model couldn't be saved to the file.
+ *
+ * @param object MemModel $model
+ * @param String $encoding
+ * @return boolean
+ * @access public
+ */
+ function saveAs(&$model, $filename, $encoding = DEFAULT_ENCODING) {
+ // serialize model
+ $RDF = $this->serialize($model, NULL, $encoding);
+
+ //write serialized model to file
+ $file_handle = @fopen($filename, 'w');
+ if ($file_handle) {
+ fwrite($file_handle, $RDF);
+ fclose($file_handle);
+ return TRUE;
+ } else {
+ return FALSE;
+ };
+ }
+
+ /**
+ * @access private
+ */
+ function writeEntityDeclarations() {
+ foreach($this->m_namespaces as $prefix => $namespace) {
+ $this->m_out .= INDENTATION . '".LINEFEED;
+ }
+ }
+
+ /**
+ * @access private
+ */
+ function writeNamespaceDeclarations() {
+ foreach($this->m_namespaces as $prefix => $namespace) {
+
+ if ($prefix == RDF_NAMESPACE_PREFIX && !$this->rdf_qnames) {
+
+ if($this->use_entities) {
+ $this->m_out .= LINEFEED . INDENTATION .XML_NAMESPACE_DECLARATION_PREFIX .
+ '="&' . $prefix . ';"';
+ } else {
+ $this->m_out .= LINEFEED . INDENTATION .XML_NAMESPACE_DECLARATION_PREFIX .
+ '="' . $namespace . '"';
+ }
+ } else {
+ if ($prefix == NULL)
+ $colon_prefix = $prefix;
+ else
+ $colon_prefix = ":" .$prefix;
+
+ if($this->use_entities) {
+ $this->m_out .= LINEFEED . INDENTATION .XML_NAMESPACE_DECLARATION_PREFIX
+ .$colon_prefix .'="&' . $prefix . ';"';
+ } else {
+ $this->m_out .= LINEFEED . INDENTATION .XML_NAMESPACE_DECLARATION_PREFIX
+ .$colon_prefix .'="' . $namespace . '"';
+ }
+ }
+ }
+ }
+
+ /**
+ * @access private
+ */
+ function writeDescriptions() {
+
+ $this->m_groupTypeStatement = NULL;
+ $this->m_attributeStatements = array();
+ $this->m_contentStatements = array();
+ $this->m_currentSubject = NULL;
+
+ foreach($this->m_statements as $key => $statement) {
+ $subject = $statement->getSubject();
+ $predicate = $statement->getPredicate();
+ $object = $statement->getobject();
+
+ // write Group and update current subject if nessesary
+ if ($this->m_currentSubject==NULL || !$this->m_currentSubject->equals($subject)) {
+ $this->writeGroup();
+ $this->m_currentSubject=$subject;
+ }
+
+ // classify the statement
+ if (($predicate->getURI() == RDF_NAMESPACE_URI.RDF_TYPE) && is_a($object, 'Resource') && !$this->m_groupTypeStatement) {
+ $this->writeGroup();
+ $this->m_groupTypeStatement = $statement;
+ }
+ elseif ($this->canAbbreviateValue($object) &&
+ $this->use_attributes &&
+ $this->checkForDoubleAttributes($predicate))
+ {
+ if (is_a($object, 'Literal')) {
+ if ($object->getDatatype() == NULL) {
+ $this->m_attributeStatements[] = $statement;
+ } else {
+ $this->m_contentStatements[] = $statement;
+ }
+ } else {
+ $this->m_attributeStatements[] = $statement;
+ }
+ } else {
+ $this->m_contentStatements[] = $statement;
+ }
+ }
+ $this->writeGroup();
+ }
+
+ /**
+ * @access private
+ */
+ function writeGroup() {
+ if ($this->m_currentSubject==NULL || ($this->m_groupTypeStatement==NULL && (count($this->m_attributeStatements)==0) && (count($this->m_contentStatements)==0)))
+ return;
+ if ($this->m_groupTypeStatement!=NULL)
+ $outerElementName=$this->getElementText($this->m_groupTypeStatement->obj->getURI());
+ else
+ $outerElementName = $this->rdf_qname_prefix . RDF_DESCRIPTION;
+ $this->m_out .= LINEFEED . '<';
+ $this->m_out .= $outerElementName;
+
+ $this->m_out .= ' ';
+
+
+ $this->writeSubjectURI($this->m_currentSubject);
+
+ // attribute Statements
+ if ($this->use_attributes)
+ $this->writeAttributeStatements();
+
+ if (count($this->m_contentStatements)==0)
+ $this->m_out .= '/>' . LINEFEED;
+ else {
+ $this->m_out .= '>' . LINEFEED;
+
+ // content statements
+ $this->writeContentStatements();
+
+ $this->m_out .= '';
+ $this->m_out .= $outerElementName;
+ $this->m_out .= '>'. LINEFEED;
+ }
+ $this->m_groupTypeStatement = NULL;
+ $this->m_attributeStatements = array();
+ $this->m_contentStatements = array();
+ }
+
+ /**
+ * @param object Node $predicate
+ * @access private
+ */
+ function checkForDoubleAttributes($predicate) {
+ foreach($this->m_attributeStatements as $key => $statement) {
+ if ($statement->pred->equals($predicate))
+ return FALSE;
+ }
+ return TRUE;
+ }
+
+ /**
+ * @param STRING $uri
+ * @access private
+ */
+ function relativizeURI($uri) {
+ $uri_namespace = RDFUtil::guessNamespace($uri);
+ if ($uri_namespace == $this->m_baseURI) {
+ return RDFUtil::guessName($uri);
+ } else {
+ return $uri;
+ }
+ }
+
+ /**
+ * @param object Node $subject_node
+ *
+ * @access private
+ */
+
+ function writeSubjectURI($subject_node) {
+ $currentSubjectURI = $subject_node->getURI();
+ $relativizedURI = $this->relativizeURI($currentSubjectURI);
+
+ // if submitted subject ist a blank node, use rdf:nodeID
+ if (is_a($this->m_currentSubject, 'BlankNode')) {
+ $this->m_out .= $this->rdf_qname_prefix . RDF_NODEID;
+ $this->m_out .= '="';
+ $this->m_out .= $relativizedURI;
+ } else {
+
+
+ if (!($relativizedURI == $currentSubjectURI)) {
+ $this->m_out .= $this->rdf_qname_prefix . RDF_ID;
+ $this->m_out .= '="';
+ $this->m_out .= $relativizedURI;
+ } else {
+ $this->m_out .= $this->rdf_qname_prefix . RDF_ABOUT;
+ $this->m_out .= '="';
+ $this->writeAbsoluteResourceReference($relativizedURI);
+ };
+ };
+ $this->m_out .= '"';
+ }
+
+ /**
+ * @access private
+ */
+ function writeAttributeStatements() {
+ foreach($this->m_attributeStatements as $key => $statement) {
+ $this->m_out .= LINEFEED;
+ $this->m_out .= INDENTATION;
+ $this->m_out .= $this->getElementText($statement->pred->getURI());
+ $this->m_out .= '=';
+ $value=$statement->obj->getLabel();
+ $quote=$this->getValueQuoteType($value);
+ $this->m_out .= $quote;
+ $this->m_out .= $value;
+ $this->m_out .= $quote;
+ }
+ }
+
+ /**
+ * @access private
+ */
+ function writeContentStatements() {
+ foreach($this->m_contentStatements as $key => $statement) {
+ $this->m_out .= INDENTATION;
+ $this->m_out .= '<';
+ $predicateElementText=$this->getElementText($statement->pred->getURI());
+ $this->m_out .= $predicateElementText;
+
+ if (is_a($statement->obj, 'Resource')) {
+ $this->writeResourceReference($statement->obj);
+ $this->m_out .= '/>' . LINEFEED;
+ } else {
+ if(is_a($statement->obj, 'Literal')) {
+ if ($statement->obj->getDatatype()!= NULL)
+ if ($statement->obj->getDatatype()== RDF_NAMESPACE_URI . RDF_XMLLITERAL) {
+ $this->m_out .= ' ' . RDF_NAMESPACE_PREFIX . ':' . RDF_PARSE_TYPE . '="' . RDF_PARSE_TYPE_LITERAL . '"';
+ } else {
+ $this->m_out .= ' ' . RDF_NAMESPACE_PREFIX . ':' . RDF_DATATYPE . '="' . $statement->obj->getDatatype() . '"';
+ }
+ if ($statement->obj->getLanguage()!= NULL)
+ $this->m_out .= ' ' . XML_NAMESPACE_PREFIX . ':' . XML_LANG . '="' . $statement->obj->getLanguage() . '"';
+ };
+ $this->m_out .= '>';
+ if ($statement->obj->getDatatype()== RDF_NAMESPACE_URI . RDF_XMLLITERAL) {
+ $this->m_out .= $statement->obj->getLabel();
+ } else {
+ $this->writeTextValue($statement->obj->getLabel());
+ }
+ $this->m_out .= '';
+ $this->m_out .= $predicateElementText;
+ $this->m_out .= '>' . LINEFEED;
+ }
+ }
+ }
+
+ /**
+ * @param Object $object_node
+ * @access private
+ */
+ function writeResourceReference($object_node) {
+ $rebaseURI = $object_node->getURI();
+ $this->m_out .= ' ';
+ if (is_a($object_node, 'BlankNode')) {
+ $this->m_out .= $this->rdf_qname_prefix . RDF_NODEID;
+ } else {
+ $this->m_out .= $this->rdf_qname_prefix . RDF_RESOURCE;
+ };
+
+ $this->m_out .= '="';
+ $relativizedURI = $this->relativizeURI($rebaseURI);
+ if (!($relativizedURI == $rebaseURI))
+ if (!is_a($object_node, 'BlankNode'))
+ $this->m_out .= '#' . $relativizedURI;
+ else
+ $this->m_out .= $relativizedURI;
+ else
+ $this->writeAbsoluteResourceReference($rebaseURI);
+ $this->m_out .= '"';
+ }
+
+
+ /**
+ * @param String $rebaseURI
+ * @access private
+ */
+ function writeAbsoluteResourceReference($rebaseURI) {
+ $namespace=RDFUtil::guessNamespace($rebaseURI);
+ $localName=RDFUtil::guessName($rebaseURI);
+ $text=$rebaseURI;
+ if ($namespace!='' and $this->use_entities) {
+ $prefix= array_search($namespace, $this->m_namespaces);
+ $text='&'.$prefix.';'.$localName;
+ } else $text = RDFUtil::escapeValue($text);
+ $this->m_out .= $text;
+ }
+
+ /**
+ * @param STRING $textValue
+ * @access private
+ */
+ function writeTextValue($textValue) {
+ if ($this->getValueQuoteType($textValue)==USE_CDATA)
+ $this->writeEscapedCDATA($textValue);
+ else
+ $this->m_out .= $textValue;
+ }
+
+ /**
+ * @param STRING $textValue
+ * @access private
+ */
+ function writeEscapedCDATA($textValue) {
+ $this->m_out .= '';
+ }
+
+ /**
+ * @param STRING $textValue
+ * @access private
+ */
+ function getValueQuoteType($textValue) {
+ $quote=USE_ANY_QUOTE;
+ $hasBreaks=FALSE;
+ $whiteSpaceOnly=TRUE;
+ for ($i=0; $i' || $c=='&')
+ return USE_CDATA;
+ if ($c==LINEFEED)
+ $hasBreaks=TRUE;
+ if ($c=='"' || $c=="\'") {
+ if ($quote==USE_ANY_QUOTE)
+ $quote=($c=='"') ? "\'" : "\"";
+ elseif ($c==$quote)
+ return USE_CDATA;
+ }
+ if (!($c == ' '))
+ $whiteSpaceOnly = FALSE;
+ }
+ if ($whiteSpaceOnly || $hasBreaks)
+ return USE_CDATA;
+ return $quote==USE_ANY_QUOTE ? '"' : $quote;
+ }
+
+ /**
+ * @param object Node $node
+ * @access private
+ */
+ function canAbbreviateValue($node) {
+ if (is_a($node, 'Literal')) {
+ $value= $node->getLabel();
+ if (strlen($value)getValueQuoteType($value);
+ return $c=='"' || $c=='\'';
+ }
+ }
+ return FALSE;
+ }
+
+ /**
+ * @param STRING $elementName
+ * @access private
+ */
+ function getElementText($elementName) {
+ $namespace=RDFUtil::guessNamespace($elementName);
+ $localName=RDFUtil::guessName($elementName);
+ if ($namespace=="")
+ return $localName;
+ $prefix=array_search($namespace, $this->m_namespaces);
+
+ if ($prefix===FALSE) {
+ $errmsg = RDFAPI_ERROR . "(class: Serializer; method: getElementText): Prefix for element '" . $elementName . "' cannot be found.";
+ trigger_error($errmsg, E_USER_ERROR);
+ }
+ switch ($prefix) {
+ case RDF_NAMESPACE_PREFIX:
+ return $this->rdf_qname_prefix . $localName;
+ case NULL:
+ return $localName;
+ default:
+ return $prefix. ":" .$localName;
+ }
+ }
+
+ /**
+ * @param object MemModel $model
+ * @access private
+ */
+ function collectNamespaces($model) {
+ foreach($model->triples as $key => $value) {
+
+ if ($this->use_entities) {
+ $this->collectNamespace($value->getSubject());
+ if(!is_a($value->getObject(), 'Literal'))
+ $this->collectNamespace($value->getObject());
+
+ } else {
+
+ if ($value->pred->getURI() == RDF_NAMESPACE_URI.RDF_TYPE)
+ $this->collectNamespace($value->getObject());
+ elseif
+ (($value->pred->getURI() == RDF_NAMESPACE_URI.RDFS_SUBCLASSOF) ||
+ ($value->pred->getURI() == RDF_NAMESPACE_URI.RDFS_SUBPROPERTYOF)) {
+ $this->collectNamespace($value->getSubject());
+ $this->collectNamespace($value->getObject());
+ }
+ }
+
+ $this->collectNamespace($value->getPredicate());
+
+ }
+ }
+
+ /**
+ * @param object Resource $resource
+ * @access private
+ */
+ function collectNamespace($resource) {
+
+ $namespace=RDFUtil::getNamespace($resource);
+ if (!in_array($namespace, $this->m_namespaces)&&$namespace!='') {
+ $prefix = array_search( $namespace, $this->m_defaultNamespaces);
+ if ($prefix===FALSE)
+ $prefix=$this->getNextNamespacePrefix();
+ $this->m_namespaces[$prefix] = $namespace;
+ }
+ }
+
+ /**
+ * @access private
+ */
+ function getNextNamespacePrefix() {
+ $this->m_nextAutomaticPrefixIndex++;
+ return GENERAL_PREFIX_BASE . $this->m_nextAutomaticPrefixIndex;
+ }
+
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/RssParser.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/RssParser.php.svn-base
new file mode 100755
index 00000000..bae1f2da
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/RssParser.php.svn-base
@@ -0,0 +1,245 @@
+. MagpieRSS is
+ * compatible with RSS 0.9 through RSS 1.0. Also parses RSS 1.0's modules, RSS 2.0, and Atom (with a few exceptions).
+ * Magpie is distributed under the GPL license. (http://magpierss.sourceforge.net/)
+ *
+ *
+ *
+ * @author Tobias Gauß
+ * @version $Id$
+ * @package syntax
+ * @access public
+ **/
+
+class RssParser extends Object {
+ var $type;
+
+ /**
+ * Main function
+ *
+ * @param $url location of the document
+ * @return parsed model
+ */
+ function generateModel($url){
+ $rss = null;
+ if(substr($url,0,7)=="http://"){
+ $rss = fetch_rss($url);
+ }else{
+ $string = file_get_contents($url);
+ $rss = new MagpieRSS($string);
+ }
+
+ $model = ModelFactory::getMemModel();
+ $bn = new Resource($url);
+
+ $this->type = $rss->feed_type;
+ $version = $rss->feed_version;
+
+ $nmsp = null;
+ if($version == "1.0")
+ $nmsp = "http://purl.org/rss/1.0/";
+ if($version == "0.91")
+ $nmsp = "http://my.netscape.com/publish/formats/rss-spec-0.91.html#";
+ if($version == "2.0")
+ $nmsp = "http://purl.org/rss/1.0/";
+ if($this->type == "Atom")
+ $nmsp = "http://www.w3.org/2005/Atom";
+
+ if($this->type == "Atom")
+ $this->channel($model,$rss,$bn,$nmsp,"feed");
+ else
+ $this->channel($model,$rss,$bn,$nmsp,"channel");
+ $this->image($model,$rss,$bn,$nmsp);
+ $this->items($model,$rss,$bn,$nmsp);
+ $model->addNamespace("rdf","http://www.w3.org/1999/02/22-rdf-syntax-ns#");
+ if($nmsp!= null)
+ $model->addNamespace($this->type,$nmsp);
+ return $model;
+ }
+
+ /**
+ * Parses the image if there is one.
+ *
+ * @param $model the model
+ * @param $rss the magpie parser object
+ * @param $bnOrg the node which represents the channel
+ * @param $nmsp the
+ */
+ function image(&$model,&$rss,&$bnOrg,&$nmsp){
+ if(count($rss->image)>0){
+ if(isset($rss->image['about'])){
+ $bn = new Resource($rss->image['about']);
+ }else if(isset($rss->image['url'])){
+ $bn = new Resource($rss->image['url']);
+ }else{
+ $bn = new BlankNode("image");
+ }
+ $model->add(new Statement($bnOrg,new Resource($nmsp."image"),$bn));
+ $model->add(new Statement($bn,new Resource("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"),new Resource($nmsp."image")));
+ }
+ foreach($rss->image as $key => $value){
+ $statement = null;
+ switch($key){
+ case "dc":
+ $this->dc($bn,$model,$value);
+ break;
+ case "sy":
+ $this->sy($bn,$model,$value);
+ break;
+ default :
+ $statement = new Statement($bn,new Resource($nmsp.$key), new Literal($value));
+ break;
+ }
+ if($statement != null){
+ $model->add($statement);
+ }
+ }
+
+ }
+
+ /**
+ * Parses the rss items/ atom entries.
+ *
+ * @param $model the model
+ * @param $rss the magpie parser object
+ * @param $bnOrg the node which represents the channel
+ * @param $nmsp the
+ */
+ function items(&$model,&$rss,&$bnOrg,&$nmsp){
+ $items = new BlankNode("items");
+ $model->add(new Statement($bnOrg,new Resource($nmsp."items"),$items));
+ $model->add(new Statement($items,new Resource("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"),new Resource("http://www.w3.org/1999/02/22-rdf-syntax-ns#Seq")));
+ $i = 1;
+ foreach($rss->items as $outerKey => $outerValue){
+ if(isset($outerValue['about'])){
+ $bn = new Resource($outerValue['about']);
+ }else if(isset($outerValue['guid'])){
+ $bn = new Resource($outerValue['guid']);
+ }else if(isset($outerValue['id'])){
+ $bn = new Resource($outerValue['id']);
+ }else{
+ $bn = new Blanknode("item".$i);
+ }
+ $model->add(new Statement($items,new Resource("http://www.w3.org/1999/02/22-rdf-syntax-ns#_".$i),$bn));
+ if($this->type == "Atom"){
+ $model->add(new Statement($bn,new Resource("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"),new Resource("http://www.w3.org/2005/Atomentry")));
+ }else{
+ $model->add(new Statement($bn,new Resource("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"),new Resource("http://purl.org/rss/1.0/item")));
+ }
+ foreach($outerValue as $key => $value){
+ $statement = null;
+ switch($key){
+ case "about":
+ break;
+ case "guid":
+ break;
+ case "dc":
+ $this->dc($bn,$model,$value);
+ break;
+ case "sy":
+ $this->sy($bn,$model,$value);
+ break;
+ default :
+ if($value != null)
+ $statement = new Statement($bn,new Resource($nmsp.$key), new Literal($value));
+ break;
+ }
+ if($statement != null){
+ $model->add($statement);
+ }
+ }
+ $i++;
+ }
+
+ }
+
+ /**
+ * Adds the dc namespace.
+ *
+ * @param $node the node
+ * @param $model the model
+ * @param $dc Array which contains the dc objects
+ */
+ function dc(&$node,&$model,&$dc){
+ $model->addNamespace("dc","http://purl.org/dc/elements/1.1/");
+ foreach($dc as $key => $value){
+ $statement = null;
+ $statement = new Statement($node,new Resource("http://purl.org/dc/elements/1.1/".$key), new Literal($value));
+ if($statement != null){
+ $model->add($statement);
+ }
+ }
+ }
+
+ /**
+ * Adds the sy namespace.
+ *
+ * @param $node the node
+ * @param $model the model
+ * @param $sy Array which contains the sy objects
+ */
+ function sy(&$node,&$model,&$sy){
+ $model->addNamespace("sy","http://purl.org/rss/1.0/modules/syndication/");
+ foreach($sy as $key => $value){
+ $statement = null;
+ $statement = new Statement($node,new Resource("http://purl.org/rss/1.0/modules/syndication/".$key), new Literal($value));
+ if($statement != null){
+ $model->add($statement);
+ }
+ }
+
+ }
+
+
+ /**
+ * Parses the rss channel/ atom feed.
+ *
+ * @param $model the model
+ * @param $rss the magpie parser object
+ * @param $node the node which represents the channel
+ * @param $nmsp the
+ */
+ function channel(&$model,&$rss,&$node,&$nmsp,$type){
+ // Channel
+ $statement = new Statement($node,new Resource('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'), new Resource($nmsp.$type));
+ $model->add($statement);
+
+ foreach($rss->channel as $key => $value){
+ $statement = null;
+ switch($key){
+ case "dc":
+ $this->dc($node,$model,$value);
+ break;
+ case "sy":
+ $this->sy($node,$model,$value);
+ break;
+ case "items":
+ break;
+ case "tagline":
+ break;
+ case "items_seq":
+ break;
+ default :
+ $statement = new Statement($node,new Resource($nmsp.$key), new Literal($value));
+ break;
+ }
+ if($statement != null){
+ $model->add($statement);
+ }
+ }
+}
+
+
+
+} //end: RssParser
+
+?>
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/SparqlResultParser.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/SparqlResultParser.php.svn-base
new file mode 100755
index 00000000..0b1c1e69
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/SparqlResultParser.php.svn-base
@@ -0,0 +1,164 @@
+
+*
+* @package sparql
+*/
+
+class SparqlResultParser extends Object {
+
+
+ var $arrOutput = array();
+ var $resParser;
+ var $strXmlData;
+ var $counter = -1;
+ var $mode = -1;
+ var $varname;
+ var $dtype;
+ var $lang;
+ var $varlist;
+ var $bncounter = 0;
+ var $current_literal;
+
+
+/**
+* Main function of SparqlResultParser
+*
+* @param String $strInputXML input document.
+*/
+ function parse($strInputXML) {
+
+ $this->resParser = xml_parser_create ();
+
+ xml_set_object($this->resParser,$this);
+ xml_set_element_handler($this->resParser, "tagOpen", "tagClosed");
+
+ xml_set_character_data_handler($this->resParser, "tagData");
+
+ $this->strXmlData = xml_parse($this->resParser,$strInputXML );
+ if(!$this->strXmlData) {
+ echo "unable to parse result
".
+ "server returned:
"
+ .$strInputXML;
+
+ return "false";
+
+ }
+
+ xml_parser_free($this->resParser);
+
+ return $this->arrOutput;
+ }
+
+// private parser functions from here //
+ function tagOpen($parser, $name, $attrs) {
+ // $tag=array("name"=>$name,"attrs"=>$attrs);
+ // array_push($this->arrOutput,$tag);
+ if(strtolower($name)=="variable"){
+ if(isset($attrs['name']))
+ $this->varlist[]=$attrs['name'];
+ if(isset($attrs['NAME']))
+ $this->varlist[]=$attrs['NAME'];
+ }
+
+ if(strtolower($name)=="result"){
+ $this->counter++;
+ if($this->counter > -1){
+ foreach($this->varlist as $value){
+ if(!isset($this->arrOutput[$this->counter][$value]))
+ $this->arrOutput[$this->counter]["?".$value]='';
+ }
+ }
+
+ }
+ if(strtolower($name)=="boolean"){
+ $this->counter++;
+ $this->mode = 3;
+ }
+ if(strtolower($name)=="binding"){
+ $this->varname = null;
+ $this->dtype = null;
+ $this->lang = null;
+
+ if(isset($attrs['name'])){
+ $this->varname = "?".$attrs['name'];
+ }else{
+ $this->varname = "?".$attrs['NAME'];
+ }
+ }
+ if(strtolower($name)=="uri"){
+ $this->mode = 0;
+ }
+ if(strtolower($name)=="literal"){
+ $this->mode = 1;
+ $this->current_literal = "";
+ if(isset($attrs['datatype'])){
+ $this->dtype = $attrs['datatype'];
+ }else if(isset($attrs['DATATYPE'])){
+ $this->dtype = $attrs['DATATYPE'];
+ }
+ if(isset($attrs['xml:lang'])){
+ $this->lang = $attrs['datatype'];
+ }else if(isset($attrs['XML:lang'])){
+ $this->lang = $attrs['XML:lang'];
+ }else if(isset($attrs['XML:LANG'])){
+ $this->lang = $attrs['XML:LANG'];
+ }else if(isset($attrs['xml:LANG'])){
+ $this->lang = $attrs['xml:LANG'];
+ }
+ }
+ if(strtolower($name)=="bnode"){
+ $this->mode = 2;
+ }
+ }
+
+ function tagData($parser, $tagData) {
+ switch($this->mode){
+ case 0 :
+ $this->arrOutput[$this->counter][$this->varname] = new Resource($tagData);
+ $this->mode = -1;
+ break;
+ case 1:
+ $this->current_literal .= $tagData;
+ break;
+ case 2:
+ if($tagData=="/"){
+ $bn = "bNode".$this->bncounter;
+ $this->bncounter++;
+ }else{
+ $bn = $tagData;
+ }
+ $this->arrOutput[$this->counter][$this->varname] = new BlankNode($bn);
+ $this->mode = -1;
+ break;
+ case 3:
+ $this->arrOutput = $tagData;
+ $this->mode = -1;
+ break;
+
+ }
+
+ }
+
+ function tagClosed($parser, $name) {
+ if ($this->mode == 1) {
+ $lit = new Literal($this->current_literal);
+ if($this->lang)
+ $lit->setLanguage($this->lang);
+ if($this->dtype)
+ $lit->setDatatype($this->dtype);
+ $this->arrOutput[$this->counter][$this->varname] = $lit ;
+ $this->mode = -1;
+ }
+ }
+}
+
+
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/SyntaxGRDDL.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/SyntaxGRDDL.php.svn-base
new file mode 100755
index 00000000..eef9cea9
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/SyntaxGRDDL.php.svn-base
@@ -0,0 +1,16 @@
+
+//
+// ----------------------------------------------------------------------------------
+
+
+// Include Syntax classes
+require_once( RDFAPI_INCLUDE_DIR . 'syntax/GRDDLParser.php' );
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/SyntaxJSON.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/SyntaxJSON.php.svn-base
new file mode 100755
index 00000000..02550074
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/SyntaxJSON.php.svn-base
@@ -0,0 +1,6 @@
+
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/SyntaxN3.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/SyntaxN3.php.svn-base
new file mode 100755
index 00000000..77f119f1
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/SyntaxN3.php.svn-base
@@ -0,0 +1,18 @@
+
+//
+// ----------------------------------------------------------------------------------
+
+
+// Include Syntax classes
+require_once( RDFAPI_INCLUDE_DIR . 'syntax/N3Parser.php' );
+require_once( RDFAPI_INCLUDE_DIR . 'syntax/N3Serializer.php' );
+require_once( RDFAPI_INCLUDE_DIR . 'syntax/NTripleSerializer.php' );
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/SyntaxRDF.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/SyntaxRDF.php.svn-base
new file mode 100755
index 00000000..dc77a60f
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/SyntaxRDF.php.svn-base
@@ -0,0 +1,17 @@
+
+//
+// ----------------------------------------------------------------------------------
+
+
+// Include Syntax classes
+require_once( RDFAPI_INCLUDE_DIR . 'syntax/RdfParser.php' );
+require_once( RDFAPI_INCLUDE_DIR . 'syntax/RdfSerializer.php' );
+require_once( RDFAPI_INCLUDE_DIR . 'syntax/NTripleSerializer.php' );
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/SyntaxRSS.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/SyntaxRSS.php.svn-base
new file mode 100755
index 00000000..6b557391
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/SyntaxRSS.php.svn-base
@@ -0,0 +1,17 @@
+
+//
+// ----------------------------------------------------------------------------------
+
+
+// Include Syntax classes
+require_once( RDFAPI_INCLUDE_DIR . 'util/magpie/rss_fetch.inc' );
+require_once( RDFAPI_INCLUDE_DIR . 'util/magpie/rss_parse.inc' );
+require_once( RDFAPI_INCLUDE_DIR . 'syntax/RssParser.php' );
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/SyntaxSparqlRes.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/SyntaxSparqlRes.php.svn-base
new file mode 100755
index 00000000..16fb6e60
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/SyntaxSparqlRes.php.svn-base
@@ -0,0 +1,15 @@
+
+//
+// ----------------------------------------------------------------------------------
+
+
+// Include Syntax classes
+require_once( RDFAPI_INCLUDE_DIR . 'syntax/SparqlResultParser.php' );
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/TriXParser.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/TriXParser.php.svn-base
new file mode 100755
index 00000000..e22b3582
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/TriXParser.php.svn-base
@@ -0,0 +1,135 @@
+ V5)
+* Currently, it doesn't support any namespaces and has problems with typed literals.
+* So this parser only works with TRIX documents where the default namespace is the TRIX namespace.
+*
+* @version $Id$
+* @author Daniel Westphal (http://www.d-westphal.de)
+*
+* @package dataset
+* @access public
+**/
+class TriXParser
+{
+ /**
+ * Reference to the graphSet
+ *
+ * @var GraphSet
+ * @access private
+ */
+ var $graphSet;
+
+ /**
+ * Constructor
+ * Needs a reference to a graphSet
+ *
+ * @param GraphSet
+ * @access public
+ */
+ function TriXParser(&$graphSet)
+ {
+ $this->graphSet=&$graphSet;
+ }
+
+ /**
+ * Parse an XML string
+ *
+ * @param string
+ * @access public
+ */
+ function parseString($string)
+ {
+ $this->_populateGraphSet(simplexml_load_string($string));
+ }
+
+ /**
+ * Parse from a file
+ *
+ * @param string
+ * @access public
+ */
+ function parseFile($pathToFile)
+ {
+ $this->_populateGraphSet(simplexml_load_file($pathToFile));
+ }
+
+ /**
+ * Populates the graphSet with namedGraphs and triples.
+ *
+ * @param object simpleXMLModel $xmlModel
+ * @access private
+ */
+ function _populateGraphSet(&$xmlModel)
+ {
+ $defaultGraphOccurred=false;
+
+ foreach ($xmlModel->graph as $graph)
+ {
+ if (isset($graph->uri))
+ {
+ $graphName=(string)$graph->uri;
+ $namedGraph=& $this->graphSet->getNamedGraph($graphName);
+ if ($namedGraph ==null)
+ $namedGraph=& $this->graphSet->createGraph($graphName);
+ } else
+ {
+ if ($defaultGraphOccurred)
+ trigger_error('Only one unnamed Graph per file allowed', E_USER_ERROR);
+
+ $namedGraph=& $this->graphSet->getDefaultGraph();
+ $defaultGraphOccurred=true;
+ }
+
+ foreach ($graph->triple as $triple)
+ {
+ $tripleCount=0;
+ $tripleArray=array();
+ foreach ($triple->children() as $tag => $value)
+ {
+ $tripleArray[$tripleCount++]=$this->_element2Resource((string)$tag,$value);
+ };
+ $namedGraph->add(new Statement($tripleArray[0],$tripleArray[1],$tripleArray[2]));
+ };
+ };
+ }
+
+ /**
+ * return a mathing resource tyoe
+ *
+ * @param string
+ * @param object simpleXMLNode $value
+ * @access private
+ */
+ function _element2Resource($tag,$value)
+ {
+ switch ($tag)
+ {
+ case 'uri':
+ return new Resource((string)$value);
+ break;
+
+ case 'id':
+ return new BlankNode((string)$value);
+ break;
+
+ case 'typedLiteral':
+ $literal=new Literal((string)$value);
+ $literal->setDatatype((string)$value['datatype']);
+ return $literal;
+ break;
+
+ case 'plainLiteral':
+ $literal=new Literal((string)$value);
+ if(isset($value['xml:lang']))
+ $literal->setLanguage((string)$value['xml:lang']);
+ return $literal;
+ break;
+ }
+ }
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/TriXSerializer.php.svn-base b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/TriXSerializer.php.svn-base
new file mode 100755
index 00000000..7bb5de77
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/.svn/text-base/TriXSerializer.php.svn-base
@@ -0,0 +1,151 @@
+graphSet=&$graphSet;
+ }
+
+ /**
+ * Serialize the dataset to a TriX string
+ *
+ * @return string
+ * @access public
+ */
+ function & serializeToString()
+ {
+ return $this->_serialize();
+ }
+
+ /**
+ * Serialize the dataset to a TriX string and save in file
+ *
+ * @param string
+ * @access public
+ */
+ function serializeToFile($fileName)
+ {
+ $serializedString=&$this->_serialize();
+ $handle = fopen($fileName, 'w');
+ fwrite($handle, $serializedString);
+ fclose($handle);
+ }
+
+
+ /**
+ * Serialize the dataset to a TriX string
+ *
+ * @return string
+ * @access private
+ */
+ function & _serialize()
+ {
+ //Trix header
+ $serializedString=
+ ''.
+ '';
+
+ //serialize defaultGraph if it is not empty
+ $defaultGraph=& $this->graphSet->getDefaultGraph();
+ if ($defaultGraph->isEmpty()===false)
+ {
+ $serializedString.='';
+ for($iterator = $this->graphSet->findInDefaultGraph(null,null,null); $iterator->valid(); $iterator->next())
+ {
+ $serializedString.='';
+
+ $statement=$iterator->current();
+
+ $serializedString.=$this->_node2string($statement->getSubject());
+ $serializedString.=$this->_node2string($statement->getPredicate());
+ $serializedString.=$this->_node2string($statement->getObject());
+
+ $serializedString.='';
+ };
+ $serializedString.='';
+ }
+
+ //serialize namedGraphs
+ foreach ($this->graphSet->listGraphNames() as $graphName)
+ {
+ $serializedString.='';
+ $serializedString.=''.$graphName.'';
+ for($iterator = $this->graphSet->findInNamedGraphs(new Resource($graphName),null,null,null); $iterator->valid(); $iterator->next())
+ {
+ $serializedString.='';
+
+ $statement=$iterator->current();
+
+ $serializedString.=$this->_node2string($statement->getSubject());
+ $serializedString.=$this->_node2string($statement->getPredicate());
+ $serializedString.=$this->_node2string($statement->getObject());
+
+ $serializedString.='';
+ };
+ $serializedString.='';
+ };
+ //TriX footer
+ $serializedString.='';
+ return $serializedString;
+ }
+
+ /**
+ * Serialize node to a TriX string
+ *
+ * @param Node
+ * @return string
+ * @access private
+ */
+ function _node2string($node)
+ {
+ switch ($node)
+ {
+ case (is_a($node,'BlankNode')):
+ return (''.$node->getLabel().'');
+
+ case (is_a($node,'Resource')):
+ return (''.$node->getLabel().'');
+
+ case (is_a($node,'Literal')):
+
+ if ($node->dtype!=null)
+ return (''.$node->getLabel().'');
+
+ if ($node->lang!=null)
+ return (''.$node->getLabel().'');
+
+ return (''.htmlentities($node->getLabel()).'');
+ }
+ }
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/GRDDLParser.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/GRDDLParser.php
new file mode 100755
index 00000000..7a490dd7
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/GRDDLParser.php
@@ -0,0 +1,120 @@
+,
+ *
+ * @package syntax
+ * @access public
+ *
+ */
+class GRDDLParser extends Object{
+
+
+ /**
+ * Document link
+ *
+ *
+ * @var String
+ * @access private
+ */
+ var $doclink;
+
+
+ /**
+ * Stylesheet link
+ *
+ *
+ * @var String[]
+ * @access private
+ */
+ var $stylelinks;
+
+
+ /**
+ * DomDocument
+ *
+ * @var DomDocument
+ * @access private
+ */
+ var $domdoc;
+
+
+ /**
+ * generates a MemModel and creates the DomDocument.
+ *
+ * @param String $doc
+ * @access public
+ * @return MemModel $model
+ */
+ function generateModel($doc){
+ $model = new MemModel();
+ $this->doclink=$doc;
+ $this->domdoc = new DomDocument;
+ $this->domdoc->load($doc);
+ $this->_getStyles();
+ $model = $this->_generateRDF();
+ return $model;
+ }
+
+
+ /**
+ * gets the used xsl stylesheets.
+ *
+ * @access private
+ */
+ function _getStyles(){
+ $link=$this->domdoc->getElementsByTagName('link');
+ $i=0;
+ while($link->item($i)!=''){
+ $item = $link->item($i);
+ if($item->getAttributeNode('rel')->value=='transformation'){
+ $temp = $item->getAttributeNode('href')->value;
+ if(substr($temp,0,1)=='/'){
+ $pos = strrpos($this->doclink,'/');
+ $part = substr($this->doclink,0,$pos);
+ $this->stylelink[]=$part.$temp;
+ }else{
+ $this->stylelink[]=$temp;
+ }
+ }
+ $i++;
+ }
+ }
+
+ /*
+ * uses the PHP build in xslt processor to
+ * generate the RDF statements and uses the
+ * RDF- Parser to generate the model
+ *
+ * @access private
+ * @return MemModel $model
+ */
+ function _generateRDF(){
+ $model=new MemModel();
+ $model->setBaseURI($this->doclink);
+ $proc = new xsltprocessor;
+ include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_RDF);
+ $pars=new RdfParser();
+ foreach($this->stylelink as $key => $value){
+ $xsl = new DomDocument;
+ $xsl->load($value);
+ $proc->importStyleSheet($xsl);
+ $model->addModel($pars->generateModel($proc->transformToXML($this->domdoc),$this->doclink));
+ }
+ return $model;
+ }
+
+
+
+}
+?>
\ No newline at end of file
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/JsonParser.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/JsonParser.php
new file mode 100755
index 00000000..33fa9f40
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/JsonParser.php
@@ -0,0 +1,54 @@
+
+ * @version $Id: JsonParser.php 555 2007-12-11 20:27:34Z p_frischmuth $
+ */
+class JsonParser extends Object {
+
+ /**
+ * This method takes a json encoded rdf-model and a reference to aa (usually empty) MemModel, parses the json
+ * string and adds the statements to the given MemModel.
+ *
+ * @param string $jsonString The string that contains the rdf model, encoded as a json-string.
+ * @param MemModel $model A reference to the model, where to add the statements, usually an empty MemModel.
+ */
+ public function generateModelFromString($jsonString, $model) {
+
+ $jsonModel = array();
+ $jsonModel = json_decode($jsonString, true);
+
+ // throws an excpetion if json model was corrupt
+ if (!is_array($jsonModel)) {
+ throw new Exception('error in json string');
+ }
+
+ foreach ($jsonModel as $subject=>$remain) {
+ foreach ($remain as $predicate=>$object) {
+ $s = (strpos($subject, '_') === 0) ? new BlankNode(substr($subject, 2)) : new Resource($subject);
+ $p = new Resource($predicate);
+
+ foreach ($object as $obj) {
+ if ($obj['type'] === 'uri') {
+ $o = new Resource($obj['value']);
+ } else if ($obj['type'] === 'bnode') {
+ $o = new BlankNode(substr($obj['value'], 2));
+ } else {
+ $dtype = (isset($obj['datatype'])) ? $obj['datatype'] : '';
+ $lang = (isset($obj['lang'])) ? $obj['lang'] : '';
+
+ $oVal = $obj['value'];
+
+ $o = new Literal($oVal, $lang);
+ $o->setDatatype($dtype);
+ }
+
+ $model->add(new Statement($s, $p, $o));
+ }
+ }
+ }
+ }
+}
+?>
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/JsonSerializer.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/JsonSerializer.php
new file mode 100755
index 00000000..30aa5b31
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/JsonSerializer.php
@@ -0,0 +1,163 @@
+
+ * @version $Id: JsonSerializer.php 555 2007-12-11 20:27:34Z p_frischmuth $
+ */
+class JsonSerializer extends Object {
+
+ /**
+ * This method takes a MemModel object ad parameter and serializes all contained triples to rdf/json format.
+ *
+ * @see http://n2.talis.com/wiki/RDF_JSON_Specification#rdf.2Fjson
+ * @param MemModel $model
+ * @return string Returns a string containing the serialized model.
+ */
+ public function serialize(MemModel $model) {
+
+ // create the root json object (root object)
+ $jsonString = '{';
+ $subjects = array();
+
+ // sort triples by subject
+ foreach ($model->triples as $triple) {
+ $subjects[$triple->toStringSubject()][] = $triple;
+ }
+
+ // sort alphabetically
+ ksort($subjects);
+
+ // triples are sorted by subject now, each key is a subject uri, containing all triples with this subject uri
+ $i = 0;
+ foreach ($subjects as $predicatesArray) {
+ $predicates = array();
+
+ if ($i > 0) {
+ $jsonString .= ',';
+ }
+ $i++;
+
+ $subj = $predicatesArray[0]->getSubject();
+
+ // add special _: sequence for blank node only
+ if ($subj instanceof BlankNode) {
+ $jsonString .= '"_:' . $this->_escapeValue($subj->getLabel()) . '":';
+ } else {
+ $jsonString .= '"' . $this->_escapeValue($subj->getLabel()) . '":';
+ }
+
+
+
+ // create a json object for each subject (subject object)
+ $jsonString .= '{';
+
+ // sort triples with current subject by predicate
+ foreach ($predicatesArray as $triple) {
+ $predicates[$triple->toStringPredicate()][] = $triple;
+ }
+
+ // sort alphabetically
+ ksort($predicates);
+
+ $j = 0;
+ foreach ($predicates as $valueArray) {
+
+ if ($j > 0) {
+ $jsonString .= ',';
+ }
+ $j++;
+
+ $jsonString .= '"' . $this->_escapeValue($valueArray[0]->getLabelPredicate()) . '":';
+
+ // create a json array (value array)
+ $jsonString .= '[';
+
+ $k = 0;
+ foreach ($valueArray as $triple) {
+ if ($k > 0) {
+ $jsonString .= ',';
+ }
+ $k++;
+
+ // create json value object (value object)
+ $jsonString .= '{';
+
+ $obj = $triple->getObject();
+
+ // add special _: sequence for blank nodes only
+ if ($obj instanceof BlankNode) {
+ $jsonString .= '"value":"_:' . $this->_escapeValue($obj->getLabel()) . '",';
+ } else if ($obj instanceof Literal) {
+ $jsonString .= '"value":"' . $this->_escapeValue($obj->getLabel()) . '",';
+ } else {
+ $jsonString .= '"value":"' . $this->_escapeValue($obj->getLabel()) . '",';
+ }
+
+ // add type of object
+ if ($obj instanceof Literal) {
+ $jsonString .= '"type":"literal"';
+ } else if ($obj instanceof BlankNode) {
+ $jsonString .= '"type":"bnode"';
+ } else {
+ $jsonString .= '"type":"uri"';
+ }
+
+ if ($obj instanceof Literal) {
+ if ($obj->getLanguage() != '') {
+ $jsonString .= ',"lang":"' . $this->_escapeValue($obj->getLanguage()) . '"';
+ }
+ if ($obj->getDatatype() != '') {
+ $jsonString .= ',"datatype":"' . $this->_escapeValue($obj->getDatatype()) . '"';
+ }
+
+ }
+
+ // close value object
+ $jsonString .= '}';
+ }
+
+ // close the value array
+ $jsonString .= ']';
+ }
+
+ // close the json object (for the subject) (subject object)
+ $jsonString .= '}';
+ }
+
+ // close root json object (root object)
+ $jsonString .= '}';
+
+ return $jsonString;
+ }
+
+ /*
+ * Escapes the following chars as specified at json.org:
+ *
+ * " -> \"
+ * \ -> \\
+ * / -> \/
+ * \b -> \\b
+ * \f -> \\f
+ * \n -> \\n
+ * \r -> \\r
+ * \t -> \\t
+ * \uXXXX -> \\uXXXX
+ */
+ protected function _escapeValue($value) {
+
+
+ $value = str_replace("\\", '\\\\', $value);
+ #$value = str_replace("/", '\/', $value);
+ $value = str_replace("\n", '\\n', $value);
+ $value = str_replace("\t", '\\t', $value);
+ $value = str_replace("\r", '\\r', $value);
+ $value = str_replace("\b", '\\b', $value);
+ $value = str_replace("\f", '\\f', $value);
+ $value = str_replace('"', '\"', $value);
+
+ return $value;
+ }
+}
+?>
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/N3Parser.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/N3Parser.php
new file mode 100755
index 00000000..13fd3064
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/N3Parser.php
@@ -0,0 +1,1137 @@
+
+ * Standard things, repeated triples ( ; and , ), blank nodes using [ ], self-reference ('<>')
+ * @prefix mappings
+ * = maps to owl#sameAs
+ * a maps to rdf-syntax-ns#type
+ * Literal datytype- and xmlLanguageTag support
+ *
+ * Un-supported N3 Features include:
+ *
+ * - Reification using { }
+ * - . and ^ operators for tree traversal
+ * - Any log operators, like log:forAll etc.
+ *
+ *
+ * This parser is based on n3.py from Epp released 2nd March, 2002.
+ * by Sean B. Palmer
+ * ( http://infomesh.net/2002/eep/20020302-013802/n3.py )
+ *
+ * This parser is released under the GNU GPL license.
+ * ( http://www.gnu.org/licenses/gpl.txt )
+ *
+ *
+ *
+ * @author Sean B. Palmer
+ * @author Gunnar AA. Grimnes
+ * @author Daniel Westphal
+ * @version $Id: N3Parser.php 517 2007-08-13 16:14:17Z cweiske $
+ * @license GPL http://www.gnu.org/licenses/gpl.txt
+ * @package syntax
+ * @access public
+ **/
+
+class N3Parser extends Object {
+
+
+ /* ==================== Variables ==================== */
+
+ var $Tokens;
+ var $bNode;
+ var $RDF_NS, $DAML_NS, $OWL_NS;
+ var $debug;
+ var $parseError;
+ var $parsedNamespaces = array();
+
+ /* ==================== Public Methods ==================== */
+
+ /**
+ * Constructor
+ * @access public
+ **/
+ function N3Parser() {
+ //Regular expressions:
+ $Name = '[A-Za-z0-9_@\.]+[^\.,;\[\]\s\) ]*';
+ $URI = '<[^> ]*>';
+ $bNode = '_:'.$Name;
+ $Univar = '\?'.$Name;
+ $QName = '(?:[A-Za-z][A-Za-z0-9_@\.]*)?:'.$Name;
+ $Literal = '(?:'
+ . '"(\\\"|[^"])*"'
+ . '|'
+ . "'(\\\'|[^'])*'"
+ . ')';
+ # '"(?:\\"|[^"])*"'
+ $Number = '[-+]?[0-9]+(\\.[0-9]+)?([eE][-+]?[0-9]+)?';
+ $Boolean = '@(?:true|false)';
+// $Literal = '"[^"\\\\]*(?:\\.\\[^"\\]*)*"'; # '"(?:\\"|[^"])*"'
+ $LangTag = '@[A-Za-z\-]*[^ \^\.\;\,]';
+ $Datatype = '(\^\^)[^ ,\.;)]+';
+ $Datatype_URI = '(\^\^)'.$URI;
+ // $LLiteral = '"""[^"\\\\]*(?:(?:.|"(?!""))[^"\\\\]*)*"""';
+ $LLiteral = '(?:'
+ . '"""[^"\\\\]*(?:(?:\\\\.|"(?!""))[^"\\\\]*)*"""'
+ . '|'
+ . "'''[^'\\\\]*(?:(?:\\\\.|'(?!''))[^\"\\\\]*)*'''"
+ . ')';
+ // '"""[^"\\]*(?:(?:\\.|"(?!""))[^"\\]*)*"""'
+ $Comment = '#.*$';
+ $Prefix = '(?:[A-Za-z][A-Za-z0-9_]*)?:';
+ $PrefixDecl = '@prefix';
+ $WS = '[ \t]';
+ $this->RDF_NS = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'; # for 'a' keyword
+ $this->DAML_NS = 'http://www.daml.org/2001/03/daml+oil#'; # for '=' keyword
+ $this->OWL_NS = 'http://www.w3.org/2002/07/owl#';
+
+ // $t = array( $LLiteral, $URI); //, $Literal, $PrefixDecl, $QName, $bNode, $Prefix,
+ // $Univar, 'a', '{', '}', '\(', '\)', '\[', '\]', ',', ';', '\.', $WS, $Comment);
+ $t = array(
+ $Datatype_URI, $Datatype, $LLiteral, $URI, $Literal,
+ $PrefixDecl, $QName, $Number, $Boolean, $bNode,
+ $Prefix, $Univar, 'a','=',
+ '{', '}', '\(', '\)', '\[', '\]', ',', ';', '\.',
+ $WS, $Comment,$LangTag
+ );
+ $this->Tokens = "/(".join($t,"|").")/m";
+
+ $this->bNode = 0;
+ $this->debug = 0;
+ $this->bNodeMap = array();
+ $this->FixBnodes = FIX_BLANKNODES;
+ $this->parseError =false;
+ }
+
+
+ /**
+ * Sets, if BlankNode labels should be replaced by the generic label from the constants.php file
+ * default is "false" -> the used label in n3 is parsed to the model
+ * @param boolean
+ * @access public
+ **/
+ function setFixBnodes($set) {
+
+ if (($set===true) OR ($set===false)) $this->FixBnodes = $set;
+ }
+
+
+ /**
+ * This parses a N3 string and prints out the triples
+ * @param string $s
+ * @access public
+ **/
+ function parse($s) {
+ // """Get a string, tokenize, create list, convert to Eep store."""
+ $stat=$this->n3tolist($s);
+ foreach ( $stat as $t) {
+
+ if (count($t)>3) {
+ $object=$t[2];
+
+ for ($i = 3; $i < 5; $i++){
+ if ($t[$i][0]=='@')$object.=$t[$i];
+ if (substr($t[$i],0,2)=='^^')$object.=$t[$i];
+ };
+ } else {$object=$t[2];};
+
+ print '('.$t[0].', '.$t[1].', '.$object.")\n";
+
+ }
+ // return [[eep.Article(t[0]), eep.Article(t[1]), eep.Article(t[2])]
+ // for t in n3tolist(s)]
+ }
+
+
+ /**
+ * This parses a N3 string and calls func($subject, $predicate, $object) with each triple
+ * @param string $s
+ * @param string $func
+ * @access public
+ **/
+ function uparse($s,$func) {
+ // """Get a string, tokenize, create list, convert to Eep store."""
+ $stat=$this->n3tolist($s);
+ foreach ( $stat as $t) {
+
+ if (count($t)>3) {
+ $object=$t[2];
+
+ for ($i = 3; $i < 5; $i++){
+ if ($t[$i][0]=='@')$object.=$t[$i];
+ if (substr($t[$i],0,2)=='^^')$object.=$t[$i];
+ };
+ } else {$object=$t[2];};
+ // print "(".$t[0].", ".$t[1].", ".$t[2].")";
+
+ $func($t[0],$t[1],$object);
+ }
+ // return [[eep.Article(t[0]), eep.Article(t[1]), eep.Article(t[2])]
+ // for t in n3tolist(s)]
+ }
+
+
+ /**
+ * This parses a N3 string and returns a memmodel
+ * @param string $s
+ * @access public
+ * @return object Model
+ **/
+
+ function parse2model($s,$model = false) {
+ if($model == false){
+ $m=new MemModel();
+ }else{
+ $m=$model;
+ }
+ // """Get a string, tokenize, create list, convert to Eep store."""
+ $stat=$this->n3tolist($s);
+
+ foreach ( $stat as $t) {
+ $s=$this->toRDFNode($t[0],$t);
+ $p=$this->toRDFNode($t[1],$t);
+ $o=$this->toRDFNode($t[2],$t);
+
+ $new_statement= new Statement($s,$p,$o);
+
+ $m->add($new_statement);
+ // print "(".$t[0].", ".$t[1].", ".$t[2].")";
+ }
+ // return [[eep.Article(t[0]), eep.Article(t[1]), eep.Article(t[2])]
+ // for t in n3tolist(s)]
+ $m->addParsedNamespaces($this->parsedNamespaces);
+ return $m;
+ }
+
+/**
+ * Generate a new MemModel from an URI or file.
+ *
+ * @access public
+ * @param $path
+ * @throws PhpError
+ * @return object MemModel
+ */
+ function & generateModel($path,$dummy=false,$model=false) {
+
+ $handle = fopen($path,'r') or die("N3 Parser: Could not open File: '$path' - Stopped parsing.");
+ $done=false;
+ $input="";
+ while(!$done)
+ {
+ $input .= fread( $handle, 512 );
+ $done = feof($handle);
+
+ };
+
+
+ fclose($handle);
+
+ $m = $this->parse2model($input,$model);
+ return $m;
+ }
+
+
+ /* ==================== Private Methods from here ==================== */
+
+ // General list processing functions
+
+/**
+ * Returns FALSE if argument is a whitespace character
+ * @access private
+ * @param string $s
+ **/
+ function isWS($s) {
+ return !preg_match('/^(#.*|\s*)$/', $s);
+ }
+
+
+
+ /**
+ * Returns true if the string is not a comment
+ * @access private
+ * @param string $s
+ * @returns boolean
+ **/
+ function notComment($s) {
+ if ($s=="") return false;
+ $N3Comment = '^[ \t]*\#';
+
+ if (ereg($N3Comment,$s)) return false;
+ else return true;
+ }
+
+ /**
+ * Removes all whitespace tokens from list
+ * @access private
+ * @param array $list
+ **/
+ function filterWs($list) {
+ // var_dump($list);
+ // """Filter whitespace from a list."""
+
+ return array_filter($list, array($this,"isWS"));
+ }
+
+/**
+* converts a string to its unicode NFC form (e.g. \uHHHH or \UHHHHHHHH).
+*
+* @param String $str
+* @return String
+* @access private
+*
+*/
+function str2unicode_nfc($str=""){
+ $result="";
+ /* try to detect encoding */
+ $tmp=str_replace("?", "", $str);
+ if(strpos(utf8_decode($tmp), "?")===false){
+ $str=utf8_decode($str);
+ }
+ for($i=0,$i_max=strlen($str);$i<$i_max;$i++){
+ $nr=0;/* unicode dec nr */
+ /* char */
+ $char=$str[$i];
+ /* utf8 binary */
+ $utf8_char=utf8_encode($char);
+ $bytes=strlen($utf8_char);
+ if($bytes==1){
+ /* 0####### (0-127) */
+ $nr=ord($utf8_char);
+ }
+ elseif($bytes==2){
+ /* 110##### 10###### = 192+x 128+x */
+ $nr=((ord($utf8_char[0])-192)*64) + (ord($utf8_char[1])-128);
+ }
+ elseif($bytes==3){
+ /* 1110#### 10###### 10###### = 224+x 128+x 128+x */
+ $nr=((ord($utf8_char[0])-224)*4096) + ((ord($utf8_char[1])-128)*64) + (ord($utf8_char[2])-128);
+ }
+ elseif($bytes==4){
+ /* 1111#### 10###### 10###### 10###### = 240+x 128+x 128+x 128+x */
+ $nr=((ord($utf8_char[0])-240)*262144) + ((ord($utf8_char[1])-128)*4096) + ((ord($utf8_char[2])-128)*64) + (ord($utf8_char[3])-128);
+ }
+ /* result (see http://www.w3.org/TR/rdf-testcases/#ntrip_strings) */
+ if($nr<9){/* #x0-#x8 (0-8) */
+ $result.="\\u".sprintf("%04X",$nr);
+ }
+ elseif($nr==9){/* #x9 (9) */
+ $result.='\t';
+ }
+ elseif($nr==10){/* #xA (10) */
+ $result.='\n';
+ }
+ elseif($nr<13){/* #xB-#xC (11-12) */
+ $result.="\\u".sprintf("%04X",$nr);
+ }
+ elseif($nr==13){/* #xD (13) */
+ $result.='\t';
+ }
+ elseif($nr<32){/* #xE-#x1F (14-31) */
+ $result.="\\u".sprintf("%04X",$nr);
+ }
+ elseif($nr<34){/* #x20-#x21 (32-33) */
+ $result.=$char;
+ }
+ elseif($nr==34){/* #x22 (34) */
+ $result.='\"';
+ }
+ elseif($nr<92){/* #x23-#x5B (35-91) */
+ $result.=$char;
+ }
+ elseif($nr==92){/* #x5C (92) */
+ $result.='\\';
+ }
+ elseif($nr<127){/* #x5D-#x7E (93-126) */
+ $result.=$char;
+ }
+ elseif($nr<65536){/* #x7F-#xFFFF (128-65535) */
+ $result.="\\u".sprintf("%04X",$nr);
+ }
+ elseif($nr<1114112){/* #x10000-#x10FFFF (65536-1114111) */
+ $result.="\\U".sprintf("%08X",$nr);
+ }
+ else{
+ /* other chars are not defined => ignore */
+ }
+ }
+ return $result;
+}
+
+
+
+ /**
+ * Gets a slice of an array.
+ * Returns the wanted slice, as well as the remainder of the array.
+ * e.g. getSpan(['p', 'q', 'r'], 1, 2) gives (['q'], ['p', 'r'])
+ * @return array
+ * @access private
+ * @param array $list
+ * @param integer $start
+ * @param integer $end
+ **/
+ function getSpan($list, $start, $end) {
+
+ $pre=array_slice($list, 0, $start);
+ $post=array_slice($list, $end);
+
+ return array(array_slice($list, $start,$end-$start),$this->array_concat($pre,$post));
+ }
+
+
+ /**
+ * Concatenates two arrays
+ * @param array $a
+ * @param array $b
+ * @returns array
+ * @access private
+ **/
+ function array_concat($a, $b) {
+ array_splice($a,count($a),0,$b);
+ return $a;
+ }
+
+ /**
+ * Returns an array with all indexes where item appears in list
+ * @param array $list
+ * @param string $item
+ * @returns array
+ * @access private
+ **/
+ function posns($list, $item) {
+ $res=array();
+ $i=0;
+ foreach ( $list as $k=>$v) {
+ if ($v === $item ) $res[]=$i;
+ $i++;
+ }
+ $res[]=$i;
+ return $res;
+ }
+
+
+ /* More N3 specific functions */
+
+ /**
+ * Returns a list of tokens
+ * @param string $s
+ * @returns array
+ * @access private
+ **/
+ function toke($s) {
+
+ // print "$s\n";
+ // """Notation3 tokenizer. Takes in a string, returns a raw token list."""
+ if (strlen($s) == 0) die('Document has no content!');
+
+ $s=str_replace("\r\n","\n",$s);
+ $s=str_replace("\r","\n",$s);
+
+
+ //$lines=explode("\n",$s);
+
+ //$reallines=array_filter($lines, array($this, "notComment"));
+ // print "LINES: ".join($reallines, " ")." :LINES\n";
+ //array_walk($reallines, array($this, "trimLine"));
+ //$res=array();
+
+ // foreach ($reallines as $l) {
+ //preg_match_all($this->Tokens, $l, $newres);
+ //$res=$this->array_concat($res,$newres[0]);
+ //}
+
+ $res=array();
+ preg_match_all($this->Tokens, $s, $newres);
+ $res=$this->array_concat($res, array_map('trim', $newres[0]));
+//var_dump($newres[0]);
+ return $res;
+ }
+
+ /**
+ * Returns a list with the elements between start and end as one quoted string
+ * e.g. listify(["a","b","c","d"],1,2) => ["a","b c", "d"]
+ * @param array $list
+ * @param integer $start
+ * @param integer $end
+ * @returns array
+ * @access private
+ **/
+ function listify($list, $start, $end) {
+
+ //Re-form a list, merge elements start->end into one quoted element
+ //Start and end are offsets...
+
+ $l=$end-$start;
+
+ $s=array_slice($list, 0, $start);
+ $m=array_slice($list, $start,$l);
+ $e=array_slice($list, $end);
+
+ // array_push($s,"\"".join($m," ")."\"");
+ array_push($s,$m);
+
+ return $this->array_concat($s,$e);
+ }
+
+ /**
+ * Returns an array with prefixes=>namespace mappings
+ * @param array $list
+ * @access private
+ * @returns array
+ **/
+ function getPrefixes($list) {
+
+ $prefixes=array();
+ $ns=1;
+ $name=2;
+ foreach ($list as $l) {
+ if ($l=='@prefix') {
+ // while '@prefix' in list {
+
+ $pos=current($list);
+ //pos = list.index('@prefix')
+ $r = $this->getSpan($list, $pos, ($pos+4)); # processes the prefix tokens
+ $binding=$r[0];
+ $list=$r[1];
+ $prefixes[$binding[$ns]] = substr($binding[$name],1,-1);
+ $this->parsedNamespaces[substr($binding[$name],1,-1)] = substr($binding[$ns],0,-1);
+ }
+ }
+
+ if (count($prefixes)<1) $list= array_slice($list,0);
+
+ return array($prefixes, $list);
+ }
+
+ /**
+ * Callback function for replacing "a" elements with the right RDF uri.
+ * @param string $l
+ * @access private
+ **/
+ function replace_a_type(&$l,$p) {
+ if ($l=='a') $l='<'.$this->RDF_NS.'type>';
+ }
+
+ /**
+ * Callback function for replacing "=" elements with the right DAML+OIL uri.
+ * @param string $l
+ * @access private
+ **/
+ function replace_equal(&$l,$p) {
+ if ($l=='=') $l='<'.$this->OWL_NS.'sameAs>';
+ }
+
+ /**
+ * Callback function for replacing "this" elements with the right RDF uri.
+ * @param string $l
+ * @access private
+ **/
+ function replace_this($l,$p) {
+ if ($l=='this') $l='';
+ }
+
+ /**
+ * Applies stuff :)
+ * Expands namespace prefixes etc.
+ * @param array $prefixes
+ * @param array $list
+ * @returns $list
+ * @access private
+ **/
+ function applyStuff($prefixes, $list)
+ {
+ array_walk($list, array($this, 'replace_a_type'));
+ array_walk($list, array($this, 'replace_equal'));
+ array_walk($list, array($this, 'replace_this'));
+
+ for ($i = 0; $i < count($list); $i++) {
+
+ if ($list[$i]=='<>') {
+ if (!isset($path)) {
+ if (!isset($_SERVER['SERVER_ADDR'])) {
+ $_SERVER['SERVER_ADDR'] = 'localhost';
+ }
+ if (!isset($_SERVER['REQUEST_URI'])) {
+ $_SERVER['REQUEST_URI'] = '/rdfapi-php';
+ }
+ $list[$i] = '';
+ } else {
+ $list[$i] = '<'.$path.'>';
+ };
+ };
+
+
+ if (preg_match('/^[-+]?[0-9]+$/', $list[$i])) {
+ //integer
+ $list[$i] = intval($list[$i]);
+ } else if (is_numeric($list[$i])) {
+ //float or decimal
+ // After conversion we cannot distinguish between both
+ $list[$i] = floatval($list[$i]);
+ } else if ((!strstr('<_"\'?.;,{}[]()@', $list[$i]{0}))
+ && (substr($list[$i],0,3) != '^^<')
+ ) {
+ //prefix or unknown
+ $_r = explode(':', $list[$i]);
+ $ns = $_r[0] . ':';
+ $name = $_r[1];
+
+ if (isset($prefixes[$ns])) {
+ $list[$i] = '<'.$prefixes[$ns].$name.'>';
+ } else if (isset($prefixes[substr($ns, 2)])) {
+ $list[$i] = '^^' . $prefixes[substr($ns, 2)] . $name . '';
+ } else {
+ //die('Prefix not declared:'.$ns);
+ $this->parseError = true;
+ trigger_error('Prefix not declared: '.$ns, E_USER_ERROR);
+ break;
+ }
+
+ } else {
+ if ($list[$i]{0} == '"') {
+ $bLiteral = true;
+ $chBase = '"';
+ } else if ($list[$i]{0} == '\'') {
+ $bLiteral = true;
+ $chBase = '\'';
+ } else {
+ $bLiteral = false;
+ }
+ if ($bLiteral) {
+ $tripleBase = $chBase . $chBase . $chBase;
+ // Congratulations - it's a literal!
+ if (substr($list[$i], 0, 3) == $tripleBase) {
+ if (substr($list[$i],-3,3) == $tripleBase) {
+ // A big literal...
+ $lit = substr($list[$i],3,-3);
+ // print "++$lit++";
+ $lit=str_replace('\n', '\\n',$lit);
+
+ //$lit=ereg_replace("[^\\]" . $chBase, "\\" . $chBase, $lit);
+ $lit = stripslashes($lit);
+
+ $list[$i] = $chBase . $lit . $chBase;
+ } else {
+ die ('Incorrect string formatting: '.substr($list[$i],-3,3));
+ }
+ } else {
+ if (strstr($list[$i],"\n")) {
+ die('Newline in literal: ' . $list[$i]);
+ }
+ $list[$i] = stripslashes($list[$i]);
+ }
+ }
+ }
+
+ if (substr($list[$i],0,2)=='^^') {
+ if ($list[$i][2]!='<') {
+ $list[$i] = '^^<' . substr($list[$i], 2) . '>';
+ }
+ };
+
+ }//foreach list item
+
+ return $list;
+ }//function applyStuff($prefixes, $list)
+
+
+
+ /**
+ * Returns an array of triples extracted from the list of n3 tokens
+ * @param array $list
+ * @returns array
+ * @access private
+ **/
+ function getStatements($list) {
+
+
+ $statements = array();
+
+ while (in_array('.', $list)) {
+ // for($i=0;$igetSpan($list, 0, $pos+1);
+
+ $statement=$r[0];
+ $list = $r[1];
+
+ array_pop($statement);
+ $statements[]=$statement;
+ }
+
+ return $statements;
+ }
+
+ /**
+ * Gets a list of triples with same subject
+ * e.g. :Gunnar :firstname "Gunnar" ; :lastname "Grimnes.
+ * @param array $list
+ * @returns array
+ * @acces private
+ **/
+ function getPovs($list) {
+ $povs = array();
+ while (in_array(';', $list)) {
+ $r=$this->posns($list,';');
+ $pos=array_slice($r,0,2);
+ $r = $this->getSpan($list, $pos[0], $pos[1]);
+ $pov=$r[0];
+ $list=$r[1];
+
+ // skip lone semicolons, e.g. " ; ."
+ if (count($pov) == 1) continue;
+
+ $povs[]=array_slice($pov,1);
+ }
+
+ return array($list, $povs);
+ }
+
+ /**
+ * Gets a list of triples with same predicate
+ * e.g. :Gunnar :likes "Cheese", "Wine".
+ * @access private
+ * @param array $list
+ * @returns array
+ **/
+ function getObjs($list) {
+
+
+ $objs = array();
+ while (in_array(",",$list)) {
+ $pos=array_search(",",$list);
+ // for($i=0;$igetSpan($list, $pos, ($pos+$get_array_fields));
+
+ $obj=$r[0];
+ if (!isset($obj[2])) $obj[2]=' ';
+ if (!isset($obj[3])) $obj[3]=' ';
+
+ $list=$r[1];
+
+
+ $objs[]=$obj;
+
+
+ }
+
+ return array($list, $objs);
+ }
+
+ /**
+ * Does the real work, returns a list of subject, predicate, object triples.
+ * @param array $list
+ * @returns array
+ * @access private
+ **/
+ function statementize($list) {
+
+ if (count($list) == 1 && preg_match("/_".BNODE_PREFIX."[0-9]+_/",$list[0])) {
+ if ($this->debug) print "Ignored bNode exists statement. $list\n";
+ return array();
+ }
+
+
+
+ if (count($list) == 3) return array($list);
+ if (count($list) < 3) {
+ throw new Exception(
+ 'N3 statement too short,'
+ . ' only ' . count($list) . ' elements instead of 3:' . "\n"
+ . implode("\n", $list)
+ );
+ }
+
+ //Get all ;
+ $r=$this->getPovs($list);
+ $spo=$r[0];
+ $po=$r[1];
+ $all=array();
+
+
+
+ // (spo, po), all = getPovs(list), []
+ $subject = $spo[0];
+ foreach ($po as $pop) {
+ // for pop in po {
+ $r=$this->getObjs($pop);
+
+ $myPo=$r[0];
+ $obj=$r[1];
+ //myPo, obj = getObjs(pop)
+
+ if (!isset($myPo[2])) $myPo[2]=' ';
+ if (!isset($myPo[3])) $myPo[3]=' ';
+
+
+ $predicate = $myPo[0];
+ $all[]=array($subject,$predicate,$myPo[1],$myPo[2],$myPo[3]);
+ // all.append([subject, predicate, myPo[1]])
+
+
+
+ foreach ($obj as $o) $all[]=array($subject,$predicate, $o[1],$o[2],$o[3]);
+ // for x in obj: all.append([subject, predicate, x])
+
+ }
+
+
+
+ $r = $this->getObjs($spo);
+ $spo=$r[0];
+
+ $objs=$r[1];
+
+ //spo, objs = getObjs(spo)
+ $subject=$spo[0];
+ $predicate=$spo[1];
+
+
+ if(!isset($spo[3])) $spo[3]=' ';
+ if(!isset($spo[4])) $spo[4]=' ';
+
+ $all[]=array($subject, $predicate, $spo[2],$spo[3],$spo[4]);
+
+ foreach ($objs as $obj) $all[]=array($subject, $predicate, $obj[1],$obj[2],$obj[3]);
+
+ return $all;
+ }
+
+ /**
+ * Makes lists of elements in list into a seperate array element.
+ * e.g. doLists(["a","b","[","c","]","d"], "[","]")=> ["a","b", ["c"], "d"]
+ * @param array $list
+ * @param string $schar
+ * @param string $echar
+ * @returns array
+ * @access private
+ **/
+ function doLists($list, $schar, $echar) {
+
+ while (in_array($schar, $list)) {
+ // while schar in list {
+ $ndict = array();
+ $nestingLevel = 0;
+ $biggest = 0;
+ for ($i = 0; $i < count($list); $i++) {
+ if ($list[$i] == $schar) {
+ $nestingLevel += 1;
+ if (!in_array($nestingLevel, array_keys($ndict))) {
+ $ndict[$nestingLevel] = array(array($i));
+ } else {
+ $ndict[$nestingLevel][]=array($i);
+ }
+ }
+ if ($list[$i] == $echar) {
+ if (!in_array($nestingLevel, array_keys($ndict))) {
+ $ndict[$nestingLevel]=array(array($i));
+ } else {
+ $ndict[$nestingLevel][count($ndict[$nestingLevel])-1][]=$i;
+ $nestingLevel-= 1;
+# elif type(list[i]) == type([]) {
+# list[i] = doLists(list[i], schar, echar)
+ }
+ }
+ }
+ foreach (array_keys($ndict) as $key) {
+ if ($key > $biggest) $biggest = $key;
+ }
+
+ $tol = $ndict[$biggest][0];
+ $list = $this->listify($list, $tol[0], ($tol[1]+1));
+ }
+ return $list;
+ }
+
+ /**
+ * Apply doLists for all different types of list.
+ * @param array
+ * @returns array
+ * @access private
+ **/
+ function listStuff($list) {
+# y, z = zip(['[', ']'], ['{', '}'], ['(', ')'])
+# return map(doLists, [list, list, list], y, z).pop()
+ $list = $this->doLists($list, '[', ']');
+ $list = $this->doLists($list, '{', '}');
+ return $this->doLists($list, '(', ')');
+ }
+
+ /**
+ * Generates a new node id.
+ * @access private
+ * @returns string
+ **/
+ function bnodeID() {
+
+ $this->bNode++;
+ return "_".BNODE_PREFIX.$this->bNode."_";
+ }
+
+ /**
+ * This makes bNodes out of variables like _:a etc.
+ * @access private
+ * @param array $list
+ * @returns array
+ **/
+ function fixAnon($list) {
+// $map=array();
+ for($i=0;$ibNodeMap[$l])) {
+ $a=$this->bnodeID();
+ $this->bNodeMap[$l]=$a;
+ } else $a=$this->bNodeMap[$l];
+ $list[$i]=$a;
+ }
+ }
+ return $list;
+ }
+
+ /**
+ * This makes [ ] lists into bnodes.
+ * @access private
+ * @param array $list
+ * @return array
+ **/
+ function expandLists($list) {
+
+ for($i=0;$ibnodeID();
+ $prop=$list[$i];
+ $list[$i]=$bnode;
+ $list[]=$bnode;
+ $list=$this->array_concat($list, array_slice($prop,1,-1));
+ $list[]='.';
+ }elseif($list[$i][0]=='(') {
+
+ $rdfNil = '<'. RDF_NAMESPACE_URI . RDF_NIL .'>';
+ $rdfFirst = '<'. RDF_NAMESPACE_URI . RDF_FIRST .'>';
+ $rdfRest = '<'. RDF_NAMESPACE_URI . RDF_REST .'>';
+
+ // local copy of list without "(" and ")"
+ $t_list = array_slice($list[$i], 1, -1);
+
+ //prepare bnodes
+ $fromBnode = $this->bnodeID();
+ $toBnode = $this->bnodeID();
+
+ //link first bnode into graph
+ $list[$i] = $fromBnode;
+
+ $count = count($t_list);
+
+ //loop through list, convert to RDF linked list
+ for ($idx = 0; $idx < $count; $idx++){
+
+ // set rdf:first
+ $list[] = $fromBnode;
+ $list[] = $rdfFirst;
+ $list[] = $t_list[$idx];
+ $list[] = '.';
+
+ // set rdf:rest (nil or next bnode)
+ if ($idx == $count - 1) {
+ $list[] = $fromBnode;
+ $list[] = $rdfRest;
+ $list[] = $rdfNil;
+ $list[] = '.';
+ }
+ else {
+ $list[] = $fromBnode;
+ $list[] = $rdfRest;
+ $list[] = $toBnode;
+ $list[] = '.';
+
+ $fromBnode = $toBnode;
+ $toBnode = $this->bnodeID();
+ }
+ }
+ }
+ else {
+ die('Only [ ] and () lists are supported!');
+ }
+ }
+
+
+ }
+ return $list;
+ }
+
+ /**
+ * Main work-horse function. This converts a N3 string to a list of statements
+ * @param string $s
+ * @returns array
+ * @access private
+ **/
+ function n3tolist($s) {
+
+ // """Convert an N3 string into a list of triples as strings."""
+ $result = array();
+
+ $t = $this->filterWs($this->toke($s)); # tokenize the stream, and filter whitespace tokens
+
+ if ($this->debug) {
+ print "Filter WS:\n";
+ var_dump($t);
+ }
+ $r=$this->getPrefixes($t); # get the prefix directives, and add to a dict
+ $prefixes=$r[0];
+ $t=$r[1];
+ if ($this->debug) {
+ print "Prefixes:\n";
+ var_dump($prefixes);
+ print "***\n";
+ var_dump($t);
+ }
+ $t=$this->applyStuff($prefixes, $t);#apply prefixes, keywords, and string formatting
+ if ($this->debug) {
+ print "Stuff applied:\n";
+ var_dump($t);
+ }
+
+ $t=$this->fixAnon($t); # fix _:a anons
+ if ($this->debug) {
+ print "Fix anon:\n";
+ var_dump($t);
+ }
+
+ $t = $this->listStuff($t); # apply list stuff: todo
+ if ($this->debug) {
+ print "Lists done:\n";
+ var_dump($t);
+ }
+ $t=$this->expandLists($t);
+ if ($this->debug) {
+ print "Lists applied:\n";
+ var_dump($t);
+ }
+ $t = $this->getStatements($t); # get all of the "statements" from the stream
+
+ foreach ($t as $stat) {
+ $stats = $this->statementize($stat);
+
+ foreach ($stats as $y) {
+ $result[]=$y;
+ }
+ }
+
+ // for x in [statementize(stat) for stat in t] {
+ // for y in x: result.append(y)
+ return $result;
+ }
+
+
+
+ /**
+ * Constructs a RAP RDFNode from URI/Literal/Bnode
+ * @access private
+ * @param string $s
+ * @returns object RDFNode
+ **/
+ function toRDFNode($s, $state)
+ {
+ $ins = substr($s, 1, -1);
+ if ($s{0} == '"' || $s{0} == '\'') {
+ $lang = NULL;
+
+ if (count($state)>3) {
+ for ($i = 3; $i < count($state); $i++) {
+ if ($state[$i][0]=='@') {
+ $lang = substr($state[3], 1);
+ }
+ if (substr($state[$i],0,2) == '^^') {
+ $dtype = substr($state[$i],2);
+ if ($dtype[0]=='<') {
+ $dtype = substr($dtype,1,-1);
+ }
+ }
+ }
+ }
+
+
+ if (UNIC_RDF) {
+ $ins = $this->str2unicode_nfc($ins);
+ }
+ $new_Literal = new Literal($ins, $lang);
+ if (isset($dtype)) {
+ $new_Literal->setDatatype($dtype);
+ }
+ return $new_Literal;
+ } else if (is_int($s)) {
+ $value = new Literal($s);
+ $value->setDatatype(XML_SCHEMA . 'integer');
+ return $value;
+ } else if (is_float($s)) {
+ $value = new Literal($s);
+ $value->setDatatype(XML_SCHEMA . 'double');
+ return $value;
+ } else if ($s == '@true') {
+ $value = new Literal(true);
+ $value->setDatatype(XML_SCHEMA . 'boolean');
+ return $value;
+ } else if ($s == '@false') {
+ $value = new Literal(false);
+ $value->setDatatype(XML_SCHEMA . 'boolean');
+ return $value;
+ }
+
+ if (strstr($s, '_' . BNODE_PREFIX)) {
+ if (($this->FixBnodes) || (!array_search($s,$this->bNodeMap))) {
+ return new BlankNode($ins);
+ } else {
+ return new BlankNode(
+ trim(
+ substr(
+ array_search($s, $this->bNodeMap),
+ 2
+ )
+ )
+ );
+ };
+ }
+
+ return new Resource($ins);
+ }//function toRDFNode($s, $state)
+
+
+
+
+} //end: N3Parser
+
+?>
diff --git a/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/N3Serializer.php b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/N3Serializer.php
new file mode 100755
index 00000000..f28b5d2c
--- /dev/null
+++ b/ws2011/Semantic Web/Uebungen/1. Bonus Aufgabe/solution/rdfAPI/api/syntax/N3Serializer.php
@@ -0,0 +1,526 @@
+
+ * Using [ ] for blank nodes, or _: if necessary
+ * Literal datatype- and xmlLanguageTag support
+ *
+ *
+ * Un-supported N3 Features include:
+ *
+ *
+ *
+ * @author Gunnar AA. Grimnes
+ * @author Daniel Westphal
+ * @author Christian Weiske