LIMA
Libre Multilingual Analyzer — C++ API
Loading...
Searching...
No Matches
EasyDumper.cpp
Go to the documentation of this file.
1// Copyright 2002-2013 CEA LIST
2// SPDX-FileCopyrightText: 2022 CEA LIST <gael.de-chalendar@cea.fr>
3//
4// SPDX-License-Identifier: MIT
5
20#include "EasyDumper.h"
21#include "easyXmlDumper.h"
22
26
27#include <iostream>
28#include <sstream>
29
30using namespace Lima::Common;
31using namespace Lima::Common::Misc;
32
33namespace Lima {
34namespace LinguisticProcessing {
35namespace AnalysisDumpers {
36namespace EasyXmlDumper {
37
40 const std::map<std::string,std::string>& relationTypeMapping,
41 const std::map<std::string,std::string>& srcVxTag,
42 const std::map<std::string,std::string>& tgtVxTag,
43 const std::string& enonceId) :
44 m_enonceId(enonceId),
45 m_relationTypeMapping(relationTypeMapping),
46 m_srcVxTag(srcVxTag),
47 m_tgtVxTag(tgtVxTag),
48 m_chaines(care.getChaines()),
49 m_vertexToFormeIds(care.getVertexToFormeIds()),
50 m_formesIndex(care.getFormesIndex()),
51 m_relations(care.getRelations()),
52 m_inRelations(care.getInRelations()),
53 m_groupes(care.getGroupes()),
54 m_positionsFormsIds(care.positionsFormsIds()),
55 m_inGroupFormsPositions(care.inGroupFormsPositions())
56{
57 std::map<uint64_t, Groupe>::iterator it, it_end;
58 it = m_groupes.begin(); it_end = m_groupes.end();
59 for (; it != it_end; it++)
60 {
61 Groupe& group = (*it).second;
62 Groupe::iterator git, git_end;
63 git = group.begin(); git_end = group.end();
64 for (; git != git_end; git++)
65 {
67 LDEBUG << "EasyDumper:: setting " << group.id() << " as group of " << git->second;
68 m_formesIdsGroupsIds[git->second]=&group;
69 }
70 }
71}
72
73
75{
76 for (std::vector<Relation*>::iterator it = m_relations.begin(); it != m_relations.end(); it++)
77 {
78 delete *it;
79 }
80}
81
82
83void EasyDumper::dump(std::ostream& out)
84{
85// computeFormeIds();
86 dumpConstituants(out);
87 dumpRelations(out);
88}
89
90void EasyDumper::dumpConstituants(std::ostream& out)
91{
92 std::map< uint64_t, uint64_t >::const_iterator posIt, posIt_end;
93 posIt = m_positionsFormsIds.begin();
94 posIt_end = m_positionsFormsIds.end();
95 uint64_t groupId = 1;
96 uint64_t formId = 1;
97 std::set< uint64_t > alreadyDumpedForms;
98 for (; posIt != posIt_end; posIt++)
99 {
100 uint64_t position = (*posIt).first;
101 uint64_t forme = (*posIt).second;
103 if (m_formesIndex[forme] == 0)
104 {
105 LWARN << "EasyDumper:: form not found " << forme;
106 continue;
107 }
108 if (alreadyDumpedForms.find(position) != alreadyDumpedForms.end())
109 {
110 LDEBUG << "EasyDumper:: already dumped " << m_formesIndex[forme]->forme;
111 continue;
112 }
113 LDEBUG << "EasyDumper:: dump " << m_formesIndex[forme]->forme;
114 if (m_inGroupFormsPositions.find(position) == m_inGroupFormsPositions.end())
115 {
116 std::string sforme = limastring2utf8stdstring(transcodeToXmlEntities(utf8stdstring2limastring((m_formesIndex[forme])->forme)));
117
118 while (sforme.find('_') != std::string::npos)
119 {
120 LDEBUG << "EasyDumper:: remove _ in " << sforme;
121 sforme[sforme.find('_')] = ' ';
122 }
123
124 std::ostringstream oss;
125 oss << m_enonceId << "F"<< formId;
126 out << " <F id=\"" << oss.str() << "\">" << sforme << "</F>" << std::endl;
127 LDEBUG << "EasyDumper:: adding to m_formesIds1: "<<m_formesIndex[forme]->forme<<" -> " << oss.str();
128 m_formesIds.insert(std::make_pair(forme, oss.str()));
129 alreadyDumpedForms.insert((m_formesIndex[forme])->poslong.position);
130 formId++;
131 }
132 else
133 {
134 std::ostringstream sout;
135 if (m_groupes.find(position) == m_groupes.end())
136 {
137 continue;
138 }
139 Groupe& groupe = m_groupes[position];
140 Groupe::const_iterator groupeIt, groupeIt_end;
141 groupeIt = groupe.begin(); groupeIt_end = groupe.end();
142 // compute the chaine id here
143 std::ostringstream oss;
144 oss << m_enonceId << "G" << groupId;
145 groupe.id(groupId);
146 sout << " <Groupe type=\"" << groupe.type() << "\" id=\"" << oss.str() << "\">" << std::endl;
147 m_groupeIdGroupStr[groupe.id()] = oss.str();
148
149 groupeIt = groupe.begin(); groupeIt_end = groupe.end();
151 for (; groupeIt != groupeIt_end; groupeIt++)
152 {
153 std::ostringstream oss;
154 oss << m_enonceId << "F" << formId;
155 std::string sforme = limastring2utf8stdstring(transcodeToXmlEntities((utf8stdstring2limastring(m_formesIndex[(*groupeIt).second]->forme))));
156
157 while (sforme.find('_') != std::string::npos)
158 {
159 LDEBUG << "EasyDumper:: remove _ in " << sforme;
160 sforme[sforme.find('_')] = ' ';
161 }
162 sout << " <F id=\"" << oss.str() << "\">" << sforme << "</F>" << std::endl;
163 m_formesIds.insert(std::make_pair((*groupeIt).second, oss.str()));
164 if (m_formesIndex.find((*groupeIt).second) != m_formesIndex.end())
165 {
166 alreadyDumpedForms.insert((m_formesIndex[(*groupeIt).second])->poslong.position);
167 }
168 else
169 {
170 LERROR << "Error at " << __FILE__ << ", line " << __LINE__;
171 }
172 formId++;
173 }
174 sout << " </Groupe>" << std::endl;
175 out << sout.str();
176 LDEBUG << "EasyDumper:: " << sout.str();
177 groupId++;
178 }
179 }
180}
181
182
183
184void EasyDumper::dumpRelations(std::ostream& out)
185{
186 int numRel=1;
187 // in easy2/passage, the relations tag can be avoided if there is no relation
188 if (m_relations.empty())
189 {
190 return;
191 }
192 out << " <relations>" << std::endl;
193 // to handle three-value relations (COORD)
194 bool notClosed(false);
195 std::string previousRelType(""), previousSrcId("");
196 std::string relType("");
197 for (std::vector<Relation*>::const_iterator it=m_relations.begin();
198 it!=m_relations.end();
199 it++)
200 {
201
202 relType=m_relationTypeMapping[(*it)->type];
204 LDEBUG << "EasyDumper:: relation '"<<relType<<"'";
205 if (relType=="") continue;
206
207 // possible complement
208 std::string complement;
209
210 std::string::size_type i=relType.find(",");
211 if (i!=std::string::npos)
212 {
213 complement=std::string(relType,i+1);
214 relType.erase(i);
215 // add possible quotes around arguments
216 i=0;
217 std::string::size_type j;
218 while ((i=complement.find("=",i)) != std::string::npos
219 && complement[i+1] != '"')
220 {
221 complement.insert(i+1,"\"");
222 j=complement.find(" ",i+1);
223 if (j == std::string::npos)
224 {
225 complement.insert(complement.end(),'"');
226 break;
227 }
228 else
229 {
230 complement.insert(j,"\"");
231 i=j+1;
232 }
233 }
234 }
235
236 std::ostringstream oss;
237 oss << m_enonceId << "R" << numRel++;
238 m_relationsIds[*it]=oss.str();
239
240 std::string srcFormeId=m_formesIds[m_vertexToFormeIds[(*it)->srcVertex]];
241 if (srcFormeId == "")
242 {
243 LWARN << "EasyDumper:: Warning: empty source form id in " << m_enonceId << " for vertex " << (*it)->srcVertex;
244 srcFormeId = m_enonceId + "F0";
245 }
246 std::string tgtFormeId=m_formesIds[m_vertexToFormeIds[(*it)->tgtVertex]];
247 if (tgtFormeId == "")
248 {
249 LWARN << "EasyDumper:: Warning: empty target form id in " << m_enonceId << " for vertex " << (*it)->tgtVertex;
250 tgtFormeId = m_enonceId + "F0";
251 }
252
253 // to handle three-value relations
254 std::string tgtVxTag=m_tgtVxTag[relType];
255 LDEBUG << "EasyDumper:: tgtVxTag=" << tgtVxTag;
256 std::string::size_type k=tgtVxTag.find(",");
257 if (k!=std::string::npos)
258 {
259 LDEBUG << "EasyDumper:: 3-ary relation";
260 if (!notClosed)
261 { //first part
262 LDEBUG << "EasyDumper:: first part: " << tgtVxTag;
263 tgtVxTag.erase(k);
264 previousRelType=relType;
265 previousSrcId=srcFormeId;
266 notClosed=true;
267 }
268 else
269 { // second part
270 notClosed=false;
271 tgtVxTag.erase(0,k+1);
272 LDEBUG << "EasyDumper:: second part: " << tgtVxTag << " ; " << relType <<"/" << previousRelType << " ; " << srcFormeId << "/" << previousSrcId << "/" << tgtFormeId;
273 if (relType==previousRelType && tgtFormeId==previousSrcId)
274 {
275 std::string href = m_enonceId + srcFormeId;
276 if (href == m_enonceId)
277 {
278 href += "F0";
279 }
280 out << " <" << tgtVxTag << " xlink:type=\"locator\" xlink:href=\"" << href << "\"/>" << std::endl;
281 out << " </relation>" << std::endl;
282 continue;
283 }
284 else
285 {
286 std::string href = m_enonceId + "F0";
287 out << " <" << tgtVxTag << " xlink:type=\"locator\" xlink:href=\""<<href<<"\"/>" << std::endl;
288 LWARN << "EasyDumper:: Warning: relation " << previousRelType << " not continued";
289 out << " </relation>" << std::endl;
290 }
291 }
292 }
293 else
294 {
295 if (notClosed)
296 {
297 // @TODO check why this happens
298 LWARN << "EasyDumper:: Warning: non 3-ary relation marked as not closed for relation " << previousRelType;
299 if (relType == "COORD")
300 {
301 std::string href = m_enonceId + "F0";
302 out << " <coord-d xlink:type=\"locator\" xlink:href=\""<<href<<"\"/>" << std::endl;
303 }
304 out << " </relation>" << std::endl;
305 notClosed=false;
306 }
307 }
308
309 bool coordgOutputed = false;
310 bool coorddOutputed = false;
311 out << " <relation xlink:type=\"extended\" type=\"" << relType << "\" id=\"" << oss.str() << "\">" << std::endl;
312
313 if (relType == "JUXT")
314 {
315 if (tgtVxTag == "coord-g") coordgOutputed = true;
316 if (tgtVxTag == "coord-d") coorddOutputed = true;
317 if (m_srcVxTag[relType] == "coord-g") coordgOutputed = true;
318 if (m_srcVxTag[relType] == "coord-d") coorddOutputed = true;
319 out << " <" << tgtVxTag << " xlink:type=\"locator\" xlink:href=\"" << tgtFormeId << "\"/>" << std::endl;
320 out << " <" << m_srcVxTag[relType] << " xlink:type=\"locator\" xlink:href=\"" << srcFormeId << "\"/>" << std::endl;
321 }
322 else
323 {
324 /*
325 DUMPERLOGINIT;
326 LDEBUG << "EasyDumper:: searching " << m_vertexToFormeIds[(*it)->srcVertex] << " in groups";
327 if ( (relType == "CPL-V" || relType == "SUJ-V" || relType == "COD-V"
328 || relType == "CPL-V" || relType == "MOD-V" || relType == "ATB-SO" || relType == "MOD-N")
329 && m_formesIdsGroupsIds.find(m_vertexToFormeIds[(*it)->srcVertex]) != m_formesIdsGroupsIds.end())
330 {
331 uint64_t gid = m_formesIdsGroupsIds[m_vertexToFormeIds[(*it)->srcVertex]]->id();
332 std::string gsid = m_groupeIdGroupStr[gid];
333 out << " <" << m_srcVxTag[relType] << " xlink:type=\"locator\" xlink:href=\"" << gsid << "\"/>" << std::endl;
334 }
335 else
336 */
337 {
338 if (m_srcVxTag[relType] == "coord-g") coordgOutputed = true;
339 if (m_srcVxTag[relType] == "coord-d") coorddOutputed = true;
340 out << " <" << m_srcVxTag[relType] << " xlink:type=\"locator\" xlink:href=\"" << srcFormeId << "\"/>" << std::endl;
341 }
342 if (tgtVxTag == "coord-g") coordgOutputed = true;
343 if (tgtVxTag == "coord-d") coorddOutputed = true;
344 out << " <" << tgtVxTag << " xlink:type=\"locator\" xlink:href=\"" << tgtFormeId << "\"/>" << std::endl;
345 }
346 if ((*it)->secondaryVertex != 0)
347 {
348 std::string href = m_formesIds[m_vertexToFormeIds[(*it)->secondaryVertex]];
349 if (href == "")
350 {
351 LWARN << "EasyDumper:: Warning: form id not found for " << (*it)->secondaryVertex;
352 href = m_enonceId + "F0";
353 }
354 coorddOutputed = true;
355 out << " <coord-d xlink:type=\"locator\" xlink:href=\"" << href << "\"/>" << std::endl;
356 }
357 if (coordgOutputed && !coorddOutputed)
358 {
359 std::string href = m_enonceId + "F0";
360 out << " <coord-d xlink:type=\"locator\" xlink:href=\"" << href << "\"/>" << std::endl;
361 coorddOutputed = true;
362 }
363
364 if (! complement.empty())
365 {
366 out << " <" << complement << "/>" << std::endl;
367 }
368
369 if (!notClosed)
370 {
371 out << " </relation>" << std::endl;
372 }
373 }
374
375 if (notClosed)
376 {
378 LWARN << "EasyDumper:: Warning: relation " << relType << " not continued";
379 out << " </relation>" << std::endl;
380 notClosed=false;
381 }
382 out << " </relations>" << std::endl;
383}
384
385
386void EasyDumper::computeFormeIds()
387{
389 LDEBUG << "EasyDumper:: computeFormeIds";
390 int i=1;
391 for (std::map<uint64_t,Forme*>::const_iterator it=m_formesIndex.begin();
392 it!=m_formesIndex.end();
393 it++, i++)
394 {
395 std::ostringstream oss;
396 oss << "F" << i++;
397 LDEBUG << "EasyDumper:: adding to m_formesIds3: "<<(*it).second->forme<<" ("<<it->first<<") -> " << oss.str();
398 m_formesIds[it->first]=oss.str();
399 }
400 LDEBUG << "EasyDumper:: DONE computeFormeIds";
401}
402
403} // end namespace EasyXmlDumper
404} // end namespace AnalysisDumpers
405} // end namespace LinguisticProcessings
406} // end namespace Lima
dump the content of the analysis graph in Easy XML format
#define LWARN
Definition LimaCommon.h:160
#define LDEBUG
Definition LimaCommon.h:157
#define LERROR
Definition LimaCommon.h:161
#define DUMPERLOGINIT
EasyDumper(const ConstituantAndRelationExtractor &care, const std::map< std::string, std::string > &relationTypeMapping, const std::map< std::string, std::string > &srcVxTag, const std::map< std::string, std::string > &tgtVxTag, const std::string &enonceId)
dump the content of the analysis graph in Easy XML format
std::string transcodeToXmlEntities(const std::string &str)
std::string limastring2utf8stdstring(const Lima::LimaString &phrase, uint32_t size0)
Convert a wide string to a string , in dest up to size bytes.
LimaString utf8stdstring2limastring(const std::string &src)
NAUTITIA.