Here is a first shot of the design docs before I post them pubically. I would be grateful of any feedback.

I am still not sure how best to support MockMagmaCollections.Here I suggest that they always be contained in an object. Is there a way of using a genuine MagmaCollection as a Mock, such that readers and so on work even though there is no database behind?

The package will be in MagmaTester, and it requires Seaside28Jetsam as well as Magma.

cheers

Keith

======
Overview

The aim of this version of the Magma-seaside integration framework is to learn some lessons from projects already using Magma in order to satisfy the following goals.

The overriding goal was to make the tutorial very easy, so as to blow away the competition!

1. Simplify Configuration.
2. Enable Magma as a Helper. Ease combining Magma with other seaside technologies, to which end we no longer subclass WASession.
3. Session Management Choice. Provide options such as shared or pooled sessions again orthogonal to the domain, or other settings.
4a. Facilitate Modularization. Provide the framwork to allow a Magma user-accounts module to be deployed as a plug-in package, combinable with other modules, such as a pier module, or a shopping-cart module.
4b. Similarly, Facilitate Project Combination. Projects having separate databases may merge into one, e.g. gjallar & pier.
5. Simplify Use and Initialization. Initialization of models, not just of the root object, but also sub-branches of the database
   which are used by different application-modules or application sub-domains.
6. Server Managed Preferences. Server to client propagation of preferences and data for multi-server operation, and load sharing schemes.
7. Direct Usage Outside of Seaside. Aim to standardize the manner in which services, tests and other procedures access a database which is configured via seaside.


====

1. Simplifying Configuration

The seaside configuration provides a selector for the database helper class which provides session management. You can provide your own scheme by subclassing any of the WAMagma helper classes.

The local database directory, is initially set to 'Automatic' which will save the data in 'magma-todo' directory for the 'todo' entry point. This ensures that by default no configuration is required while at the same time separate applications will not step on each others' databases files.

2. Enable Magma as a Helper

In order for Magma to be used alongside other frameworks which have specialized session classes such as Glorp, the configuration of Magma is now orthogonal to the choice of WASession. You may subclass WASession if you need to, in order to support your application domain, but it is not necessary to do so either to use Magma, or to store session state. Session state can now be stored using the WASession-#properties dictionary.

This is accomplished through the WASessionHelper framework which is part of Seaside28Jetsam. Magma is supported by one such helper and the chosen Magma helper is accessed via WASession-#magma.

Instanciation.

Magma helpers provide session management, options include:
    single    - WAMagma
    shared    - WAMagmaShared
    pooled    - WAMagmaPooled
    mock    - WAMockMagma
   
4. Facilitate Modularization.

Modularization requires the objects in the database to manage their own behaviour.

Rather than fill the database with generic containers such as Dictionaries and MagmaCollections without any specialization, we should recommend subclassing and specializing the typical model container objects. The base classes would be  WADictionaryRoot, Object or MagmaCollection.

However it is as well to point out that subclassing MagmaCollection directly lands us with a significant limitation. It prevents us from easily switching all MagmaCollections for MockMagmaCollections!

To make this switching ability transparent the class WAMagmaCollection is provided as a base class to use for specialization instead. By default it contains a MagmaCollection (or a MockMagmaCollection) and you can also add slots to persist your favorite reader queries defined on initialization. This approach also guarantees that the model has a place to put these query optimizations should you need them.

For example, to define an application specific model "ToDoList" for your database, subclass WADatabaseRoot (which is an IdentityDictionary) and define your custom accessors on that class e.g.

ToDoList-#items
^ self at: #items
ToDoList-#users
^ self at: #users

If #items is a subclass of WAMagmaCollection called TodoListItemsCollection then you can define your custom item based queries on your own subclass of WAMagmaCollection, encouraging typical object-oriented encapsulation.

itemsForUser: name
    self where: [ :each | each usersName equals: name ]

On your domain objects or components, access your database like so:

MyComponent-todoListDatabase
    ^ self session magma rootAs: ToDoList

and...

MyComponent-todoListItems
    ^ self todoListDatabase items
   
However for a sub-domain or module model you can also do.

MyComponent-todoListItems
    ^ self session magma rootAs: TodoListItemsCollection
   
This means that the sub-domain or module models can be referenced by the domain irrespective of their place in the actual database structure, which is defined in your specialized model classes. They know where in the database they are located, and importantly they know how to initialize themselves.

This scheme allows several applications or modules to be layered upon a single database. Each model class can nominate its own personal root object in the main database which is returned via the rootAs: idiom  (see class methods #getVirtualRootIn: #initializeVirtualRootIn: etc)

It also allows the database to be re-organised by changing model classes only. The domains view of the database is decoupled from the modular structure of the database.

5. Simplify Use and Initialization.

Initialization is performed automatically as far as is possible.

When using the standard accessing idiom: 'self session magma rootAs: MyModel'. If this is performed and the database does not exist, or has no root class, then, the root will automatically be initialized according to the #actualRootClass nominated by the model class. This makes databases auto-initializing. If the virtualRoot model object for MyModel itself is not present in the database, then it will also be initialized automatically.

The initialized root or model-objects are configured, and indexes added if needed, in their respective #initialize methods.

If a model is retrieved that is not of the correct class, #rootAs: attempts to mutate the instance into the desired class, thus providing some automatic schema migration at the module level.

6. Server Managed Preferences.

An optional module which allows a seaside-server-magma-client application to pick up settings and preferences from the magma-server. Whenever a new seaside session is started, on the first time only, the root object's #firstRead: method can call 'helper rootAs: WAServerManagedPreferences'.

WAServerManagedPreferences is implemented as a module, being as self contained as possible to demonstrate the principles outlines above. It assumes the root object of the database is a dictionary (if not it will need to be reconfigured appropriately).

This module, when #firstRead:, checks its #expiry time, and if it has expired, it loads the current application's preferences with the values that it contains. The values are each sent #value before being written.

This would allow #location to return a version of MagmaRemoteLocation which when sent #value, evaluates picking a remote server based upon the client's identity. This scheme would enable seaside-server-magma-client to be deployed, the first time anyone accesses the server it would obtain its new settings and potentially redirect to a new server.


7. Direct Usage Outside of Seaside

Standardize the manner in which services, tests and other procedures access a database which is configured via seaside.
WAMagma helper may be used with Seaside, or directly. Configuration is per-seaside application e.g.

(WAMagma forApp: 'todo') location.
(WAMagma forApp: 'todo') readStrategyClass.
(WAMagma forApp: 'todo') areMaterializationNotificationsEnabled.
(WAMagma forApp: 'todo') commit: [] etc.