LIMA
Libre Multilingual Analyzer — C++ API
Loading...
Searching...
No Matches
CoreLinguisticProcessingClient.cpp
Go to the documentation of this file.
1// Copyright 2004-2021 CEA LIST
2// SPDX-FileCopyrightText: 2022 CEA LIST <gael.de-chalendar@cea.fr>
3//
4// SPDX-License-Identifier: MIT
5
6#ifdef WIN32
7#define _WINSOCKAPI_
8#endif
9
10#ifndef WIN32
11#include <cstdint> //uint32_t
12#endif
13
15
29
30#include <QDate>
31#include <QFileInfo>
32#include <QRegularExpression>
33
34uint64_t t1;
35
36using namespace std;
37using namespace Lima::Common::MediaticData;
39
40//using namespace boost;
41
42uint64_t t2;
43
44namespace Lima
45{
46
47namespace LinguisticProcessing
48{
49std::unique_ptr<CoreLinguisticProcessingClientFactory> CoreLinguisticProcessingClientFactory::s_instance=std::unique_ptr<CoreLinguisticProcessingClientFactory>(new CoreLinguisticProcessingClientFactory());
50
51
53{
54 //CORECLIENTLOGINIT;
55 //LERROR << "CoreLinguisticProcessingClient::CoreLinguisticProcessingClient()";
56}
57
59{
60 //CORECLIENTLOGINIT;
61 //LERROR << "CoreLinguisticProcessingClient::~CoreLinguisticProcessingClient()";
62}
63
64std::shared_ptr<AnalysisContent> CoreLinguisticProcessingClient::analyze(
65 const std::string& text,
66 const std::map<std::string,std::string>& metaData,
67 const std::string& pipelineId,
68 const std::map<std::string, AbstractAnalysisHandler*>& handlers,
69 const std::set<std::string>& inactiveUnits) const
70
71{
72 auto limatext = QString::fromStdString(text);
73
74 return analyze(limatext, metaData, pipelineId, handlers, inactiveUnits);
75}
76
77std::shared_ptr<AnalysisContent> CoreLinguisticProcessingClient::analyze(
78 const QString& text,
79 const std::map<std::string,std::string>& metaData,
80 const std::string& pipelineId,
81 const std::map<std::string, AbstractAnalysisHandler*>& handlers,
82 const std::set<std::string>& inactiveUnits) const
83
84{
85 Lima::TimeUtilsController timer("CoreLinguisticProcessingClient::analyze");
87
88 //if (text.isEmpty())
89
90 QString whitespaceOnly("\\s*");
91
92 whitespaceOnly = QRegularExpression::anchoredPattern(whitespaceOnly);
93 auto analysis = std::make_shared<AnalysisContent>();
94 if (QRegularExpression(whitespaceOnly).match(text).hasMatch())
95 {
96 LWARN << "Empty text given to LIMA linguistic processing client. Nothing to do.";
97 return analysis;
98 }
99
100 // create analysis content
101 LinguisticMetaData* metadataholder=new LinguisticMetaData(); // will be destroyed in AnalysisContent destructor
102 analysis->setData("LinguisticMetaData",metadataholder);
103
104 metadataholder->setMetaData(metaData);
105 LimaStringText* lstexte=new LimaStringText(text); // will be destroyed in AnalysisContent destructor
106 analysis->setData("Text", lstexte);
107
108 LINFO << "CoreLinguisticProcessingClient::analyze(";
109 for(auto attrIt = metaData.cbegin() ; attrIt != metaData.cend() ; attrIt++ ) {
110 LINFO << "attr:" << attrIt->first << "value:" << attrIt->second << ", " ;
111 }
112 LINFO;
113
114 // add date/time/location metadata in LinguisticMetaData
115#ifdef DEBUG_LP
116 if (metaData.empty()) {
117 LDEBUG << "CoreLinguisticProcessingClient::analyze: no metadata";
118 }
119#endif
120 for (auto it=metaData.cbegin(), it_end=metaData.cend(); it!=it_end; it++)
121 {
122 if ((*it).first=="date")
123 {
124 try {
125 const auto& str = (*it).second;
126 auto i = str.find("T"); //2006-12-11T12:44:00
127 /*if (i!=std::string::npos) {
128 QTime docTime=posix_time::time_from_string(str);
129 metadataholder->setTime("document",docTime);
130 LDEBUG << "use '"<< str << "' as document time";
131 }*/
132 std::string date(str, 0, i);
133 auto docDate = QDate::fromString(date.c_str(),Qt::ISODate);
134 metadataholder->setDate("document",docDate);
135
136#ifdef DEBUG_LP
137 LDEBUG << "use '"<< date << "' as document date";
138 LDEBUG << "use boost'"<< docDate.day() <<"/"<< docDate.month() <<"/"<< docDate.year() << "' as document date";
139#endif
140 }
141 catch (std::exception& e)
142 {
143 LERROR << "Error in date conversion (date '"<< (*it).second
144 << "' will be ignored): " << e.what();
145 }
146 }
147 else if ((*it).first=="location")
148 {
149 metadataholder->setLocation("document",(*it).second);
150#ifdef DEBUG_LP
151 LDEBUG << "use '"<< (*it).second<< "' as document location";
152#endif
153 }
154 else if ((*it).first=="time")
155 {
156 try {
157 auto docTime= QTime::fromString((*it).second.c_str(),"hh:mm:ss.z" );
158 metadataholder->setTime("document",docTime);
159#ifdef DEBUG_LP
160 LDEBUG << "use '"<< (*it).second<< "' as document time";
161#endif
162 }
163 catch (std::exception& e)
164 {
165 LERROR << "Error in ptime conversion (time '"<< (*it).second
166 << "' will be ignored): " << e.what();
167 }
168 }
169 else if ((*it).first=="docid")
170 {
171#ifdef DEBUG_LP
172 LDEBUG << "use '"<< (*it).second<< "' as document id";
173#endif
174 metadataholder->setMetaData("DocId",(*it).second);
175 }
176 }
177
178 std::string docId;
179 try
180 {
181 docId = metadataholder->getMetaData("DocId");
182 }
184 {
185 metadataholder->setMetaData("DocId", docId);
186 }
187 LINFO << "CoreLinguisticProcessingClient::analyze(" << docId << "...)";
188
189
190 // try to retrieve offset
191 try
192 {
193 const auto& offsetStr = metadataholder->getMetaData("StartOffset");
194 metadataholder->setStartOffset(atoi(offsetStr.c_str()));
195 }
197 {
198 metadataholder->setStartOffset(0);
199 }
200
201 const auto& fileName = metadataholder->getMetaData("FileName");
202 // get language
203 const auto& lang = metadataholder->getMetaData("Lang");
204 LINFO << "analyze file is: '" << fileName << "'";
205 LINFO << "analyze pipeline is '" << pipelineId << "'";
206 LINFO << "analyze language is '" << lang << "'";
207#ifdef DEBUG_LP
208 LDEBUG << "text : " << text;
209#endif
210 //LDEBUG << "text : " << Common::Misc::limastring2utf8stdstring(texte);
211
212 auto langId = MediaticData::single().getMediaId(lang);
213
214 // get pipeline
215 auto pipeline = MediaProcessors::single().getPipelineForId(langId,pipelineId);
216 if (pipeline == nullptr)
217 {
218 LERROR << "can't get pipeline '" << pipelineId << "'";
220 std::string("can't get pipeline '" + pipelineId + "' for language '" + lang + "'") );
221 }
222 InactiveUnitsData* inactiveUnitsData = new InactiveUnitsData();
223 for (auto inactiveUnit: inactiveUnits)
224 {
225// const_cast<MediaProcessUnitPipeline*>(pipeline)->setInactiveProcessUnit(*it);
226 inactiveUnitsData->insert(inactiveUnit);
227 }
228 analysis->setData("InactiveUnits", inactiveUnitsData);
229
230 // add handler to analysis
231#ifdef DEBUG_LP
232 LDEBUG << "add handler to analysis" ;
233 for (auto hit = handlers.begin(); hit != handlers.end(); hit++)
234 {
235 LDEBUG << " " << (*hit).first << (*hit).second;
236 }
237#endif
238 auto h = new AnalysisHandlerContainer(const_cast<std::map<std::string, AbstractAnalysisHandler*>& >(handlers));
239#ifdef DEBUG_LP
240 LDEBUG << "set data" ;
241#endif
242 analysis->setData("AnalysisHandlerContainer", h);
243
244 // process analysis
245#ifdef DEBUG_LP
246 LDEBUG << "Process pipeline..." ;
247#endif
248 auto status = pipeline->process(*analysis);
249#ifdef DEBUG_LP
250 LDEBUG << "pipeline process returned status " << (int)status ;
251#endif
252 if (status!=SUCCESS_ID)
253 {
254 LIMA_LP_EXCEPTION( "analysis failed : receive status " << (int)status
255 << " from pipeline." );
256 }
257 return analysis;
258}
259
260CoreLinguisticProcessingClientFactory::CoreLinguisticProcessingClientFactory() :
262{
263 //std::cerr << "CoreLinguisticProcessingClientFactory::CoreLinguisticProcessingClientFactory()" << std::endl;
264 //std::cerr << " calling AbstractLinguisticProcessingClientFactory(\"lima-coreclient\")" << std::endl;
265}
266
268{
269 //std::cerr << "CoreLinguisticProcessingClientFactory::~CoreLinguisticProcessingClientFactory()" << std::endl;
270}
271
274 std::deque<std::string> langs,
275 std::deque<std::string> pipelines)
276{
277 Lima::TimeUtilsController timer("LPCoreClientInit");
279 LINFO << "CoreLinguisticProcessingClientFactory::configure";
280
281 // initialize some entity types internally used in linguistic processing
283
284 deque<string> langToload(langs);
285 if (langToload.empty())
286 {
287 try
288 {
289 langToload = configuration.getModuleGroupListValues("lima-coreclient",
290 "mediaProcessingDefinitionFiles",
291 "available");
292 }
293 catch (NoSuchList& )
294 {
295 LERROR << "no parameter lima-coreclient/mediaProcessingDefinitionFiles/available !";
296 throw InvalidConfiguration("no parameter lima-coreclient/mediaProcessingDefinitionFiles/available !");
297 }
298 }
299
300 for (const auto& lang: langToload)
301 {
302 LINFO << "CoreLinguisticProcessingClientFactory::configure load language " << lang;
303 auto langid = MediaticData::single().getMediaId(lang);
304 QString file;
305 try
306 {
307 auto configPaths = QString::fromUtf8(Common::MediaticData::MediaticData::single().getConfigPath().c_str()).split(LIMA_PATH_SEPARATOR);
308 if (configPaths.isEmpty())
309 {
310 LERROR << "no config paths available in MediaticData";
311 throw InvalidConfiguration("no config paths available in MediaticData");
312 }
313 auto mediaProcessingDefinitionFile = QString::fromUtf8(configuration.getModuleGroupParamValue(
314 "lima-coreclient",
315 "mediaProcessingDefinitionFiles",
316 lang).c_str());
317 Q_FOREACH(QString confPath, configPaths)
318 {
319 if (QFileInfo::exists(confPath + "/" + mediaProcessingDefinitionFile))
320 {
321 file = confPath + "/" + mediaProcessingDefinitionFile;
322 break;
323 }
324 }
325 if (file.isEmpty())
326 {
327 LERROR << "no language definition file"<< mediaProcessingDefinitionFile
328 << "for language" << lang << "found in config paths"
329 << configPaths;
330 throw InvalidConfiguration("no language definition file for language ");
331 }
332 }
333 catch (NoSuchParam& )
334 {
335 LERROR << "no language definition file for language " << lang;
336 throw InvalidConfiguration("no language definition file for language ");
337 }
338 XMLConfigurationFileParser langParser(file);
339
340 //initialize SpecificEntities
342
343 // initialize resources
344 LINFO << "configure resources for language " << lang;
345 try
346 {
347 auto& module = langParser.getModuleConfiguration("Resources");
348 LinguisticResources::changeable().initLanguage(
349 langid,
350 module,
351 lang.find("ud-") != 0 && lang != "ud"); // load main keys for non ud languages
352 }
353 catch (NoSuchModule& )
354 {
355 LERROR << "no module 'Resources' in configuration file " << file;
356 throw InvalidConfiguration("no module 'Resources' in configuration file ");
357 }
358
359 // initialize processors
360 LINFO << "initialize processors";
361 try
362 {
363 auto& procmodule = langParser.getModuleConfiguration("Processors");
365 langid,
366 procmodule/*,
367 dumpmodule*/);
368 }
369 catch (NoSuchModule& )
370 {
371 LERROR << "missing module 'Processors' in language configuration file " << file;
372 throw InvalidConfiguration("missing module 'Processors' in language configuration file ");
373 }
374
375 }
376
377 LINFO << "initialize Pipelines";
378 try
379 {
380 auto& group = configuration.getModuleGroupConfiguration("lima-coreclient","pipelines");
382 }
383 catch (NoSuchModule& )
384 {
385 LERROR << "no module 'pipelines' in lima-analysis.xml (configuration file)";
386 throw InvalidConfiguration("no module 'pipelines' in mm-LP.xml (configuration file)");
387 }
388}
389
390std::shared_ptr< AbstractProcessingClient > CoreLinguisticProcessingClientFactory::createClient() const
391{
392 return std::shared_ptr< AbstractProcessingClient >(new CoreLinguisticProcessingClient());
393}
394
395
396} // LinguisticProcessing
397
398} // Lima
#define LIMA_PATH_SEPARATOR
Definition FileUtils.h:25
#define LWARN
Definition LimaCommon.h:160
#define LDEBUG
Definition LimaCommon.h:157
#define LINFO
Definition LimaCommon.h:158
#define LERROR
Definition LimaCommon.h:161
#define LPCLIENTFACTORYLOGINIT
#define CORECLIENTLOGINIT
#define LIMA_LP_EXCEPTION(X)
This macro writes the message X to a previously configured error stream before throwing a LinguisticP...
virtual void initEntityTypes(XMLConfigurationFiles::XMLConfigurationFileParser &configParser)
return a message when a 'module' is not found
return a message when a 'param' was not found
Parser class for the lima's xml configuration files.
GroupConfigurationStructure & getModuleGroupConfiguration(const std::string &moduleName, const std::string &groupName)
std::deque< std::string > & getModuleGroupListValues(const std::string &moduleName, const std::string &groupName, const std::string &key)
std::string & getModuleGroupParamValue(const std::string &moduleName, const std::string &groupName, const std::string &key)
ModuleConfigurationStructure & getModuleConfiguration(const std::string &moduleName)
Use this exception to signal an error in one of the configuration files.
Definition LimaCommon.h:345
A factory for the AbstractLinguisticProcessingClient: contains the registration of all implemented cl...
void configure(Common::XMLConfigurationFiles::XMLConfigurationFileParser &configuration, std::deque< std::string > langs, std::deque< std::string > pipelines) override
This function configures the factory, using an XML configuration file S2-lp.xml.
std::shared_ptr< AbstractProcessingClient > createClient() const override
This function create a LinguisticProcessing client.
std::shared_ptr< AnalysisContent > analyze(const QString &texte, const std::map< std::string, std::string > &metaData, const std::string &pipeline, const std::map< std::string, AbstractAnalysisHandler * > &handlers, const std::set< std::string > &inactiveUnits=std::set< std::string >()) const override
This function runs the linguistic analysis on a simple text, specifying the language,...
define the limaStringText resource which is the text in limaString formal
contains metadata to be kept during the analysis: global generic metadata: file name,...
void setLocation(const std::string &locName, const std::string &)
void setTime(const std::string &timeName, const QTime &)
void setMetaData(const std::string &id, const std::string &value)
const std::string & getMetaData(const std::string &id) const
void setDate(const std::string &dateName, const QDate &)
void initPipelines(Common::XMLConfigurationFiles::GroupConfigurationStructure &confModule, const std::deque< std::string > &pipelines)
void initMedia(MediaId, Common::XMLConfigurationFiles::ModuleConfigurationStructure &procConf)
std::shared_ptr< MediaProcessUnitPipeline > getPipelineForId(MediaId med, const std::string &id) const
get the pipeline for the given id and media
static const MediaProcessors & single()
const singleton accessor
Definition Singleton.h:51
static MediaticData & changeable()
singleton accessor
Definition Singleton.h:71
This file contains a class to control log of informations about time, such as logging cumulated time ...
NAUTITIA.
@ SUCCESS_ID
Definition LimaCommon.h:237
STL namespace.
launch exception related to the configuration file parsing