LIMA
Libre Multilingual Analyzer — C++ API
Loading...
Searching...
No Matches
MultiLevelAnalysisDictionary.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
6/***************************************************************************
7 * Copyright (C) 2004-2012 by CEA LIST *
8 * *
9 ***************************************************************************/
13
20
21#include <iostream>
22
23using namespace Lima::Common;
24using namespace Lima::Common::Misc;
25using namespace Lima::Common::MediaticData;
27
28namespace Lima
29{
30
31namespace LinguisticProcessing
32{
33
34namespace AnalysisDict
35{
36
39
40
41struct LevelDico {
42 LevelDico() : id(),keys(0),data(),mainKeys(false) {};
43 std::string id;
44 std::shared_ptr<Lima::Common::AbstractAccessByString> keys;
47};
48
50{
53
55
58
63 std::vector<LevelDico> m_dicos;
65 uint64_t m_mainKeySize;
66
67};
68
69
75
76
81
84 Manager* manager)
85{
87 LINFO << "init MultiLevelAnalysisDictionary";
88 auto language = manager->getInitializationParameters().language;
90 m_d->m_mainKeySize = 0;
91 try
92 {
93 const auto& accesses = unitConfiguration.getListsValueAtKey("accessKeys");
94 const auto& data = unitConfiguration.getListsValueAtKey("dictionaryValuesFiles");
95 if (accesses.size() != data.size())
96 {
97 QString errorString;
98 QTextStream qts(&errorString);
99 qts << "accessKeys and dictionaryValuesFiles do not have the same number of entries for language "
100 << (int) language;
101 LERROR << errorString;
102 throw InvalidConfiguration(errorString.toStdString());
103 }
104 auto keyIt = accesses.cbegin(), dataIt = data.cbegin();
105 auto hasMainKeys = false;
106 for (; keyIt!=accesses.end() && dataIt!=data.end();)
107 {
108 LINFO << "load LevelDictionary : key=" << *keyIt << " data=" << *dataIt;
109 auto res = LinguisticResources::single().getResource(language, *keyIt);
110 auto aar = std::dynamic_pointer_cast<AbstractAccessResource>(res);
111 LevelDico ldico;
112 ldico.id = *keyIt;
113 ldico.keys = aar->getAccessByString();
114 ldico.mainKeys = aar->isMainKeys();
115 if (aar->isMainKeys())
116 {
117 hasMainKeys = true;
118 m_d->m_mainKeySize = ldico.keys->getSize();
119 }
120 auto dataFile = findFileInPaths(Common::MediaticData::MediaticData::single().getResourcesPath().c_str(),
121 (*dataIt).c_str());
122 ldico.data = new DictionaryData();
123 ldico.data->loadBinaryFile(dataFile.toStdString());
124 m_d->m_dicos.push_back(ldico);
125 keyIt++;
126 dataIt++;
127 }
128 if ((keyIt!=accesses.end()) || (dataIt!=data.end()))
129 {
130 QString errorString;
131 QTextStream qts(&errorString);
132 qts << "missing keys or data in configuration for MultiLevelAnalysisDictionary ! for language "
133 << (int) language;
134 LERROR << errorString;
135 throw InvalidConfiguration(errorString.toStdString());
136 }
137 if (!hasMainKeys)
138 {
139 QString errorString;
140 QTextStream qts(&errorString);
141 qts << "no accessKeys are main keys (stringspool keys) in MultiLevelAnalysisDictionary for language "
142 << (int) language;
143 LERROR << errorString;
144 throw InvalidConfiguration(errorString.toStdString());
145 }
146 }
147 catch (NoSuchList& )
148 {
149 QString errorString;
150 QTextStream qts(&errorString);
151 qts << "no param 'accessKeys' in MultiLevelAnalysisDictionary group for language "
152 << (int) language;
153 LERROR << errorString;
154 throw InvalidConfiguration(errorString.toStdString());
155 }
156}
157
159{
160 StringsPoolIndex form(0);
161 std::vector<uint64_t> indexes;
162 for (const auto& dico: m_d->m_dicos)
163 {
164 indexes.push_back(dico.keys->getIndex(word));
165 if (dico.mainKeys)
166 {
167 form=indexes.back();
168 }
169 }
170 return getEntry(form, indexes);
171}
172
173DictionaryEntry MultiLevelAnalysisDictionary::getEntry(const StringsPoolIndex wordId) const
174{
175 const auto& csp = *m_d->m_sp;
176 LimaString word = csp[wordId];
177 return getEntry(wordId, word);
178}
179
181 const Lima::LimaString& word) const
182{
183 std::vector<uint64_t> indexes;
184 for (const auto& dico : m_d->m_dicos)
185 {
186 if (dico.mainKeys)
187 {
188 if (wordId < m_d->m_mainKeySize)
189 {
190 indexes.push_back(wordId);
191 }
192 else
193 {
194 indexes.push_back(0);
195 }
196 }
197 else
198 {
199 indexes.push_back(dico.keys->getIndex(word));
200 }
201 }
202 return getEntry(wordId, indexes);
203}
204
205DictionaryEntry MultiLevelAnalysisDictionary::getEntry(const std::vector<uint64_t>& indexes) const
206{
208 LDEBUG << "MultiLevelAnalysisDictionary::getEntry" << indexes.size();
209 auto indexItr = indexes.cbegin();
210 for (auto dicoItr = m_d->m_dicos.cbegin();
211 (indexItr != indexes.cend()) && (dicoItr != m_d->m_dicos.cend());
212 indexItr++, dicoItr++)
213 {
214 if (dicoItr->mainKeys)
215 {
216 break;
217 }
218 }
219 Q_ASSERT(indexItr!=indexes.end());
220 if (*indexItr != 0)
221 {
222 return getEntry(static_cast<StringsPoolIndex>(*indexItr), indexes);
223 }
224 // entry doesn't exist in main key : search in other key
225 indexItr = indexes.cbegin();
226 StringsPoolIndex form(0);
227 for (auto dicoItr = m_d->m_dicos.cbegin();
228 (indexItr != indexes.end()) && (dicoItr != m_d->m_dicos.end());
229 indexItr++, dicoItr++)
230 {
231 if (*indexItr > 0)
232 {
233 form = (*m_d->m_sp)[dicoItr->keys->getSpelling(*indexItr)];
234 break;
235 }
236 }
237 return getEntry(form,indexes);
238}
239
241 const std::vector<uint64_t>& indexes) const
242{
244 LDEBUG << "getEntry";
245
246 std::vector<MultiLevelAnalysisDictionaryEntry::LevelData> entryData;
247
248 auto empty = true;
249 auto final = false;
250 auto hasLing = false;
251 auto hasAccented = false;
252 auto hasConcat = false;
253
254 auto indexIt = indexes.cbegin();
255 auto dicoIt = m_d->m_dicos.cbegin();
257 for (;indexIt != indexes.end() && dicoIt != m_d->m_dicos.end() && !final;
258 indexIt++, dicoIt++)
259 {
260 LDEBUG << "read level " << dicoIt->id << " : entry index = " << *indexIt;
261 auto p = dicoIt->data->getEntryAddr(*indexIt);
262 auto read = DictionaryData::readCodedInt(p);
263 LDEBUG << "read " << read;
264 if (read == 1)
265 {
266 LDEBUG << "final = true";
267 final = true;
269 }
270 if (read == 0)
271 {
272 // this entry is empty, skip it
273 LDEBUG << "entry is empty";
274 continue;
275 }
276 // if here, then entry is not empty
277 empty = false;
278 LDEBUG << "entry has length " << read;
279 data.startEntryData = p;
280 data.endEntryData = p + read;
282 if (read!=0)
283 {
284 hasLing=true;
285 }
286 LDEBUG << "info length = " << read;
287 p += read;
288 if (p != data.endEntryData)
289 {
291 LDEBUG << "accented length = " << read;
292 if (read != 0)
293 {
294 hasAccented = true;
295 }
296 p += read;
297 if (p != data.endEntryData)
298 {
300 LDEBUG << "concat length = " << read;
301 if (read != 0)
302 {
303 hasConcat = true;
304 }
305 p += read;
306 }
307 }
308 Q_ASSERT(p == data.endEntryData);
309
310 data.dicoData = dicoIt->data;
311 data.keys = dicoIt->keys;
312 data.mainKeys = dicoIt->mainKeys;
313 entryData.push_back(data);
314 }
315 return DictionaryEntry(std::make_shared<MultiLevelAnalysisDictionaryEntry>(form,
316 final,
317 empty,
318 hasLing,
319 hasConcat,
320 hasAccented,
321 entryData,
322 m_d->m_sp));
323}
324
325std::pair< DictionarySubWordIterator, DictionarySubWordIterator > MultiLevelAnalysisDictionary::getSubWordEntries(
326 const int offset, const LimaString& key) const
327{
328 // build iterator
329 std::vector<std::pair<Common::AccessSubWordIterator,Common::AccessSubWordIterator> > accessItrs;
330 for (const auto& dico : m_d->m_dicos)
331 {
332 accessItrs.push_back(dico.keys->getSubWords(offset, key));
333 }
334
335 // build end iterator
336 std::vector<std::pair<Common::AccessSubWordIterator,Common::AccessSubWordIterator> > accessItrsEnd(accessItrs);
337 for (auto& accessItr : accessItrsEnd)
338 {
339 accessItr.first = accessItr.second;
340 }
341
342 return std::pair< DictionarySubWordIterator, DictionarySubWordIterator >(
345}
346
347std::pair< DictionarySuperWordIterator, DictionarySuperWordIterator > MultiLevelAnalysisDictionary::getSuperWordEntries(
348 const LimaString& key) const
349{
350 LIMA_UNUSED(key);
351 // TODO unimplemented method
352 std::cerr << "unimplemented method at "<<__FILE__<<", line "<<__LINE__<< std::endl;
353 Q_ASSERT(false);
354 return std::make_pair( DictionarySuperWordIterator(0), DictionarySuperWordIterator(0));
355}
356
358{
359 // TODO unimplemented method
360 std::cerr << "unimplemented method at "<<__FILE__<<", line "<<__LINE__<< std::endl;
361 Q_ASSERT(false);
362 return 0;
363}
364
366{
367 return m_d->m_dicos.size();
368}
369
370}
371
372}
373
374}
#define LIMA_UNUSED(x)
Definition LimaCommon.h:224
#define LDEBUG
Definition LimaCommon.h:157
#define LINFO
Definition LimaCommon.h:158
#define LERROR
Definition LimaCommon.h:161
#define ANALYSISDICTLOGINIT
#define MULTILEVELANALYSISDICTIONARY_CLASSID
Defines a Factory to create Object of type Base.
const FsaStringsPool & stringsPool(MediaId med) const
std::deque< std::string > & getListsValueAtKey(const std::string &key)
Use this exception to signal an error in one of the configuration files.
Definition LimaCommon.h:345
virtual std::pair< DictionarySuperWordIterator, DictionarySuperWordIterator > getSuperWordEntries(const LimaString &key) const override
return superword entries A superword entry is an entry that begins with the given key
virtual void init(Common::XMLConfigurationFiles::GroupConfigurationStructure &unitConfiguration, Manager *manager) override
virtual std::pair< DictionarySubWordIterator, DictionarySubWordIterator > getSubWordEntries(const int offset, const LimaString &key) const override
return subword entries A subword entry is a word in the key string that begin at the given offset.
virtual DictionaryEntry getEntry(const Lima::LimaString &word) const override
get dictionary entry for a word
virtual uint64_t getSize() const override
return number of keys in dictionary
static const LinguisticResources & single()
const singleton accessor
Definition Singleton.h:51
static MediaticData & changeable()
singleton accessor
Definition Singleton.h:71
QString findFileInPaths(const QString &paths, const QString &fileName, const QChar &separator)
Find the given file in the given paths.
SimpleFactory< AbstractResource, MultiLevelAnalysisDictionary > multiLevelAnalysisDictionaryFactory(MULTILEVELANALYSISDICTIONARY_CLASSID)
NAUTITIA.
QString LimaString
Definition LimaString.h:33
std::shared_ptr< Lima::Common::AbstractAccessByString > keys
launch exception related to the configuration file parsing