STBInFiler and events

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

STBInFiler and events

Vladimir Musulainen
Hello all.

I have next model of objects
Every object of class A own collection of objects of class B.
Every object of class B own collection ob objects of class C.

When object class A append  object of class B to collection (objects
of class B), that objectB get next event

objectB when:#change send: #changeObjectsB to: self

where self is object of class A.

Class B do same event for object of class C (when object B append to
collection object of class C)

I want save my model to file and later restore it.
But, if use standart  STBINFiler STBOutFiler, that events for objects
not save/restore.

I proposes, that heed  use STBProxy, but not understand work with it.

May anybody tell me with this?


Reply | Threaded
Open this post in threaded view
|

Re: STBInFiler and events

Ian Bartholomew-19
Musulainen,

> I want save my model to file and later restore it.
> But, if use standart  STBINFiler STBOutFiler, that events for objects
> not save/restore.
>
> I proposes, that heed  use STBProxy, but not understand work with it.

Wouldn't it be easier to just keep it as simple as possible and restore the
events yourself?

ClassA>>restoreFrom: aStream
    collectionA := Object binaryReadFrom: aStream. "or whatever"
    collectionA do: [:eachB |
        eachB restoreEvents.
        eachB when: #change send: #changeObjectsB to: self]

ClassB>>restoreEvents
    collectionB do: [:eachC |
                eachC when: #change send: #changeObjectsC to: self]

--
Ian

Use the Reply-To address to contact me.
Mail sent to the From address is ignored.


Reply | Threaded
Open this post in threaded view
|

Re: STBInFiler and events

Vladimir Musulainen
> Wouldn't it be easier to just keep it as simple as possible and restore the
> events yourself?
>
> ClassA>>restoreFrom: aStream
>     collectionA := Object binaryReadFrom: aStream. "or whatever"
>     collectionA do: [:eachB |
>         eachB restoreEvents.
>         eachB when: #change send: #changeObjectsB to: self]
>
> ClassB>>restoreEvents
>     collectionB do: [:eachC |
>                 eachC when: #change send: #changeObjectsC to: self]

Am I right understand, that I must save collectionB and CollectionC
to other file(s) (for example).
 
I restore object of class A (entry point to my model) standart
STBOutFiler, after that, I restore myself  objects from collectionB
and collectionC.

It's correct?


Reply | Threaded
Open this post in threaded view
|

Re: STBInFiler and events

Ian Bartholomew-19
Musulainen Vladimir wrote:

> I restore object of class A (entry point to my model) standart
> STBOutFiler, after that, I restore myself  objects from collectionB
> and collectionC.
>
> It's correct?

No.  When you store your class A instance then anything referenced by it's
instance variables (and, recursively, anything referenced by their instance
variables) are also stored in the binary stream.  When you restore the saved
bytes then _all_ the objects are restored.

A demonstration.  Copy the code below into a workspace, select it all and
then "File It In" from the Workspace menu.  You will have 3 new classes in
the image, ClassA, ClassB and ClassC.

Save the image.

Evaluate the following in an workspace.

a := ClassA new.
    10 timesRepeat: [
        b := ClassB new.
        11 timesRepeat: [
            c := ClassC new.
            12 timesRepeat: [
                c add: Time microsecondClockValue -> Time now].
            b add: c].
    a add: b].

fs := FileStream write: 'test.bin' text: false.
[a binaryStoreOn: fs] ensure: [fs close].

That will create a nested collection of instances of the new classes and
save them into a file.

Shut down and restart Dolphin.  The 3 classes added above will still be in
the image so you can open up a new workspace and evaluate.

fs := FileStream read: 'test.bin' text: false.
[a1 := Object binaryReadFrom: fs] ensure: [fs close].
a1 inspect

You should see that the entire structure that you created in the first
workspace has been reconstructed.  Note that although the objects are
recreated their original values are restored - the Times stored in the
ClassC instances are the ones from when the instance was first created.

Note that the classes for the objects stored in the file must be present in
the image.  If you had started again with a clean image in which ClassA,
ClassB and ClassC did not exist, then restoring the file will fail.

=~=~=~=~=~=
Object subclass: #ClassA

instanceVariableNames: 'collectionA'

classVariableNames: ''

poolDictionaries: ''

classInstanceVariableNames: ''!

ClassA guid: (GUID fromString: '{8358D41E-838B-4835-8B57-13338C55DC42}')!

ClassA comment: ''!

!ClassA categoriesForClass!Kernel-Objects! !

!ClassA methodsFor!

add: anObject

collectionA ifNil: [collectionA := OrderedCollection new].

collectionA add: anObject! !

!ClassA categoriesFor: #add:!public! !

Object subclass: #ClassB

instanceVariableNames: 'collectionB'

classVariableNames: ''

poolDictionaries: ''

classInstanceVariableNames: ''!

ClassB guid: (GUID fromString: '{9861C63B-DD02-4870-B94E-D0E5477421E7}')!

ClassB comment: ''!

!ClassB categoriesForClass!Kernel-Objects! !

!ClassB methodsFor!

add: anObject

collectionB ifNil: [collectionB := Set new].

collectionB add: anObject! !

!ClassB categoriesFor: #add:!public! !

Object subclass: #ClassC

instanceVariableNames: 'collectionC'

classVariableNames: ''

poolDictionaries: ''

classInstanceVariableNames: ''!

ClassC guid: (GUID fromString: '{5871B861-2105-4949-A2A6-9A720C8C87ED}')!

ClassC comment: ''!

!ClassC categoriesForClass!Kernel-Objects! !

!ClassC methodsFor!

add: anObject

collectionC ifNil: [collectionC := Bag new].

collectionC add: anObject! !

!ClassC categoriesFor: #add:!public! !

=~=~=~=~=~=

I hope that helps.  If not please ask again.

--
Ian

Use the Reply-To address to contact me.
Mail sent to the From address is ignored.


Reply | Threaded
Open this post in threaded view
|

Re: STBInFiler and events

Chris Uppal-3
In reply to this post by Vladimir Musulainen
Musulainen Vladimir wrote:

> I want save my model to file and later restore it.
> But, if use standart  STBINFiler STBOutFiler, that events for objects
> not save/restore.

The problem is that the events attached to an object are logically part of the
Observer, not of the Observee.  Hence (quite correctly) the default Dolphin STB
mechanism does not save them as part of the object's saved state*.

In fact, by default, the event set *isn't* part of the Observee's state even at
the implementation level.  Some classes (notably Model) that "expect" to make
heavy use of events have an optimisation where the event set is implemented by
keeping it in one the object's instance variables, but in those cases the class
has a special version of #stbSaveOn: that explicitly prevents the event set
being saved with the rest of the object.

But you have a case where the events are part of a (compound) object's internal
state.  So what you have to do is re-establish the connections when the object
is de-STBed.  I use code like

========================
stbFixup: anSTBInFiler at: newObjectIndex
 "overriden to rebuild the internal dependencies"

 self rebuildDependencies.

 ^ super stbFixup: anSTBInFiler at: newObjectIndex.
========================

Where #rebuildDependencies is the method that actually re-establishes the
Observer/Observee relationships (as in Ian's post).

BTW, if your (compound) objects can also be #copy-ed then you probably want to
do something similar in your #postCopy method too.

One warning: the above method won't work for Views -- that's because Views are
saved via an STBViewProxy.  When I needed to do this with a View (only once so
far), I just put the reconnection code into an override of #onCreated:.  There
may be better ways to do it.

    -- chris

[*] Arguably if both the Observer and Observee are part of the same STB file,
then the events linking them should be saved too.  I suspect that would be a
great deal of work to implement, and probably not really worth the effort.