Hi,
I simply serialize objects to a file. Initially instances of MyClass used Time objects, but now they use DateAndTime objects. How do I do I read files which contain old version of objects? Thank you -- Sergei Gnezdov |
Sergei,
> I simply serialize objects to a file. Initially instances of MyClass > used Time objects, but now they use DateAndTime objects. How do I do > I read files which contain old version of objects? Reading the files shouldn't be a problem, Dolphin will just recreate objects using the information contained in the file. If the file contains an instance of Time then that is what will be recreated. I imagine the problem you are trying to get around is what happens next - your restored class contains an instance of Time but you are now sending it messages appropriate to a DateAndTime object. To get round this you will have to automatically convert the Time object into a DateAndTime.... 1) You can use the STBVersioning mechanism in MyClass. There are plenty of example stbConvertFromVersionX class methods in the image [1], and it has been mentioned in the newsgroups a few times. Basically you can intercept the recreation of the object in the file and tweak it by performing any conversions you need 2) The easy way is just to do a test/conversion when you read the file, although this depends on whether the file load is done by code that you own. Something like.... myClass := Object binaryReadFrom: aFileStream. myClass convertTimeToDateAndTime. .... MyClass>>convertTimeToDateAndTime (time isKindOf: DateAndTime) ifTrue: [^self]. time := DateAndTime fromTime: time Ask again if you are having some other sort of problem with the file in. [1] Although most of them are concerned with changes to the shape (the number of instance variables) in the class. -- Ian Use the Reply-To address to contact me. Mail sent to the From address is ignored. |
In reply to this post by Sergei Gnezdov-2
Sergei Gnezdov wrote:
> > Hi, > > I simply serialize objects to a file. Initially instances of MyClass > used Time objects, but now they use DateAndTime objects. How do I do > I read files which contain old version of objects? > > Thank you > -- > Sergei Gnezdov *before* you make the first change of the kind you mentioned, start including both className and version# as a header for the stored output. From then on, at each release, move the restore method to restoreFromVersionX, where x is the version being replaced, then make the changes, and modify the current save/restore methods. And increment the stored version#, of course. -cstb |
cstb wrote:
> > I simply serialize objects to a file. Initially instances of MyClass > > used Time objects, but now they use DateAndTime objects. How do I do > > I read files which contain old version of objects? [...] > *before* you make the first change of the kind you mentioned, > start including both className and version# as a header for the > stored output. These things are already part of the STB framework. You do have to increment the version number (which defaults to 1, I think) and write your own conversion routines, of course, but STB stores the classname and version for you. -- chris |
In reply to this post by cstb
> *before* you make the first change of the kind you mentioned,
> start including both className and version# as a header for the > stored output. From then on, at each release, move the restore > method to restoreFromVersionX, where x is the version being replaced, > then make the changes, and modify the current save/restore methods. > And increment the stored version#, of course. I have found OA's recommendation of incremental conversions to be very sound, and STB already notes the class and version of each object. Have a good one, Bill -- Wilhelm K. Schwab, Ph.D. [hidden email] |
In reply to this post by Sergei Gnezdov-2
On Wed, 21 Jan 2004 06:11:51 GMT, Sergei Gnezdov <sergei@munged> wrote:
>Hi, > >I simply serialize objects to a file. Initially instances of MyClass >used Time objects, but now they use DateAndTime objects. How do I do >I read files which contain old version of objects? > > Thank you Thanks for the responses. I decided to try STB based solution for a case when a new instance variable is added to a class. I keep getting an exception: "End of stream" and I have no idea what to do next. I tried to use self halt and it does not work in stb methods. Is it an indication that methods don't execute? I followed Education Center "Converting STB data after instance layout changes" chapter. MyClass is a subclass of Model class. I know that Model has its own #stbConvertFrom, but I don't know if it makes any difference. Here is what I've got: MyClass>>stbVersion ^1 "Copied from Education Center example." MyClass>>stbConvertFrom: anSTBClassFormat | selector array newInstance | ^ [:data | array := data. anSTBClassFormat version to: self stbVersion - 1 do: [:version | selector := ('stbConvertFromVersion' , version asString , ':') asSymbol. array := self perform: selector with: array]. newInstance := self basicNew. 1 to: self instSize do: [:i | newInstance instVarAt: i put: (array at: i)]. newInstance] "this method is a complete guess based on the code in the image" stbConvertFromVersion0: array | newSize | newSize := array size + 1. "1 instance variable was added" ^(Array new: newSize) replaceFrom: 1 to: array size with: array startingAt: 1; at: newSize put: 0; yourself |
Sergei,
> I decided to try STB based solution for a case when a new instance > variable is added to a class. I keep getting an exception: "End of > stream" and I have no idea what to do next. I tried to use > self halt > and it does not work in stb methods. Is it an indication that methods > don't execute? Yes. I have often set breakpoints in STB conversion methods, and had no problems. The only other thing I've seen (quite often recently, FWIW) is a debugger that fails to open because of print string problems. Invariably, there is something else wrong that leads to the problem, but the debugger sometimes falls victim to it :( > I followed Education Center "Converting STB data after instance layout > changes" chapter. > > MyClass is a subclass of Model class. I know that Model has its own > #stbConvertFrom, but I don't know if it makes any difference. You must be careful to work with it rather than against it. For that reason, I much prefer to subclass Object (which is not allowed to have instance variables, hence avoiding the problems of what to do when both OA and I want to change them). > Here is what I've got: > > MyClass>>stbVersion > ^1 That makes objects that you save now be at version 1, but so would have been any previously saved objects, thanks to the method on Model. In short, you have not changed the version number, which is a risk any time you subclass base system classes that have instance variables. > "this method is a complete guess based on the code in the image" > stbConvertFromVersion0: array > | newSize | > newSize := array size + 1. "1 instance variable was added" > ^(Array new: newSize) > replaceFrom: 1 > to: array size > with: array > startingAt: 1; > at: newSize put: 0; > yourself I much prefer to use streams, one to read the old format content and one to write the new version array. There are samples in the image. Have a good one, Bill -- Wilhelm K. Schwab, Ph.D. [hidden email] |
In reply to this post by Sergei Gnezdov-2
Sergei,
> MyClass is a subclass of Model class. I know that Model has its own > #stbConvertFrom, but I don't know if it makes any difference. OA added the extra Model instVar some time ago so it's _very_ unlikely you will come across a Model that was saved under stbVersion 0. Taking that into account you can just assume that the underlying Model will use stbVersion 1 and make things a lot easier. NB This does mean that if OA change the shape of the Model class in future then your code will also need changing! Add the following .... MyModel class>>stbVersion ^99 This just ensures that the stbVersion number will not match for your original saved instances. You could just use 2, the next logical version number, but you may cause yourself a bit of confusion if OA update Model to stbVersion 2. MyModel class>>stbConvertFrom: anSTBClassFormat ^[:data | | newInst | newInst := self basicNew. data keysAndValuesDo: [:i :v | newInst instVarAt: i put: v]. newInst updateTimeToDateAndTime. newInst] You will also need to add a MyModel>>updateTimeToDateAndTime method that checks to see if the appropriate instVar contains a Time and, if so, updates it to a DateAndTime. All the above method does is copy across the instVars, the class shape is the same so a direct copy is ok, and then allows the new instance to be updated. NB (again) This will _only_ work if your class and it's superclasses have the save number of instVars as they did when the instance was saved. If not then you will need to get a bit more creative. -- Ian Use the Reply-To address to contact me. Mail sent to the From address is ignored. |
Ian, Sergei,
It would probably be best to override #stbSaveOn: to use a custom STB proxy. The proxy can start out at version one, and increment without fear of conflict with OA's changes. Have a good one, Bill -- Wilhelm K. Schwab, Ph.D. [hidden email] |
In reply to this post by Sergei Gnezdov-2
On Tue, 27 Jan 2004 07:49:45 GMT, Sergei Gnezdov <sergei@munged> wrote:
>On Wed, 21 Jan 2004 06:11:51 GMT, Sergei Gnezdov <sergei@munged> wrote: > >>Hi, >> >>I simply serialize objects to a file. [snip] >> How do I do >>I read files which contain old version of objects? >I decided to try STB based solution for a case when a new instance >variable is added to a class. I keep getting an exception: "End of >stream" and I have no idea what to do next. I tried to use > self halt >and it does not work in stb methods. Thanks. The answers helped as usual :) The stb code is executed when I update version number to be higher then one, so breakpoints work. The following code solves a problem when new instance variable was added to a MyClass. The class itself is a subclass of the Model class. MyClass>>stbVersion "Use version 101, because superclass (Model) uses version 1." ^101 MyClass>>stbConvertFrom: anSTBClassFormat "Convert from earlier binary filed versions." | newInstance array | ^ [:data | array := self stbConvertFromVersion1: data. newInstance := self basicNew. 1 to: self instSize do: [:i | newInstance instVarAt: i put: (array at: i)]. newInstance] MyClass>>stbConvertFromVersion1: array "Private - Perform an STB conversion from a version 1 (comes from Model) to version 101 (comes from MyClass). | newSize | newSize := array size + 1. "1 instance variable was added" ^(Array new: newSize) replaceFrom: 1 to: array size with: array startingAt: 1; at: newSize put: nil; "new var is initialized to nil" yourself |
In reply to this post by Bill Schwab-2
On Tue, 27 Jan 2004 12:50:16 -0500, "Bill Schwab"
<[hidden email]> wrote: >Ian, Sergei, > >It would probably be best to override #stbSaveOn: to use a custom STB proxy. >The proxy can start out at version one, and increment without fear of >conflict with OA's changes. > >Have a good one, > >Bill I am somewhat confused about the following statements (my own creation, oh...): It is recommended to use Model to create user specific Model classes. It is not recommended to use Model if data is serialized, because model classes are not that easy to version. Which class should I base my model on? Should I just use STB proxy next time? |
Free forum by Nabble | Edit this page |