/* accidence * Copyright (C) 2007 Gabriel Bakiewicz * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include "accidence.h" #include "accidence-provider.h" #ifndef COGROO_HOST #define COGROO_HOST "localhost" #endif #ifndef COGROO_PORT #define COGROO_PORT "55000" #endif #ifndef COGROO_METHOD #define COGROO_METHOD "br.usp.pcs.lta.cogroo.integration.server.simple.proxy.CogrooSimpleResponse.checkText" #endif ACCIDENCE_PLUGIN_DECLARE ("Cogroo") typedef struct _CogrooMistake CogrooMistake; struct _CogrooMistake { int iId; int iStart; int iEnd; std::string sMessage; std::vector m_vecSuggestion; }; class Cogroo { public: Cogroo(); ~Cogroo(); accidence_check_status checkSentence(const std::string& sentence); CogrooMistake* getMistake(int iNumMistake); int getNumMistakes() { return m_vecMistake.size(); } bool isConnOK(void) { return !m_bConError; } private: void _parseResult(const std::string& result); void _purgeMistakes(); bool m_bConError; std::string serverUrl; std::vector m_vecMistake; }; Cogroo::Cogroo() :m_bConError(false) { serverUrl += COGROO_HOST; serverUrl += ':'; serverUrl += COGROO_PORT; } Cogroo::~Cogroo() { _purgeMistakes(); } accidence_check_status Cogroo::checkSentence(const std::string& sentence) { if (m_bConError) { return ACCIDENCE_CHECK_ERROR; } g_debug("DEBUG: COGROO SERVER URL: %s", serverUrl.c_str()); g_debug("DEBUG: COGROO Sentence: %s", sentence.c_str()); xmlrpc_c::clientSimple myClient; xmlrpc_c::value result; // Free mistake vector _purgeMistakes(); try { myClient.call(serverUrl, COGROO_METHOD, "s", &result, sentence.c_str()); std::string sResult((xmlrpc_c::value_string(result))); // parse the XML-like result _parseResult(sResult); } catch (girerr::error const error) { std::cout << "DEBUG: unable to connect to cogroo backend" << std::endl; m_bConError = true; return ACCIDENCE_CHECK_ERROR; } g_debug("Cogroo found %d mistakes", m_vecMistake.size()); if (m_vecMistake.size()) return ACCIDENCE_CHECK_MISTAKES; return ACCIDENCE_CHECK_OK; } // TODO: use libxml to parse the result void Cogroo::_parseResult(const std::string& sResult) { std::string::size_type iMistakePos = sResult.find("", 0); while (iMistakePos != std::string::npos) { std::string::size_type iMistakeEnd = sResult.find("", iMistakePos); std::string sMistake = sResult.substr(iMistakePos, iMistakeEnd); CogrooMistake * mstk = NULL; mstk = new CogrooMistake; // looks for the mistake id std::string::size_type idPos = sMistake.find("", 0); std::string::size_type idEnd = sMistake.find("", idPos); std::istringstream ids(sMistake.substr(idPos + 4, idEnd - 1)); ids >> mstk->iId; // std::cout << "DEBUG: cogroo id: " << mstk->iId << std::endl; // looks for mistake message std::string::size_type iMessagePos = sMistake.find("", idEnd); std::string::size_type iMessageEnd = sMistake.find("", iMessagePos); mstk->sMessage = sMistake.substr(iMessagePos + 9, iMessageEnd - iMessagePos - 9); // std::cout << "DEBUG: cogroo message: " << mstk->sMessage.c_str() << std::endl; // looks for mistake start std::string::size_type iStartPos = sMistake.find("", iMessageEnd); std::string::size_type iStartEnd = sMistake.find("", iStartPos); std::istringstream start(sMistake.substr(iStartPos + 7, iStartEnd - iStartPos - 7)); start >> mstk->iStart; // std::cout << "DEBUG: cogroo start: " << mstk->iStart << std::endl; // looks for mistake end std::string::size_type iEndPos = sMistake.find("", iStartEnd); std::string::size_type iEndEnd = sMistake.find("", iEndPos); std::istringstream end(sMistake.substr(iEndPos + 5, iEndEnd - iEndPos - 5)); end >> mstk->iEnd; // std::cout << "DEBUG: cogroo end: " << mstk->iEnd << std::endl; // looks for mistake suggestions std::string::size_type iSuggestionPos = sMistake.find("", iEndEnd); while (iSuggestionPos != std::string::npos) { std::string::size_type iSuggestionEnd = sMistake.find("", iSuggestionPos); std::string sSuggestion = sMistake.substr(iSuggestionPos + 12, iSuggestionEnd - iSuggestionPos - 12); mstk->m_vecSuggestion.push_back(sSuggestion); // std::cout << "DEBUG: cogroo suggestion: " << sSuggestion.c_str() << std::endl; iSuggestionPos = sMistake.find("", iSuggestionEnd); } m_vecMistake.push_back(mstk); iMistakePos = sResult.find("", iMistakeEnd); } // std::cout << "DEBUG: cogroo: End of parse " << std::endl; } CogrooMistake* Cogroo::getMistake(int nMistake) { return m_vecMistake.at(nMistake); } void Cogroo::_purgeMistakes() { std::vector::iterator itVectorData; for (itVectorData = m_vecMistake.begin(); itVectorData != m_vecMistake.end(); itVectorData++) { delete(*itVectorData); } m_vecMistake.clear(); } /******************************/ /* Accidence module functions */ /******************************/ static accidence_check_status cogroo_checker_check_sentence (AccidenceChecker *checker, const char *const sentence) { Cogroo *cogroo_checker; cogroo_checker = (Cogroo *) checker->grammar_data; if (!cogroo_checker) return ACCIDENCE_CHECK_ERROR; return cogroo_checker->checkSentence(sentence); } static AccidenceMistake * convertMistake (CogrooMistake *cogroo_mstk) { int nSuggestions; gsize length; char *szSuggestion; AccidenceMistake *mstk = NULL; mstk = g_new0(AccidenceMistake, 1); mstk->pos_start = cogroo_mstk->iStart; mstk->pos_end = cogroo_mstk->iEnd; mstk->message = const_cast(cogroo_mstk->sMessage.c_str()); nSuggestions = cogroo_mstk->m_vecSuggestion.size(); mstk->num_suggestions = nSuggestions; mstk->suggestions = NULL; mstk->next = NULL; if (nSuggestions > 0) { mstk->suggestions = g_new0 (char *, nSuggestions + 1); for (int iSuggestion = 0; iSuggestion < nSuggestions; iSuggestion++) { szSuggestion = const_cast(cogroo_mstk->m_vecSuggestion.at(iSuggestion).c_str()); mstk->suggestions[iSuggestion] = g_convert (szSuggestion, strlen (szSuggestion), "utf-8", "iso8859-8", NULL, &length, NULL); } } return mstk; } static AccidenceMistake * cogroo_checker_get_mistakes (AccidenceChecker *checker) { AccidenceMistake *mistakes = NULL; AccidenceMistake *mstk_prev = NULL; Cogroo *cogroo_checker; cogroo_checker = (Cogroo *) checker->grammar_data; if (!cogroo_checker) return NULL; for (int i = 0; i < cogroo_checker->getNumMistakes(); i++) { AccidenceMistake *mstk; mstk = convertMistake(cogroo_checker->getMistake(i)); if (mstk_prev) mstk_prev->next = mstk; else mistakes = mstk; mstk_prev = mstk; } return mistakes; } static void cogroo_checker_dispose_mistakes (AccidenceChecker *acc_checker, AccidenceMistake *mistakes) { AccidenceMistake* p_mistake; while (mistakes) { p_mistake = mistakes; mistakes = mistakes->next; g_free(p_mistake->message); g_strfreev(p_mistake->suggestions); g_free(p_mistake); } } static void cogroo_provider_dispose (AccidenceProvider *provider) { g_free (provider); } static AccidenceChecker* cogroo_provider_request_checker (AccidenceProvider *provider, const char *lang_tag) { Cogroo* cogroo_checker; g_return_val_if_fail(provider, NULL); g_return_val_if_fail(lang_tag, NULL); if (provider->checker_exists(provider, lang_tag) == 0) return NULL; cogroo_checker = new Cogroo(); if (!cogroo_checker || !cogroo_checker->isConnOK()) return NULL; AccidenceChecker* checker = g_new0(AccidenceChecker, 1); checker->grammar_data = (void *) cogroo_checker; checker->check_sentence = cogroo_checker_check_sentence; checker->get_mistakes = cogroo_checker_get_mistakes; checker->dispose_mistakes = cogroo_checker_dispose_mistakes; return checker; } static void cogroo_provider_dispose_checker (AccidenceProvider *provider, AccidenceChecker *checker) { // printf("cogroo checker dispose\n"); Cogroo *cogroo_checker; cogroo_checker = (Cogroo *) checker->grammar_data; delete cogroo_checker; g_free(checker); } static const char * cogroo_provider_identify (AccidenceProvider *provider) { return "cogroo"; } static const char * cogroo_provider_describe (AccidenceProvider *provider) { return "Cogroo Provider"; } static bool cogroo_provider_server_is_running (void) { Cogroo checker; return checker.isConnOK(); } static int cogroo_provider_checker_exists (AccidenceProvider *me, const char *const tag) { if (!strcmp ("pt", tag) || !strcmp ("pt_BR", tag)) { return cogroo_provider_server_is_running (); } return 0; } #ifdef __cplusplus extern "C" { #endif AccidenceProvider * init_accidence_provider(void) { AccidenceProvider *provider; provider = g_new0(AccidenceProvider, 1); provider->request_checker = cogroo_provider_request_checker; provider->dispose_checker = cogroo_provider_dispose_checker; provider->dispose = cogroo_provider_dispose; provider->identify = cogroo_provider_identify; provider->describe = cogroo_provider_describe; provider->checker_exists = cogroo_provider_checker_exists; return provider; } #ifdef __cplusplus } /* extern "C" */ #endif