Make class PersistKey that is going to be used as a type-save key for mapping different PersistenceOptions. It should have id, value class and default value. All needed keys will be defined in PersistenceUtil. The persistence Mode (save or load) will be kept by the PersistKey<Mode> MODE.
The FileAccess save method should take the PersistenceOptions as argument and if they are null to persist with default PersistenceOptions for save (only the MODE key is set to save). The logic is similar with the previous one. You call the persisters for the current resource revision with an empty storage and then the ZipPackagePersister.
The FileLocator open method should have similar logic just in reverse. First it should call the ZipPackagePersister with an empty storage and then should pass this storage to the revision persister.
The revision persister`s logic should be separate for saving and loading. It should get the value of the PersistenceKey HISTORY_LEN and call the changes persister for the last x changes. It calls the ResourceModelPersister for the initial model. The order of those depends on the Mode.
We will no longer need separate persisters for books, pages, frames, annotation sets, etc. Every Key will have a method persist(). It will be used by the ResourceModelPersister for persistence of the value kept by this key in the model. The method will take arguments:
- the persisted format.
- ValueRef to the persisted value
- Storage where the value should be persisted
- and persistence options.
The default behavior of this method should be to check if it is loading value that was not persisted. In this case it should just set the ref to null. Otherwise should be called the appropriate persister for the child of the given storage with name- the last part of the key`s id. The best way to find the appropriate persistence schema is using a utility method from the PersistenceUtil.
This logic should be provided by the persistR3() method of the DefaultPersistableKey that inherits Key. The Simple and Templated Keys should inherit the DefaultPersistableKey. Some of the concrete keys in the model should override this method.
The RootKey and CompositeKey should inherit the abstract class SubEntriesKey that extends Key<SubEntryNames> and implements the get method as simply calls the getRaw() from the model. Its persistR3 method should never be called and thus should throw an unhandled exception. It should also provide method getSubEntryNames() that takes a class argument and returns the all possible sub-entries of the key. This method will be used by the ResourceModelPersister.
There will be no change in the persistence of the children elements. They are attributes in the same storage as the _resource.xml and the ZipPackagePersister creates directories with the same names.
For backward compatibility the KEY_KIND should implement the persistence logic in more specific way: First it should call the StringPersister for the attribute “kind” of the given storage. If the given options point it is a save mode this is all but if you are loading there should be a check if this is an old resource and its kind is just “frame”. In that case you should get the child “content” of the given storage and get its attribute kind. Then you should compose the string to be set to the value ref by the content type + “-frame”.
There are some other model keys that override the persistR3 method to implement specific logic or for backward compatibility.
Most persisters for immutable will inherit an base abstract class RefToStoragePersister that is constructed from an class and implements the getSchema method using the PersistenceUtil.
There should be abstract class ImmCollectionPersister<E, L> that should provide common logic for persistence of collections. It should have method getElementsType() that returns the class of the objects kept in this collection. This is going to be used to get the appropriate schema for persistence of the kept objects. This class should also have abstract method persistElements, that takes as arguments: the value ref to the collection, the storage, the persistence options and size of the collection. The persist method just gets the size of the collection and calls the persistElements method with the appropriate arguments.
There should be abstract class ImmListPersister<E, L extends ImmList<E>> that provides common logic for persistence of lists. It provides two abstract methods for different list persisters to implement - createEmptyList and addToList. It should give the common implementation of the persistElements method using those methods. Then The NaiveImmListPersister and ImmTreeListPersister would just implement the two methods that create an empty list of the required type and add elements to it.
There will be needed a helper method in the ResourceRefList to persist ref lists is specific tags to be compatible with previously saved books. It will take one extra argument – the tag name for the list elements. Its logic will be similar to the collections persistence.
For Channels common logic will be needed an abstract ChannelPersister. It should provide method for saving all entries in the map of the channel – persistEntries. It should prvide an abstract method getValueClass that gets the class of the timed values (for ActivationChannelPersister this is the TimePos.class and for LocationChannelPersister it is the ImmPoint.class). This method will be used to get appropriate schema for saving the entries by PersistenceUtil method – getImmEntrySchemma.All ChannePersisters should use it in their persist method. To handle the persistence of the different ImmEntry objects should be created an abstract ImmEntryPersister<K, V> that just needs the two methods: getKeyClass() and getValueClass(). It is good to be made TimelineEntryPersister that simply returns TimePos.class for key class. The other method could be implemented directly on the registration the persister object.