2
# Builtins for generated implementations of modeled objects
3
# and runtime support for managing object references.
6
# Author: Eldar Abusalimov
9
ifndef __model_eobject_mk
10
__model_eobject_mk := 1
14
# 2. Instance class name.
16
# 4. Flags, which may contain:
18
define builtin_func-eobject
21
# Extends implementations of each super class.
22
$(foreach s,$(or $3,EObject),
25
$$(getter eMetaClassId,
27
# A little optimization.
35
# 2. Instance property name.
36
# 3. Flags, which may contain:
38
define builtin_func-eobject-attribute
40
$(if $(filter changeable,$3),
41
# Changeable attributes are just property-fields.
42
$$(property-field $2$(if $(filter many,$3),...)),
44
# Otherwise, only getter should be defined.
45
$$(property $2$(if $(filter many,$3),...))
46
$$(field $2$(if $(filter many,$3),...))
55
# 2. Instance property name.
57
# 4. Opposite property name (if any).
58
# 5. Flags, which may contain:
59
# changeable many containment container linkable
60
define builtin_func-eobject-reference
63
# Declare a propery (though it has already been declared in API class).
64
$$(property $2$(if $(filter many,$5),...) : $3)
67
$(if $(filter contain%,$5),
68
# Container and containment references share the same field.
70
$$(suffix $$(filter $2/%,$$(get-field \
71
$(if $(filter container,$5),__eContainer,__eContents))))),
73
# Otherwise define a new field.
74
# Cross references are stored in raw fields.
75
$$(field $2$(if $(filter many,$5),...))
76
# There is also a custom serializer for such fields.
77
$$(method __serialize_field-$2,
78
$$(call __eObjectSerializeCrossReference,$2,$1))
81
# Linkable references also support on-demand linkage.
82
$(if $(filter linkable,$5),
83
$$(call __eObjectResolveLinks,
84
$$(filter %./,$$(get-field $2)),$1))
85
# Getting suffix is mandatory here!
86
$$(suffix $$(get-field $2)))
90
$(if $(filter containment,$5),Containment,
91
$(if $(filter container,$5),Container,
92
$(if $4,Bidirectional,Unidirectional))),
95
$(__eobject_ref_setter)
97
$(if $(filter linkable,$5),
98
$(for property <- $(property)_link$(if $(filter many,$5),s),
99
fn_suffix <- $(fn_suffix)_link,
101
# Declare a propery for links.
102
$$(property $(property)$(if $(filter many,$5),...) : $3)
104
$$(getter $(property),
105
$$(subst ./,,$$(dir $$(get-field $2))))
107
$(__eobject_ref_setter)
115
# Same as to 'eobject-reference' builtin.
119
define __eobject_ref_setter
120
$(if $(filter changeable,$5),
121
$$(setter $(property),
122
$(if $(not $(filter many,$5)),
123
$$(assert $$(not $$2),
124
Set '$$2' invoked for a non-list EReference $1)
126
$$(call __eObjectSet$(fn_suffix)$$2,$2,$$(suffix $$1),$4,$1))
132
# 2. Meta reference ID.
133
define __eObjectSerializeCrossReference
134
$(assert $(not $(or $(get $2->isContainment),$(get $2->isContainer))),
135
$0: Can't handle non-cross references)
140
$(for r <- $(get-field $1),
141
$(for l <- $(subst ./,,$(dir $r)),# Link.
142
$($l.__serial_id__)./)
143
$(for t <- $(suffix $r),# Target.
144
$(for l <- $(basename $(notdir $r)),# Opposite link.
146
$($t.__serial_id__)))
150
# Container and containment references.
156
# 3. Containment property in the container.
157
define __eObjectSetContainer
158
$(assert $(not $(multiword $2)))
160
$(for oldContainer <- $(get-field __eContainer),
161
$(if $(basename $(oldContainer)),
162
# Regular containment.
163
$(set-field- oldContainer->__eContents,
164
$(notdir $(basename $(oldContainer)))/$(this)),
165
# Resource containment.
166
$(set oldContainer->contentsRoot,)
170
$(set-field __eContainer,$1/$3$2)
172
$(set-field+ 2->__eContents,$3/$(this))
178
# 3. Opposite property.
179
define __eObjectSetContainment+
180
$(silent-for this <- $2,
181
# XXX Using '__this'. -- Eldar
182
$(call __eObjectSetContainer,$3,$(__this),$1))
188
# 3. Opposite property.
189
__eObjectSetContainment* = \
190
$(__eObjectSetContainment+)
195
# 3. Opposite property.
196
__eObjectSetContainment- = \
197
$(foreach ,$2,$(warning $0: NIY))
202
# 3. Opposite property.
203
define __eObjectSetContainment
204
$(call __eObjectSetContainment-,$1,$(get $1),$3)
205
$(call __eObjectSetContainment+,$1,$2,$3)
209
# Unidirectional cross-references.
215
__eObjectSetUnidirectional+ = \
222
# 4. Meta reference ID.
223
define __eObjectSetUnidirectional_link+
226
$(assert $(not $(get-field link->eSource)),
227
Link $(link) has already got a source)
228
$(set-field link->eSource,$4$(this))
229
# 'link./target' for resolved links, 'link./' otherwise.
230
$(link)./$(get-field link->eTarget))
237
__eObjectSetUnidirectional* = \
244
# 4. Meta reference ID.
245
__eObjectSetUnidirectional_link* = \
246
$(call __eObjectSetUnidirectional_link+,$1, \
247
$(filter-out $(get-field $1),$2),,$4)
252
__eObjectSetUnidirectional- = \
253
$(foreach ,$2,$(warning $0: NIY))
258
__eObjectSetUnidirectional_link- = \
259
$(foreach ,$2,$(warning $0: NIY))
264
define __eObjectSetUnidirectional
265
$(set-field $1,)#TODO Deresolve of link before removing not implemented
266
$(call __eObjectSetUnidirectional+,$1,$2)
273
# 4. Meta reference ID.
274
define __eObjectSetUnidirectional_link
275
$(call __eObjectSetUnidirectional_link-,$1,$(get-field $1))
276
$(call __eObjectSetUnidirectional_link+,$1,$2,,$4)
280
# Bidirectional cross-references.
286
# 3. Opposite property.
287
define __eObjectSetBidirectional+
289
$(set-field+ 2->$3,$(this))
295
# 3. Opposite property.
296
# 4. Meta reference ID.
297
define __eObjectSetBidirectional_link+
300
$(assert $(not $(get-field link->eSource)),
301
Link $(link) has already got a source)
302
$(set-field link->eSource,$4$(this))
303
# 'link./target' for resolved links, 'link./' otherwise.
304
$(link)./$(for target <- $(get-field link->eTarget),
305
$(set-field+ target->$3,$(link)$(this))
313
# 3. Opposite property.
314
__eObjectSetBidirectional* = \
315
$(call __eObjectSetBidirectional+,$1,$(filter-out $(get-field $1),$2),$3)
320
# 3. Opposite property.
321
# 4. Meta reference ID.
322
__eObjectSetBidirectional_link* = \
323
$(call __eObjectSetBidirectional_link+,$1, \
324
$(filter-out $(get-field $1),$2),$3,$4)
329
# 3. Opposite property.
330
__eObjectSetBidirectional- = \
331
$(foreach ,$2,$(warning $0: NIY))
336
# 3. Opposite property.
337
__eObjectSetBidirectional_link- = \
338
$(foreach ,$2,$(warning $0: NIY))
343
# 3. Opposite property.
344
define __eObjectSetBidirectional
345
$(call __eObjectSetBidirectional-,$1,$(get-field $1),$3)
346
$(call __eObjectSetBidirectional+,$1,$2,$3)
352
# 3. Opposite property.
353
# 4. Meta reference ID.
354
define __eObjectSetBidirectional_link
355
$(call __eObjectSetBidirectional_link-,$1,$(get-field $1),$3)
356
$(call __eObjectSetBidirectional_link+,$1,$2,$3,$4)
360
# On-demand linkage and link target resolution.
364
# 1. List of unresolved (at the call time) references with './' at their ends.
365
# 2. Meta reference ID.
366
define __eObjectResolveLinks
367
$(and $1,$(for resource <- $(get this->eResource),
368
# $(for link <- $(subst ./,,$1),
369
# $(warning on-demand linkage: \
370
# [$(get link->eMetaReference)] '$(get link->name)'))
371
$(invoke resource->resourceSet>linker>resolveLinksGroup,
372
$(subst ./,,$1),$($2))
377
# 1. New value of 'eTarget' property of this link.
378
define __eLinkSetTarget
379
$(assert $(not $(multiword $1)))
380
$(assert $(invoke eSource),
381
Can't set a target on the link with no source)
383
$(for oldTarget <- $(get-field eTarget),
384
$(warning $0: NIY; (old target: '$(oldTarget)')))
386
$(set-field eTarget,$1)
388
$(for newTarget <- $1,
389
source <- $(invoke eSource),
390
metaReference <- $(get eMetaReference),
391
referenceProperty <- $(get metaReference->instanceProperty),
393
$(set-field source->$(referenceProperty),
394
$(patsubst $(this)./,$(this)./$(newTarget),
395
$(get-field source->$(referenceProperty))))
397
$(for opposite <- $(get metaReference->eOpposite),
398
$(set-field+ newTarget->$(get opposite->instanceProperty),
405
endif # __model_eobject_mk