aGrUM
0.20.2
a C++ library for (probabilistic) graphical models
PRMClass_tpl.h
Go to the documentation of this file.
1
/**
2
*
3
* Copyright 2005-2020 Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
4
* info_at_agrum_dot_org
5
*
6
* This library is free software: you can redistribute it and/or modify
7
* it under the terms of the GNU Lesser General Public License as published by
8
* the Free Software Foundation, either version 3 of the License, or
9
* (at your option) any later version.
10
*
11
* This library is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU Lesser General Public License for more details.
15
*
16
* You should have received a copy of the GNU Lesser General Public License
17
* along with this library. If not, see <http://www.gnu.org/licenses/>.
18
*
19
*/
20
21
22
/**
23
* @file
24
* @brief Inline implementation of gum::Class
25
*
26
* @author Lionel TORTI and Pierre-Henri WUILLEMIN(@LIP6)
27
*/
28
29
// to ease parsing
30
#
include
<
queue
>
31
32
#
include
<
agrum
/
PRM
/
elements
/
PRMClass
.
h
>
33
34
#
include
<
agrum
/
PRM
/
elements
/
PRMInterface
.
h
>
35
36
namespace
gum
{
37
namespace
prm
{
38
template
<
typename
GUM_SCALAR >
39
PRMClass< GUM_SCALAR >::PRMClass(
const
std::string& name) :
40
PRMClassElementContainer< GUM_SCALAR >(name), superClass__(
nullptr
),
41
implements__(
nullptr
), bijection__(
nullptr
) {
42
GUM_CONSTRUCTOR(PRMClass);
43
}
44
45
template
<
typename
GUM_SCALAR
>
46
PRMClass
<
GUM_SCALAR
>::
PRMClass
(
const
std
::
string
&
name
,
47
PRMClass
<
GUM_SCALAR
>&
super
,
48
bool
delayInheritance
) :
49
PRMClassElementContainer
<
GUM_SCALAR
>(
name
),
50
superClass__
(&
super
),
implements__
(
nullptr
),
51
bijection__
(
52
new
Bijection
<
const
DiscreteVariable
*,
const
DiscreteVariable
* >()) {
53
GUM_CONSTRUCTOR
(
PRMClass
);
54
if
(!
delayInheritance
) {
55
dag__
=
super
.
containerDag
();
56
inheritClass__
(
super
);
57
}
58
}
59
60
template
<
typename
GUM_SCALAR
>
61
PRMClass
<
GUM_SCALAR
>::
PRMClass
(
const
std
::
string
&
name
,
62
const
Set
<
PRMInterface
<
GUM_SCALAR
>* >&
set
,
63
bool
delayInheritance
) :
64
PRMClassElementContainer
<
GUM_SCALAR
>(
name
),
65
superClass__
(
nullptr
),
66
implements__
(
new
Set
<
PRMInterface
<
GUM_SCALAR
>* >(
set
)),
67
bijection__
(
nullptr
) {
68
GUM_CONSTRUCTOR
(
PRMClass
);
69
70
if
(!
delayInheritance
) {
implementInterfaces__
(
false
); }
71
}
72
73
template
<
typename
GUM_SCALAR
>
74
PRMClass
<
GUM_SCALAR
>::
PRMClass
(
const
std
::
string
&
name
,
75
PRMClass
<
GUM_SCALAR
>&
super
,
76
const
Set
<
PRMInterface
<
GUM_SCALAR
>* >&
set
,
77
bool
delayInheritance
) :
78
PRMClassElementContainer
<
GUM_SCALAR
>(
name
),
79
superClass__
(&
super
),
implements__
(
nullptr
),
80
bijection__
(
81
new
Bijection
<
const
DiscreteVariable
*,
const
DiscreteVariable
* >()) {
82
GUM_CONSTRUCTOR
(
PRMClass
);
83
if
(!
delayInheritance
) {
84
dag__
=
super
.
containerDag
();
85
inheritClass__
(
super
);
86
}
87
88
// Adding other implementation
89
if
(
implements__
==
nullptr
) {
// super has not created implements__
90
implements__
=
new
Set
<
PRMInterface
<
GUM_SCALAR
>* >(
set
);
91
}
else
{
// we just add the new implementations
92
for
(
const
auto
elt
:
set
) {
93
implements__
->
insert
(
elt
);
94
}
95
}
96
97
if
(!
delayInheritance
) {
implementInterfaces__
(
false
); }
98
}
99
100
template
<
typename
GUM_SCALAR
>
101
void
PRMClass
<
GUM_SCALAR
>::
implementInterfaces__
(
bool
delayedInheritance
) {
102
for
(
const
auto
impl
: *
implements__
) {
103
impl
->
addImplementation__
(
this
);
104
if
((!
superClass__
) || (!
super
().
isSubTypeOf
(*
impl
))
105
||
delayedInheritance
) {
106
// Reserve reference id in DAG
107
for
(
auto
ref
:
impl
->
referenceSlots
()) {
108
dag__
.
addNodeWithId
(
ref
->
id
());
109
}
110
// Reserve attribute id in DAG
111
for
(
auto
attr
:
impl
->
attributes
()) {
112
dag__
.
addNodeWithId
(
attr
->
id
());
113
}
114
}
115
}
116
}
117
118
template
<
typename
GUM_SCALAR
>
119
PRMClass
<
GUM_SCALAR
>::~
PRMClass
() {
120
GUM_DESTRUCTOR
(
PRMClass
);
121
122
for
(
const
auto
&
elt
:
nodeIdMap__
) {
123
delete
elt
.
second
;
124
}
125
126
if
(
implements__
) {
delete
implements__
; }
127
128
if
(
bijection__
) {
delete
bijection__
; }
129
}
130
131
template
<
typename
GUM_SCALAR
>
132
void
PRMClass
<
GUM_SCALAR
>::
initializeInheritance
() {
133
if
(
superClass__
) {
134
superClass__
->
addExtension__
(
this
);
135
// Adding implemented interfaces, if any
136
if
(
superClass__
->
implements__
) {
137
if
(!
implements__
) {
138
implements__
=
new
Set
<
PRMInterface
<
GUM_SCALAR
>* >(
139
*(
superClass__
->
implements__
));
140
}
else
{
141
for
(
auto
i
: *(
superClass__
->
implements__
)) {
142
implements__
->
insert
(
i
);
143
}
144
}
145
}
146
}
147
if
(
implements__
) {
implementInterfaces__
(
true
); }
148
}
149
150
template
<
typename
GUM_SCALAR
>
151
void
PRMClass
<
GUM_SCALAR
>::
inheritReferenceSlots
() {
152
if
(
superClass__
) {
153
// Copying reference slots
154
for
(
const
auto
c_refslot
:
superClass__
->
referenceSlots__
) {
155
auto
ref
=
new
PRMReferenceSlot
<
GUM_SCALAR
>(
156
c_refslot
->
name
(),
157
const_cast
<
PRMClassElementContainer
<
GUM_SCALAR
>& >(
158
c_refslot
->
slotType
()),
159
c_refslot
->
isArray
());
160
161
ref
->
setId
(
c_refslot
->
id
());
162
// Not reserved by an interface
163
if
(!
dag__
.
existsNode
(
ref
->
id
())) {
dag__
.
addNodeWithId
(
ref
->
id
()); }
164
nodeIdMap__
.
insert
(
ref
->
id
(),
ref
);
165
referenceSlots__
.
insert
(
ref
);
166
167
if
(
superClass__
->
nameMap__
[
c_refslot
->
name
()]
168
==
superClass__
->
nameMap__
[
c_refslot
->
safeName
()]) {
169
nameMap__
.
insert
(
ref
->
name
(),
ref
);
170
}
171
172
nameMap__
.
insert
(
ref
->
safeName
(),
ref
);
173
}
174
}
175
}
176
177
template
<
typename
GUM_SCALAR
>
178
void
PRMClass
<
GUM_SCALAR
>::
inheritParameters
() {
179
if
(
superClass__
) {
180
// Copying parameters
181
for
(
const
auto
c_param
:
superClass__
->
parameters__
) {
182
auto
param
=
new
PRMParameter
<
GUM_SCALAR
>(
c_param
->
name
(),
183
c_param
->
valueType
(),
184
c_param
->
value
());
185
186
parameters__
.
insert
(
param
);
187
188
param
->
setId
(
c_param
->
id
());
189
dag__
.
addNodeWithId
(
param
->
id
());
190
nodeIdMap__
.
insert
(
param
->
id
(),
param
);
191
nameMap__
.
insert
(
param
->
name
(),
param
);
192
}
193
}
194
}
195
196
template
<
typename
GUM_SCALAR
>
197
void
PRMClass
<
GUM_SCALAR
>::
inheritAttributes
() {
198
if
(
superClass__
) {
199
for
(
const
auto
c_attr
:
superClass__
->
attributes__
) {
200
// using multiDimSparse to prevent unecessary memory allocation for
201
// large arrays (the potentials are copied latter)
202
auto
attr
=
c_attr
->
newFactory
(*
this
);
203
204
bijection__
->
insert
(&(
c_attr
->
type
().
variable
()),
205
&(
attr
->
type
().
variable
()));
206
attr
->
setId
(
c_attr
->
id
());
207
try
{
208
dag__
.
addNodeWithId
(
attr
->
id
());
209
}
catch
(
gum
::
Exception
&) {
210
// Node reserved by an interface
211
}
212
nodeIdMap__
.
insert
(
attr
->
id
(),
attr
);
213
attributes__
.
insert
(
attr
);
214
215
if
(
superClass__
->
nameMap__
[
c_attr
->
name
()]
216
==
superClass__
->
nameMap__
[
c_attr
->
safeName
()]) {
217
nameMap__
.
insert
(
attr
->
name
(),
attr
);
218
}
219
220
nameMap__
.
insert
(
attr
->
safeName
(),
attr
);
221
}
222
}
223
}
224
225
template
<
typename
GUM_SCALAR
>
226
void
PRMClass
<
GUM_SCALAR
>::
inheritAggregates
() {
227
if
(
superClass__
) {
228
for
(
const
auto
c_agg
:
superClass__
->
aggregates__
) {
229
PRMAggregate
<
GUM_SCALAR
>*
agg
=
nullptr
;
230
231
try
{
232
agg
=
new
PRMAggregate
<
GUM_SCALAR
>(
c_agg
->
name
(),
233
c_agg
->
agg_type
(),
234
c_agg
->
type
(),
235
c_agg
->
label
());
236
}
catch
(
OperationNotAllowed
&) {
237
agg
=
new
PRMAggregate
<
GUM_SCALAR
>(
c_agg
->
name
(),
238
c_agg
->
agg_type
(),
239
c_agg
->
type
());
240
agg
->
sharedLabel
(
c_agg
->
sharedLabel
());
241
agg
->
setLabel
(
c_agg
->
labelValue
());
242
}
243
244
bijection__
->
insert
(&(
c_agg
->
type
().
variable
()),
245
&(
agg
->
type
().
variable
()));
246
agg
->
setId
(
c_agg
->
id
());
247
dag__
.
addNodeWithId
(
agg
->
id
());
248
nodeIdMap__
.
insert
(
agg
->
id
(),
agg
);
249
aggregates__
.
insert
(
agg
);
250
251
if
(
superClass__
->
nameMap__
[
c_agg
->
name
()]
252
==
superClass__
->
nameMap__
[
c_agg
->
safeName
()])
253
nameMap__
.
insert
(
agg
->
name
(),
agg
);
254
255
nameMap__
.
insert
(
agg
->
safeName
(),
agg
);
256
}
257
}
258
}
259
260
template
<
typename
GUM_SCALAR
>
261
void
PRMClass
<
GUM_SCALAR
>::
inheritSlotChains
() {
262
if
(
superClass__
) {
263
// Copying slot chains
264
for
(
const
auto
c_sc
:
superClass__
->
slotChains__
) {
265
// Because of aggregators, some slotchains may exists already
266
if
(!(
nameMap__
.
exists
(
c_sc
->
name
())
267
&&
nameMap__
.
exists
(
c_sc
->
safeName
()))) {
268
// We just need to change the first PRMReferenceSlot<GUM_SCALAR> in
269
// the
270
// chain
271
auto
chain
=
c_sc
->
chain
();
272
273
chain
.
setAtPos
(0,
nameMap__
[
c_sc
->
chain
().
front
()->
name
()]);
274
275
auto
sc
=
new
PRMSlotChain
<
GUM_SCALAR
>(
c_sc
->
name
(),
chain
);
276
bijection__
->
insert
(&(
c_sc
->
type
().
variable
()),
277
&(
sc
->
type
().
variable
()));
278
sc
->
setId
(
c_sc
->
id
());
279
dag__
.
addNodeWithId
(
sc
->
id
());
280
nodeIdMap__
.
insert
(
sc
->
id
(),
sc
);
281
slotChains__
.
insert
(
sc
);
282
283
if
(!
nameMap__
.
exists
(
sc
->
name
())) {
284
nameMap__
.
insert
(
sc
->
name
(),
sc
);
285
}
286
if
(!
nameMap__
.
exists
(
sc
->
safeName
())) {
287
nameMap__
.
insert
(
sc
->
safeName
(),
sc
);
288
}
289
}
290
}
291
}
292
}
293
294
template
<
typename
GUM_SCALAR
>
295
void
PRMClass
<
GUM_SCALAR
>::
completeInheritance
(
const
std
::
string
&
name
) {
296
if
(
superClass__
) {
297
auto
&
elt
=
this
->
get
(
name
);
298
if
(!(
PRMClassElement
<
GUM_SCALAR
>::
isAttribute
(
elt
)
299
||
PRMClassElement
<
GUM_SCALAR
>::
isAggregate
(
elt
))) {
300
GUM_ERROR
(
OperationNotAllowed
,
301
"you can only complete inheritance for attributes"
);
302
}
303
304
for
(
const
auto
&
prnt
:
super
().
containerDag
().
parents
(
elt
.
id
())) {
305
this
->
addArc
(
super
().
get
(
prnt
).
safeName
(),
elt
.
safeName
());
306
}
307
308
if
(
PRMClassElement
<
GUM_SCALAR
>::
isAttribute
(
elt
)) {
309
auto
&
attr
=
static_cast
<
PRMAttribute
<
GUM_SCALAR
>& >(
elt
);
310
auto
&
super_attr
311
=
static_cast
<
const
PRMAttribute
<
GUM_SCALAR
>& >(
super
().
get
(
name
));
312
attr
.
copyCpf
(*
bijection__
,
super_attr
);
313
}
314
}
315
}
316
317
template
<
typename
GUM_SCALAR
>
318
void
PRMClass
<
GUM_SCALAR
>::
inheritClass__
(
const
PRMClass
<
GUM_SCALAR
>&
c
) {
319
if
(
superClass__
) {
320
superClass__
->
addExtension__
(
this
);
321
// Adding implemented interfaces of c, if any
322
if
(
c
.
implements__
) {
323
if
(!
implements__
) {
324
implements__
325
=
new
Set
<
PRMInterface
<
GUM_SCALAR
>* >(*(
c
.
implements__
));
326
}
else
{
327
for
(
auto
i
: *(
c
.
implements__
)) {
328
implements__
->
insert
(
i
);
329
}
330
}
331
}
332
333
// Copying attributes, the bijection's firsts are attributes in this and
334
// its
335
// seconds are attributes
336
// in c.
337
Bijection
<
const
DiscreteVariable
*,
const
DiscreteVariable
* >
bij
;
338
339
// Copying parameters
340
for
(
const
auto
c_param
:
c
.
parameters__
) {
341
auto
param
=
new
PRMParameter
<
GUM_SCALAR
>(
c_param
->
name
(),
342
c_param
->
valueType
(),
343
c_param
->
value
());
344
345
parameters__
.
insert
(
param
);
346
347
param
->
setId
(
c_param
->
id
());
348
nodeIdMap__
.
insert
(
param
->
id
(),
param
);
349
nameMap__
.
insert
(
param
->
name
(),
param
);
350
}
351
352
// Copying attributes
353
for
(
const
auto
c_attr
:
c
.
attributes__
) {
354
// using multiDimSparse to prevent unecessary memory allocation for
355
// large arrays (the potentials are copied latter)
356
auto
attr
=
c_attr
->
newFactory
(*
this
);
357
358
bij
.
insert
(&(
c_attr
->
type
().
variable
()), &(
attr
->
type
().
variable
()));
359
attr
->
setId
(
c_attr
->
id
());
360
nodeIdMap__
.
insert
(
attr
->
id
(),
attr
);
361
attributes__
.
insert
(
attr
);
362
363
if
(
c
.
nameMap__
[
c_attr
->
name
()] ==
c
.
nameMap__
[
c_attr
->
safeName
()]) {
364
nameMap__
.
insert
(
attr
->
name
(),
attr
);
365
}
366
367
nameMap__
.
insert
(
attr
->
safeName
(),
attr
);
368
}
369
370
// Copying aggregates
371
for
(
const
auto
c_agg
:
c
.
aggregates__
) {
372
PRMAggregate
<
GUM_SCALAR
>*
agg
=
nullptr
;
373
374
try
{
375
agg
=
new
PRMAggregate
<
GUM_SCALAR
>(
c_agg
->
name
(),
376
c_agg
->
agg_type
(),
377
c_agg
->
type
(),
378
c_agg
->
label
());
379
}
catch
(
OperationNotAllowed
&) {
380
agg
=
new
PRMAggregate
<
GUM_SCALAR
>(
c_agg
->
name
(),
381
c_agg
->
agg_type
(),
382
c_agg
->
type
());
383
}
384
385
bij
.
insert
(&(
c_agg
->
type
().
variable
()), &(
agg
->
type
().
variable
()));
386
agg
->
setId
(
c_agg
->
id
());
387
nodeIdMap__
.
insert
(
agg
->
id
(),
agg
);
388
aggregates__
.
insert
(
agg
);
389
390
if
(
c
.
nameMap__
[
c_agg
->
name
()] ==
c
.
nameMap__
[
c_agg
->
safeName
()])
391
nameMap__
.
insert
(
agg
->
name
(),
agg
);
392
393
nameMap__
.
insert
(
agg
->
safeName
(),
agg
);
394
}
395
396
// Copying reference slots
397
for
(
const
auto
c_refslot
:
c
.
referenceSlots__
) {
398
PRMReferenceSlot
<
GUM_SCALAR
>*
ref
=
new
PRMReferenceSlot
<
GUM_SCALAR
>(
399
c_refslot
->
name
(),
400
const_cast
<
PRMClassElementContainer
<
GUM_SCALAR
>& >(
401
c_refslot
->
slotType
()),
402
c_refslot
->
isArray
());
403
404
ref
->
setId
(
c_refslot
->
id
());
405
nodeIdMap__
.
insert
(
ref
->
id
(),
ref
);
406
referenceSlots__
.
insert
(
ref
);
407
408
if
(
c
.
nameMap__
[
c_refslot
->
name
()] ==
c
.
nameMap__
[
c_refslot
->
safeName
()])
409
nameMap__
.
insert
(
ref
->
name
(),
ref
);
410
411
nameMap__
.
insert
(
ref
->
safeName
(),
ref
);
412
}
413
414
// Copying slot chains
415
for
(
const
auto
c_slotchain
:
c
.
slotChains__
) {
416
// We just need to change the first PRMReferenceSlot<GUM_SCALAR> in
417
// the
418
// chain
419
Sequence
<
PRMClassElement
<
GUM_SCALAR
>* >
chain
(
c_slotchain
->
chain
());
420
421
chain
.
setAtPos
(0,
nameMap__
[
c_slotchain
->
chain
().
front
()->
name
()]);
422
423
PRMSlotChain
<
GUM_SCALAR
>*
sc
424
=
new
PRMSlotChain
<
GUM_SCALAR
>(
c_slotchain
->
name
(),
chain
);
425
bij
.
insert
(&(
c_slotchain
->
type
().
variable
()), &(
sc
->
type
().
variable
()));
426
sc
->
setId
(
c_slotchain
->
id
());
427
nodeIdMap__
.
insert
(
sc
->
id
(),
sc
);
428
slotChains__
.
insert
(
sc
);
429
430
nameMap__
.
insert
(
sc
->
name
(),
sc
);
431
nameMap__
.
insert
(
sc
->
safeName
(),
sc
);
432
}
433
434
// Copying dependencies yield by arcs
435
for
(
const
auto
&
arc
:
c
.
containerDag
().
arcs
()) {
436
nodeIdMap__
[
arc
.
tail
()]->
addChild
(*(
nodeIdMap__
[
arc
.
head
()]));
437
nodeIdMap__
[
arc
.
head
()]->
addParent
(*(
nodeIdMap__
[
arc
.
tail
()]));
438
}
439
440
// Copying the IO flag
441
this
->
copyIOFlags_
(
c
);
442
// Copying content of CPF
443
for
(
const
auto
attr
:
c
.
attributes__
) {
444
auto
a
=
static_cast
<
PRMAttribute
<
GUM_SCALAR
>* >(
445
nameMap__
[
attr
->
safeName
()]);
446
a
->
copyCpf
(
bij
, *
attr
);
447
}
448
}
449
}
450
451
template
<
typename
GUM_SCALAR
>
452
bool
PRMClass
<
GUM_SCALAR
>::
isSubTypeOf
(
453
const
PRMClassElementContainer
<
GUM_SCALAR
>&
cec
)
const
{
454
switch
(
cec
.
obj_type
()) {
455
case
PRMObject
::
prm_type
::
CLASS
: {
456
const
PRMClass
<
GUM_SCALAR
>*
current
=
this
;
457
458
while
(
current
!= 0) {
459
if
(
current
== &(
cec
))
return
true
;
460
461
current
=
current
->
superClass__
;
462
}
463
464
return
false
;
465
}
466
467
case
PRMObject
::
prm_type
::
PRM_INTERFACE
: {
468
if
(
implements__
!=
nullptr
) {
469
const
PRMInterface
<
GUM_SCALAR
>&
i
470
=
static_cast
<
const
PRMInterface
<
GUM_SCALAR
>& >(
cec
);
471
472
if
(
implements__
->
exists
(
473
const_cast
<
PRMInterface
<
GUM_SCALAR
>* >(&
i
)))
474
return
true
;
475
476
for
(
const
auto
impl
: *
implements__
)
477
if
(
impl
->
isSubTypeOf
(
i
))
return
true
;
478
}
479
480
return
false
;
481
}
482
483
default
: {
484
GUM_ERROR
(
FatalError
,
"unknown ClassElementContainer<GUM_SCALAR>"
);
485
}
486
}
487
}
488
489
template
<
typename
GUM_SCALAR
>
490
void
PRMClass
<
GUM_SCALAR
>::
addArc
(
const
std
::
string
&
tail_name
,
491
const
std
::
string
&
head_name
) {
492
PRMClassElement
<
GUM_SCALAR
>*
tail
= 0;
493
PRMClassElement
<
GUM_SCALAR
>*
head
= 0;
494
495
try
{
496
tail
=
nameMap__
[
tail_name
];
497
head
=
nameMap__
[
head_name
];
498
}
catch
(
NotFound
&) {
499
GUM_ERROR
(
NotFound
,
500
"tail and/or head of arc does not exists in this Class"
);
501
}
502
503
if
((
tail
->
elt_type
() ==
PRMClassElement
<
GUM_SCALAR
>::
prm_refslot
)
504
|| (
head
->
elt_type
() ==
PRMClassElement
<
GUM_SCALAR
>::
prm_refslot
)) {
505
GUM_ERROR
(
OperationNotAllowed
,
506
"a PRMReferenceSlot<GUM_SCALAR> can "
507
"not on neither side of an arc"
);
508
}
509
510
if
((
tail
->
elt_type
() ==
PRMClassElement
<
GUM_SCALAR
>::
prm_slotchain
)
511
&& (
head
->
elt_type
() ==
PRMClassElement
<
GUM_SCALAR
>::
prm_slotchain
)) {
512
GUM_ERROR
(
OperationNotAllowed
,
513
"illegal insertion of an arc between two SlotChain<GUM_SCALAR>"
);
514
}
515
516
if
(!
dag__
.
existsArc
(
Arc
(
tail
->
id
(),
head
->
id
()))) {
517
dag__
.
addArc
(
tail
->
id
(),
head
->
id
());
518
}
else
{
519
GUM_ERROR
(
DuplicateElement
,
520
"duplicate arc "
<<
tail_name
<<
"->"
<<
head_name
);
521
}
522
523
get
(
tail
->
id
()).
addChild
(
get
(
head
->
id
()));
524
get
(
head
->
id
()).
addParent
(
get
(
tail
->
id
()));
525
526
// Defining input / output nodes
527
if
(
tail
->
elt_type
() ==
PRMClassElement
<
GUM_SCALAR
>::
prm_slotchain
) {
528
PRMSlotChain
<
GUM_SCALAR
>*
sc
529
=
static_cast
<
PRMSlotChain
<
GUM_SCALAR
>* >(
tail
);
530
this
->
setInputNode
(*
head
,
true
);
531
sc
->
end
().
setOutputNode
(
sc
->
end
().
get
(
sc
->
lastElt
().
safeName
()),
true
);
532
}
533
}
534
535
template
<
typename
GUM_SCALAR
>
536
void
PRMClass
<
GUM_SCALAR
>::
checkInterfaces__
(
537
PRMClassElement
<
GUM_SCALAR
>*
elt
) {
538
try
{
539
for
(
auto
i
:
implements
()) {
540
if
(
i
->
exists
(
elt
->
name
())) {
checkInterface__
(
elt
,
i
); }
541
}
542
}
catch
(
NotFound
&) {
543
// No interface
544
}
545
}
546
547
template
<
typename
GUM_SCALAR
>
548
void
549
PRMClass
<
GUM_SCALAR
>::
checkInterface__
(
PRMClassElement
<
GUM_SCALAR
>*
elt
,
550
PRMInterface
<
GUM_SCALAR
>*
i
) {
551
const
auto
&
i_elt
=
i
->
get
(
elt
->
name
());
552
bool
is_attr
=
PRMClassElement
<
GUM_SCALAR
>::
isAttribute
(
i_elt
);
553
bool
is_agg
=
PRMClassElement
<
GUM_SCALAR
>::
isAggregate
(
i_elt
);
554
555
if
(!(
is_attr
||
is_agg
)) {
556
GUM_ERROR
(
OperationNotAllowed
,
"Class does not respect it's interface"
);
557
}
558
559
if
(!
elt
->
type
().
isSubTypeOf
(
i_elt
.
type
())) {
560
GUM_ERROR
(
OperationNotAllowed
,
561
"Attribute type does not respect class interface"
);
562
}
563
564
if
(
elt
->
type
() !=
i_elt
.
type
()) {
565
if
(!
this
->
exists
(
i_elt
.
safeName
())) {
566
GUM_ERROR
(
OperationNotAllowed
,
567
"Attribute type does not respect class interface"
);
568
}
569
elt
= &(
this
->
get
(
i_elt
.
safeName
()));
570
}
571
572
// Node must be reserved by constructor
573
if
(!
dag__
.
existsNode
(
i_elt
.
id
())) {
574
GUM_ERROR
(
FatalError
,
"Class does not reserved implemented nodes"
);
575
}
576
577
// Removing unused node and changing to proper node
578
if
(
elt
->
id
() !=
i_elt
.
id
()) {
579
// Update cast descendants
580
for
(
auto
child
:
dag__
.
children
(
elt
->
id
())) {
581
dag__
.
addArc
(
i_elt
.
id
(),
child
);
582
}
583
dag__
.
eraseNode
(
elt
->
id
());
584
}
585
nodeIdMap__
.
erase
(
elt
->
id
());
586
elt
->
setId
(
i_elt
.
id
());
587
nodeIdMap__
.
insert
(
elt
->
id
(),
elt
);
588
}
589
590
template
<
typename
GUM_SCALAR
>
591
void
PRMClass
<
GUM_SCALAR
>::
checkRefInterfaces__
(
592
PRMReferenceSlot
<
GUM_SCALAR
>*
ref
) {
593
try
{
594
for
(
auto
i
:
implements
()) {
595
if
(
i
->
exists
(
ref
->
name
())) {
checkRefInterface__
(
ref
,
i
); }
596
}
597
}
catch
(
NotFound
&) {
598
// No interface to check
599
}
600
}
601
602
template
<
typename
GUM_SCALAR
>
603
void
PRMClass
<
GUM_SCALAR
>::
checkRefInterface__
(
604
PRMReferenceSlot
<
GUM_SCALAR
>*
ref
,
605
PRMInterface
<
GUM_SCALAR
>*
i
) {
606
auto
&
i_elt
=
i
->
get
(
ref
->
name
());
607
if
(
i_elt
.
elt_type
() !=
ref
->
elt_type
()) {
608
GUM_ERROR
(
OperationNotAllowed
,
"Class does not respect it's interface"
);
609
}
610
auto
&
i_ref
=
static_cast
<
PRMReferenceSlot
<
GUM_SCALAR
>& >(
i_elt
);
611
if
(!
ref
->
slotType
().
isSubTypeOf
(
i_ref
.
slotType
())) {
612
GUM_ERROR
(
OperationNotAllowed
,
613
"ReferenceSlot type does not respect class interface"
);
614
}
615
// Node must be reserved by constructor
616
if
(!
dag__
.
exists
(
i_ref
.
id
())) {
617
GUM_ERROR
(
FatalError
,
618
"class "
<<
this
->
name
() <<
" does not respect interface "
619
<<
i
->
name
() <<
" implementation"
);
620
}
621
// Removing unused node and changin to propoer node
622
if
(
ref
->
id
() !=
i_ref
.
id
()) {
dag__
.
eraseNode
(
ref
->
id
()); }
623
nodeIdMap__
.
erase
(
ref
->
id
());
624
ref
->
setId
(
i_ref
.
id
());
625
nodeIdMap__
.
insert
(
ref
->
id
(),
ref
);
626
}
627
628
template
<
typename
GUM_SCALAR
>
629
NodeId
PRMClass
<
GUM_SCALAR
>::
add
(
PRMClassElement
<
GUM_SCALAR
>*
elt
) {
630
if
(
nameMap__
.
exists
(
elt
->
name
())) {
631
GUM_ERROR
(
DuplicateElement
,
632
"name "
<<
elt
->
name
()
633
<<
" already used by another ClassElement"
);
634
}
635
636
elt
->
setId
(
nextNodeId
());
637
dag__
.
addNodeWithId
(
elt
->
id
());
638
nodeIdMap__
.
insert
(
elt
->
id
(),
elt
);
639
nameMap__
.
insert
(
elt
->
name
(),
elt
);
640
641
try
{
642
nameMap__
.
insert
(
elt
->
safeName
(),
elt
);
643
}
catch
(
DuplicateElement
&
e
) {
644
if
(!(
PRMClassElement
<
GUM_SCALAR
>::
isSlotChain
(*
elt
)
645
||
PRMClassElement
<
GUM_SCALAR
>::
isParameter
(*
elt
))) {
646
throw
DuplicateElement
(
e
);
647
}
648
}
649
650
switch
(
elt
->
elt_type
()) {
651
case
PRMClassElement
<
GUM_SCALAR
>::
prm_attribute
: {
652
attributes__
.
insert
(
static_cast
<
PRMAttribute
<
GUM_SCALAR
>* >(
elt
));
653
addCastDescendants__
(
static_cast
<
PRMAttribute
<
GUM_SCALAR
>* >(
elt
));
654
655
// Update attribute or cast descendant id to respect implemented
656
// interface
657
checkInterfaces__
(
elt
);
658
659
addIOInterfaceFlags__
(
elt
);
660
break
;
661
}
662
663
case
PRMClassElement
<
GUM_SCALAR
>::
prm_aggregate
: {
664
aggregates__
.
insert
(
static_cast
<
PRMAggregate
<
GUM_SCALAR
>* >(
elt
));
665
addCastDescendants__
(
static_cast
<
PRMAttribute
<
GUM_SCALAR
>* >(
elt
));
666
667
// Update attribute or cast descendant id to respect implemented
668
// interface
669
checkInterfaces__
(
elt
);
670
671
addIOInterfaceFlags__
(
elt
);
672
break
;
673
}
674
675
case
PRMClassElement
<
GUM_SCALAR
>::
prm_refslot
: {
676
auto
ref
=
static_cast
<
PRMReferenceSlot
<
GUM_SCALAR
>* >(
elt
);
677
referenceSlots__
.
insert
(
ref
);
678
679
// Updating ref's id if ref implements an interface
680
checkRefInterfaces__
(
ref
);
681
break
;
682
}
683
684
case
PRMClassElement
<
GUM_SCALAR
>::
prm_slotchain
: {
685
slotChains__
.
insert
(
static_cast
<
PRMSlotChain
<
GUM_SCALAR
>* >(
elt
));
686
break
;
687
}
688
689
case
PRMClassElement
<
GUM_SCALAR
>::
prm_parameter
: {
690
parameters__
.
insert
(
static_cast
<
PRMParameter
<
GUM_SCALAR
>* >(
elt
));
691
break
;
692
}
693
694
default
: {
695
GUM_ERROR
(
FatalError
,
"unknown ClassElement<GUM_SCALAR> type"
);
696
}
697
}
698
699
return
elt
->
id
();
700
}
701
702
template
<
typename
GUM_SCALAR
>
703
void
PRMClass
<
GUM_SCALAR
>::
addCastDescendants__
(
704
PRMClassElement
<
GUM_SCALAR
>*
attr
) {
705
auto
parent
=
attr
;
706
PRMAttribute
<
GUM_SCALAR
>*
child
= 0;
707
708
while
(
parent
->
type
().
isSubType
()) {
709
child
=
parent
->
getCastDescendant
();
710
711
// Check if id was reserved by one of the class interfaces
712
bool
found
=
false
;
713
try
{
714
for
(
auto
i
:
implements
()) {
715
if
(
i
->
exists
(
child
->
safeName
())) {
716
child
->
setId
(
i
->
get
(
child
->
safeName
()).
id
());
717
found
=
true
;
718
break
;
719
}
720
}
721
}
catch
(
NotFound
&) {
722
// No interface
723
}
724
if
(!
found
) {
725
child
->
setId
(
nextNodeId
());
726
dag__
.
addNodeWithId
(
child
->
id
());
727
}
728
nodeIdMap__
.
insert
(
child
->
id
(),
child
);
729
// Only use child's safe name when adding to the name map!
730
nameMap__
.
insert
(
child
->
safeName
(),
child
);
731
attributes__
.
insert
(
child
);
732
// Do not use Class<GUM_SCALAR>::insertArc(), child's CPF is already
733
// initialized properly
734
dag__
.
addArc
(
parent
->
id
(),
child
->
id
());
735
736
parent
=
child
;
737
}
738
}
739
740
template
<
typename
GUM_SCALAR
>
741
NodeId
PRMClass
<
GUM_SCALAR
>::
overload
(
742
PRMClassElement
<
GUM_SCALAR
>*
overloader
) {
743
try
{
744
if
(!
super
().
exists
(
overloader
->
name
())) {
745
GUM_ERROR
(
OperationNotAllowed
,
746
"found no ClassElement<GUM_SCALAR> to overload"
);
747
}
748
}
catch
(
NotFound
&) {
749
GUM_ERROR
(
OperationNotAllowed
,
750
"overload is possible only with subclasses"
);
751
}
752
753
PRMClassElement
<
GUM_SCALAR
>*
overloaded
=
nameMap__
[
overloader
->
name
()];
754
if
(
overloaded
==
overloader
) {
755
GUM_ERROR
(
DuplicateElement
,
756
"dupplicate ClassElement "
<<
overloader
->
name
());
757
}
758
// Checking overload legality
759
if
(!
checkOverloadLegality__
(
overloaded
,
overloader
)) {
760
GUM_ERROR
(
OperationNotAllowed
,
"illegal overload"
);
761
}
762
763
switch
(
overloader
->
elt_type
()) {
764
case
PRMClassElement
<
GUM_SCALAR
>::
prm_attribute
: {
765
auto
overloader_attr
766
=
static_cast
<
PRMAttribute
<
GUM_SCALAR
>* >(
overloader
);
767
auto
overloaded_attr
768
=
static_cast
<
PRMAttribute
<
GUM_SCALAR
>* >(
overloaded
);
769
overloadAttribute__
(
overloader_attr
,
overloaded_attr
);
770
addIOInterfaceFlags__
(
overloader
);
771
break
;
772
}
773
774
case
PRMClassElement
<
GUM_SCALAR
>::
prm_aggregate
: {
775
overloadAggregate__
(
776
static_cast
<
PRMAggregate
<
GUM_SCALAR
>* >(
overloader
),
777
overloaded
);
778
addIOInterfaceFlags__
(
overloader
);
779
break
;
780
}
781
782
case
PRMClassElement
<
GUM_SCALAR
>::
prm_refslot
: {
783
// checkOverloadLegality__ guaranties that overloaded is a
784
// PRMReferenceSlot<GUM_SCALAR>
785
auto
overloader_ref
786
=
static_cast
<
PRMReferenceSlot
<
GUM_SCALAR
>* >(
overloader
);
787
auto
overloaded_ref
788
=
static_cast
<
PRMReferenceSlot
<
GUM_SCALAR
>* >(
overloaded
);
789
overloadReference__
(
overloader_ref
,
overloaded_ref
);
790
break
;
791
}
792
793
case
PRMClassElement
<
GUM_SCALAR
>::
prm_slotchain
: {
794
GUM_ERROR
(
OperationNotAllowed
,
795
"SlotChain<GUM_SCALAR> can not be overloaded"
);
796
break
;
797
}
798
799
case
PRMClassElement
<
GUM_SCALAR
>::
prm_parameter
: {
800
auto
overloaded_param
801
=
static_cast
<
PRMParameter
<
GUM_SCALAR
>* >(
overloaded
);
802
auto
overloader_param
803
=
static_cast
<
PRMParameter
<
GUM_SCALAR
>* >(
overloader
);
804
overloadParameter__
(
overloader_param
,
overloaded_param
);
805
break
;
806
}
807
default
: {
808
GUM_ERROR
(
OperationNotAllowed
,
"unknown ClassElement<GUM_SCALAR> type"
);
809
}
810
}
811
812
return
overloader
->
id
();
813
}
814
815
template
<
typename
GUM_SCALAR
>
816
void
PRMClass
<
GUM_SCALAR
>::
overloadAttribute__
(
817
PRMAttribute
<
GUM_SCALAR
>*
overloader
,
818
PRMAttribute
<
GUM_SCALAR
>*
overloaded
) {
819
dag__
.
eraseParents
(
overloaded
->
id
());
820
821
// Checking if we have to add cast descendant
822
if
(
overloader
->
type
() !=
overloaded
->
type
()) {
823
overloader
->
setId
(
nextNodeId
());
824
dag__
.
addNodeWithId
(
overloader
->
id
());
825
nodeIdMap__
.
insert
(
overloader
->
id
(),
overloader
);
826
nameMap__
[
overloader
->
name
()] =
overloader
;
827
nameMap__
.
insert
(
overloader
->
safeName
(),
overloader
);
828
attributes__
.
insert
(
overloader
);
829
addCastDescendants__
(
overloader
,
overloaded
);
830
}
else
{
831
overloader
->
setId
(
overloaded
->
id
());
832
nodeIdMap__
[
overloader
->
id
()] =
overloader
;
833
nameMap__
[
overloader
->
name
()] =
overloader
;
834
nameMap__
[
overloader
->
safeName
()] =
overloader
;
835
attributes__
.
erase
(
overloaded
);
836
attributes__
.
insert
(
overloader
);
837
overloader
->
overload
(
overloaded
);
838
delete
overloaded
;
839
}
840
}
841
842
template
<
typename
GUM_SCALAR
>
843
void
PRMClass
<
GUM_SCALAR
>::
overloadReference__
(
844
PRMReferenceSlot
<
GUM_SCALAR
>*
overloader
,
845
PRMReferenceSlot
<
GUM_SCALAR
>*
overloaded
) {
846
// Adding overloading reference
847
overloader
->
setId
(
overloaded
->
id
());
848
nodeIdMap__
[
overloader
->
id
()] =
overloader
;
849
nameMap__
[
overloader
->
name
()] =
overloader
;
850
nameMap__
.
insert
(
overloader
->
safeName
(),
overloader
);
851
referenceSlots__
.
insert
(
overloader
);
852
PRMSlotChain
<
GUM_SCALAR
>*
sc
= 0;
853
PRMReferenceSlot
<
GUM_SCALAR
>*
ref
= 0;
854
PRMClassElement
<
GUM_SCALAR
>*
next
= 0;
855
std
::
vector
<
PRMSlotChain
<
GUM_SCALAR
>* >
toRemove
,
toAdd
;
856
857
// Updating PRMSlotChain<GUM_SCALAR> which started with overloaded
858
for
(
const
auto
slotchain
:
slotChains__
) {
859
// If the attribute pointed by this slotchain is overloaded, we need to
860
// change the slotchain
861
// names to it's safename version: ref.attr is replaced by
862
// ref.(type)attr.
863
if
((
slotchain
->
chain
().
atPos
(0) ==
overloaded
)) {
864
Sequence
<
PRMClassElement
<
GUM_SCALAR
>* >
seq
;
865
seq
.
insert
(
overloader
);
866
867
auto
elt
= ++(
slotchain
->
chain
().
begin
());
868
869
while
(
elt
!=
slotchain
->
chain
().
end
()) {
870
ref
=
static_cast
<
PRMReferenceSlot
<
GUM_SCALAR
>* >(
seq
.
back
());
871
next
= &(
ref
->
slotType
().
get
((*
elt
)->
name
()));
872
seq
.
insert
(
next
);
873
++
elt
;
874
}
875
876
// If the slotchain last element type changes, we change the slotchain
877
// to
878
// point towards the cast decendant
879
// with the correct type
880
if
(
seq
.
back
()->
type
() !=
slotchain
->
lastElt
().
type
()) {
881
seq
.
erase
(
seq
.
back
());
882
seq
.
insert
(&(
static_cast
<
PRMReferenceSlot
<
GUM_SCALAR
>* >(
seq
.
back
())
883
->
slotType
()
884
.
get
(
slotchain
->
lastElt
().
safeName
())));
885
std
::
string
sc_name
;
886
std
::
string
dot
=
"."
;
887
888
for
(
Size
i
= 0;
i
<
seq
.
size
() - 1; ++
i
) {
889
sc_name
+=
seq
.
atPos
(
i
)->
name
() +
dot
;
890
}
891
892
sc_name
+=
seq
.
back
()->
safeName
();
893
sc
=
new
PRMSlotChain
<
GUM_SCALAR
>(
sc_name
,
seq
);
894
sc
->
setId
(
slotchain
->
id
());
895
896
for
(
const
auto
child
:
this
->
containerDag
().
children
(
sc
->
id
())) {
897
auto
&
elt
=
get
(
child
);
898
if
(
PRMClassElement
<
GUM_SCALAR
>::
isAttribute
(
elt
)) {
899
auto
&
attr
=
static_cast
<
PRMAttribute
<
GUM_SCALAR
>& >(
elt
);
900
auto
&
old_type
=
slotchain
->
lastElt
().
type
();
901
auto
&
new_type
=
sc
->
lastElt
().
type
();
902
attr
.
swap
(
old_type
,
new_type
);
903
}
else
{
904
GUM_ERROR
(
OperationNotAllowed
,
"unexpected ClassElement"
);
905
// get( child ).cpf().replace(
906
// slotchain->lastElt().type().variable(),
907
// sc->lastElt().type().variable() );
908
}
909
}
910
911
toAdd
.
push_back
(
sc
);
912
toRemove
.
push_back
(
slotchain
);
913
}
else
{
914
// Types are identical, we just need to change the first reference
915
slotchain
->
chain
().
setAtPos
(0,
overloader
);
916
}
917
}
918
}
919
920
for
(
const
auto
torem
:
toRemove
) {
921
nameMap__
.
erase
(
torem
->
name
());
922
slotChains__
.
erase
(
torem
);
923
delete
torem
;
924
}
925
926
for
(
const
auto
toadd
:
toAdd
) {
927
nameMap__
.
insert
(
toadd
->
name
(),
toadd
);
928
nodeIdMap__
[
toadd
->
id
()] =
toadd
;
929
slotChains__
.
insert
(
sc
);
930
}
931
932
// Removing overloaded PRMReferenceSlot<GUM_SCALAR>
933
referenceSlots__
.
erase
(
overloaded
);
934
nameMap__
.
erase
(
overloaded
->
safeName
());
935
delete
overloaded
;
936
}
937
938
template
<
typename
GUM_SCALAR
>
939
void
PRMClass
<
GUM_SCALAR
>::
overloadParameter__
(
940
PRMParameter
<
GUM_SCALAR
>*
overloader
,
941
PRMParameter
<
GUM_SCALAR
>*
overloaded
) {
942
overloader
->
setId
(
overloaded
->
id
());
943
nodeIdMap__
[
overloader
->
id
()] =
overloader
;
944
nameMap__
[
overloader
->
name
()] =
overloader
;
945
nameMap__
[
overloader
->
safeName
()] =
overloader
;
946
parameters__
.
erase
(
overloaded
);
947
parameters__
.
insert
(
overloader
);
948
delete
overloaded
;
949
}
950
951
template
<
typename
GUM_SCALAR
>
952
void
PRMClass
<
GUM_SCALAR
>::
addCastDescendants__
(
953
PRMAttribute
<
GUM_SCALAR
>*
start
,
954
PRMAttribute
<
GUM_SCALAR
>*
end
) {
955
PRMAttribute
<
GUM_SCALAR
>*
parent
=
start
;
956
PRMAttribute
<
GUM_SCALAR
>*
child
= 0;
957
958
while
(
parent
->
type
().
superType
() !=
end
->
type
()) {
959
child
=
parent
->
getCastDescendant
();
960
child
->
setId
(
nextNodeId
());
961
nodeIdMap__
.
insert
(
child
->
id
(),
child
);
962
dag__
.
addNodeWithId
(
child
->
id
());
963
// Only use child's safe name when adding to the name map!
964
nameMap__
.
insert
(
child
->
safeName
(),
child
);
965
attributes__
.
insert
(
child
);
966
addIOInterfaceFlags__
(
child
);
967
// Do not use Class<GUM_SCALAR>::insertArc(), child's CPF is already
968
// initialized properly
969
dag__
.
addArc
(
parent
->
id
(),
child
->
id
());
970
parent
=
child
;
971
}
972
973
parent
->
setAsCastDescendant
(
end
);
974
dag__
.
addArc
(
parent
->
id
(),
end
->
id
());
975
}
976
977
template
<
typename
GUM_SCALAR
>
978
void
PRMClass
<
GUM_SCALAR
>::
findAllSubtypes_
(
979
Set
<
PRMClassElementContainer
<
GUM_SCALAR
>* >&
set
) {
980
for
(
auto
ext
:
extensions__
) {
981
set
.
insert
(
ext
);
982
ext
->
findAllSubtypes_
(
set
);
983
}
984
}
985
986
template
<
typename
GUM_SCALAR
>
987
void
PRMClass
<
GUM_SCALAR
>::
addIOInterfaceFlags__
(
988
PRMClassElement
<
GUM_SCALAR
>*
elt
) {
989
// We only add IO Flags if elt matches is required by and interface
990
if
(
implements__
!=
nullptr
) {
991
for
(
const
auto
impl
: *
implements__
) {
992
PRMInterface
<
GUM_SCALAR
>*
super
=
impl
;
993
while
(
super
) {
994
// If the attribute is defined in an interface, we set it as an
995
// OutputNode
996
if
(
impl
->
exists
(
elt
->
name
())) {
997
try
{
998
this
->
getIOFlag_
(*
elt
).
second
=
true
;
999
}
catch
(
NotFound
&) {
1000
this
->
setIOFlag_
(*
elt
,
std
::
make_pair
(
false
,
true
));
1001
}
1002
}
1003
try
{
1004
super
= &(
super
->
super
());
1005
}
catch
(
NotFound
&) {
super
=
nullptr
; }
1006
}
1007
}
1008
}
1009
}
1010
1011
template
<
typename
GUM_SCALAR
>
1012
void
PRMClass
<
GUM_SCALAR
>::
updateDescendants_
(
1013
const
PRMClassElement
<
GUM_SCALAR
>&
elt
) {
1014
// for ( const auto ext : extensions__ ) {
1015
// // We test to prevent unnecessary recursive call from iter
1016
// if ( !ext->isOutputNode( elt ) ) {
1017
// ext->setOutputNode( elt, true );
1018
// }
1019
//}
1020
}
1021
1022
template
<
typename
GUM_SCALAR
>
1023
INLINE
typename
PRMObject
::
prm_type
PRMClass
<
GUM_SCALAR
>::
obj_type
()
const
{
1024
return
PRMObject
::
prm_type
::
CLASS
;
1025
}
1026
1027
template
<
typename
GUM_SCALAR
>
1028
INLINE
const
DAG
&
PRMClass
<
GUM_SCALAR
>::
dag_
()
const
{
1029
return
dag__
;
1030
}
1031
1032
template
<
typename
GUM_SCALAR
>
1033
INLINE
DAG
&
PRMClass
<
GUM_SCALAR
>::
dag_
() {
1034
return
dag__
;
1035
}
1036
1037
template
<
typename
GUM_SCALAR
>
1038
INLINE
PRMClassElement
<
GUM_SCALAR
>&
PRMClass
<
GUM_SCALAR
>::
get
(
NodeId
id
) {
1039
try
{
1040
return
*(
nodeIdMap__
[
id
]);
1041
}
catch
(
NotFound
&) {
1042
GUM_ERROR
(
NotFound
,
"no ClassElement<GUM_SCALAR> with the given NodeId"
);
1043
}
1044
}
1045
1046
template
<
typename
GUM_SCALAR
>
1047
INLINE
const
PRMClassElement
<
GUM_SCALAR
>&
1048
PRMClass
<
GUM_SCALAR
>::
get
(
NodeId
id
)
const
{
1049
try
{
1050
return
*(
nodeIdMap__
[
id
]);
1051
}
catch
(
NotFound
&) {
1052
GUM_ERROR
(
NotFound
,
1053
"no ClassElement<GUM_SCALAR> with the given NodeId ("
<<
id
1054
<<
")"
);
1055
}
1056
}
1057
1058
template
<
typename
GUM_SCALAR
>
1059
INLINE
PRMClassElement
<
GUM_SCALAR
>&
1060
PRMClass
<
GUM_SCALAR
>::
get
(
const
std
::
string
&
name
) {
1061
try
{
1062
return
*(
nameMap__
[
name
]);
1063
}
catch
(
NotFound
&) {
1064
GUM_ERROR
(
NotFound
,
1065
"no ClassElement<GUM_SCALAR> with the given name ("
<<
name
1066
<<
")"
);
1067
}
1068
}
1069
1070
template
<
typename
GUM_SCALAR
>
1071
INLINE
const
PRMClassElement
<
GUM_SCALAR
>&
1072
PRMClass
<
GUM_SCALAR
>::
get
(
const
std
::
string
&
name
)
const
{
1073
try
{
1074
return
*(
nameMap__
[
name
]);
1075
}
catch
(
NotFound
&) {
1076
GUM_ERROR
(
NotFound
,
1077
"no ClassElement<GUM_SCALAR> with the given name ("
<<
name
1078
<<
")"
);
1079
}
1080
}
1081
1082
template
<
typename
GUM_SCALAR
>
1083
INLINE
const
Set
<
PRMAttribute
<
GUM_SCALAR
>* >&
1084
PRMClass
<
GUM_SCALAR
>::
attributes
()
const
{
1085
return
attributes__
;
1086
}
1087
1088
template
<
typename
GUM_SCALAR
>
1089
INLINE
const
Set
<
PRMParameter
<
GUM_SCALAR
>* >&
1090
PRMClass
<
GUM_SCALAR
>::
parameters
()
const
{
1091
return
parameters__
;
1092
}
1093
1094
// Private struct for retrieving all params in scope
1095
template
<
typename
GUM_SCALAR
>
1096
struct
ParamScopeData
{
1097
std
::
string
prefix
;
1098
const
PRMClass
<
GUM_SCALAR
>*
c
;
1099
Idx
depth
;
1100
1101
ParamScopeData
(
const
std
::
string
&
s
,
1102
const
PRMReferenceSlot
<
GUM_SCALAR
>&
ref
,
1103
Idx
d
) :
1104
prefix
(
s
+
ref
.
name
() +
"."
),
1105
c
(
static_cast
<
const
PRMClass
<
GUM_SCALAR
>* >(&(
ref
.
slotType
()))),
1106
depth
(
d
) {}
1107
};
1108
1109
template
<
typename
GUM_SCALAR >
1110
INLINE HashTable<
std
::
string
,
const
PRMParameter
<
GUM_SCALAR
>* >
1111
PRMClass
<
GUM_SCALAR
>::
scope
()
const
{
1112
HashTable
<
std
::
string
,
const
PRMParameter
<
GUM_SCALAR
>* >
params
;
1113
1114
for
(
const
auto
p
:
parameters
()) {
1115
params
.
insert
(
p
->
name
(),
p
);
1116
}
1117
1118
std
::
queue
<
ParamScopeData
<
GUM_SCALAR
> >
queue
;
1119
1120
for
(
const
auto
ref
:
referenceSlots
()) {
1121
if
(
PRMObject
::
isClass
(
ref
->
slotType
())) {
1122
queue
.
push
(
ParamScopeData
<
GUM_SCALAR
>(
""
, *
ref
, 1));
1123
}
1124
}
1125
1126
while
(!
queue
.
empty
()) {
1127
auto
data
=
queue
.
front
();
1128
queue
.
pop
();
1129
1130
if
(
data
.
depth
< 5) {
1131
for
(
const
auto
p
:
data
.
c
->
parameters
()) {
1132
params
.
insert
(
data
.
prefix
+
p
->
name
(),
p
);
1133
}
1134
1135
for
(
const
auto
ref
:
data
.
c
->
referenceSlots
()) {
1136
if
(
PRMObject
::
isClass
(
ref
->
slotType
())) {
1137
queue
.
push
(
1138
ParamScopeData
<
GUM_SCALAR
>(
data
.
prefix
, *
ref
,
data
.
depth
+ 1));
1139
}
1140
}
1141
}
else
{
1142
// @todo depth>5 is a workaround. Cycle detection is needed here !
1143
GUM_TRACE
(
"Depth limit reached when looking up parameters"
);
1144
}
1145
}
1146
1147
return
params
;
1148
}
1149
1150
template
<
typename
GUM_SCALAR
>
1151
INLINE
const
Set
<
PRMAggregate
<
GUM_SCALAR
>* >&
1152
PRMClass
<
GUM_SCALAR
>::
aggregates
()
const
{
1153
return
aggregates__
;
1154
}
1155
1156
template
<
typename
GUM_SCALAR
>
1157
INLINE
const
Set
<
PRMReferenceSlot
<
GUM_SCALAR
>* >&
1158
PRMClass
<
GUM_SCALAR
>::
referenceSlots
()
const
{
1159
return
referenceSlots__
;
1160
}
1161
1162
template
<
typename
GUM_SCALAR
>
1163
INLINE
const
Set
<
PRMSlotChain
<
GUM_SCALAR
>* >&
1164
PRMClass
<
GUM_SCALAR
>::
slotChains
()
const
{
1165
return
slotChains__
;
1166
}
1167
1168
template
<
typename
GUM_SCALAR
>
1169
INLINE
const
PRMClass
<
GUM_SCALAR
>&
PRMClass
<
GUM_SCALAR
>::
super
()
const
{
1170
if
(
superClass__
) {
1171
return
*
superClass__
;
1172
}
else
{
1173
GUM_ERROR
(
NotFound
,
"this Class is not a subclass"
);
1174
}
1175
}
1176
1177
template
<
typename
GUM_SCALAR
>
1178
INLINE
const
Set
<
PRMInterface
<
GUM_SCALAR
>* >&
1179
PRMClass
<
GUM_SCALAR
>::
implements
()
const
{
1180
if
(
implements__
) {
1181
return
*
implements__
;
1182
}
else
{
1183
GUM_ERROR
(
NotFound
,
1184
"this Class does not implement any Interface<GUM_SCALAR>"
);
1185
}
1186
}
1187
1188
template
<
typename
GUM_SCALAR
>
1189
INLINE
PRMClassElement
<
GUM_SCALAR
>&
1190
PRMClass
<
GUM_SCALAR
>::
operator
[](
NodeId
id
) {
1191
return
get
(
id
);
1192
}
1193
1194
template
<
typename
GUM_SCALAR
>
1195
INLINE
const
PRMClassElement
<
GUM_SCALAR
>&
1196
PRMClass
<
GUM_SCALAR
>::
operator
[](
NodeId
id
)
const
{
1197
return
get
(
id
);
1198
}
1199
1200
template
<
typename
GUM_SCALAR
>
1201
INLINE
PRMClassElement
<
GUM_SCALAR
>&
1202
PRMClass
<
GUM_SCALAR
>::
operator
[](
const
std
::
string
&
name
) {
1203
return
get
(
name
);
1204
}
1205
1206
template
<
typename
GUM_SCALAR
>
1207
INLINE
const
PRMClassElement
<
GUM_SCALAR
>&
1208
PRMClass
<
GUM_SCALAR
>::
operator
[](
const
std
::
string
&
name
)
const
{
1209
return
get
(
name
);
1210
}
1211
1212
template
<
typename
GUM_SCALAR
>
1213
INLINE
void
PRMClass
<
GUM_SCALAR
>::
overloadAggregate__
(
1214
PRMAggregate
<
GUM_SCALAR
>*
overloader
,
1215
PRMClassElement
<
GUM_SCALAR
>*
overloaded
) {
1216
nameMap__
.
insert
(
overloader
->
safeName
(),
overloader
);
1217
aggregates__
.
insert
(
overloader
);
1218
}
1219
1220
template
<
typename
GUM_SCALAR
>
1221
INLINE
bool
PRMClass
<
GUM_SCALAR
>::
checkOverloadLegality__
(
1222
const
PRMClassElement
<
GUM_SCALAR
>*
overloaded
,
1223
const
PRMClassElement
<
GUM_SCALAR
>*
overloader
) {
1224
if
(
overloaded
->
elt_type
() !=
overloader
->
elt_type
()) {
return
false
; }
1225
1226
switch
(
overloaded
->
elt_type
()) {
1227
case
PRMClassElement
<
GUM_SCALAR
>::
prm_attribute
: {
1228
if
(!
overloader
->
type
().
isSubTypeOf
(
overloaded
->
type
())) {
1229
return
false
;
1230
}
1231
break
;
1232
}
1233
1234
case
PRMClassElement
<
GUM_SCALAR
>::
prm_refslot
: {
1235
const
auto
&
new_slot_type
1236
=
static_cast
<
const
PRMReferenceSlot
<
GUM_SCALAR
>* >(
overloader
)
1237
->
slotType
();
1238
const
auto
&
old_slot_type
1239
=
static_cast
<
const
PRMReferenceSlot
<
GUM_SCALAR
>* >(
overloaded
)
1240
->
slotType
();
1241
1242
if
(!
new_slot_type
.
isSubTypeOf
(
old_slot_type
)) {
return
false
; }
1243
1244
break
;
1245
}
1246
1247
case
PRMClassElement
<
GUM_SCALAR
>::
prm_parameter
: {
1248
auto
overloaded_param
1249
=
static_cast
<
const
PRMParameter
<
GUM_SCALAR
>* >(
overloaded
);
1250
auto
overloader_param
1251
=
static_cast
<
const
PRMParameter
<
GUM_SCALAR
>* >(
overloader
);
1252
1253
return
overloaded_param
->
valueType
() ==
overloader_param
->
valueType
();
1254
break
;
1255
}
1256
1257
default
: {
1258
return
false
;
1259
}
1260
}
1261
return
true
;
1262
}
1263
1264
template
<
typename
GUM_SCALAR
>
1265
INLINE
const
Set
<
PRMClass
<
GUM_SCALAR
>* >&
1266
PRMClass
<
GUM_SCALAR
>::
extensions
()
const
{
1267
return
extensions__
;
1268
}
1269
1270
template
<
typename
GUM_SCALAR
>
1271
INLINE
void
PRMClass
<
GUM_SCALAR
>::
addExtension__
(
PRMClass
<
GUM_SCALAR
>*
c
) {
1272
extensions__
.
insert
(
c
);
1273
}
1274
1275
template
<
typename
GUM_SCALAR
>
1276
INLINE
bool
PRMClass
<
GUM_SCALAR
>::
isCastDescendant
(
1277
const
std
::
string
&
safe_name
)
const
{
1278
const
PRMClassElement
<
GUM_SCALAR
>&
elt
=
get
(
safe_name
);
1279
1280
try
{
1281
return
elt
.
type
().
name
() ==
get
(
elt
.
name
()).
type
().
name
();
1282
}
catch
(
OperationNotAllowed
&) {
1283
GUM_ERROR
(
NotFound
,
"no attribute with the given name"
);
1284
}
1285
}
1286
1287
template
<
typename
GUM_SCALAR
>
1288
INLINE
bool
PRMClass
<
GUM_SCALAR
>::
isOutputNode
(
1289
const
PRMClassElement
<
GUM_SCALAR
>&
elt
)
const
{
1290
try
{
1291
if
(!
this
->
getIOFlag_
(
elt
).
second
) {
1292
if
(
implements__
) {
1293
for
(
auto
i
: *
implements__
) {
1294
if
(
i
->
isOutputNode
(
elt
)) {
return
true
; }
1295
}
1296
}
1297
1298
if
(
superClass__
&& (
superClass__
->
isOutputNode
(
elt
))) {
return
true
; }
1299
1300
}
else
{
1301
return
true
;
1302
}
1303
}
catch
(
NotFound
&) {}
1304
return
false
;
1305
}
1306
1307
1308
}
/* namespace prm */
1309
}
/* namespace gum */
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:669
gum::prm::ParamScopeData::ParamScopeData
ParamScopeData(const std::string &s, const PRMReferenceSlot< GUM_SCALAR > &ref, Idx d)
Definition:
PRMClass_tpl.h:1101