LCOV - code coverage report
Current view: top level - libreoffice/helpcompiler/source - HelpCompiler.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 194 223 87.0 %
Date: 2012-12-27 Functions: 12 13 92.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : 
      21             : #include <helpcompiler/HelpCompiler.hxx>
      22             : #include <limits.h>
      23             : #include <stdlib.h>
      24             : #include <string.h>
      25             : #include <libxslt/xslt.h>
      26             : #include <libxslt/xsltInternals.h>
      27             : #include <libxslt/transform.h>
      28             : #include <libxslt/xsltutils.h>
      29             : #include <osl/thread.hxx>
      30             : 
      31           0 : static void impl_sleep( sal_uInt32 nSec )
      32             : {
      33             :     TimeValue aTime;
      34           0 :     aTime.Seconds = nSec;
      35           0 :     aTime.Nanosec = 0;
      36             : 
      37           0 :     osl::Thread::wait( aTime );
      38           0 : }
      39             : 
      40        8906 : HelpCompiler::HelpCompiler(StreamTable &in_streamTable, const fs::path &in_inputFile,
      41             :     const fs::path &in_src, const fs::path &in_resEmbStylesheet,
      42             :     const std::string &in_module, const std::string &in_lang, bool in_bExtensionMode)
      43             :     : streamTable(in_streamTable), inputFile(in_inputFile),
      44             :     src(in_src), module(in_module), lang(in_lang), resEmbStylesheet(in_resEmbStylesheet),
      45        8906 :     bExtensionMode( in_bExtensionMode )
      46             : {
      47        8906 :     xmlKeepBlanksDefaultValue = 0;
      48        8906 :     char* guitmp = getenv("GUI");
      49        8906 :     if (guitmp)
      50             :     {
      51        8906 :         gui = (strcmp(guitmp, "UNX") ? gui : "UNIX");
      52        8906 :         gui = (strcmp(guitmp, "MAC") ? gui : "MAC");
      53        8906 :         gui = (strcmp(guitmp, "WNT") ? gui : "WIN");
      54             :     }
      55        8906 : }
      56             : 
      57        8906 : xmlDocPtr HelpCompiler::getSourceDocument(const fs::path &filePath)
      58             : {
      59             :     static const char *params[4 + 1];
      60             :     static xsltStylesheetPtr cur = NULL;
      61             : 
      62             :     xmlDocPtr res;
      63        8906 :     if( bExtensionMode )
      64             :     {
      65           0 :         res = xmlParseFile(filePath.native_file_string().c_str());
      66           0 :         if( !res ){
      67           0 :             impl_sleep( 3 );
      68           0 :             res = xmlParseFile(filePath.native_file_string().c_str());
      69             :         }
      70             :     }
      71             :     else
      72             :     {
      73        8906 :         if (!cur)
      74             :         {
      75           8 :             static std::string fsroot('\'' + src.toUTF8() + '\'');
      76           8 :             static std::string esclang('\'' + lang + '\'');
      77             : 
      78           8 :             xmlSubstituteEntitiesDefault(1);
      79           8 :             xmlLoadExtDtdDefaultValue = 1;
      80           8 :             cur = xsltParseStylesheetFile((const xmlChar *)resEmbStylesheet.native_file_string().c_str());
      81             : 
      82           8 :             int nbparams = 0;
      83           8 :             params[nbparams++] = "Language";
      84           8 :             params[nbparams++] = esclang.c_str();
      85           8 :             params[nbparams++] = "fsroot";
      86           8 :             params[nbparams++] = fsroot.c_str();
      87           8 :             params[nbparams] = NULL;
      88             :         }
      89        8906 :         xmlDocPtr doc = xmlParseFile(filePath.native_file_string().c_str());
      90        8906 :         if( !doc )
      91             :         {
      92           0 :             impl_sleep( 3 );
      93           0 :             doc = xmlParseFile(filePath.native_file_string().c_str());
      94             :         }
      95             : 
      96             :         //???res = xmlParseFile(filePath.native_file_string().c_str());
      97             : 
      98        8906 :         res = xsltApplyStylesheet(cur, doc, params);
      99        8906 :         xmlFreeDoc(doc);
     100             :     }
     101        8906 :     return res;
     102             : }
     103             : 
     104             : // returns a node representing the whole stuff compiled for the current
     105             : // application.
     106      939275 : xmlNodePtr HelpCompiler::clone(xmlNodePtr node, const std::string& appl)
     107             : {
     108      939275 :     xmlNodePtr root = xmlCopyNode(node, 2);
     109      939275 :     if (node->xmlChildrenNode)
     110             :     {
     111      532819 :         xmlNodePtr list = node->xmlChildrenNode;
     112     2000443 :         while (list)
     113             :         {
     114      934805 :             if (strcmp((const char*)list->name, "switchinline") == 0 || strcmp((const char*)list->name, "switch") == 0)
     115             :             {
     116       11434 :                 std::string tmp="";
     117       11434 :                 if (strcmp((const char*)xmlGetProp(list, (xmlChar*)"select"), "sys"))
     118             :                 {
     119        5584 :                     tmp = gui;
     120             :                 }
     121       11434 :                 if (strcmp((const char*)xmlGetProp(list, (xmlChar*)"select"), "appl"))
     122             :                 {
     123        5850 :                     tmp = appl;
     124             :                 }
     125       11434 :                 if (tmp.compare("") != 0)
     126             :                 {
     127       11434 :                     bool isCase=false;
     128       11434 :                     xmlNodePtr caseList=list->xmlChildrenNode;
     129       42031 :                     while (caseList)
     130             :                     {
     131       19163 :                         xmlChar *select = xmlGetProp(caseList, (xmlChar*)"select");
     132       19163 :                         if (select)
     133             :                         {
     134       12810 :                             if (!strcmp((const char*)select, tmp.c_str()) && !isCase)
     135             :                             {
     136           0 :                                 isCase=true;
     137           0 :                                 xmlNodePtr clp = caseList->xmlChildrenNode;
     138           0 :                                 while (clp)
     139             :                                 {
     140           0 :                                     xmlAddChild(root, clone(clp, appl));
     141           0 :                                     clp = clp->next;
     142             :                                 }
     143             :                             }
     144       12810 :                             xmlFree(select);
     145             :                         }
     146             :                         else
     147             :                         {
     148        6353 :                             if ((strcmp((const char*)caseList->name, "defaultinline") != 0) && (strcmp((const char*)caseList->name, "default") != 0))
     149             :                             {
     150           0 :                                 xmlAddChild(root, clone(caseList, appl));
     151             :                             }
     152             :                             else
     153             :                             {
     154        6353 :                                 if (!isCase)
     155             :                                 {
     156        6353 :                                     xmlNodePtr clp = caseList->xmlChildrenNode;
     157       19704 :                                     while (clp)
     158             :                                     {
     159        6998 :                                         xmlAddChild(root, clone(clp, appl));
     160        6998 :                                         clp = clp->next;
     161             :                                     }
     162             :                                 }
     163             :                             }
     164             :                         }
     165       19163 :                         caseList = caseList->next;
     166             :                     }
     167       11434 :                 }
     168             :             }
     169             :             else
     170             :             {
     171      923371 :                 xmlAddChild(root, clone(list, appl));
     172             :             }
     173      934805 :             list = list->next;
     174             :         }
     175             :     }
     176      939275 :     return root;
     177             : }
     178             : 
     179        8906 : class myparser
     180             : {
     181             : public:
     182             :     std::string documentId;
     183             :     std::string fileName;
     184             :     std::string title;
     185             :     HashSet *hidlist;
     186             :     Hashtable *keywords;
     187             :     Stringtable *helptexts;
     188             : private:
     189             :     HashSet extendedHelpText;
     190             : public:
     191        8906 :     myparser(const std::string &indocumentId, const std::string &infileName,
     192             :         const std::string &intitle) : documentId(indocumentId), fileName(infileName),
     193        8906 :         title(intitle)
     194             :     {
     195        8906 :         hidlist = new HashSet;
     196        8906 :         keywords = new Hashtable;
     197        8906 :         helptexts = new Stringtable;
     198        8906 :     }
     199             :     void traverse( xmlNodePtr parentNode );
     200             : private:
     201             :     std::string module;
     202             :     std::string dump(xmlNodePtr node);
     203             : };
     204             : 
     205      140861 : std::string myparser::dump(xmlNodePtr node)
     206             : {
     207      140861 :     std::string app;
     208      140861 :     if (node->xmlChildrenNode)
     209             :     {
     210       67497 :         xmlNodePtr list = node->xmlChildrenNode;
     211      214200 :         while (list)
     212             :         {
     213       79206 :             app += dump(list);
     214       79206 :             list = list->next;
     215             :         }
     216             :     }
     217      140861 :     if (xmlNodeIsText(node))
     218             :     {
     219       73176 :         xmlChar *pContent = xmlNodeGetContent(node);
     220       73176 :         app += std::string((const char*)pContent);
     221       73176 :         xmlFree(pContent);
     222             :     }
     223      140861 :     return app;
     224             : }
     225             : 
     226       61337 : void trim(std::string& str)
     227             : {
     228       61337 :     std::string::size_type pos = str.find_last_not_of(' ');
     229       61337 :     if(pos != std::string::npos)
     230             :     {
     231       61161 :         str.erase(pos + 1);
     232       61161 :         pos = str.find_first_not_of(' ');
     233       61161 :         if(pos != std::string::npos)
     234       61161 :             str.erase(0, pos);
     235             :     }
     236             :     else
     237         176 :         str.erase(str.begin(), str.end());
     238       61337 : }
     239             : 
     240      932098 : void myparser::traverse( xmlNodePtr parentNode )
     241             : {
     242             :     // traverse all nodes that belong to the parent
     243             :     xmlNodePtr test ;
     244     1855290 :     for (test = parentNode->xmlChildrenNode; test; test = test->next)
     245             :     {
     246      923192 :         if (fileName.empty() && !strcmp((const char*)test->name, "filename"))
     247             :         {
     248        8906 :             xmlNodePtr node = test->xmlChildrenNode;
     249        8906 :             if (xmlNodeIsText(node))
     250             :             {
     251        8906 :                 xmlChar *pContent = xmlNodeGetContent(node);
     252        8906 :                 fileName = std::string((const char*)pContent);
     253        8906 :                 xmlFree(pContent);
     254             :             }
     255             :         }
     256      914286 :         else if (title.empty() && !strcmp((const char*)test->name, "title"))
     257             :         {
     258        8906 :             title = dump(test);
     259        8906 :             if (title.empty())
     260           8 :                 title = "<notitle>";
     261             :         }
     262      905380 :         else if (!strcmp((const char*)test->name, "bookmark"))
     263             :         {
     264       46442 :             xmlChar *branchxml = xmlGetProp(test, (const xmlChar*)"branch");
     265       46442 :             xmlChar *idxml = xmlGetProp(test, (const xmlChar*)"id");
     266       46442 :             std::string branch((const char*)branchxml);
     267       46442 :             std::string anchor((const char*)idxml);
     268       46442 :             xmlFree (branchxml);
     269       46442 :             xmlFree (idxml);
     270             : 
     271       46442 :             std::string hid;
     272             : 
     273       46442 :             if (branch.find("hid") == 0)
     274             :             {
     275       41593 :                 size_t index = branch.find('/');
     276       41593 :                 if (index != std::string::npos)
     277             :                 {
     278       41593 :                     hid = branch.substr(1 + index);
     279             :                     // one shall serve as a documentId
     280       41593 :                     if (documentId.empty())
     281        6037 :                         documentId = hid;
     282       41593 :                     extendedHelpText.push_back(hid);
     283       41593 :                     std::string foo = anchor.empty() ? hid : hid + "#" + anchor;
     284             :                     HCDBG(std::cerr << "hid pushback" << foo << std::endl);
     285       41593 :                     hidlist->push_back( anchor.empty() ? hid : hid + "#" + anchor);
     286             :                 }
     287             :                 else
     288           0 :                     continue;
     289             :             }
     290        4849 :             else if (branch.compare("index") == 0)
     291             :             {
     292        4847 :                 LinkedList ll;
     293             : 
     294       23741 :                 for (xmlNodePtr nd = test->xmlChildrenNode; nd; nd = nd->next)
     295             :                 {
     296       18894 :                     if (strcmp((const char*)nd->name, "bookmark_value"))
     297           0 :                         continue;
     298             : 
     299       18894 :                     std::string embedded;
     300       18894 :                     xmlChar *embeddedxml = xmlGetProp(nd, (const xmlChar*)"embedded");
     301       18894 :                     if (embeddedxml)
     302             :                     {
     303           0 :                         embedded = std::string((const char*)embeddedxml);
     304           0 :                         xmlFree (embeddedxml);
     305             :                         std::transform (embedded.begin(), embedded.end(),
     306           0 :                             embedded.begin(), tocharlower);
     307             :                     }
     308             : 
     309       18894 :                     bool isEmbedded = !embedded.empty() && embedded.compare("true") == 0;
     310       18894 :                     if (isEmbedded)
     311           0 :                         continue;
     312             : 
     313       18894 :                     std::string keyword = dump(nd);
     314       18894 :                     size_t keywordSem = keyword.find(';');
     315       18894 :                     if (keywordSem != std::string::npos)
     316             :                     {
     317             :                         std::string tmppre =
     318       13741 :                                     keyword.substr(0,keywordSem);
     319       13741 :                         trim(tmppre);
     320             :                         std::string tmppos =
     321       13741 :                                     keyword.substr(1+keywordSem);
     322       13741 :                         trim(tmppos);
     323       13741 :                         keyword = tmppre + ";" + tmppos;
     324             :                     }
     325       18894 :                     ll.push_back(keyword);
     326       18894 :                 }
     327        4847 :                 if (!ll.empty())
     328        4847 :                     (*keywords)[anchor] = ll;
     329             :             }
     330           2 :             else if (branch.compare("contents") == 0)
     331             :             {
     332             :                 // currently not used
     333       46442 :             }
     334             :         }
     335      858938 :         else if (!strcmp((const char*)test->name, "ahelp"))
     336             :         {
     337       33855 :             std::string text = dump(test);
     338       33855 :             trim(text);
     339       33855 :             std::string name;
     340             : 
     341       33855 :             HashSet::const_iterator aEnd = extendedHelpText.end();
     342       75090 :             for (HashSet::const_iterator iter = extendedHelpText.begin(); iter != aEnd; ++iter)
     343             :             {
     344       41235 :                 name = *iter;
     345       41235 :                 (*helptexts)[name] = text;
     346             :             }
     347       33855 :             extendedHelpText.clear();
     348             :         }
     349             :         // traverse children
     350      923192 :         traverse(test);
     351             :     }
     352      932098 : }
     353             : 
     354        8906 : bool HelpCompiler::compile( void ) throw( HelpProcessingException )
     355             : {
     356             :     // we now have the jaroutputstream, which will contain the document.
     357             :     // now determine the document as a dom tree in variable docResolved
     358             : 
     359        8906 :     xmlDocPtr docResolvedOrg = getSourceDocument(inputFile);
     360             : 
     361             :     // now add path to the document
     362             :     // resolve the dom
     363             : 
     364        8906 :     if (!docResolvedOrg)
     365             :     {
     366           0 :         impl_sleep( 3 );
     367           0 :         docResolvedOrg = getSourceDocument(inputFile);
     368           0 :         if( !docResolvedOrg )
     369             :         {
     370           0 :             std::stringstream aStrStream;
     371           0 :             aStrStream << "ERROR: file not existing: " << inputFile.native_file_string().c_str() << std::endl;
     372           0 :             throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
     373             :         }
     374             :     }
     375             : 
     376        8906 :     std::string documentId;
     377        8906 :     std::string fileName;
     378        8906 :     std::string title;
     379             :     // returns a clone of the document with switch-cases resolved
     380        8906 :     std::string appl = module.substr(1);
     381       56382 :     for (unsigned int i = 0; i < appl.length(); ++i)
     382             :     {
     383       47476 :         appl[i]=toupper(appl[i]);
     384             :     }
     385        8906 :     xmlNodePtr docResolved = clone(xmlDocGetRootElement(docResolvedOrg), appl);
     386        8906 :     myparser aparser(documentId, fileName, title);
     387        8906 :     aparser.traverse(docResolved);
     388        8906 :     documentId = aparser.documentId;
     389        8906 :     fileName = aparser.fileName;
     390        8906 :     title = aparser.title;
     391             : 
     392             :     HCDBG(std::cerr << documentId << " : " << fileName << " : " << title << std::endl);
     393             : 
     394        8906 :     xmlDocPtr docResolvedDoc = xmlCopyDoc(docResolvedOrg, false);
     395        8906 :     xmlDocSetRootElement(docResolvedDoc, docResolved);
     396             : 
     397        8906 :     streamTable.dropappl();
     398        8906 :     streamTable.appl_doc = docResolvedDoc;
     399        8906 :     streamTable.appl_hidlist = aparser.hidlist;
     400        8906 :     streamTable.appl_helptexts = aparser.helptexts;
     401        8906 :     streamTable.appl_keywords = aparser.keywords;
     402             : 
     403        8906 :     streamTable.document_id = documentId;
     404        8906 :     streamTable.document_path = fileName;
     405        8906 :     streamTable.document_title = title;
     406        8906 :     std::string actMod = module;
     407             : 
     408        8906 :     if ( !bExtensionMode && !fileName.empty())
     409             :     {
     410        8906 :         if (fileName.find("/text/") == 0)
     411             :         {
     412        8906 :             int len = strlen("/text/");
     413        8906 :             actMod = fileName.substr(len);
     414        8906 :             actMod = actMod.substr(0, actMod.find('/'));
     415             :         }
     416             :     }
     417        8906 :     streamTable.document_module = actMod;
     418        8906 :     xmlFreeDoc(docResolvedOrg);
     419        8906 :     return true;
     420             : }
     421             : 
     422             : namespace fs
     423             : {
     424       79308 :     rtl_TextEncoding getThreadTextEncoding( void )
     425             :     {
     426             :         static bool bNeedsInit = true;
     427             :         static rtl_TextEncoding nThreadTextEncoding;
     428       79308 :         if( bNeedsInit )
     429             :         {
     430           9 :             bNeedsInit = false;
     431           9 :             nThreadTextEncoding = osl_getThreadTextEncoding();
     432             :         }
     433       79308 :         return nThreadTextEncoding;
     434             :     }
     435             : 
     436          25 :     void create_directory(const fs::path indexDirName)
     437             :     {
     438             :         HCDBG(
     439             :             std::cerr << "creating " <<
     440             :             rtl::OUStringToOString(indexDirName.data, RTL_TEXTENCODING_UTF8).getStr()
     441             :             << std::endl
     442             :            );
     443          25 :         osl::Directory::createPath(indexDirName.data);
     444          25 :     }
     445             : 
     446          30 :     void copy(const fs::path &src, const fs::path &dest)
     447             :     {
     448          30 :         osl::File::copy(src.data, dest.data);
     449          30 :     }
     450             : }
     451             : 
     452             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10