Preparing for future versions

 - It would be a good idea to do a "refresh" on at least one diagnostic screen
   on the "Data PlugIns" tab of each DataManager derivative (Rack, Specialist,
   LoginManager, UserSource, etc.) that is in an existing site.
   'DataManager.__setstate__()' automatically upgrades from the old provider
   registries, but we would like to get rid of this code in future releases,
   so please update your objects by either refreshing a diagnostic screen on
   them or by editing them in some way.

 - Please get rid of any references to RackMountable, including ZClasses based
   on it.  RackMountable only exists for backward compatibility - it's going
   to be history in 0.5.0.  Derive from ZPatterns.DataSkins.DataSkin instead.

 - Acquired Attribute Providers and Acquired Sheet Providers are disappearing
   in favor of "Link to parent Data plug-ins", which has the features of both
   and makes parent triggers active as well.  0.4.0 removes the ability to
   create them; please migrate your existing ones, as in 0.5.0 the classes
   will disappear.

New Features in 0.4.0

 - Attributes and Triggers

   - Added the "Generic Trigger" plug-in, which executes a DTML expression
   when selected (Add,Change,Delete) events occur, and can save pre-change
   or pre-delete values of expressions involving the changed/deleted object,
   for use in the executed expression.  It can also be used as an attribute
   set/delete handler.

   - Added the "Generic Attribute Provider", which computes attribute values
   using DTML expressions - and can call SQL or other methods to get groups
   of attributes.

   - Introduced support for "Agents" (triggers and indexes).  Not yet fully
   functional, and can't be properly supported before Zope 2.2 due to
   the way transactions currently work in Zope.

 - Using RackMountables outside Racks

   - Added "DataSkins", which are like the old RackMountable except that they
   can work in regular ZODB folders (so long as their path includes a
   "Folder w/Customization Support" in it).  Note that DataSkins do not support
   cut-and-paste (move) under Zope versions prior to 2.2 due to an issue with
   Moniker binding which is fixed in 2.2.  You can use copy-and-paste, however.

   - Added "Customizer" and "Folder w/Customization Support" products.  Customizer
   plugs into "Folder w/Customization Support" to add attributes, sheets,
   triggers, and/or indexes to DataSkins contained anywhere under the
   "Folder w/Customization Support".

 - Racks

   - Racks now cache retrieved items by key for the duration of a transaction

   - Racks now support two ways to store objects: "real", by storing them in
   the ZODB, and "virtual", by creating an empty object and then trying to
   read a specified attribute.  (If the attribute doesn't exist, the rack
   considers the object not to exist.)  This eliminates the need to create
   subclasses of Rack to support different kinds of non-ZODB storage, since
   any AttributeProvider can now be the primary source of data for an object.

   - Racks offer a "getPersistentItemIDs()" method which returns the ids of
     all items which have data stored persistently in the rack.  (Note that
     not all of these objects may exist if "virtual" storage is in use.

   - Racks now can "pack" and remove unused slots (since slots can be orphaned
     in "virtual" mode if an object is deleted from a foreign database).

 - PlugIns

   - The constructor protocols for PlugIns have been further simplified, to
   the point that plugins whose add forms only ask for id and title can now
   have their constructors generated automatically.  See any of the places
   where PlugIns (other than Racks) are registered for examples.

 - Other

   - There is a new "Transactions" module with handy classes for interacting with
   Zope's transaction system.  Subclassing 'Transactional' lets you receive
   transaction-related events in your object, and the 'TransientMapping' class
   lets you have a dictionary-like object that is automatically cleared after
   every transaction.


API/Structural Changes in 0.4.0

 - We went back to having Rack._RawItem() not being deprecated.  It turned
   out that it was a perfect place to ensure the new structural invariants
   for DataSkins.  Go figure.  :)

 - RackMountables became DataSkins.  Please change your objects/code to get
   rid of references to the RackMountable class, it will go away altogether
   in 0.5.0

 - The namesForRegistration() API has changed to allow Providers/Agents to
   register as providing a variety of things (e.g. attributes and sheets
   from the same provider).

 - Attribute Providers, Sheet Providers, etc. all got merged into one tab,
   "Data plug-ins", to avoid having a bunch more tabs for triggers, indexes,
   etc.


Upgrading from Version 0.2.0

 - ZClasses based on RackMountable and its subclasses (such as LoginUser)
   may need to be recreated to take advantage of dynamic properties and
   propertysheets, and possibly to work at all.  You can use either the
   setBasesHoldOnToYourButts method or the "make a new class and copy
   stuff" method.  RackMountable (or a subclass of RackMountable such as
   LoginUser) **must** be listed first in your base classes to ensure
   proper interaction with the new DynPersist C extension module.


New Features in 0.3.0

 - DynPersist C extension that lets you put __get/set/del_attr__ hooks
   on persistent objects.  Used by RackMountable to support AttributeProviders.

 - The Rack base class is now actually useful in its own right, providing
   a persistent object store, and the ability to add arbitrary propertysheets
   to RackMountables.

 - Racks can now store items which are Python classes (i.e., as well as
   ZClasses) as long as they register as ZClass base classes.


API/Structural Changes in 0.3.0

 - The SheetProvider API has changed quite a bit, mostly because it's been
   fleshed out enough to actually work.  :)

 - The 'PropertySheets()' and 'PropertySheet()' methods on RackMountable are
   now deprecated, because the standard 'propertysheets' attribute now works
   fine, even on ZClasses derived from RackMountable and its successors.

 - Rack._RawItem() is deprecated in favor of Rack._v_itemConstructor() as the
   preferred way of creating an "empty" RackMountable of the Rack's chosen
   class.  (The change is for efficiency of retrieval when using non-ZODB
   data sources, since _v_itemConstructor is the cached, actual constructor
   rather than a method to look up the constructor.)

 - PlugIns and PlugInContainers now have a _setup() hook that gets called by
   manage_afterAdd.  This is intended to allow an opportunity to configure
   default sub-objects such as attribute and sheet providers.  If using the
   _setup() hook, you should make sure it only executes once.  (The Rack
   _setup() method sets a self._initialized flag to keep track.)

 - The PlugIn base class now subclasses SimpleItem.Item, Persistent, and
   Acquisition.Implicit for you.  If you need the old pure mixin class, it's
   now PlugInBase.

 - Many other internal structure changes occurred which we won't document
   because they're things you probably shouldn't have been messing with.  :)
   And if you did know enough to be *able* to mess with them, you probably
   won't have much trouble figuring out what we changed anyway.  :)

