public function testRDFAnnotations()
 {
     try {
         // - Test parsing from source code.
         // 1. Defensive tests.
         $annotations = tao_helpers_translation_RDFUtils::unserializeAnnotations("");
         $this->assertEquals($annotations, array());
         $annotations = tao_helpers_translation_RDFUtils::unserializeAnnotations("sd@eipredicate%\nblu");
         $this->assertEquals($annotations, array());
         $annotations = tao_helpers_translation_RDFUtils::unserializeAnnotations("@fake FUBAR");
         $this->assertEquals($annotations, array());
         $annotations = tao_helpers_translation_RDFUtils::unserializeAnnotations("@predicate ");
         $this->assertEquals($annotations, array());
         $annotations = tao_helpers_translation_RDFUtils::unserializeAnnotations("@predicate\n@subject");
         $this->assertEquals($annotations, array());
         // 2. Other tests.
         $annotations = tao_helpers_translation_RDFUtils::unserializeAnnotations("@predicate http://www.tao.lu/Ontologies/tao.rdf#aFragment\n@fake FUBAR");
         $this->assertEquals($annotations, array("predicate" => "http://www.tao.lu/Ontologies/tao.rdf#aFragment"));
         $annotations = tao_helpers_translation_RDFUtils::unserializeAnnotations("@source This is a source test.");
         $this->assertEquals($annotations, array("source" => "This is a source test."));
         $annotations = tao_helpers_translation_RDFUtils::unserializeAnnotations("@source This is a source test.\n@sourceLanguage en-US");
         $this->assertEquals($annotations, array("source" => "This is a source test.", "sourceLanguage" => "en-US"));
         $annotations = tao_helpers_translation_RDFUtils::unserializeAnnotations("@source بعض النصوص في اللغة العربية");
         $this->assertEquals($annotations, array("source" => "بعض النصوص في اللغة العربية"));
         // 3. Test escaping.
         $annotations = tao_helpers_translation_RDFUtils::unserializeAnnotations("@source lorem \\-\\- ipsum \\\\ dolomet.\n@sourceLanguage fr-CA");
         $this->assertEquals($annotations, array("source" => "lorem -- ipsum \\ dolomet.", "sourceLanguage" => "fr-CA"));
         $annotations = tao_helpers_translation_RDFUtils::serializeAnnotations(array("source" => "lorem -- ipsum \\ \n dolomet.", "sourceLanguage" => "fr-CA"));
         $this->assertEquals($annotations, "@source lorem \\-\\- ipsum \\\\ \n dolomet.\n    @sourceLanguage fr-CA");
         // - Test serialization from array.
         $annotations = tao_helpers_translation_RDFUtils::serializeAnnotations(array("source" => "This is a source test.", "sourceLanguage" => "en-US", "targetLanguage" => "fr-CA", "predicate" => "http://www.tao.lu/Ontologies/tao.rdf#aFragment"));
         $this->assertEquals($annotations, "@source This is a source test.\n    @sourceLanguage en-US\n    @targetLanguage fr-CA\n    @predicate http://www.tao.lu/Ontologies/tao.rdf#aFragment");
         // - Test Annotations parsing while reading with RDFFileWriter.
         $reader = new tao_helpers_translation_RDFFileReader(dirname(__FILE__) . self::FAKE_RDF_TRANSLATION_MODEL_ANNOTATIONS);
         $reader->read();
         $tf = $reader->getTranslationFile();
         $this->assertEquals($tf->getAnnotations(), array('sourceLanguage' => 'EN', 'targetLanguage' => 'es'));
         $tus = $tf->getTranslationUnits();
         $this->assertEquals($tus[0]->getSourceLanguage(), 'EN');
         $this->assertEquals($tus[0]->getTargetLanguage(), 'es');
         $this->assertEquals($tus[0]->getSource(), 'TAO Object');
         $this->assertEquals($tus[0]->getTarget(), 'TAO objeto');
         $this->assertEquals($tus[0]->getAnnotation('sourceLanguage'), array('name' => 'sourceLanguage', 'value' => 'EN'));
         $this->assertEquals($tus[0]->getAnnotation('targetLanguage'), array('name' => 'targetLanguage', 'value' => 'es'));
         $this->assertEquals($tus[10]->getTarget(), 'Función de usuario de flujo de trabajo: el papel asignado por defecto a todos los usuarios backend, no eliminable');
     } catch (tao_helpers_translation_TranslationException $e) {
         $this->assertFalse(true, "No TranslationException should be thrown in testRDFAnnotations test.");
     }
 }
 /**
  * Short description of method read
  *
  * @access public
  * @author Jerome Bogaerts, <*****@*****.**>
  * @return mixed
  */
 public function read()
 {
     $translationUnits = array();
     try {
         $translationFile = $this->getTranslationFile();
     } catch (tao_helpers_translation_TranslationException $e) {
         $translationFile = new tao_helpers_translation_RDFTranslationFile();
     }
     $this->setTranslationFile($translationFile);
     $inputFile = $this->getFilePath();
     if (file_exists($inputFile)) {
         if (is_file($inputFile)) {
             if (is_readable($inputFile)) {
                 try {
                     $doc = new DOMDocument('1.0', 'UTF-8');
                     $doc->load($inputFile);
                     $xpath = new DOMXPath($doc);
                     $rdfNS = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#';
                     $xmlNS = 'http://www.w3.org/XML/1998/namespace';
                     $xpath->registerNamespace('rdf', $rdfNS);
                     $rootNodes = $xpath->query('//rdf:RDF');
                     if ($rootNodes->length == 1) {
                         // Try to get annotations from the root node.
                         $sibling = $rootNodes->item(0)->previousSibling;
                         while ($sibling !== null) {
                             if ($sibling instanceof DOMNode && $sibling->nodeType == XML_COMMENT_NODE) {
                                 $annotations = tao_helpers_translation_RDFUtils::unserializeAnnotations($sibling->data);
                                 $translationFile->setAnnotations($annotations);
                                 if (isset($annotations['sourceLanguage'])) {
                                     $translationFile->setSourceLanguage($annotations['sourceLanguage']);
                                 }
                                 if (isset($annotations['targetLanguage'])) {
                                     $translationFile->setTargetLanguage($annotations['targetLanguage']);
                                 }
                                 break;
                             }
                             $sibling = $sibling->previousSibling;
                         }
                         $descriptions = $xpath->query('//rdf:Description');
                         foreach ($descriptions as $description) {
                             if ($description->hasAttributeNS($rdfNS, 'about')) {
                                 $subject = $description->getAttributeNS($rdfNS, 'about');
                                 // Let's retrieve properties.
                                 foreach ($description->childNodes as $property) {
                                     if ($property->nodeType == XML_ELEMENT_NODE) {
                                         // Retrieve namespace uri of this node.
                                         if ($property->namespaceURI != null) {
                                             $predicate = $property->namespaceURI . $property->localName;
                                             // Retrieve an hypothetic target language.
                                             $lang = tao_helpers_translation_Utils::getDefaultLanguage();
                                             if ($property->hasAttributeNS($xmlNS, 'lang')) {
                                                 $lang = $property->getAttributeNS($xmlNS, 'lang');
                                             }
                                             $object = $property->nodeValue;
                                             $tu = new tao_helpers_translation_RDFTranslationUnit('');
                                             $tu->setTargetLanguage($lang);
                                             $tu->setTarget($object);
                                             $tu->setSubject($subject);
                                             $tu->setPredicate($predicate);
                                             // Try to get annotations.
                                             $sibling = $property->previousSibling;
                                             while ($sibling !== null) {
                                                 if ($sibling instanceof DOMNode && $sibling->nodeType == XML_COMMENT_NODE) {
                                                     // We should have the annotations we are looking for.
                                                     $annotations = tao_helpers_translation_RDFUtils::unserializeAnnotations($sibling->data);
                                                     $tu->setAnnotations($annotations);
                                                     // Set the found sources and sourcelanguages if found.
                                                     if (isset($annotations['source'])) {
                                                         $tu->setSource($annotations['source']);
                                                     }
                                                 }
                                                 $sibling = $sibling->previousSibling;
                                             }
                                             $translationUnits[] = $tu;
                                         }
                                     }
                                 }
                             }
                         }
                         $this->getTranslationFile()->addTranslationUnits($translationUnits);
                     } else {
                         throw new tao_helpers_translation_TranslationException("'{$inputFile}' has no rdf:RDF root node or more than one rdf:RDF root node.");
                     }
                 } catch (DOMException $e) {
                     throw new tao_helpers_translation_TranslationException("'{$inputFile}' cannot be parsed.");
                 }
             } else {
                 throw new tao_helpers_translation_TranslationException("'{$inputFile}' cannot be read. Check your system permissions.");
             }
         } else {
             throw new tao_helpers_translation_TranslationException("'{$inputFile}' is not a file.");
         }
     } else {
         throw new tao_helpers_translation_TranslationException("The file '{$inputFile}' does not exist.");
     }
 }
 /**
  * Implementation of the 'create' action.
  *
  * @access public
  * @author Joel Bout, <*****@*****.**>
  * @return void
  */
 public function actionCreate()
 {
     $extensionsToCreate = explode(',', $this->options['extension']);
     $extensionsToCreate = array_unique($extensionsToCreate);
     foreach ($extensionsToCreate as $etc) {
         $this->options['extension'] = $etc;
         $this->options['input'] = dirname(__FILE__) . '/../../' . $etc . '/' . self::DEF_INPUT_DIR;
         $this->options['output'] = dirname(__FILE__) . '/../../' . $etc . '/' . self::DEF_OUTPUT_DIR;
         $this->outVerbose("Creating language '" . $this->options['language'] . "' for extension '" . $this->options['extension'] . "' ...");
         // We first create the directory where locale files will go.
         $dir = $this->buildLanguagePath($this->options['extension'], $this->options['language']);
         $dirExists = false;
         if (file_exists($dir) && is_dir($dir) && $this->options['force'] == true) {
             $dirExists = true;
             $this->outVerbose("Language '" . $this->options['language'] . "' exists for extension '" . $this->options['extension'] . "'. Creation will be forced.");
             // Clean it up.
             foreach (scandir($dir) as $d) {
                 if ($d !== '.' && $d !== '..' && $d !== '.svn') {
                     if (!tao_helpers_File::remove($dir . '/' . $d, true)) {
                         $this->err("Unable to clean up 'language' directory '" . $dir . "'.", true);
                     }
                 }
             }
         } else {
             if (file_exists($dir) && is_dir($dir) && $this->options['force'] == false) {
                 $this->err("The 'language' " . $this->options['language'] . " already exists in the file system. Use the 'force' parameter to overwrite it.", true);
             }
         }
         // If we are still here... it means that we have to create the language directory.
         if (!$dirExists && !@mkdir($dir)) {
             $this->err("Unable to create 'language' directory '" . $this->options['language'] . "'.", true);
         } else {
             if ($this->options['build'] == true) {
                 $sortingMethod = tao_helpers_translation_TranslationFile::SORT_ASC_I;
                 $this->outVerbose("Building language '" . $this->options['language'] . "' for extension '" . $this->options['extension'] . "' ...");
                 // Let's populate the language with raw PO files containing sources but no targets.
                 // Source code extraction.
                 $fileExtensions = array('php', 'tpl', 'js', 'ejs');
                 $filePaths = array();
                 foreach (self::$WHITE_LIST as $subFolder) {
                     $filePaths[] = $this->options['input'] . DIRECTORY_SEPARATOR . $subFolder;
                 }
                 $sourceExtractor = new tao_helpers_translation_SourceCodeExtractor($filePaths, $fileExtensions);
                 $sourceExtractor->extract();
                 $translationFile = new tao_helpers_translation_POFile();
                 $translationFile->setSourceLanguage(tao_helpers_translation_Utils::getDefaultLanguage());
                 $translationFile->setTargetLanguage($this->options['language']);
                 $translationFile->addTranslationUnits($sourceExtractor->getTranslationUnits());
                 $file = MenuService::getStructuresFilePath($this->options['extension']);
                 if (!is_null($file)) {
                     $structureExtractor = new tao_helpers_translation_StructureExtractor(array($file));
                     $structureExtractor->extract();
                     $translationFile->addTranslationUnits($structureExtractor->getTranslationUnits());
                 }
                 $sortedTus = $translationFile->sortBySource($sortingMethod);
                 $sortedTranslationFile = new tao_helpers_translation_POFile();
                 $sortedTranslationFile->setSourceLanguage(tao_helpers_translation_Utils::getDefaultLanguage());
                 $sortedTranslationFile->setTargetLanguage($this->options['language']);
                 $sortedTranslationFile->addTranslationUnits($sortedTus);
                 $this->preparePOFile($sortedTranslationFile, true);
                 $poPath = $dir . '/' . self::DEF_PO_FILENAME;
                 $writer = new tao_helpers_translation_POFileWriter($poPath, $sortedTranslationFile);
                 $writer->write();
                 $this->outVerbose("PO Translation file '" . basename($poPath) . "' in '" . $this->options['language'] . "' created for extension '" . $this->options['extension'] . "'.");
                 $writer->write();
                 // Writing JS files
                 $jsPath = $dir . '/' . self::DEF_JS_FILENAME;
                 $writer = new tao_helpers_translation_JSFileWriter($jsPath, $sortedTranslationFile);
                 $writer->write(false);
                 $this->outVerbose("JavaScript Translation file '" . basename($jsPath) . "' in '" . $this->options['language'] . "' created for extension '" . $this->options['extension'] . "'.");
                 $writer->write();
                 // Now that PO files & JS files are created, we can create the translation models
                 // if we find RDF models to load for this extension.
                 $translatableProperties = array(RDFS_LABEL, RDFS_COMMENT);
                 foreach ($this->getOntologyFiles() as $f) {
                     common_Logger::d('reading rdf ' . $f);
                     $translationFile = $this->extractPoFileFromRDF($f, $translatableProperties);
                     $writer = new tao_helpers_translation_POFileWriter($dir . '/' . $this->getOntologyPOFileName($f), $translationFile);
                     $writer->write();
                     $this->outVerbose("PO Translation file '" . $this->getOntologyPOFileName($f) . "' in '" . $this->options['language'] . "' created for extension '" . $this->options['extension'] . "'.");
                 }
                 $this->outVerbose("Language '" . $this->options['language'] . "' created for extension '" . $this->options['extension'] . "'.");
             } else {
                 // Only build virgin files.
                 // (Like a virgin... woot !)
                 $translationFile = new tao_helpers_translation_POFile();
                 $translationFile->setSourceLanguage(tao_helpers_translation_Utils::getDefaultLanguage());
                 $translationFile->setTargetLanguage($this->options['language']);
                 $this->preparePOFile($translationFile, true);
                 foreach ($this->getOntologyFiles() as $f) {
                     common_Logger::d('reading rdf ' . $f);
                     $translationFile = new tao_helpers_translation_POFile();
                     $translationFile->setSourceLanguage(tao_helpers_translation_Utils::getDefaultLanguage());
                     $translationFile->setTargetLanguage($this->options['language']);
                     $translationFile->setExtensionId($this->options['extension']);
                     $writer = new tao_helpers_translation_POFileWriter($dir . '/' . $this->getOntologyPOFileName($f), $translationFile);
                     $writer->write();
                 }
                 $this->outVerbose("Language '" . $this->options['language'] . "' created for extension '" . $this->options['extension'] . "'.");
             }
             // Create the language manifest in RDF.
             if ($this->options['extension'] == 'tao') {
                 $langDescription = tao_helpers_translation_RDFUtils::createLanguageDescription($this->options['language'], $this->options['languageLabel']);
                 $langDescription->save($dir . '/' . self::DEF_LANG_FILENAME);
             }
         }
     }
 }
 /**
  * Writes the RDF file on the file system.
  *
  * @access public
  * @author Jerome Bogaerts, <*****@*****.**>
  * @return mixed
  */
 public function write()
 {
     $targetPath = $this->getFilePath();
     $file = $this->getTranslationFile();
     $semanticNamespaces = array('rdf' => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', 'rdfs' => 'http://www.w3.org/2000/01/rdf-schema#');
     $xmlNS = 'http://www.w3.org/XML/1998/namespace';
     $xmlnsNS = 'http://www.w3.org/2000/xmlns/';
     try {
         $targetFile = new DOMDocument('1.0', 'UTF-8');
         $targetFile->formatOutput = true;
         // Create the RDF root node and annotate if possible.
         $rdfNode = $targetFile->createElementNS($semanticNamespaces['rdf'], 'rdf:RDF');
         $targetFile->appendChild($rdfNode);
         $rootAnnotations = $this->getTranslationFile()->getAnnotations();
         if (count($rootAnnotations)) {
             $annotationsString = tao_helpers_translation_RDFUtils::serializeAnnotations($rootAnnotations);
             $annotationsNode = $targetFile->createComment("\n    " . $annotationsString . "\n");
             $targetFile->insertBefore($annotationsNode, $rdfNode);
         }
         $rdfNode->setAttributeNS($xmlNS, 'xml:base', $file->getBase());
         $rdfNode->setAttributeNS($xmlnsNS, 'xmlns:rdfs', $semanticNamespaces['rdfs']);
         $xPath = new DOMXPath($targetFile);
         $xPath->registerNamespace($semanticNamespaces['rdf'], 'rdf');
         $xPath->registerNamespace($semanticNamespaces['rdfs'], 'rdfs');
         foreach ($file->getTranslationUnits() as $tu) {
             // Look if the predicate is a semantic namespace.
             $uri = explode('#', $tu->getPredicate());
             if (count($uri) == 2) {
                 $namespace = $uri[0] . '#';
                 $qName = $uri[1];
                 if (($searchedNS = array_search($namespace, $semanticNamespaces)) !== false) {
                     $tuNode = $targetFile->createElement("{$searchedNS}:{$qName}");
                     $tuNode->setAttributeNS($xmlNS, 'xml:lang', $tu->getTargetLanguage());
                     $cdataValue = $tu->getTarget() == '' ? $tu->getSource() : $tu->getTarget();
                     $tuNodeValue = $targetFile->createCDATASection($cdataValue);
                     $tuNode->appendChild($tuNodeValue);
                     // Check if an rdf:Description exists for
                     // the target of the TranslationUnit.
                     $subject = $tu->getSubject();
                     $result = $xPath->query("//rdf:Description[@rdf:about='{$subject}']");
                     if ($result->length > 0) {
                         // Append to the existing rdf:Description.
                         $existingDescription = $result->item(0);
                         $existingDescription->appendChild($tuNode);
                     } else {
                         // Append to a new rdf:Description node.
                         $descriptionNode = $targetFile->createElementNS($semanticNamespaces['rdf'], 'rdf:Description');
                         $descriptionNode->setAttributeNS($semanticNamespaces['rdf'], 'rdf:about', $subject);
                         $descriptionNode->appendChild($tuNode);
                         $rdfNode->appendChild($descriptionNode);
                     }
                     // Finally add annotations.
                     $annotations = $tu->getAnnotations();
                     if (count($annotations) > 0) {
                         $annotationString = "\n    " . tao_helpers_translation_RDFUtils::serializeAnnotations($annotations) . "\n    ";
                         $annotationNode = $targetFile->createComment($annotationString);
                         $tuNode->parentNode->insertBefore($annotationNode, $tuNode);
                     }
                 }
             }
         }
         $targetFile->save($targetPath);
     } catch (DOMException $e) {
         throw new tao_helpers_translation_TranslationException("An error occured while writing the RDF File at '{$targetPath}'.");
     }
 }