======================
CPS 3 Document objects
======================

:Revision: $Id: objects.txt 30440 2005-12-08 20:30:40Z dkuhlman $

.. sectnum::    :depth: 4
.. contents::   :depth: 4


**Warning:** This document is not up to date.  Many details are
wrong.

This is an overview of the basic object structure used in
NuxCPS3Document.

This list of classes and groups of classes will start with the
ones that do not rely on other classes, and work itself "upwards".
This is so that you can read this document from the start without
having to jump around in the document. It doesn't work 100%, but
that's the aim. :)


General classes
===============

The OrderedDictionary class is not connected to anything
document-like but is simply an ordered version of
PersistentMapping. If it is ever useful in any other product, we
should probably move it to NuxCPS3 core.

DataStructure is also free of dependencies, and may have other
uses completely independent of CPS and even Zope, but I'll
describe it here anyway as it's an important and non-obvious part
of the happenings.


General to do
=============

- Nothing has any kind of user interface so far. Most objects do
  need that. Either add to them to make them persistent and have a
  UI, or make subclasses with UI's. This would be a pain with
  Fields, and create lots of duplication if each field had it's
  own UI, so for field we need a special UI. One way is to make a
  general UI for the BasicField, and let every single subclass
  just have a definition of fields to decide what should be shown
  in a nice self-referential, bootstrap-yourself-into-existence
  structure. Formulator does this. It requires some heavy
  thinking, but will make it much easier to make new field types.


Renderers
=========

A Renderer is an object that knows how to render a logical design
element, such as a combo-box or a border. There may be several
different Renderers, such as HtmlRender, XmlRenderer and
PdfRenderer. In this first phase only one renderer will be
implemented to render things within CPS pages.


Used by:

- FieldWidgets


Decisions to be taken:

- When implementing each field and implementing the Renderer, we
  need to decide exactly which design elements ti implement. This
  will probably only be possible to decide during the actual
  implementation, and it change in the future if new types of
  renderers are implemented. Once renderers for web, print and
  data exchange has been created we should have something general
  and solid.

- How to knit the rendering into the portal_skins. One possibility
  is to create a MetalRenderer, where you can in the renderer
  define a file with METAL macros that render each element.


Fields
======

There are several types of fields, and more types will be needed,
so they should be easy to add. All fields need to inherit
BasicField. Each Field class needs a corresponding FieldWidget
class.

Used by:

- Adapters (to get field storage ids)
- Schemas (for collection)
- DataModels (for validation)

Related to

- FieldWidgets

Responsibility

- Fields are the smallest part of data validation. It's class will
  determine the type of data contained in the field. It's class
  will also determine which FieldWidget to use.

- Fields carry the information about the physical name used to
  store the data in the storage.

- Keeping default values, and returning these for non-existing
  required fields.

- Each field will validate one piece of content. It will validate
  that:

  - The data entered in forms can be converted into the type of
    object used for the field (such as string into DateTime)

  - Required fields are not None

Decisions to be taken:

- Should fields also carry out other validation, such as max and
  min validation? There are higher-level validations that are
  necessary, such as validating data across several fields. This
  needs to be carried out either in schemas or in templates. It
  may be that even single-field validation should be carried out
  in the same place for simplicity. However, conversion and
  therefore conversion validation, is definitely the
  responsibility of the field objects.

Things to do

- Add support to change the physical field storage id (today it is
  always the same as the field id).

- Add a field type registry. There are Zope support for doing this
  so I guess using the standard Zope class registry would be the
  best way. PluginIndexes use this, as an example of usage. The
  alternative would be to write our own registry, which although
  easy, is probably not necessary.


FieldWidgets
============

Each Field has a corresponding FieldWidget. Each FieldWidget needs
to inherit from the BasicFieldWidget class.

Contained by:

- Layouts (for collection and rendering)

Uses:

- Renderer (for rendering)

Related to:

- Fields

Responsibility:

- The FieldWidget knows what graphical elements a field needs when
  it is rendered. For example, a text field will need a piece of
  text when rendered in view mode, or a text box in edit mode. A
  SelectionField in edit mode may be a list box, or a list of
  checkboxes. The FieldWidget will know which to use, depending on
  settings in the widget, and will call the Renderer to ask the
  renderer to draw this particular graphical element.


StorageAdapters
===============

A StorageAdapter is a transient object that is responsible for
storing and retrieving the data connected to a particular Schema.
All StorageAdapters inherit from BasicStorageAdapter. The only
StorageAdapter to be implemented in the first phase is
AttributeStorageAdapter, that stores data as attributes on the
document.

Uses:

- Fields (to determine field storage Ids)
- To do: Schemas (to determine name space and to list fields)
- Documents (for storage)

Related to

- StorageAdapterFactories

Responsibility:

- Stores and loads data from a storage

- Determines the schema namespace usage for data storing, for
  example, the attribute adapter prefixes it to the attribute id,
  like ``namespace_<fieldid>``. An SqlStorageAdapter might use the
  namespace as a table determiner, or simply not at all.


StorageAdapterFactories
=======================

These are objects that create StorageAdapters. They have settings
for the StorageAdapter behavior. An SqlStorageAdapterFactory
would have a setting for which SqlConnection to use, and maybe
which table to use, and so on.

Used by:

- Schemas (to determine storage type and settings)

Responsibility:

- Determine Storage type and settings

- Create StorageAdapters


Schema
======

Schemas hold a list of fields that make up one part of a documents
data model. There will be schemas local to a particular document
type as well as inherited or global schemas. Each schema has a
namespace.

Contains:

- Fields
- A StorageAdapterFactory

Used by:

- Templates
- DataModels

Responsibilities:

- Keeping track of a bunch of fields

Decisions to be taken:

- Where non-local schemas are to be set and how they are to be
  used.


Layout
======

Layouts are ordered lists of FieldWidgets. These FieldWidgets all
correspond to one field in the schemas available to the document.

Contains:

- FieldWidgets

Uses:

- Schemas (to fetch field data)

Responsibilities:

- The layouts decide which fields to display for a document, and
  also which order these fields are to be displayed, and how the
  fields are to be displayed (editing / viewing / ...)

To be determined:

- Details about how to group fields


Template
========

Templates is the definition of the document type.

Contains:

- Schemas
- Layouts

Responsibilities:

- Define the data model (through schemas) the views (through
  layouts) and other behavior for a document.

- Create the DataModel for a document


DataStructure
=============

This is a container of data in a "displayable" and "inputable"
form. This means text or numbers, as opposed to objects. The
DataStructure is used to display data, and to hold the data
received from form input.

Responsibilities:

- Keeping track of all changes to the data.

- Updating the data from a REQUEST object.


DataModel
=========

The model of the data contained in one document. This is a
transient object created when it needs to be used and then thrown
away.

Contains:

- References to Schemas
- List of all fields
- Copies of the documents data

Uses:

- Schema
- Field
- Adapter
- Document

Responsibilities:

- Acts as a single point for retrieval and updating all the
  documents data, independently of where it is stored.

- Acts as a "data cache". It gets all data from a storage in one
  go, as well as setting all data from one storage in one go,
  thereby making sure that external storages isn't expensively
  called many times. This does mean you need to "commit" the data
  after changing.

- Creating a DataStructure from the data in the data model

- Loading the default field data when created without an
  associated document

- Saving DataStructures, either to the document that is associated
  with the DataModel, or to a new document (also used when
  copying, I guess?)

Things to do:

- Implement laziness of data retrieval, for the benefit of
  external storages.


