Contains attribute history functionality that keeps history of attribute changes.

Attribute history supposes that every user object (SWRecord) can have several attributes. Attribute is an entity that has a name and a value. We're working with textual attributes, i.e. values are of the String type. It doesn't matter what are the attributes and where they are stored, we consider only their changes here.

Every attrubute change is a part of a user action. User action is described by the {@link com.supportwizard.functionalities.attributehistory.ejb.SWAttributeHistoryLogRecordBean SWAttributeHistoryLogRecord} bean and holds the following data:

Relationship between SWAttributeHistoryLogRecord and SWAttributeChange is showed in the following entity diagram:

This package has 4 main tasks:

  1. Hold attribute changes history
  2. Provide some means to modify it
  3. Automatically remove the history when records, functionality or the entire table is removed
  4. When someone reads table data insert attribute changes descriptions in some virtual column
These tasks are accomplished by the following beans:
{@link com.supportwizard.functionalities.attributehistory.ejb.SWAttributeHistoryLogRecordBean SWAttributeHistoryLogRecord} and {@link com.supportwizard.functionalities.attributehistory.ejb.SWAttributeChangeBean SWAttributeChange} entity beans are holding the attribute history.
{@link com.supportwizard.functionalities.attributehistory.ejb.SWAttributeHistoryWriterBean SWAttributeHistoryWriter} stateless session bean allows to modify it (add new history records).
{@link com.supportwizard.functionalities.attributehistory.SWAttributeHistoryFunctionalityLogic SWAttributeHistoryFunctionalityLogic} and the {@link com.supportwizard.functionalities.attributehistory.ejb.SWAttributeHistoryFunctionalityBean SWAttributeHistoryFunctionality} itself are responsible for removing the history when necessary, and
{@link com.supportwizard.functionalities.attributehistory.SWAttributeHistoryFunctionalityLogic SWAttributeHistoryFunctionalityLogic} inserts textual changes descriptions in the data being read.

Usage

First of all attribute history functionality must be properly created and registered.

SWTable table = ...

SWAttributeHistoryFunctionalityHome attributeHistoryFunctionalityHome;
SWAttributeHistoryFunctionality attributeHistoryFunctionality;

attributeHistoryFunctionalityHome = (SWAttributeHistoryFunctionalityHome) PortableRemoteObject.narrow(
        new InitialContext().lookup("functionalities/attributehistoru/SWAttributeHistoryFunctionality"),
        SWAttributeHistoryFunctionalityHome.class);

attributeHistoryFunctionality = attributeHistoryFunctionalityHome.create(table);
Now attribute history can be added using {@link com.supportwizard.functionalities.attributehistory.ejb.SWAttributeHistoryWriterBean#addHistoryData(com.supportwizard.seance.Seance, com.supportwizard.dml.SWRecordPK, java.lang.Long, java.util.Date, java.util.List, java.util.List, java.util.List) SWAttributeHistoryWriter.addHistoryData} method.

Functionality activities can be temporarily stopped using usual setEnabled(boolean) method:

SWAttributeHistoryFunctionality.setEnabled(false);//suspend roDataReading interception
//do whatever; adding and removing columns to/from table won't break the things down
SWAttributeHistoryFunctionality.setEnabled(true);//resume roDataReading interception

There are two ways to get rid of history data: either drop a target table (via SWDictionaryDDL) or kill the attribute history functionality:

//drop target table
SWDictionaryDDLHome dictionaryDDLHome;
SWDictionaryDDL dictionaryDDL;

dictionaryDDLHome = (SWDictionaryDDLHome) PortableRemoteObject.narrow(
        new InitialContext.lookup("dictionary/SWDictionaryDDL"),
        SWDictionaryDDLHome.class);
dictionaryDDL = dictionaryDDLHome.create();
dictionaryDDL.dropTable (PROJECT_ID,table.getName());
dictionaryDDL.remove();

//or kill history functionality:
SWFunctionalitiesRemoverHome functionalitiesRemoverHome;
SWFunctionalitiesRemover remover;

functionalitiesRemoverHome = (SWFunctionalitiesRemoverHome) PortableRemoteObject.narrow(
        new InitialContext().lookup("functionalities/SWFunctionalitiesRemover"),
        SWFunctionalitiesRemoverHome.class);

remover = functionalitiesRemoverHome.create();
remover.removeFunctionality(attributeHistoryFunctionality);  //don't call attributeHistoryFunctionality.remove() directly!
remover.remove();

Performance considerations

Attribute history functionality runs quite fast. The most time consuming operations are filling the artificial history column and removing all the history. They both execute 1+N+M SQL select commands where N is either number of actions connected with the records being read or the total number of actions. M = M_1+M_2+...+M_N where M_i is number of attribute changes in the i-th action.

Storage space spending

Every action entails creation of 1+M_i entity beans where M_i is number of attribute changes in the action.

Design overview

Here is the UML diagram that shows key elements of the attribute history functionality. {@link com.supportwizard.functionalities.attributehistory.SWAttributeHistoryFunctionalityLogic SWAttributeHistoryFunctionalityLogic} intercepts recordRemoving and roDataReading events. Here are sequence diagrams for Record removing and Data reading events. I think everything is rather simple and self-describing. Please email me if there are some incomprehensibilities, I will immediately update the documentation.

Caveats

Not known.