Abstract Data Sources

Morfik Abstract Data Sources give you absolute freedom to bring information in from any source into your application or website. Abstract Data Sources provide a mechanism through which the developer by writing a couple of event handlers on the server side of the application can make any information stream appear as a table in the application. This allows all the functionality that is available for visually creating rich application interfaces based on the data sources to work with just about any data source.

Defining an Abstract Data Source

The first step in defining an Abstract Data Source is to create a Table of custom type. Standard table objects represent actual database tables in the default database or in an external database. Custom tables on the other hand define the structure of data to be handled by the Morfik Framework as if it where a table in all places where data binding is possible, but which actually relies in user supplied code to obtain and update data, through a pair of event handler procedures.

To create an Abstract Data Source, go to the Power menu and choose the option to create a New Item|New Table. The small dialog box that will be displayed when you select this option will allow you to choose between creating a Standard or a Custom table. You should select the Custom option.

abstract-data-sources-new-table.png
New Table Dialog


Morfik will display a grid where you can enter the names and types of the fields that you will wish your data source to have. It is important to have in mind that this data source will have no data storage of its own.


abstract-data-sources-table-definition.png
Abstract Table Designer

Abstract Data Sources and Data Binding

Once an Abstract Data Source is defined and the supporting code implemented, the Morfik Framework and the Morfik development environment will treat it basically in the same way as a regular data source. This means that you will be able to design your application in the same way you would, if it were accessing data from a table in the built-in database.

Accessing Web Data as a Table

Using Abstract Data Sources you can write server side code that recovers data from any data source and presents it as a regular database table. In order to retrieve information from an external source and make it available as a data source you must implement the OnLoadDataevent on the server side and "insert" the data into a record set which will then be treated as a regular table by the Morfik Framework, on the browser side of your application or website.

In order to demonstrate how this can be done and just how powerful this feature is, a sample that displays pictures from Flickr as if they were on a regular table in the project's default database.


Server Side Events

A couple of events on the server side code are responsible for handling the data input and output of an Abstract Data Source. In this below is included a code snippet with an implementation of the OnLoadData event for an abstract data source. This example retrieves publicly available pictures from Flickr and returns them as if they were stored in a local table.

The OnLoadData Event - This event is called when the RecordSet is opened. The developer can use this event to load the data source with information from a variety of sources such as: Web Service results, File system directory listing, contents of a text or XML file, etc.


Note: This sample makes use of the Ararat Synapse add-on package.


Morfik Pascal code for requesting images from Flickr and returning them as content of a data source

FX Code

Procedure Table1Provider.WebTableLoadData(Recordset: TAnyDBRecordset);
Var
    Sl       : TStrings;
    Title    : String;
    SmallUrl : String;
    LargeUrl : String;
    i        : Integer;
 
    Function ExtractValue(Const S, Subst : String) : String;
    Var
        P : Integer;
    Begin
        P := Pos(Subst + '=', S);
        If P <> 0 Then
        Begin
            Result := Trim(Copy(S, P + Length(Subst) + 1, MaxInt));
            If Result.StartsWith('\"') Then
                Delete(Result, 1, 2);
            P := Pos('\"', Result);
            If P <> 0 Then
                Result := Copy(Result, 1, P - 1);
        End;
    End;
 
    Function ReplaceSuffix(Const S : String) : String;
    Begin
        Result := ChangeFileExt(S, '');
        Result[Length(Result)] := 's';
        Result := Result + ExtractFileExt(s);
    End;
 
    Function RemoveSuffix(Const S : String) : String;
    Begin
        Result := ChangeFileExt(S, '');
        Delete(Result, Length(Result) - 1, 2);
        Result := Result + ExtractFileExt(s);
    End;
 
    Function ExtractPicture(Const S : String; Var Title, SmallUrl, LargeUrl : String) : Boolean;
    Var
        Url : String;
    Begin
        Title := ExtractValue(S, 'title');
        Url := ExtractValue(S, 'img src');
        Result := Url <> '';
        If Result Then
        Begin
            LargeUrl := Url;
            SmallUrl := Url;
            Url := ChangeFileExt(Url, '');
            If Url.EndsWith('_m') Then
            Begin
                SmallUrl := ReplaceSuffix(SmallUrl);
                LargeUrl := RemoveSuffix(LargeUrl);
            End;
        End;
    End;
 
Begin
    Sl := TStringList.Create;
    Try
        If HttpGetText('http://api.flickr.com/services/feeds/photos_public.gne?en-us&format=csv', Sl)
           And (Sl.Count > 0) Then
        Begin
            For i := 0 To Sl.Count - 1 Do
            Begin
                If ExtractPicture(Sl[i], Title, SmallURL, LargeURL) Then
                Begin
                    Recordset.Append;
                    Recordset.FieldByName('Title').AsString := Title;
                    Recordset.FieldByName('ThumbUrl').AsString := SmallUrl;
                    Recordset.FieldByName('PictureUrl').AsString := LargeUrl;
                    Recordset.Post;
                End;
            End;
        End;
    Finally
        Sl.Free;
    End;
End;

Design Time Data Entry

When you have chosen to create a custom table and defined its data structure, the Morfik development environment allows you to directly input data into it. Any data that is manually entered through the data view of the development environment will be stored as a resource of the application and loaded the when the data set is initialized upon a request for data.

This feature allows for immediate testing of application logic that might be dependent on external information from services which are not yet available. For example, if you are building an application that will display some supporting information that will be extracted from a legacy system through a web services interface, but that interface is not yet available, you can enter some test data into the custom data source and your application will present that information as if it had come from the external service. Once the external service is available the developer can implement the OnLoadData event on the server side of the abstract data source and import the external information on demand. To the application in general there will be no difference between the information that was manually entered in the development environment and that which is returned from the external web service.

Related Topics