/
getModelExtra.go
271 lines (225 loc) · 8.94 KB
/
getModelExtra.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
// Copyright (c) 2016 OpenM++
// This code is licensed under the MIT license (see LICENSE.txt for details)
package main
import (
"errors"
"strconv"
"github.com/openmpp/go/ompp/db"
"github.com/openmpp/go/ompp/omppLog"
"golang.org/x/text/language"
)
// LangListByDigestOrName return lang_lst db rows by model digest or name.
// First language is model default language.
// It may contain more languages than model actually have.
func (mc *ModelCatalog) LangListByDigestOrName(dn string) ([]db.LangLstRow, bool) {
// if model digest-or-name is empty then return empty results
if dn == "" {
omppLog.Log("Warning: invalid (empty) model digest and name")
return []db.LangLstRow{}, false
}
// lock model catalog and return copy of langauge list
mc.theLock.Lock()
defer mc.theLock.Unlock()
idx, ok := mc.indexByDigestOrName(dn)
if !ok {
omppLog.Log("Warning: model digest or name not found: ", dn)
return []db.LangLstRow{}, false
}
ls := make([]db.LangLstRow, len(mc.modelLst[idx].langMeta.Lang))
for k := range mc.modelLst[idx].langMeta.Lang {
ls[k] = mc.modelLst[idx].langMeta.Lang[k].LangLstRow
}
return ls, true
}
// ModelProfileByName return model profile db rows by model digest-or-name and by profile name.
func (mc *ModelCatalog) ModelProfileByName(dn, profile string) (*db.ProfileMeta, bool) {
// if model digest-or-name is empty then return empty results
if dn == "" {
omppLog.Log("Warning: invalid (empty) model digest and name")
return &db.ProfileMeta{}, false
}
if profile == "" {
omppLog.Log("Warning: invalid (empty) profile name")
return &db.ProfileMeta{}, false
}
// get database connection
_, dbConn, ok := mc.modelMeta(dn)
if !ok {
omppLog.Log("Warning: model digest or name not found: ", dn)
return &db.ProfileMeta{}, false
}
// read profile from database
p, err := db.GetProfile(dbConn, profile)
if err != nil {
omppLog.Log("Error at get profile: ", dn, ": ", profile, ": ", err.Error())
return &db.ProfileMeta{}, false // return empty result: model not found or error
}
return p, true
}
// ProfileNamesByDigestOrName return list of profile(s) names by model digest-or-name.
// This is a list of profiles from model database, it is not a "model" profile(s).
// There is no explicit link between profile and model, profile can be applicable to multiple models.
func (mc *ModelCatalog) ProfileNamesByDigestOrName(dn string) ([]string, bool) {
// if model digest-or-name is empty then return empty results
if dn == "" {
omppLog.Log("Warning: invalid (empty) model digest and name")
return []string{}, false
}
// get database connection
_, dbConn, ok := mc.modelMeta(dn)
if !ok {
omppLog.Log("Warning: model digest or name not found: ", dn)
return []string{}, false // return empty result: model not found or error
}
// read profile names from database
nameLst, err := db.GetProfileList(dbConn)
if err != nil {
omppLog.Log("Error at get profile list from model database: ", dn, ": ", err.Error())
return []string{}, false
}
return nameLst, true
}
// WordListByDigestOrName return model "words" by model digest and preferred language tags.
// Model "words" are arrays of rows from lang_word and model_word db tables.
// It can be in preferred language, default model language or empty if no lang_word or model_word rows exist.
func (mc *ModelCatalog) WordListByDigestOrName(dn string, preferredLang []language.Tag) (*ModelLangWord, bool) {
// if model digest-or-name is empty then return empty results
if dn == "" {
omppLog.Log("Warning: invalid (empty) model digest and name")
return &ModelLangWord{}, false
}
// match preferred languages and model languages
lc := mc.languageTagMatch(dn, preferredLang)
lcd, _, _ := mc.modelLangs(dn)
if lc == "" && lcd == "" {
omppLog.Log("Error: invalid (empty) model default language: ", dn)
return &ModelLangWord{}, false
}
// lock model catalog
mc.theLock.Lock()
defer mc.theLock.Unlock()
idx, ok := mc.indexByDigestOrName(dn)
if !ok {
return &ModelLangWord{}, false // return empty result: model not found or error
}
// find lang_word rows in preferred or model default language
mlw := ModelLangWord{
ModelName: mc.modelLst[idx].meta.Model.Name,
ModelDigest: mc.modelLst[idx].meta.Model.Digest}
var nd, i int
for i = 0; i < len(mc.modelLst[idx].langMeta.Lang); i++ {
if mc.modelLst[idx].langMeta.Lang[i].LangCode == lc {
break // language match
}
if mc.modelLst[idx].langMeta.Lang[i].LangCode == lcd {
nd = i // index of default language
}
}
if i >= len(mc.modelLst[idx].langMeta.Lang) {
i = nd // use default language or zero index row
}
// copy lang_word rows, if exist for that language index
if i < len(mc.modelLst[idx].langMeta.Lang) {
mlw.LangCode = mc.modelLst[idx].langMeta.Lang[i].LangCode // actual language of result
for c, v := range mc.modelLst[idx].langMeta.Lang[i].Words {
mlw.LangWords = append(mlw.LangWords, codeLabel{Code: c, Label: v})
}
}
// find model_word rows in preferred or model default language
nd = 0
for i = 0; i < len(mc.modelLst[idx].modelWord.ModelWord); i++ {
if mc.modelLst[idx].modelWord.ModelWord[i].LangCode == lc {
break // language match
}
if mc.modelLst[idx].modelWord.ModelWord[i].LangCode == lcd {
nd = i // index of default language
}
}
if i >= len(mc.modelLst[idx].modelWord.ModelWord) {
i = nd // use default language or zero index row
}
// copy model_word rows, if exist for that language index
if i < len(mc.modelLst[idx].modelWord.ModelWord) {
mlw.ModelLangCode = mc.modelLst[idx].modelWord.ModelWord[i].LangCode // actual language of result
for c, v := range mc.modelLst[idx].modelWord.ModelWord[i].Words {
mlw.ModelWords = append(mlw.ModelWords, codeLabel{Code: c, Label: v})
}
}
return &mlw, true
}
// EntityGenByName select entity_gen and entity_gen_attr db row by entity name, run id and model digest or name.
func (mc *ModelCatalog) EntityGenByName(dn string, runId int, entityName string) (*db.EntityMeta, *db.EntityGenMeta, bool) {
if dn == "" {
omppLog.Log("Error: invalid (empty) model digest and name")
return nil, nil, false
}
if entityName == "" {
omppLog.Log("Error: invalid (empty) entity name")
return nil, nil, false
}
meta, dbConn, ok := mc.modelMeta(dn)
if !ok {
omppLog.Log("Error: model digest or name not found: ", dn)
return nil, nil, false // return empty result: model not found or error
}
// find model entity by entity name
eIdx, ok := meta.EntityByName(entityName)
if !ok {
omppLog.Log("Error: model entity not found: ", entityName)
return nil, nil, false
}
ent := &meta.Entity[eIdx]
// get list of entity generations for that model run
egLst, err := db.GetEntityGenList(dbConn, runId)
if err != nil {
omppLog.Log("Error at get run entities: ", entityName, ": ", runId, ": ", err.Error())
return nil, nil, false
}
// find entity generation by entity id, as it is today model run has only one entity generation for each entity
gIdx := -1
for k := range egLst {
if egLst[k].EntityId == ent.EntityId {
gIdx = k
break
}
}
if gIdx < 0 {
omppLog.Log("Error: model run entity generation not found: ", entityName, ": ", runId)
return nil, nil, false
}
return ent, &egLst[gIdx], true
}
// EntityGenAttrsRunList select entity_gen and entity_gen_attr db rows and run_entity rows by entity name, run id and model digest or name.
func (mc *ModelCatalog) EntityGenAttrsRunList(dn string, runId int, entityName string) (*db.EntityMeta, *db.EntityGenMeta, []db.EntityAttrRow, []db.RunEntityRow, error) {
ent, entGen, ok := mc.EntityGenByName(dn, runId, entityName)
if !ok {
return nil, nil, []db.EntityAttrRow{}, []db.RunEntityRow{}, errors.New("Error: model run entity generation not found: " + dn + ": " + entityName + ": " + strconv.Itoa(runId))
}
_, dbConn, ok := mc.modelMeta(dn)
if !ok {
return nil, nil, []db.EntityAttrRow{}, []db.RunEntityRow{}, errors.New("Error: model digest or name not found: " + dn)
}
// collect generation attribues
attrs := make([]db.EntityAttrRow, len(entGen.GenAttr))
for k, ga := range entGen.GenAttr {
aIdx, ok := ent.AttrByKey(ga.AttrId)
if !ok {
return nil, nil, []db.EntityAttrRow{}, []db.RunEntityRow{}, errors.New("entity attribute not found by id: " + strconv.Itoa(ga.AttrId) + " " + entityName)
}
attrs[k] = ent.Attr[aIdx]
}
// find all run_entity rows for that entity generation
runEnt, err := db.GetRunEntityGenByModel(dbConn, entGen.ModelId)
if err != nil {
return nil, nil, []db.EntityAttrRow{}, []db.RunEntityRow{}, errors.New("Error at get run entities by model id: " + strconv.Itoa(entGen.ModelId) + ": " + err.Error())
}
n := 0
for k := 0; k < len(runEnt); k++ {
if runEnt[k].GenHid == entGen.GenHid {
runEnt[n] = runEnt[k]
n++
}
}
runEnt = runEnt[:n]
return ent, entGen, attrs, runEnt, nil
}