LIMA
Libre Multilingual Analyzer — C++ API
Loading...
Searching...
No Matches
SpecificEntitiesLoader.cpp
Go to the documentation of this file.
1// Copyright 2002-2022 CEA LIST
2// SPDX-FileCopyrightText: 2022 CEA LIST <gael.de-chalendar@cea.fr>
3//
4// SPDX-License-Identifier: MIT
5
6/************************************************************************
7 * @author Romaric Besancon <romaric.besancon@cea.fr>
8 * @date Thu Jun 16 2011
9 ***********************************************************************/
10
19#include <queue>
20
21#include <QXmlStreamReader>
22
25
26namespace Lima {
27namespace LinguisticProcessing {
28namespace SpecificEntities {
29
31
33{
35 public:
38
39 bool parse(QIODevice *device);
40
41 QString errorString() const;
42
43 QXmlStreamReader m_reader;
44 MediaId m_language;
45 QString m_graphName;
46
47// AnalysisContent& m_analysis;
49 uint64_t m_position;
50 uint64_t m_length;
51 std::string m_type;
52 std::string m_string;
53 std::string m_currentElement;
54
55 // private member functions
56 std::string toString(const QString& xercesString);
57
60 const std::string& str,
61 const std::string& type,
62 uint64_t position,
63 uint64_t length);
64};
65
66//***********************************************************************
67// constructors and destructors
72
74 m_language(0),
75 m_graphName("AnalysisGraph")
76{
77}
78
79//***********************************************************************
81 Manager* manager)
82
83{
84 LOGINIT("LP::SpecificEntities");
85
86 m_d->m_language=manager->getInitializationParameters().media;
87
88 AnalysisLoader::init(unitConfiguration,manager);
89 try {
90 m_d->m_graphName = QString::fromStdString(unitConfiguration.getParamsValueAtKey("graph"));
91 }
92 catch (Common::XMLConfigurationFiles::NoSuchParam& ) {} // keep default value
93
94 try {
95 // may need to initialize a modex, to know about the entities in external file
96 auto& modexes = unitConfiguration.getListsValueAtKey("modex");
97 for (const auto& modex: modexes)
98 {
99 LDEBUG << "loader: initialize modex " << modex;
100 QString filename = Common::Misc::findFileInPaths(
101 QString::fromStdString(Common::MediaticData::MediaticData::single().getConfigPath()),
102 QString::fromStdString(modex));
105 }
106 }
108 LWARN << "loader: no modex specified in parameter: types in file loaded may not be known";
109 }
110}
111
113{
114 // get analysis graph
115 auto graph = std::dynamic_pointer_cast<AnalysisGraph>(analysis.getData(m_d->m_graphName.toStdString()));
116 if (graph == nullptr)
117 {
118 LOGINIT("LP::SpecificEntities");
119 LERROR << "no graph '" << m_d->m_graphName << "' available !";
120 return MISSING_DATA;
121 }
122
123 //create a RecognizerData (such as in ApplyRecognizer) to be able to use
124 //CreateSpecificEntity actions
125 auto recoData = new RecognizerData();
126 analysis.setData("RecognizerData", recoData);
127 auto resultData = new RecognizerResultData(m_d->m_graphName.toStdString());
128 recoData->setResultData(resultData);
129
130 try
131 {
132 auto filename = getInputFile(analysis);
133 QFile file(filename);
134 if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
135 LIMA_EXCEPTION_SELECT_LOGINIT(LOGINIT("LP::SpecificEntities"),
136 "Cannot open file" << filename,
138 if (!m_d->parse(&file))
139 {
140 LIMA_EXCEPTION_SELECT_LOGINIT(LOGINIT("LP::SpecificEntities"),
141 "Error: failed to parse XML input file" << filename << m_d->m_reader.errorString(),
143 }
144 }
145 catch (const XMLException& )
146 {
147 }
148
149 // remove recognizer data (used only internally to this process unit)
150 recoData->deleteResultData();
151 resultData=0;
152 analysis.removeData("RecognizerData");
153
154 return SUCCESS_ID;
155}
156
158{
159 LOGINIT("LP::SpecificEntities");
160 LTRACE << "parse";
161 m_reader.setDevice(device);
162 while (m_reader.readNextStartElement())
163 {
164 bool ok;
165 if (m_reader.name() == QLatin1String("specific_entity"))
166 {
167 if (m_type != "")
168 {
169 LDEBUG << "SpecificEntitiesLoaderPrivate add SE " << m_type << "," << m_position << "," << m_length << "," << m_graph;
171 }
172 m_string="";
173 m_type="";
174 m_position=0;
175 m_length=0;
176 }
177 else if (m_reader.name() == QLatin1String("position"))
178 {
179 m_position = m_reader.readElementText().toInt(&ok);
180 if (!ok)
181 {
182 m_reader.raiseError(QObject::tr("Cannot convert position value %1 to integer.").arg(m_reader.text()));
183 }
184 }
185 else if (m_reader.name() == QLatin1String("length"))
186 {
187 m_length = m_reader.readElementText().toInt(&ok);
188 if (!ok)
189 {
190 m_reader.raiseError(QObject::tr("Cannot convert position value %1 to integer.").arg(m_reader.text()));
191 }
192 }
193 else if (m_reader.name() == QLatin1String("type"))
194 {
195 m_type = m_reader.readElementText().toStdString();
196 }
197 else if (m_reader.name() == QLatin1String("string"))
198 {
199 m_string = m_reader.readElementText().toStdString();
200 }
201 else
202 {
203 m_reader.skipCurrentElement();
204 }
205 }
206 return !m_reader.error();
207}
208
209
210//***********************************************************************
212 AnalysisContent& analysis,
214 const std::string& str,
215 const std::string& type,
216 uint64_t position,
217 uint64_t length)
218{
219 LOGINIT("LP::SpecificEntities");
220 LDEBUG << "loader: add entity " << str << "," << type << ",[" << position << "," << length << "]";
221 // create RecognizerMatch
222 Automaton::RecognizerMatch match(anagraph);
223
224 uint64_t posBegin=position;
225 uint64_t posEnd=posBegin+length;
226
227 // find vertices corresponding to pos/len : have to go through the graph
228 LinguisticGraph* graph=anagraph->getGraph();
229 std::queue<LinguisticGraphVertex> toVisit;
230 std::set<LinguisticGraphVertex> visited;
231 LinguisticGraphOutEdgeIt outItr,outItrEnd;
232
233 // output vertices between begin and end,
234 toVisit.push(anagraph->firstVertex());
235
236 bool first=true;
237 bool inEntity=false;
238 while (!toVisit.empty()) {
239 LinguisticGraphVertex v=toVisit.front();
240 toVisit.pop();
241 if (v == anagraph->lastVertex()) {
242 break;
243 }
244
245 if (first) {
246 first=false;
247 }
248 else if (inEntity) {
250 if (t->position() >= posEnd) {
251 inEntity=false;
252 break; // no need to go further
253 }
254 else {
255 // OME?? valeur true?,"SE"?
256 match.addBackVertex(v,true,"SE");
257 }
258 }
259 else {
261 if(t!=0) {
262 if (t->position() == posBegin) {
263 match.addBackVertex(v,true,"SE");
264 inEntity=true;
265 }
266 }
267 }
268
269 // add next vertices
270 for (boost::tie(outItr,outItrEnd)=out_edges(v,*graph); outItr!=outItrEnd; outItr++)
271 {
272 LinguisticGraphVertex next=target(*outItr,*graph);
273 if (visited.find(next)==visited.end())
274 {
275 visited.insert(next);
276 toVisit.push(next);
277 }
278 }
279 }
280
281 if (match.size()==0) {
282 LWARN << "Warning: no matching vertices for given position/length";
283 }
284
285 // set entity properties
287 try {
288 entityType = Common::MediaticData::MediaticData::single().getEntityType(QString::fromStdString(type));
289 } catch (const LimaException& e) {
290 LIMA_EXCEPTION("Unknown entity" << QString::fromStdString(type) << e.what());
291 }
292 match.setType(entityType);
293 // set normalized form similar to string (otherwise, may cause problem when trying to access the created specific entity)
295
296 // create specific entity from RecognizerMatch using default action
297 CreateSpecificEntity createEntity(m_language);
298 createEntity(match,analysis);
299}
300
302{
303 LOGINIT("LP::SpecificEntities");
304 auto errorStr = QObject::tr("%1, Line %2, column %3")
305 .arg(m_reader.errorString())
306 .arg(m_reader.lineNumber())
307 .arg(m_reader.columnNumber());
308 LERROR << errorStr;
309 return errorStr;
310}
311
312
313} // end namespace
314} // end namespace
315} // end namespace
#define DEFAULT_ATTRIBUTE
#define LWARN
Definition LimaCommon.h:160
#define LIMA_EXCEPTION_SELECT_LOGINIT(X, Y, Z)
This macro writes the message Y to the error stream configured by its first parameter X,...
Definition LimaCommon.h:332
#define LIMA_EXCEPTION(X)
This macro writes the message X to a previously configured error stream before throwing a LimaExcepti...
Definition LimaCommon.h:293
#define LTRACE
Definition LimaCommon.h:156
#define LOGINIT(X)
Definition LimaCommon.h:187
#define LDEBUG
Definition LimaCommon.h:157
#define LERROR
Definition LimaCommon.h:161
@ vertex_token
LinguisticGraph::vertex_descriptor LinguisticGraphVertex
LinguisticGraph::out_edge_iterator LinguisticGraphOutEdgeIt
boost::adjacency_list< boost::vecS, boost::vecS, boost::bidirectionalS, LinguisticVertexProperties > LinguisticGraph
Property to identify the chains in the graph.
Defines a Factory to create Object of type Base.
#define SPECIFICENTITIESLOADER_CLASSID
Holds all data that pass through the ProcessUnits Analysis data are shared pointers,...
void removeData(const QString &id)
remove the analysisData with the given id
std::shared_ptr< AnalysisData > getData(const QString &id)
return AnalysisData by id
void setData(const QString &id, std::shared_ptr< AnalysisData > data)
set an analysisData with the given id.
EntityType getEntityType(const LimaString &entityName) const
entity types manager
virtual void initEntityTypes(XMLConfigurationFiles::XMLConfigurationFileParser &configParser)
std::deque< std::string > & getListsValueAtKey(const std::string &key)
return a message when a 'param' was not found
Parser class for the lima's xml configuration files.
Manage initialization of InitializableObjects using configuration module and parameters.
const InitializationParameters & getInitializationParameters() const
get Initialization Parameters
The main LIMA exception class.
Definition LimaCommon.h:262
virtual const char * what() const override
Definition LimaCommon.h:280
void init(Common::XMLConfigurationFiles::GroupConfigurationStructure &unitConfiguration, Manager *manager) override
initialize with parameters from configuration file.
QString getInputFile(AnalysisContent &analysis) const
void setFeature(const std::string &name, const ValueType &value)
void setType(const Common::MediaticData::EntityType &t)
void addBackVertex(const LinguisticGraphVertex &, bool isKept=true, const LimaString &ruleElementId="")
An AnalysisData containing a LinguisticGraph with a language and an id.
const LinguisticGraphVertex & lastVertex(void) const
Returns the last vertex of the graph.
const LinguisticGraph * getGraph(void) const
Returns the underlying graph structure.
const LinguisticGraphVertex & firstVertex(void) const
Returns the first vertex of the graph.
This action creates a new vertex for given match containing a specific entity's data.
void addSpecificEntity(AnalysisContent &analysis, LinguisticAnalysisStructure::AnalysisGraph *graph, const std::string &str, const std::string &type, uint64_t position, uint64_t length)
void init(Common::XMLConfigurationFiles::GroupConfigurationStructure &unitConfiguration, Manager *manager) override
initialize with parameters from configuration file.
LimaStatusCode process(AnalysisContent &analysis) const override
Process on data in analysisContent.
static const MediaticData & single()
const singleton accessor
Definition Singleton.h:51
static MediaticData & changeable()
singleton accessor
Definition Singleton.h:71
Throw this exception when encountering problems with XML files opening or parsing.
Definition LimaCommon.h:470
QString findFileInPaths(const QString &paths, const QString &fileName, const QChar &separator)
Find the given file in the given paths.
LimaString utf8stdstring2limastring(const std::string &src)
SimpleFactory< MediaProcessUnit, SpecificEntitiesLoader > SpecificEntitiesLoaderFactory(SPECIFICENTITIESLOADER_CLASSID)
NAUTITIA.
LimaStatusCode
Definition LimaCommon.h:236
@ SUCCESS_ID
Definition LimaCommon.h:237
@ MISSING_DATA
Definition LimaCommon.h:243