ECO-B-3.2.10

Document Sample
ECO-B-3.2.10 Powered By Docstoc
					The Online-Book for




Borland’s




                         ECO III
Version 3.2.10 – 05/19/2006




Author: Alois Schmid


© Copyright 2005, 2006, DV-Service Schmid
Reproduction only with explicit written approval.


DV-Service Schmid
Föhrenstr. 8
93152 Nittendorf


URL: http://www.dvservice.net
Mail: ecobook@dvservice.net
All texts and images contained in this book were produced with utmost diligence. However,
errors cannot be excluded.
DV-Service Schmid and the author will not have any liability or legal responsibility for any
kind of usage of the information contained in this book, as well as any given incorrect
information and their possible consequences resulting there from.

All company names, product names, trademarks, trade names, etc., contained in this book
are usually protected by their owners.

This book is translated from the German language edition, with the title
’Das Online Buch zu Borland’s ECOIII, Version 3.2.10 – 05/19/2006’.


Translated by

         Bernd Lukasch
         Regina Kober
         Francis Skeete




Page 2
                                                          Table of contents


Preamble .................................................................................................................................. 11
1. ECO-basics .......................................................................................................................... 15
   1.1 The ECO-approach ...................................................................................................... 15
   1.2 ECO – Terms and Connections................................................................................... 17
      1.2.1 ECO´s roots ............................................................................................................. 18
      1.2.2 The structure of an ECO-WinForms-application .................................................... 18
         EcoSpace ...................................................................................................................... 19
         Persistence-Mapper ...................................................................................................... 19
         RootHandle, ExpressionHandle and CurrencyManagerHandle................................... 20
      1.2.3 ECO and the „traditional OOP“ .............................................................................. 20
   1.3 A short UML and OCL overview ............................................................................... 23
      1.3.1 ECO class diagrams ................................................................................................ 24
      1.3.2 State diagrams ......................................................................................................... 25
      1.3.3 OCL......................................................................................................................... 26
      1.3.4 ECO Action Language (EAL)................................................................................. 28
   1.4 ECO, IDE and a first example .................................................................................... 29
     1.4.1 Delphi, Together and ECO...................................................................................... 29
     1.4.2 ECO-projects........................................................................................................... 31
        The creation of an ECO project.................................................................................... 31
        The project management window ................................................................................ 32
        Open project files not shown yet.................................................................................. 33
        Other IDE windows...................................................................................................... 33
        Basic IDE Settings for ECO......................................................................................... 34
     1.4.3 Modeling ................................................................................................................. 36
        The class model – part 1............................................................................................... 36
        The class model – part 2............................................................................................... 38
        The automatically generated Code in the Unit Package_1Unit ................................... 38
     1.4.4 Persistence............................................................................................................... 39
     1.4.5 The Interface ........................................................................................................... 41
     1.4.6 Testing and further development............................................................................. 45
        AutoForm and Drag & Drop ........................................................................................ 45
        The first coding ............................................................................................................ 46
        An Autoincrement attribute for our ID ........................................................................ 48
2. Modeling with ECO............................................................................................................. 49
   2.1 An EcoSpace overview ................................................................................................. 49
   2.2 EcoSpace – Persistence and databases ....................................................................... 51
     2.2.1 Choosing of a PersistenceMapper-component........................................................ 51
     2.2.2 Installing a PersistenceMapper-component ............................................................ 52
     2.2.3 Create and enhance a database schema ................................................................... 53
     2.2.4 Wrap existing database with ECO .......................................................................... 54
     2.2.5 Properties of a PersistenceMapper-component ....................................................... 54
     2.2.6 Mapping of Non-key-Attributes.............................................................................. 56
        An Integer-Mapper....................................................................................................... 58
        A String-Mapper .......................................................................................................... 60
        A Guid (Globally Unique Identifier)-Attribute............................................................ 62




                                                                                                                                   Page:3
                                                      Table of contents


     2.2.7 Primary key and key attributes................................................................................ 63
       A Guid-PrimaryKey instead of the ECO_ID Integer ................................................... 63
       A standard attribute used as a primary key .................................................................. 64
     2.2.8 Using a PersistenceMapper Provider Unit .............................................................. 65
  2.3 EcoSpace – Service overview....................................................................................... 67
  2.4 EcoSpace – the subscription mechanism.................................................................... 68
    2.4.1 The Reevaluate-process........................................................................................... 69
    2.4.2 The Resubscribe-process......................................................................................... 70
    2.4.3 Custom-made Subscriptions.................................................................................... 72
       Implementing a ISubscriber-Interface.......................................................................... 72
       Deriving a custom class from SubscriberAdapterBase ................................................ 75
  2.5 EcoSpace – Versioning................................................................................................. 77
    2.5.1 Requirements........................................................................................................... 77
    2.5.2 Technical realization ............................................................................................... 77
    2.5.3 Creating versioned objects ...................................................................................... 77
    2.5.4 Access to versioned objects..................................................................................... 78
  2.6 Modelling of classes...................................................................................................... 81
     2.6.1 An Attribute-Properties overview ........................................................................... 81
        Attribute get/set-methods and UserCode ..................................................................... 82
     2.6.2 An overview of the class properties ........................................................................ 83
     2.6.3 Meta-Attributes and TaggedValues ........................................................................ 84
        Meta-Attributes ............................................................................................................ 84
        TaggedValues............................................................................................................... 85
     2.6.4 Derived attributes .................................................................................................... 86
         An example of derived attributes with OCL-expression [                                    DerivedAttribute1]...... 86
         An example of derived attributes with function value [                                 DerivedAttribute2] ......... 87
       An example of a reverse derived attribute [                          DerivedAttribute3] ........................... 90
     2.6.5 Constraints............................................................................................................... 93
       Definition ..................................................................................................................... 93
       Access to Constraints-Elements of a class ................................................................... 95
       Evaluating Constraint-expressions............................................................................... 96
       A Constraint example application [             Constraints] ................................................... 98
     2.6.6 Operations and Triggers ........................................................................................ 103
  2.7 Modelling of Associations .......................................................................................... 104
     2.7.1 An Association-Properties overview..................................................................... 105
     2.7.2 Multiplicity............................................................................................................ 106
        1:1 Association........................................................................................................... 106
        1:n Association........................................................................................................... 106
        n:m Association.......................................................................................................... 106
        Strict 1:1 Association ................................................................................................. 107
     2.7.3 Aggregation........................................................................................................... 108
     2.7.4 Cascading deletion ................................................................................................ 109
     2.7.5 Association classes (attributed association) .......................................................... 109
     2.7.6 Derived associations.............................................................................................. 111
     2.7.7 Associations, recursion and generalization ........................................................... 112




Page 4
                                                         Table of contents


   2.8 State diagrams ............................................................................................................ 115
     2.8.1 The structure of a state diagram ............................................................................ 115
     2.8.2 The components of a state diagram....................................................................... 116
        State............................................................................................................................ 116
        Transitions.................................................................................................................. 116
     2.8.3 An example ........................................................................................................... 118
        Class model ................................................................................................................ 118
        State diagram.............................................................................................................. 119
        GUI............................................................................................................................. 121
     2.8.4 Hierarchical state diagrams ................................................................................... 122
        Entering sub diagrams ................................................................................................ 123
        Composite states......................................................................................................... 123
        Transition in a state with sub diagrams...................................................................... 124
        Exit from a state with sub diagrams ........................................................................... 124
     2.8.5 An example with sub diagrams ............................................................................. 125
   2.9 Regions ........................................................................................................................ 127
      2.9.1 Defining a region................................................................................................... 127
      2.9.2 The Region Definition Language.......................................................................... 128
   2.10 Diagrams and UML-Packages ................................................................................ 129
     2.10.1 Secondary class diagrams.................................................................................... 130
     2.10.2 Multiple UML-Packages ..................................................................................... 133
     2.10.3 Outsourcing of UML-Packages into a ECO-Package ......................................... 135
     2.10.4 Referencing UML-Packages in an application.................................................... 136
   2.11 Patterns ..................................................................................................................... 139
      2.11.1 Patterns in Delphi - overview.............................................................................. 139
        Source-Code-Templates ............................................................................................. 141
        Design-pattern ............................................................................................................ 141
        First-Class-Citizen (FCC)-Pattern.............................................................................. 141
        Stub-Implementation-Pattern ..................................................................................... 142
      2.11.2 Pattern management ............................................................................................ 143
      2.11.3 Creating patterns ................................................................................................. 144
      2.11.4 Using patterns...................................................................................................... 145
3. ECO and the OCL ............................................................................................................. 147
   3.1 General information for using OCL......................................................................... 147
     3.1.1 Structure, uses and syntax ..................................................................................... 147
        Uses and context......................................................................................................... 149
        Calling Metadata / Structure data............................................................................... 150
        Comments and special characters in OCL-expressions ............................................. 150
        Iterators in OCL-expressions ..................................................................................... 151
        Regular Expressions................................................................................................... 152
        Escape-Sequences ...................................................................................................... 152
        Collection types.......................................................................................................... 152
     3.1.2 Structure elements ................................................................................................. 153
     3.1.3 Additional Notes ................................................................................................... 154
   3.2 EAL (ECO Action Language) ................................................................................... 155
        Class methods with body............................................................................................ 155
        Button controls with ActionExpression ..................................................................... 156



                                                                                                                                   Page 5
                                                         Table of contents


          Make buttons active and visible ................................................................................. 157
          EAL and state diagrams ............................................................................................. 158
          ActionLanguageService ............................................................................................. 159
   3.3 OCLPsHandle and OCLPsService ........................................................................... 161
        OclPsHandle............................................................................................................... 161
        OCLPsService ............................................................................................................ 163
   3.4 OCL-Variables ........................................................................................................... 165
        Databinding instead of an event method .................................................................... 167
        Dynamic integration of OCL variables ...................................................................... 167
   3.5 User-defined OCL-Operations.................................................................................. 169
        An example ................................................................................................................ 169
        OCLOperation – Programming interface................................................................... 171
   3.6 OCL-expressions: overview....................................................................................... 173
4. ECO at runtime (EcoSpace-Coding) ................................................................................ 181
   4.1 Access levels of EcoSpace .......................................................................................... 181
        ECO-Object................................................................................................................ 182
        IElement ..................................................................................................................... 182
   4.2 The model structure at runtime (UML-RT) ............................................................ 185
      4.2.1 UML- and ECO-Interface ..................................................................................... 185
        IClass / IEcoClass....................................................................................................... 186
        IStateMachine / IEcoStateMachine............................................................................ 187
        IMethod / IEcoMethod ............................................................................................... 188
      4.2.2 Basic components.................................................................................................. 189
        TaggedValues............................................................................................................. 189
        Constraints.................................................................................................................. 190
        Packages ..................................................................................................................... 190
      4.2.3 Access to a model element .................................................................................... 191
        Classifier..................................................................................................................... 191
        Features ...................................................................................................................... 193
        Structure information on the IElement-level.............................................................. 194
        Method analysis with Reflection................................................................................ 195
   4.3 Object-Identification in EcoSpace ............................................................................ 197
        ObjectID ..................................................................................................................... 197
        Locator ....................................................................................................................... 197
   4.4 Eco-Cache ................................................................................................................... 198
      4.4.1 FrontSidePolicy-component.................................................................................. 198
      4.4.2 ICache interface..................................................................................................... 199
         Basics ......................................................................................................................... 199
         Attributes and association ends .................................................................................. 200
         ExistenceState and PersistenceState........................................................................... 204
         Timestamp.................................................................................................................. 205
         Events ......................................................................................................................... 205
   4.5 Object-Handling ......................................................................................................... 207
     4.5.1 Creating and deleting objects ................................................................................ 207
     4.5.2 Basic load strategy ................................................................................................ 208



Page 6
                                                         Table of contents


         Explicit Prefetching.................................................................................................... 209
       4.5.3 Administrating and saving object changes............................................................ 209
         DirtyObjectList........................................................................................................... 209
         Collective saving ........................................................................................................ 211
         Selective saving.......................................................................................................... 211
   4.6 Uses for EcoSpace-Coding......................................................................................... 213
        xxxEcoSpace-Unit...................................................................................................... 213
        Package_xUnit ........................................................................................................... 215
        WinForm-Unit............................................................................................................ 216
        Additional Units ......................................................................................................... 218
   4.7 Securing data integrity............................................................................................... 219
     4.7.1 Overview ............................................................................................................... 219
     4.7.2 EcoSpace-Syncronising......................................................................................... 219
          Example application SyncServer/SynClient [                             SyncModelPackage, SyncClient,
          SyncServer] ................................................................................................................ 219
          SyncServer [    SyncServer] .................................................................................... 220
          SyncServer: Server-Part ............................................................................................. 220
          SyncServer: Client-Part.............................................................................................. 223
         SyncClient [      SyncClient]...................................................................................... 225
         Synchronization and conflict management ................................................................ 225
         Remoting-Parameter................................................................................................... 229
       4.7.3 Optimistic Locking................................................................................................ 229
       4.7.4 Transactions .......................................................................................................... 232
   4.8 Undo- and Redo-Operations ..................................................................................... 235
5. ECO and the GUI .............................................................................................................. 239
   5.1 Basics ........................................................................................................................... 239
     5.1.1 EcoSpace, WinForm and ECO Handles................................................................ 239
     5.1.2 ECO Handle Properties ......................................................................................... 241
        ECO Handle and IElement......................................................................................... 241
        Property-overview...................................................................................................... 242
        IBindingList, IList, ITypedList .................................................................................. 243
     5.1.3 Databinding ........................................................................................................... 243
        .NET Data-binding and ECO ..................................................................................... 243
        Complex databinding with a DataSource-Property.................................................... 244
        Simple Data-binding with the Property DataBindings............................................... 245
     5.1.4 ECO-WinForms .................................................................................................... 246
        WinForm vs. ECO-WinForm..................................................................................... 247
        The 5 Standard-ECO-components ............................................................................. 247
        Unit-spanning referencing of ECO Handles ............................................................. 248
        Force or prevent a GUI-Update.................................................................................. 249
   5.2 Columns and Nestings................................................................................................ 251
      5.2.1 Columns ................................................................................................................ 251
         Hierarchic Columns.................................................................................................... 252
      5.2.2 Nestings................................................................................................................. 254
      5.2.3 Code Derived Columns ......................................................................................... 256




                                                                                                                                   Page 7
                                                         Table of contents


   5.3 Datagrid, Listbox and Combobox............................................................................. 259
      5.3.1 Datagrid - Sorting.................................................................................................. 259
        Sorting with OCL-Expression of the ECO Handle .................................................... 259
        Editing and positioning .............................................................................................. 260
      5.3.2 Data input Listbox/Combobox .............................................................................. 263
      5.3.3 Datagrid - TableStyles........................................................................................... 266
   5.4 Autoforms ................................................................................................................... 269
     5.4.1 Using the IAutoContainer-Interface...................................................................... 269
     5.4.2 AutoForm Factories............................................................................................... 270
6. ECO, ASP.NET and WebService...................................................................................... 275
   6.1 First step...................................................................................................................... 275
      6.1.1 ASP.NET components .......................................................................................... 275
      6.1.2 ASP.NET process control ..................................................................................... 276
      6.1.3 Sessions ................................................................................................................. 277
      6.1.4 A first ECO ASP.NET Web-application............................................................... 278
         Modeling .................................................................................................................... 278
         Persistence.................................................................................................................. 279
         EcoSpace .................................................................................................................... 279
         GUI............................................................................................................................. 279
         WebForm.................................................................................................................... 280
   6.2 Basics ........................................................................................................................... 285
     6.2.1 Controls ................................................................................................................. 285
        HTML elements ......................................................................................................... 285
        Server controls............................................................................................................ 286
        Web controls .............................................................................................................. 287
        DBWeb controls......................................................................................................... 288
        Properties and formatting ........................................................................................... 289
        Creating controls dynamically ................................................................................... 290
        Placeholders for controls............................................................................................ 292
     6.2.2 Postback and Roundtrip ........................................................................................ 292
     6.2.3 Session strategies................................................................................................... 294
        Viewstate.................................................................................................................... 294
        Session-State .............................................................................................................. 296
        Application-State........................................................................................................ 298
        EcoSpace strategies .................................................................................................... 299
        EcoSpace pooling....................................................................................................... 299
   6.3 Databinding................................................................................................................. 301
      6.3.1 Introduction ........................................................................................................... 301
        CursorHandle vs. CurrencyManagerHandle .............................................................. 301
        Binding expressions ................................................................................................... 302
      6.3.2 Simple and complex databinding .......................................................................... 302
      6.3.3 Databinding expressions and Databinder.Eval...................................................... 303
        Binding to control properties...................................................................................... 303
        Binding to ECO Handle attributes ............................................................................. 304
        Binding to methods .................................................................................................... 305
      6.3.4 The [    ASP4] example ...................................................................................... 306
        Binding to a CursorHandle......................................................................................... 306



Page 8
                                                         Table of contents


           Binding to a datagrid cell ........................................................................................... 309
           Binding with a CodeBehind-Method ......................................................................... 309
   6.4 WebForm and Web controls ..................................................................................... 311
     6.4.1 Datagrid................................................................................................................. 311
       Property generator – general ...................................................................................... 311
       Property generator – columns .................................................................................... 312
       Property generator - paging........................................................................................ 314
       Property generator – format and frame ...................................................................... 316
     6.4.2 List controls........................................................................................................... 317
     6.4.3 Repeater and DataList control............................................................................... 321
     6.4.4 Validators .............................................................................................................. 324
       Overview .................................................................................................................... 324
       Connection to an input field ....................................................................................... 325
       Sever side and client side check................................................................................. 325
       Displaying error messages ......................................................................................... 325
       Example [ASP7]......................................................................................................... 326
     6.4.5 AutoForm .............................................................................................................. 327
     6.4.6 Navigation and data input between WebForms .................................................... 328
   6.5 WebServices................................................................................................................ 331
     6.5.1 Basics .................................................................................................................... 331
     6.5.2 Creating an ECO-Webservice ............................................................................... 332
        Project files of a WebService-application.................................................................. 332
        Example [WebService1] ............................................................................................ 332
        Data export ................................................................................................................. 334
     6.5.3 Using a webservice................................................................................................ 335
        Integrated testing mode .............................................................................................. 335
        Requirements and process of a webservice query...................................................... 336
        Example [WSClient] .................................................................................................. 337
Appendix ................................................................................................................................ 341
   ECO-Newsgroups and -Forums...................................................................................... 341
      Borland ECO Newsgroup........................................................................................... 341
      ECO-Wiki................................................................................................................... 341
      German ECO-Forum .................................................................................................. 341
   ECO-Blogs......................................................................................................................... 342
      Borland ....................................................................................................................... 342
      Others ......................................................................................................................... 342
   ECO-Articles..................................................................................................................... 342
      Borland ....................................................................................................................... 342
      Others ......................................................................................................................... 342
   Recommended books........................................................................................................ 343




                                                                                                                                   Page 9
Preamble
Microsoft’s introduction of the .NET-technology spawned a new generation of software
development systems.
Regarding Borland’s Delphi development system, this lead to a first .NET version in the
beginning of 2004, called Delphi.Net or Delphi 8, followed only one year later by Delphi 2005,
and in the final months of 2005 the next Delphi version 2006 (codename Dexter) was
released.
In these new versions Borland added the ECO (enterprise core objects) module to Delphi,
whose predecessor was already available for Delphi 7 and win32 development under the
name of Bold for Delphi.
The architect version of Delphi 8 featured the ECO-I module, Delphi 2005 Architect the ECO-
II module.
ECO-III is delivered with the current version of Delphi 2006. Also ECO-III isn’t only available
with the architect version but now also with other Delphi models, only as a basic version with
fewer functions.
This book primarily deals with the ECO-III conception of Delphi 2006
This book exclusively deals with the implementation of the so-called Model Driven
Architecture (MDA) of Delphi 8 / 2005 / 2006, called Enterprise Core Objects (ECO) by
Borland.
We will only scratch the surface of the topics Delphi IDE and .NET technology.


Notes for reading this book
To be able to handle ECO-III, it’s definitely necessary to know and use Delphi 2006 or if
needed 2005 Architect. You also should be familiar with Object oriented programming (oop),
the basic concepts of Unified Modelling Language (UML) and Object Constraint Language
(OCL). If you don’t have a working knowledge of UML and OCL, the short introduction in
chapter 1.3 and the more detailed OCL chapter 3 can provide you with the basic knowledge
needed to understand this book.
Concerning ECO itself, all you need to know is that Eco is a kind of an extension for Delphi
and that it is contained in Delphi 2006 or the architect version of Delphi 2005 (Delphi 8).

For ECO-rookies it is recommended to work through the book from beginning to end. Some
examples in the chapters are based on the ones from preceding chapters, getting more and
more complex chapter by chapter.

Eco insiders on the other hand may want to deal with selected topics, which will be possible
without any difficulties. If a chapter refers to Eco-topics in other chapters, there usually is a
connecting link.

With this current version 3.2.10 – 5/19/2006 the book has reached its planned range
regarding contents (versionnumber 3.2 means ECO-III, Update2; 10 means first review).
Being an online book it sure has the advantage that it can easily be adapted to further ECO
developments (e.g. ECO-III -> ECO-IV).


Notes for the example applications
All the example applications in this book are coded in Delphi-Pascal. The applications in this
book are marked with a [      xxx] symbol. The complete source code of the particular
applications can be downloaded at http://www.ecospace.de/ecobook.html , where you can
also find a Readme.PDF containing further information on the example applications.



                                                                                        Page:11
                                           Preamble



With the update from ECO-II to ECO-III, changes in the automatic code generation took
place. For example the default name of the class source code unit was changed. How these
changes affect e.g. the porting in our example applications will be explained in chapter 1.4.1.

To install, compile and test the example you need Delphi 2006, update 2. Some of the
example applications need Microsoft SQL-Server. The downloadable Readme.PDF also
contains the database default settings for each example application.
Usually you can change the database default settings at any time in the programs and you
can configure a data storage in an xml-file for the example applications. You can find further
information on database/xml integration in the introductory example, paragraph Persistence
and in chapter 2.2 Persistence und Databases.

In the book’s appendix you can find links to additional information on ECO, as well as some
reading suggestions. Furthermore at http://www.ecospace.de/ecoforum.html you can find the
new German ECO-forum, that’ll deal with all questions about ECO-programming. It also
contains a section that especially deals with the example applications of this book.
If you have any questions, criticism or suggestions concerning this book, please use the
forum or send me a mail.

To avoid any confusion of tongues I tried to use the common terms of OOP as shown below.

 Identifier                  Explanation
 class                       a Delphi-class
 attribute                   an element of a class
 method                      an operation of a class
 function                    a method with return value

 instance or                 an example of a class (on purpose not named an object)
 class-instance
 property                    general attribute value, set for example by an object inspector
 object                      anything else that can be called an object

In the source code of our examples you usually find certain prefixes in front of the identifiers,
so the type of the identifier is already shown in the name.

 prefix                      explanation
 C                           constant: e.g. CMaxEntries
 T                           type: e.g. TNewsString
 CL_                         class: e.g. CL_Person
 o                           instance of a class. e.g. oPerson
 i                           integer variable: e.g. iCount
 s                           string variable: e.g. sNews
 e                           list type: e.g. eCompanyType
 r                           record variable: e.g. rAdresse

In some of the source codes printed in this book additional line breaks were inserted to
conserve space or keep the format. Also some parts of the code were replaced by “...“.
Because of that the printed source code is “syntactically incorrect”, but more readable, which
is more important here.




Page 12
                                           Preamble



Technical Review
I am very happy that the ECO R&D team offered me a review on the text. In May I received a
lot of very important review hints, comments and additional informations that covers about 80
percent of the book. Most of it has been integrated into the current release. Some
recommendations will lead to more structural changes within the text and will therefore be
considered in a later book release.
With the help of Jan Norden, Jonas Hogstrom and Jesper Hogstrom the contents has been
widely improved, for which I am very grateful.



Regards
To conclude this preamble I’d also like to thank the numerous „ECO-Warriors“, who helped
reducing the lack of ECO-documentations by releasing tutorials and participating in the
discussions in the Borland Eco Newsgroup.

A special thanks goes out to the Borland employees

•   Jan Nordén
•   Jesper Hogstrom
•   Jonas Hogstrom
•   Anders Ivner
•   Henrik Jondell
•   Malcom Grooves

and most of all to

•   Peter Morris from Droppy Eyes Software


Finally, a very very big “thank you” goes to Bernd Lukasch, Regina Kober and Francis
Skeete for their great translation work.



Enjoy reading and all the best with eco!

Alois Schmid




                                                                                     Page 13
1. ECO-basics
1.1 The ECO-approach
A possible way to explain the goals and significance of Borland’s Enterprise Core Objects
(ECO) in Delphi 2006 is to look at the ECO concept in relation to object oriented software
development.

The image below shows a simplified diagram of an ECO-WinForms-application, consisting of
4 components: UML-EcoPackage, database (DB), user interface (ECO-Winform) and the
central EcoSpace.




In this diagram the following ECO components can be identified and assigned:

     •    The so-called UML-ECOPackage, where the whole class model originates in
          UML-notation (in development time) and that serve as base for EcoSpace.
     •    The so-called EcoSpace, that dynamically loads all required objects into memory
          and enables their editing.
     •    The ECO-Persistence-Mapper that provides EcoSpace with the objects it gets
          from the database using object relational mapping and that sends back the
          changed objects to the database via OR-mapping.
     •    The so-called ECO-activated WinForm that provides the user interface and is –
          thanks to ECO-Connection – able to visualize and edit the objects existing in
          EcoSpace via the usual .NET-interface controls.



                                                                                  Page 15
                                   1.1 The ECO-approach


To make the first steps easier, this image shows a simplified model of an object oriented
application. The possible fields of application of ECO in multi-user environments, as an
ASP.NET-application or as a web service will be dealt with in detail later in the book.

Watching this diagram one can already anticipate where the advantages of the ECO-
approach are:

      •    The graphically produced class model and from that the automatically generated
           source code form together the base of the application. Class diagram and code
           are synchronized permanently.
      •    A Persistence-Mapping system automatically maps the class model on a
           (relational) database thus taking care of the fully automatic creation and updating
           of the database schema.
      •    At runtime the Persistence-Mapping system takes care of the transformation of
           relational data to class model objects in EcoSpace and back into the database
           tables.
      •    EcoSpace is in charge of the complete runtime management for objects, for
           example Caching, Pooling, Synchronization, Transactions, and OCL-Evaluation
           etc.
      •    GUI-controls based on .NET or ASP.NET can easily be attached to objects in
           EcoSpace using the automatic „ECO-activation“.
      •    At runtime objects are bound to certain controls, thus enabling automatic data
           transfer between EcoSpace objects and control.

A first result:
   Thanks to its graphical model design and automatic code generation the Eco concept
   compensates a lot of manual coding.
   This saves a lot of time during development, updating and especially debugging and
   testing. The ECO-concept harmonizes modelling.
   The central business class model of an application finds its one-to-one representation with
   the database as well as with the GUI, without any help of additional or external
   components or libraries. Thus model inconsistencies can be avoided widely.




Page 16
                                        1. ECO-basics



1.2 ECO – Terms and Connections
ECO is part of the so-called Model Driven Architecture (MDA) tools.
The MDA-concept, specified and standardized by the Object Management Group (OMG),
pursues the goal of making the business- and application logic of an application platform
independent.
Unified Modelling Language (UML), also specified by OMG 1997, is again a central part of
the MDA concept. UML defines the syntactic and semantic elements of an object oriented
(business) model. So UML turned out as the standard „language“ for the common MDA-
tools, also for ECO.

Concentrating on ECO this means that an ECO-generated UML class model can be used for
Winforms- as well as for ASP.NET- or webservice-applications.
Generally this same model can be used on every other UML-compatible development
system with any given OS platform (usage of the XML model data interface).

Since UML in general is platform independent (PIM=Platform Independent Model), but ECO
represents a precise transformation of UML to the .NET framework using Delphi
(PSM=Platform Specific Model), an ECO class has compared to an UML class additional
attributes and functions making it .NET and Delphi compatible.

At this point it definitely has to be stated that Eco only realizes a small part of UML, the UML
class diagrams and UML state diagrams. All other UML Diagrams, like application-, activity-,
or sequence diagrams can be created with the Together-module which is integrated in Delphi
2006 (design projects), but are not realized in ECO itself.

In 1999 OMG added the so-called Object Constraint Language (OCL) to UML. OCL is used
to realize certain parts of object oriented modelling that can’t be realized with UML only, for
example constraints that specify class attributes.
For example if you want to display persons who drive cars in a class CL_Driver, it definitely
makes sense to define the constraint age >= 18 within this class. This kind of constraint
usually is done with an OCL-Statement.

OCL is used intensively in ECO, both at development time and runtime.
You can find a short overview for UML and OCL in Chapter 1.3. Possible uses for OCL in
ECO applications are explained in detail in Chapter 3.

In general you can say that MDA development systems and tools emphasize the business
model of a software system. All other system sectors are derived from this business model.

Because of this Eco is also called a development tool for domain object systems.

Generally objects can be separated into two categories:

First there are domain objects that form the components of the model that is to be displayed.
In a business model, domain objects usually are persons, customers, orders, products, etc.
At runtime the Eco application mainly uses instances of those model components, that
means with specific person- , product-, or order objects that are administrated in EcoSpace.

The objects of the second category are called implementation objects. Those objects are not
model specific, but generic. Examples are container objects, interface controls like datagrids,
list boxes, etc.



                                                                                       Page 17
                            1.2 ECO – Terms and Connections


In a nutshell ECO can be described as a package of software components that is used to
model object oriented software projects at development time in an ECO framework and to
activate them at runtime.


1.2.1 ECO´s roots
The predecessor of ECO was Bold for Delphi that was originally created by the Swedish
company BoldSoft AB. The first version of Bold for Delphi was released in 1997 for Delphi 2.
Meanwhile Borland released an extensive MDA/UML tool called Together. Together which
came to Borland through the acquisition of TogetherSoft, is used as an add-on for various
development systems (Delphi 2006, Visual Studio, Eclipse etc.).

When .NET was introduced ECO-I emerged from Bold, as part of Delphi 8 architect Version
and later on its successor ECO-II as part of Delphi 2005 Architect Version. All ECO-Versions
have an integrated Together-module. Delphi 2006 contains almost the complete Together
functionality.
Eco makes integration of the Borland-MDA approach into the Delphi IDE possible. But it can
only be used for .NET development.

Note:
  This book deals with ECO-III exclusively. In the following the term ECO always means
  ECO-III, as well as Borland Delphi always means Delphi 2006 Architect.


1.2.2 The structure of an ECO-WinForms-application
Based on a simple ECO-WinForms-application for .NET, such an application usually consists
of:
     •   a project file
     •   an EcoSpace file
     •   a class model in form of one or more UML-EcoPackages
     •   the GUI in form of (usually multiple) ECO-activated WinForms.




Page 18
                                       1. ECO-basics

The following diagram shows the general structure of an Eco application.




EcoSpace
EcoSpace is the central ECO component at runtime. Picture it as a kind of intelligent cache or
object manager in the central memory. At runtime this object manager loads class instances
from the database, administrates access to these objects and their durability and releases
these objects again. ECO always reloads objects automatically, which for example are
needed for display in a datagrid.
Additionally to the automated administration a lot of functions are used in EcoSpace with
explicit coding by using various EcoSpace services. Among others these are methods of
transaction-, redo-, and undo-handling, OCL queries, synchronization, etc.
In an ECO-project EcoSpace is represented by xxxEcoSpaceUnit.PAS and
xxxEcoSpace.Design Files at development time, with xxx being the project name.
In this process EcoSpace is always automatically connected to the class model in the UML
EcoPackage (Package 1Unit PAS).



Persistence-Mapper
A Persistence Mapper is an ECO-component that is placed on a xxxEcoSpace.Design-File
and is assigned to EcoSpace. The Persistence Mapper administrates transformation from
object to data that is saved in a database and transformation from data back into objects.
Because of this the Persistence Mapper is usually connected to a Db component and can
use mapping information from the UML-EcoPackage.




                                                                                      Page 19
                              1.2 ECO – Terms and Connections


RootHandle, ExpressionHandle and CurrencyManagerHandle
Eco knows two kinds of Handle, the so-called Root Handle and the Rooted Handle. A
RootHandle is an ECO-component that lies on an Eco-activated WinForm. A RootHandle
establishes the general connection between EcoSpace and WinForm, the GUI.

An ExpressionHandle is a Rooted Handle. It is also placed on an Eco-activated WinForm.
Like all Rooted Handles this ExpressionHandle is connected to a Root Handle or another
Rooted Handle e.g. another ExpressionHandle, thus having access to EcoSpace and the
class model at runtime. Usually the ExpressionHandle is used to access a certain kind of
class objects, for example all customers or all items of a certain customer at runtime. A
Datagrid, used to display and edit data, generally uses an ExpressionHandle as data source.
Which objects the ExpressionHandle refers to is determined by its Property Expression.
Usually an OCL term is behind this Property, for example CL_Person.allInstances.

A CurrencyManagerHandle is also a Rooted Handle, which as well is placed on an ECO-
activated WinForm. Generally the CurrencyManagerHandle is connected to an
ExpressionHandle and is used to reference the current object in the list of all objects covered
by the expression handle. So the CurrencyManagerHandle is a kind of a dataset indicator.


1.2.3 ECO and the „traditional OOP“
As generally known, in a „traditional“ object oriented Win32/.NET application without Eco
support we come across classes, attributes, objects, methods and events, the Gui of the
application and of course saving data for example in a relational DB.

Using Eco, this basic concept in general remains, but is realized in a very different way.

In development stage the class model, more precisely the domain model is no longer created
mainly by coding but is created graphically with use of the integrated Together-Editors based
on the UML-Notation (Package_1-Diagram). Each class is represented by a rectangle
symbol, to each class symbol attributes and methods can be added using the context menu.
The inheritance hierarchy is displayed by generalization arrows between the classes, but
please consider that Eco doesn’t support multiple inheritance.
It’s up to you if you want to develop the domain model with text or graphically, the integrated
Together-Editor with its Live-source function takes care that diagram and source code are
synchronized permanently.

For realizing persistence using a relational database each class gets assigned its own table
in the database. Each class object automatically receives a PrimaryKey, the so-called
ECO_ID, that can neither be seen in the diagram nor in the source code, but it is a primary
key field in the table and of course is used internally in EcoSpace.

Eco also enables – UML-Compliant- modelling of associations as a link between instances of
different classes. This resembles the design of relational connections in databases.
Associations are also created graphically in form of a line between two classes and are
configured by the object inspector.
An association between two classes is defined in particular through its multiplicity. By that the
1:n, n:m - Relations known from relational databases are displayed. Therefore ECO creates
automatically the matching foreign key entries for each association in the affected tables;
respectively it creates appropriate key-pair tables in the database for n:m relations.




Page 20
                                         1. ECO-basics

Each table automatically receives a primary index for the primary key, and if the table
contains primaryKeys of associated tables, indices for those are automatically created as
well.

This way ECO almost fully takes over the task of database design based on the class model.

At runtime the ECO´s PersistenceMapper-component´s O/R-Mapping provides fully
automatic transformation of db data to EcoSpace instances and back.

If necessary EcoSpace itself requests all instances from the database, which are needed to
process methods or for visualization.

The GUI-controls of the Eco-activated WinForm are on the other hand connected to the
corresponding objects in EcoSpace via Eco-Handles. An explicitly “Reforming” of data
between EcoSpace objects and controls display fields is not necessary.

With ECO III an additional UML diagram type is supported, the state diagram.
The attribute values of a class instance define the status of this instance at a certain point of
time. One or more state diagrams can be assigned to each class, where the possible status
of the instances of this class and transitions, caused by so-called triggers, are defined and
administered. State diagrams are suitable for example for the display of object life cycles and
for modelling dialog processes.

Of course the ECO-concept saves a lot of coding thus reducing the testing efforts
dramatically, compared to applications with „traditional“ oop-coding.




                                                                                        Page 21
                                       1. ECO-basics


1.3 A short UML and OCL overview
Class modelling in ECO is based on the UML-Standard Version 1.5., for state diagrams
version 2.0 is used. In this chapter we want to provide beginners with a short overview about
Unified Modelling Language and Object Constraint Language.

UML defines a notation, which means a huge amount of characters and symbols as well as
their semantics, meaning their relevance for the specification, development and
documentation of models. UML is used especially for modelling object oriented software
systems.
UML doesn’t provide a method how to implement a software system, only a sort of a
language to describe models, which by now became a standard for object oriented software
development.

For the display of a real system with a model, UML offers the following kinds of diagrams:

     •    Structure diagrams
          class diagrams
          object diagrams
          component diagrams
          composite structure diagrams
          package diagrams
          deployment diagrams

     •    Behaviour diagrams
          activity diagrams
          use case diagrams
          state machine diagrams

     •    Interaction diagrams
           sequence diagrams
           communication diagrams
           timing diagrams
           interaction overview diagrams


The Together-module integrated in Delphi 2006 supports nine different types of diagrams.
But only class diagrams and state diagrams are implemented in ECO. All other diagram
types can “only” be used as so-called design projects. This book will deal with class and
state diagrams only.

Hint:
  ECO implements its own versions of the class and state diagrams. While they are similar
  to the Together diagrams they have a totally different meaning, since the regular diagrams
  show the actual Delphi or C# code, while the ECO diagrams define the domain objects in
  a more abstract way (see chapter 1.4.1).




                                                                                      Page 23
                            1.3 A short UML and OCL overview


1.3.1 ECO class diagrams
Elements of class diagrams are
     •   Classes with their attributes and operations
     •   The Generalization for the display of inheritance relations and
     •   Associations for the display of relations between instances and classes

In general this matches the perception of object oriented language elements in Delphi. The
following table provides you with a comparison of the identifiers.

UML-Elements              Delphi- language elements             Elements in a relational
                                                                DB
class                     Class                                 TableDef
Object                    Object, Instance                      Row
attribute                 Property                              Column
value                     Variable                              Field
Operation                 Method                                -
visibility:public...      Visibility:public...                  -
Generalization            Inheritance                           -
Interface                 Interface
Association               -                                     Relation
Link                      -                                     Relation-Tupel

In UML – and in the ECO Together-model-designer – classes are symbolized with a
rectangle, which is split into the segments class name, attribute and operations.
Generalization are displayed as arrows and association are displayed as lines.

Here is a small example of a class diagram




After placing the UML elements in the diagram, the configuration of classes, attributes,
operations and associations follows, which is usually done with the object inspector, which
has, depending on the element type, various property settings, some of which are part of
UML, others originate from the ECO-specific realization.




Page 24
                                       1. ECO-basics

Element type               genuine UML properties                 additional ECO- specific
                                                                  parameters
class                      abstract                               table name
                           Name, Stereotype…                      Optimistic Locking…
attribute                  Name, visibility                       DefaultDBValue
                           Stereotype…                            PMapper…
operations                 Name, visibility                       Abstract
                           Stereotype…                            Virtual…
association                Name, visibility                       column name (ass. end)
                           Multiplicity…                          delete action…

Important: Eco doesn’t display all UML properties for class diagrams. For example the
attribute constraints is supported by Eco only within a class, not at attribute level.

Since model elements of UML class diagrams are quite similar to elements of object oriented
languages, an automatic source code generation based on a class diagram is possible and is
performed by ECO.
The ECO code generation permanently takes care of synchronizing the UML class diagram
and the code representation in your project.


1.3.2 State diagrams
Whereas class diagrams display the structure of a class, state diagrams display a sequence
of states und the state changes of a class. So a state diagram never stands alone, it is
always bound to a class.

With a state diagram, processes that refer to the life cycle of a class instance, can be
displayed, for example the states of an instance of the class order can be displayed, from the
creation of the instance to the book entry “done”. The state diagram is a good means of
modelling a business logic and the processes that belong to the dialog steps.

The elements of a state diagram are:
   • An initialt state as a pseudo state of an instance
   • An optional final state, that causes the deletion of the instance
   • Usually several states, with their enter- and exit actions
   • Usually several transitions that are initiated by a trigger method and that can start an
       effect action




                                                                                      Page 25
                              1.3 A short UML and OCL overview


The following state diagram shows a simplified display of state sequences at a seminary
booking, from date selection to verification to the confirmation of the booking.




1.3.3 OCL
Besides the class- and state diagrams design, ECO also supports the UML extension
component OCL (Version2.0), both at development time and runtime.
With OCL so-called constraints can be defined, which limit the contents or semantics of UML
model elements. In the example above the OCL expression iID>0 would only allow positive
Ids in the class CL_Basis.
In Eco, OCL isn’t just used to express constraints, but also as a general language element
for controlling the model. You can basically say that the class model is “animated” by OCL.

A distinctive feature of OCL expressions is the navigation within a class model. OCL-
expressions for example begin in a class and end at a class attribute. By using the role
indicator (association end) of associations, complex expressions can be formed.

The opposite end of an association is called the object role. In the above class diagram, the
role University is assigned to each instance oPerson of the class CL_Person with cardinality
0..1, which means either once or not at all. So you can reach the instance of the class
CL_University that is visited by oPerson with oPerson.University.

Starting point of each navigation is the context of an OCL expression.
The context of an expression results from where the OCL expression is defined and used.
To refer to the starting object of a navigation, usually the indicator self is put in front of the
OCL expression.

Examples:
OCL-Expression                            Explanation
self.iID > 0                              returns TRUE/FALSE of an instance of a class
                                          derived from CL_Basis
self.sFirstname                           returns the attribute sFirstname of an instance of
                                          CL_Person
self.University.sName                     returns the university name based on an person-
                                          instance
self.Student.sFirstName                   Returns – based on a university – a list containing
                                          all of the university’s enlisted students




Page 26
                                         1. ECO-basics

The elements of a navigation expression are separated with a dot.
The return value of an OCL expression can be a single value (Boolean, String, Integer...) a
list of values, an object (instance) or a list of objects (list of instances).

OCL consists of various operations and functions, which can be classified as following:

language construct               explanation and example
Object access                   allInstances, allLoadedObjects, emptyList …
Attribute access                navigating via .Attribute name e.g. self.sFirstName
Arithmetic Operators        and Addition, Subtraction, Multiplication, Division… e.g. self.iID
expressions                     + 5, Round(self.iPrice)...
Boolean Operators               >, <, =, >=, <=, <>, or, and not …e.g. self.iID >= 24
String functions                concat, length, pad, subString, toLower...
                                e.g.. self.sFirstName + ‘ ‘ + self.sLastName
                                e.g.. self.sFirstName.Length
Date/time functions             indateRange, strToDate, formatDateTime...
collections                     allInstances->forAll(…), ->orderby (…), ->first, ->last,
                                ->count, ->select (..), ->union(..)…
                                e.g.:allInstances->select(sFirstName > ‘AAA’)
                                allInstances->collect(employees->size))
Type      analysis          and oclType, oclIsTypeOf, oclAsType, allSubClasses...
TypeCasting

All operators or functions used on collections begin with a -> Symbol (e.g. ->select), all other
Operators/Functions are added to the OCL-expression with a dot (e.g. .length).
As OCL also allows conditions (if ... then ... else ... endif), Iterators (->forAll) and recursive
references, this results to a modelling element that is very powerful and flexible in use.

OCL doesn’t have an assignment operator, that means a CCL expression should not and
can not change objects and values that it accesses. Besides that OCL can’t reference class
methods. OMG requested an query language free of side effects (see the next chapter 1.3.4
or the overview in chapter 2.6.4).

This very short introduction on UML and OCL is sufficient to understand the following
chapters of the book.
In chapter 2 we will encounter lots of example applications and details to UML modelling and
OCL usage.
Chapter 3 deals entirely with the usage of OCL in ECO.




                                                                                         Page 27
                              1.3 A short UML and OCL overview


1.3.4 ECO Action Language (EAL)
ECO Action language is not a part of the UML specification, but an ECO-specific OCL-
extension, which is available since ECO-II.

The OCL language range within ECO was on the one side extended with additional functions
from the OCL version 2.0 and on the other side is was extended with components by itself.

   •   An OCL expression can call (certain) class methods
   •   An OCL expression can assign values to object attributes
   •   An OCL expression can create objects and release them again
   •   An OCL expression has its own list operations: add, remove, removeAt, clear

With this the range of usage of OCL has been expanded largely. The action language is
used in the following areas:

   •   State diagrams
          Definition of the entry action of a state
          Definition of the exit action of a state
          Definition of the effect action of a transition

   •   As an alternative to a “coded” class method
          A class method can have a so-called body, which contains an EAL expression.
          When the method is called this expression gets executed

   •   Buttons in WinForms
          An EAL expression that is executed as an On-Click-Event can be assigned to
          each button


In chapter 3.2 EAL and its usage is explained in more detail with several examples.




Page 28
                                         1. ECO-basics



1.4 ECO, IDE and a first example
The integrated Together-Module in Delphi 2006 offers a lot of powerful functions which can
be used for ECO-Usage and also for non-ECO-projects (Win32, .NET). The way of usage
can be partly in similar but also in different ways.
When you start dealing with the topic modelling within Delphi, these similarities and
differences by using the Together-functionality are not always visible.
Before we start with our first ECO-example, it’s sensible to first look into more detail into the
integration of Together within the Delphi-IDE.


1.4.1 Delphi, Together and ECO
With Delphi 2006 Together was integrated into the IDE. With that the following functions are
also available for non ECO-Usage:

   •   Class diagrams (Code-visualization diagrams) with live-source (adjustment of
       diagram and code)
   •   Design diagrams (only diagrams without code generation)
   •   Patterns (patterns as diagram and code)
   •   Refactoring
   •   Audits
   •   Metrics
   •   Automated project documentation


                                       In the project management window of an application,
                                       under the index page Modell Viiew you find in parallel
                                                                Mode V ew
                                       to every Delphi-Unit, the code-visualization of the
                                       source code of the unit.
                                       In there, derived from the underlying source code,
                                       classes with their attributes and methods as well as the
                                       inheritance hierarchy between the classes are
                                       graphically represented
                                       Within this visualized representation, classes can be
                                       edited with the help of graphic elements out of the
                                       UML-class-diagram library (tool-palette).




Optional available under the Modell Viiew are these UML-elements via the context menu. In
                             Mode V ew
addition the context menu offers access to all other Together-functions Patterns, Audits,
Metrics and more.




                                                                                        Page 29
                             1.4 ECO, IDE and a first example




In principle this way of modeling can also be used for ECO-applications. But the code-
visualization-diagrams can not be used for the modeling of the ECO-class-diagrams, if at all
they will only be used for non-ECO-classes within ECO-projects.

ECO-class-diagrams are also created with the integrated Together-module, but they have
their own edit- and representation function, as we will see in the next chapter.

This means that for ECO-applications you have in general two class-modelling-functions.
The ECO-conform solution with the ECO-diagram and the above showed standard solution,
which can be used for all other forms of code-visualization.

In connection to a concrete ECO-project,
    • Existing of a ECO-package (Package_1)
    • Which on the other hand contains a ECO-diagram (Package_1[Diagram])
    • Which automatically has assigned a source-code-unit (Package_1Unit)
    • Which can be directly visualized (Package_1Unit[Diagram])




Page 30
                                         1. ECO-basics

The result for one and the same unit is the following modelling possibility:

Projekt-Unit / -Diagram                    Modelling with
Package_1[Diagram]                         ECO-Model (only ECO-classes)
Package_1Unit                              Source code
Package_1Unit[Diagram]                     Together (not for ECO-classes)

Beside special cases, it certainly makes no sense within an ECO-application to model a
Package_1Unit[Diagram] version in parallel to the Package_1[Diagram]. In cases in which
you require ECO-classes and non-ECO-classes in parallel, you would administer these in
separate units.

This separation between ECO- and standard-modelling affects the pattern-functionality. The
GoF-Pattern, delivered with Delphi (see Chapter 2.11) are ‘standard-modelled’, which means
they can’t be integrated into ECO-diagrams (as ECO-classes), but they can ‘only’ be used on
the level of Package_1Unit[Diagram].
But of course the pattern organization allows exporting elements out of our own ECO-
diagrams and importing them again into other ECO-applications.


1.4.2 ECO-projects
The best way to explain Eco components is by using an example. In this chapter we will
create step by step a simple ECO winForms application in the integrated Delphi development
environment [     Basics, Basics-SQL].

For a better comprehension of this first little Eco example in Delphi IDE you should „clear“
the Delphi IDE first.
That means if another project is already loaded; first unload its project data from the IDE by
selecting <Fiille> -- <Cllose Allll> .
           <F e> <C ose A >
In this "cleared" IDE we create our first ECO project.


The creation of an ECO project
To create a new Eco project, select <Fiille> -- <New> -- <Other> , in the following dialog
                                       <F e> <New> <Other>
choose Dellphii ffor ..NET Projjects .
        De ph or NET Pro ects
Amongst other symbols you will encounter:

      •   ECO ASP.NET Web application
      •   ECO ASP.NET Web-Service-application and
      •   ECO WinForms-application
      •   ECO Package in Package




                                                                                      Page 31
                              1.4 ECO, IDE and a first example


Now select ECO WinForms-application.
Next choose a project name- we call this example project Basics - and (optional) a project
data folder.

Notes:
  Each project should have its own folder!
  The following explanations refer to ECO-WinForms-application only, ECO package
  projects and ECO ASP.NET projects are explained in chapter 6.
  There are multiple ways of creating a new Delphi project.
  The way how ECO administers the source-code-units to the class-diagrams can be
  influenced with the IDE options in various ways (see section ‘Basic IDE settings for ECO’)

As soon as you have completed the project assistant, the following files are available for your
ECO-Project Basics:

     •    the "standard" Delphi-project file Basics.bdsproj
     •    a standard UML-EcoPackage called Package_1
     •    an EcoSpace-Unit called BasicsEcoSpace
     •    an Eco-activated Winform, called WinForm

Most likely you won’t be able to see all of these files on standard view. Details on this will
follow soon.


The project management window
For managing a project the IDE provides you with a Projject management wiindow that
                                                       Pro ect management w ndow
has 3 tabs (on the upper right hand of the IDE by default).




The page called Basiics..bdsprojj shows the project management known from earlier Delphi
                Bas cs bdspro
versions.
The Data--Expllorer page gives access to "currently available" DB files. This way the DB
     Data Exp orer
representation of the Eco model can be analyzed and changed within the IDE at
development time.



Page 32
                                       1. ECO-basics

In this case ‘currently available’ means that the selected database can be accessed from the
project.
The page Modell Viiew shows all project files with their model representation (UML-
            Mode V ew
diagrams), in particular Package_1 diagrams. The modeling concept which is taken over
from Together shows further diagrams – more on that later in the book.


Open project files not shown yet
Now we want to open the files in the IDE which are generated by the project assistant but are
not shown automatically.

The project file is opened Basics.bdsproj as follows:
     •    Activate the tab Basiics..bdsprojj in project management
                             Bas cs bdspro
     •    right-click the first entry Basics.exe
     •    select Viiew Source
                    V ew Source

The source code file of the UML-EcoPackage Package_1 can be opened like this:
     •   Activate the tab Basiics..bdsprojj in project management
                           Bas cs bdspro
     •   open the first entry Basics.exe
     •   double click Package_1Unit

The diagram file of the UML-EcoPackage Package_1 can be opened like this:
     •    activate the Modell Viiew tab
                        Mode V ew
     •    open the first entry Basics
     •    double click the entry Package_1 below


Note:
  You can rename the individual project files in the project window. Though in this text we
  will use the default names.


Other IDE windows
In the lower right corner the component selection window is shown by default. Here the
components available for the selected project file are shown. On the left side of the main
window the object inspector is located. More basic explanations of the IDE won’t be
necessary for Delphi developers.




                                                                                     Page 33
                             1.4 ECO, IDE and a first example




Basic IDE Settings for ECO
The menu item <Toolls> -- <Optiions> opens the comprehensive Option-Editor, that – in the
                 <Too s> <Opt ons>
left selection window- offers the entry <ECO Generall Optiions> for the configuration of
                                        <ECO Genera Opt ons>
basic ECO parameters.




The IDE offers additional functions for the development of an ECO application, e.g. for the
automatic creation and further development of a database structure, whose use requires
compiling the application in advance.
In such cases the option Auto compiille takes care, that the application is compiled
                              Auto comp e
automatically after a model change.

The persistence of an ECO application is created by special persistence mapper and data
connection- (see chapter 2.2). The linking between these components and the connection to
ECO space is largely automated by the option Hook up EcoSpace components
                                                      Hook up EcoSpace components
automatiicalllly .
automat ca y




Page 34
                                          1. ECO-basics

ECO administers the source code that belongs to each class- and state diagram (see
Chapter 1.4.2). The synchronization of diagram and source code happens automatically, if
the option synchronze Eco code on Idle is activated. If not, the synchronization has to be
            synchronze Eco code on Idle
done manually by the context menu Synchronize Model View in the diagram or the
                                      Synchronize Model View
source code unit. In addition the page Model View in the project management window
                                        Model View
offers the following function.


       Refresh Model View

       Regenerate ECO source code

       Update ECO source code

When modelling an association (see chapter 2.7) Eco uses the name of the class an
association-end points to, as name of the association end.

If the multiplicity of the association-end is greater than one, a Pllurall suffffiix is added to the
                                                                  P ura su x
association-end-name, a „s“ by default.

If a class diagram consists of multiple classes, the source code file is of course huge (see
chapter 1.4.2). Activating the option One ffiille per cllass has the effect that an extra source
                                        One e per c ass
code unit is created for each class of a diagram.
The file name is structured according to the pattern {0}Unit by default, with {0} being a
placeholder for the class name.
In a class diagram with the two classes CL_Customer and CL_Order two source code units
CL_CustomerUnit and CL_OrderUnit are created.
If the option One ffiille per cllass is deactivated, only one source code unit is created, with
              One e per c ass
{0} being a placeholder for the diagram name.
In this case a source code unit ProductPackageUnit is generated for a diagram with the
name ProductPackage.

Important note:
  In the example applications of this book we often use only one source code file
  (Package_1Unit) for each class diagram!
  Since some examples are converted from ECO-II to ECO-III with the converting function
  and not coded new, you will find a CoreClassesUnit instead of a Package_1Unit!




                                                                                           Page 35
                             1.4 ECO, IDE and a first example


1.4.3 Modeling

The class model – part 1
First we want to take a look at the class model. Activate the project file Package_1-Diagram.
At first this window is empty; a grid in the background makes the placing of UML elements
easier.
The component window (lower right side) offers you 8 different ECO/UML components.
Generally there are 2 ways of placing an element:
       •     Double click the component in the component window and then position it in the
             diagram
       •     Choose component by clicking in the component window and position it explicitly
             in the diagram

Now place two ECO-classes in the diagram and assign attributes to them. To add attributes
use the context menu (right click) of the class.
To rename and configure classes and attributes just use the object inspector.
It should look like in the image below.




Now place two note elements on the diagram, one to describe the project, the other to
describe the class CL_Person. Connect the second to the class using Note--Liink--Ellementt.
                                                                    Note L nk E emen
It should look like this:




Now create a first association between the two classes.
Activate the Associiatiion--Ellement , click on the class CL_Person, hold the mouse button
             Assoc at on E ement
and move the cursor to the class CL_University. Now release the mouse button.

Note:
  The direction, to which an association is dragged to, is generally of importance. More
  information about associations in chapter 2.7.

We want to configure this association with the object inspector.
To do this edit Name , Multiplicity and the Namen in the associative ends End1 and End2
like shown below.



Page 36
                                     1. ECO-basics




Summary:
  We created the classes CL_Person and CL_University in the class model of our project.
  Each class has some “trivial” attributes. The two classes are connected with a 1:n
  association. A person can attend one or no university. A university can have no, one or
  more students.




                                                                                 Page 37
                              1.4 ECO, IDE and a first example




The class model – part 2
Now we want to add a class inheritance / generalization.
Add another class CL_Basis to your class diagram; set the class property Abstract to TRUE
and add the attribute iID:Integer to this class.
Place a Generalliizatiion--Ellementt in the diagram, drag the generalization arrow from
         Genera zat on E emen
CL_Person to CL_Basis; which means CL_Basis is defined as master class.
Drag another Generalliizatiion--Ellementt from CL_University to CL_Basis.
             Genera zat on E emen

Below you can see the extended diagram.




At the end of the class modelling you should save everything and translate it for the purpose
of testing.


The automatically generated Code in the Unit Package_1Unit
Have a look at the project file Package_1Unit. It contains the source code representation of
our UML diagram.

The unit shows the source code for the three classes CL_Basis, CL_Person and
CL_University as well as an object interface ICL_BasisList etc. as UML-Collection of each
class.
Please take a note in particular of the code sections [Eco generated code] and
[autogenerated ECO code] – marked with a $Region directive-, which mark the parts of the
source code that ECO automatically creates and administrates.

In each class for each attribute we find a property with the corresponding get- and set-
methods. Besides that a member for class attributes exists, where an explicit number within
the class is assigned to each attribute. This enables indicated access to each class attribute.

Each element of the class model is marked with a unique ID. This ID is assigned via UML
attribute just before defining the element.


  [UmlElement('Association', Id='47157a57-13ea-4067-8686…2f1d4')]
  ASS_PersonVisitsUniversity = class




Page 38
                                         1. ECO-basics

The class constructor, whose implementation part already contains a comment for adding
user code, is of special importance.
Each class has two constructors, an “internal” constructor with an Icontent-passing-
parameter, and the “exported” version that needs an IECOServiceProvider-parameter, which
can be enhanced for your own use.

This class constructor is a preferred place to, for example, implement the initialization of
class attributes. You can find an example application for that in chapter 2.2.6 [    PM2].

Other typical use cases for implementing user code into Unit Package_1Unit are functional
extensions of a class. In chapter 2.6.5 you can find an example application for that
[     Constraints].

Summary:
    Now our model consists of three classes. The class CL_Basis is abstract, no instances
    are created from it. CL_Person and CL_University inherits the attribute iID from
    CL_Basis and implements further attributes themselves.



1.4.4 Persistence
Next we want to get a permanent storage for the objects in our model. Usually this is done
with a database, in this case though we use a XML-File.

Note:
    The example application [    Basics] contains the xml-, the application [       Basics-SQL]
    contains the MS SQL-version.

Switch to the BasicsEcoSpace page in the IDE. In the lower tab of this project file you find the
switch between design- and code view.
For now activate Desiign--viiew . Place a PersiistenceMapperXML--componentt from the
                  Des gn v ew             Pers stenceMapperXML componen
component window, category ECO on the BasicsEcoSpace-Design page.
                              ECO




Note:
  To find a component faster in the component window you can choose the category
  beforehand or limit the options by activating the filter switch and than entering the initial
  letters.

To configure this PersistenceMapperXML-component it’s sufficient to set the Property
Filename in the Object inspector. Here enter filename and path (optional) of a user-defined
text file. The file will be created automatically at runtime.




                                                                                        Page 39
                             1.4 ECO, IDE and a first example




Here the question arises: how does our EcoSpace get connected                       to   this
PersistenceMapperXML? The answer is: automatically (see chapter 1.4.1).

Please click on an unused part of the BasicsEcoSpace-design page.
The object inspector now shows the properties of our EcoSpace. As you can see the
property PersistenceMapper is already set.

Note:
  As we will see later on, you can also work with several EcoSpace instances in an ECO
  application. In these cases the associations between PersistenceMapper and EcoSpace
  have to be set explicitly.

Is there already a connection between our class model and EcoSpace?
The answer is here as well: the connection was created automatically.

Open the code page of the project file BasicsEcoSpace. In the list of uses you’ll come across
the entry Package_1Unit; this unit contains the code representation of our class diagram
(see the preceding chapter).
Since EcoSpace knows our class model and the PersistenceMapper is connected to
EcoSpace the PM can map the structure of the class model as a database schema to a
database and transfers objects between EcoSpace and database at runtime.

But since we only use a XML mapper in this example, we won’t create a database schema
now.

Instead you should save and compile your project.

Summary:
  Our application now also has a persistence component. Instances of both classes,
  CL_Person and CL_University , can be saved to an xml file and can be read out of it.




Page 40
                                        1. ECO-basics


1.4.5 The Interface
Finally we create a simple user interface for our application.
To do this switch to the project file WinForm. This file has several sub pages that you can
select at the lower part of the window. First activate the Desiign--page .
                                                           Des gn page
You will see a window that is divided horizontally. In the small, lower part some ECO
components are already placed. Those are entered automatically, since this WinForm is a
so-called ECO-activated WinForm. Those components take care of connecting the WinForm
to ECO.

In the upper window you’ll find the WinForm itself.

In the components window (lower right side) you can choose from the usual .Net interface
controls.
Place two data grids and six buttons on the WinForm. Additionally we need two
ExpressiionHandlles and two CurrencyManagerHandlles from the ECO -category.
Express onHand es               CurrencyManagerHand es                       ECO
These handles have to be and can only be placed in the lower part of the window.

The image below shows how it now should look like.




Now we want to configure the single components with the object inspector and make their
functions more obvious this way.

We begin with the root handle rhRoot, which was already placed by the project assistant. A
root handle establishes the general connection between EcoSpace and WinForm. So in
rhRoot we put the property EcoSpaceType to our BasicsEcoSpace.TBasicsEcoSpace
using the selection list.




                                                                                   Page 41
                               1.4 ECO, IDE and a first example


Notes:
  Probably this value has already been set.
  If no entries are displayed in the selection list of the property, you probably forgot to
  compile the application beforehand.

Next we want to define a precise „handle access path“ for each of our classes. To do this we
set the following properties in the ExpressionHandle1:

          Object inspector                   ExpressionHandle1
          Name                               exphPerson
          RootHandle                         rhRoot
          Expression                         CL_Person.allInstances

Via rhRoot our exphPerson has access to the persistence system in EcoSpace and provides
all instances of the class CL_Person based on its Expression.

In the ExpressionHandle2 we set the analogue values for the class CL_University:

          Object inspector                  ExpressionHandle2
          Name                              exphUniversity
          RootHandle                        rhRoot
          Expression                        CL_University.allInstances

The next step is to configure the display of instances in the datagrids.
The values for both data grids are:

 Object inspector          DataGrid1                          DataGrid2
 Name                      dgPerson                           dgUniversity
 DataSource                exphPerson                         exphUniversity

As a result both grids should now display the corresponding class attributes.
In addition to the class-internal attributes the reference to an assigned university, created
with the association ASS_PersonVisitsUniversity is displayed in the data grid dgPerson.

Adjacent to the complete list of instances we also want to create an instance indicator (data
set indicator). To do this we configure the two CurrencyManagerHandle as follows:

 Object inspector          CurrencyManagerHandle1             CurrencyManagerHandle2
 Name                      cmhPerson                          cmhUniversity
 BindingKontext            dgPerson                           dgUniversity
 RootHandle                exphPerson                         exphUniverity

Now we have a matching CurrencyManagerHandle for each ExpressionHandle that always
refers to the selected instance from the list of instances displayed on the corresponding data
grid.




Page 42
                                         1. ECO-basics

 For user interactions we provided buttons. Set their attributes like shown below:

Object           Button1           Button2          Button3                Button4
inspector
Name             BtnAddPerson      BtnDelPerson     BtnAddUniversity       BtnDelUniversity
Bindingcontext   dgPerson          dgPerson         dgUniversity           dgUniversity
EcoListAction    Add               Delete           Add                    Delete
RootHandle       exphPerson        exphPerson       exphUniversity         exphUniversity




                      Object           Button5              Button6
                      inspector
                      Name             BtnSave        BtnLink
                      EcoAction        UpdateDatabase
                      Text                            Link



 This is how the final result looks:




                                                                                     Page 43
                           1.4 ECO, IDE and a first example


Note:
  We will deal with the meaning of the ECO components which are left out now,
  EcoGlobalActions, EcoAutoForm and EcoListActions, in chapter 5.1.4.

Summary:
  Our application now also has a user interface, where instances of both classes,
  CL_Person and CL_University are displayed. The user can add data, edit it in the grid
  and delete it. The changes made can be saved in the database or the xml file.
  For the development of this interface not a single line of code had to be written.
  The ExpressionHandles take care of the data transfer between the GUI controls and
  EcoSpace, depending on the defined OCL expression. The controls are ECO compatible
  by design and are connected to the expression handles by the property DataSource.
  EcoSpace automatically loads the data-set requested at runtime from the database
  (respective the XML file). With the button Update DB edited data will be saved.




Page 44
                                        1. ECO-basics


1.4.6 Testing and further development
Save, compile and start your new application.
You can create new objects that will show up in the corresponding grid with the button add.
The attributes of those objects can be edited in the grid.

As stated before the data grid Persons also contain the column University. This is not a
class attribute but the association end of our association ASS_PersonVisitsUniversity,
which refers to the class CL_University.
You can’t edit this column in the data grid. Its value gets set every time a connection
between the person-instance and the university-instance is created, edited or deleted.
With the button Update DB you can save your changes to the XML-File.

So how can we establish a connection between a person and a university?
There are two ways:

    a) Without additional coding using the Drag & Drop Function
    b) With an explicit link button, to which we add the corresponding code

Alternative a) first:


AutoForm and Drag & Drop
The data grid control has an integrated drag & drop mechanism. We can activate this
mechanism in the object inspector like shown below:

                        Object          dgPerson         dgUniversity
                        inspector
                        EcoAutoForm     TRUE             TRUE
                        EcoDragSource   TRUE             FALSE
                        EcoDropTarget   FALSE            TRUE

The property EcoAutoForm adds a line editor, called AutoForm-Editor to our data grid. The
AutoForm-Editor displays the attributes of the selected instance (person or university) in
detail, thus providing another way to enter data than the data grid.
We activate this editor with the settings from the table above.
After compiling and starting the application, open the editor by double clicking the
selection column of the selected instance.

For instances of the datagrid Persons the AutoForm-Editor shows an attributes page
containing the attributes of the instances, as well as the “read only” association end
University.
However for instances of the data grid Universities, the AutoForm-Editor provides two
pages: the page Propertiies with the attributes of the object and the page Student listing all
                Propert es
persons assigned to the selected university.

According to the table above we also have set the drag & drop properties for both data grids,
in addition to the property EcoAutoForm.
So the table Persons is the drag source and the table Universities is the Drop-Target of a
Drag & Drop-Action.
With those settings a drag & drop mechanism is enabled, meaning that a person- instance
can be dragged onto a university-instance.



                                                                                      Page 45
                              1.4 ECO, IDE and a first example


Because of that select a university from the universities table and double-click the selection
column. This way you open the AutoForm-Editor containing the details of the selected
university.
Activate the Student tab in this autoform. This page is supposed to list all persons assigned
to the university as students. Of course right now this list is empty.

Now switch to the table Persons with the AutoForm still open. Click on the selection column
of any person, keep the mouse button pressed and drag the mouse to the Student tab of the
AutoForm-window. There you can drop the person-instance.




Notes:
  Using drag & drop usually requires another position of the autoForm window to prevent
  the windows from overlapping.
  The Drag & Drop Action sometimes causes the application to hang up. As far as I know
  the integrated debugger causes this problem. In an ‘exported’ application without IDE or
  with the debugger in the IDE deactivated this problem doesn’t occur.
  More on EcoAutoFormExtender-components in chapter 5.1.4.

With each drag & drop actions the corresponding link between a person-instance and a
university-instance is set. You can see this in the table Persons. The column University,
that refers to the connected university, shows CL_University instead of the <null> entry.
By double clicking the selection column of a person-instance in the AutoForm window you
can open an AutoForm dialog for this person-instance.
Starting from the autoform of a person that’s already assigned to a university, you can now
open the autoform for the corresponding university by clicking the attribute button University
etc.

Now alternative b)


The first coding
We want to show an alternative way to connect two instances and have a closer look at
coding in EcoSpace.

During the development of our small ECO application we placed a sixth button called
BtnLink which we haven’t used yet.
With the object inspector (event tab) we assign an OnClick-Method to this button, which we
provide with the following code in the CoreClassesUnit:




Page 46
                                       1. ECO-basics

  procedure TWinForm.BtnLink_Click
                       (sender: System.Object; e: System.EventArgs);
  var oPerson      : CL_Person;
       oUniversity : CL_University;
  begin
    if (Assigned (cmhPerson.Element) and
         Assigned (cmhUniversity.Element) and
         Assigned (cmhPerson.Element.AsObject) and
         (cmhPerson.Element.AsObject IS CL_Person) and
         Assigned (cmhUniversity.Element.AsObject) and
         (cmhUniversity.Element.AsObject is CL_University)) then
        begin
          oPerson := CL_Person (cmhPerson.Element.AsObject);
          oUniversity:=CL_University(cmhUniversity.Element.AsObject);
          oPerson.University := oUniversity;
          //alternative way
          //oUniversity.Student.Add(oPerson);
        end;
  end;

Explanation of the code:

   o   First we check the two CurrencyManagerHandle. We can only assign a person to a
       university, if exactly one person and one university are selected with the
       CurrencyManagerHandles. So for example we have to avoid that there are no
       persons or no universities available in the table when calling this code segment.
   o   In our example checking if the current objects really are persons or universities isn’t
       really necessary, but makes sense in other cases, since you can of course edit the
       first configuration of a CurrencyManagerHandle at runtime later on by coding!
   o   Now we use two local instance variables, oPerson and oUniversity to keep track of
       the two selected instances.
   o   We have two ways to create a link between the two instances. One is starting from
       the university. Since a university can have n students (Multiplicity 0..n), we use the
       Add-Method. The other way is to assign the university directly to the selected person.
       In both cases we use the respective name of the association-end as navigation path.
   o   For a potential unlink we can use oPerson.University := NIL or as an
       alternative oUniversity.Student.Remove(oPerson).

Note:
  When accessing the current element of an ExpressionHandle we will always use a
  CurrencyManagerHandle within the book examples. In fact this is only needed, when that
  current element is used as the root value of another handle, as we will see in some of the
  examples in the following chapters.
  When there is no “handle chaining” we can access the current handle by using the static
  method GetCurrentElement of CurrencyManagerHandle. That will provide a simplier
  access to what we need here.
  oPerson := CurrencyManagerHandle.GetCurrentElement (exphPerson).AsObject AS
  CL_Person
  In the source code of our example you will find a complete alternative BtnLink_Click
  method.




                                                                                      Page 47
                              1.4 ECO, IDE and a first example



Important note:
  In the code above and in the following program examples of chapter 2 and 3 you come
  across EcoSpace functions like Element.AsObject, that are not explained explicitly
  when they appear. This is not necessary for the understanding of the examples. The
  „internal“ EcoSpace-Structures, -Methods and –interrelations are explained in chapter 4.1
  in detail.

Save, compile and start the application.
Then enter several persons and universities into the data grid and test the function of the link
button.


An Autoincrement attribute for our ID
In this mini application a field iID : Integer is reserved for each object. This field should
contain a distinct ID, which should not be edited by the user but should be provided by the
system, to be more exact, by the database. This attribute will not be used as a primary key in
the database.
Therefore only two property settings in the object inspector for the attribute iID of the class
CL_Basis are needed:

                              Object inspector        IID
                              save action             DBAssign
                              PMapper                 AutoInc

The setting DBAssign makes sure that the value is reloaded from the database when the
object is stored the first time. The PersistenceMapper AutoInc puts the corresponding
column types into the database table CL_Basis when creating the database schema.
So when our mini application gets modified as shown, all newly created person- and
university-instances are automatically given distinct Ids. However those Ids are only available
after saving the objects, since only creating objects doesn’t lead to a database query in
EcoSpace, as a result a DBAssign hasn’t taken place yet!

Note:
  The usage of DBAssign and AutoInc requires a database with the corresponding
  functionality, for example MS SQL-Server. Of course when saving data to an XML file, like
  in our example, this functionality isn’t available. For being able to use this example in this
   context you have to refer to the MS SQL-Version of this example [       Basics-SQL].
   More on PersistenceMappers in chapter 2.2.

Summary:
   For linking two instances, person and university, we used EcoAutoForm and the Drag &
   Drop properties of DataGrids. As an Alternative to this we used a code-based object link
   for the first time.
   The possibility of navigating both ends of an association enables a very flexible handling
   of associations.
   To further improve our application we have created an AutoInc-Field.

Now our first little application is complete. Hopefully you could get a first impression of the
components of an ECO application with this example. In the next chapters we will go into
more details.




Page 48
2. Modeling with ECO
As we have seen, ECO is a development framework fully integrated into the Delphi IDE and
at the same time a runtime framework based on .NET.
Being a MDA (model driven architecture) oriented development system; the focus is on the
business model (domain model). In this chapter we want to give special attention to the
modeling of ECO applications and we will come across various ECO specific features.



2.1 An EcoSpace overview
As stated before EcoSpace is the main component of the ECO-concept. On the one hand it’s
connected to the database via the PersistenceMapping-System, on the other hand it
transfers objects for visualization and editing to the user interface.
In an ECO-WinForms-application database components and persistence mapping
components are placed on the design file page of the xxxEcoSpace-Unit.
On the one hand with the help of these components the database schema needed for the
realization of persistence can automatically be created and improved. On the other hand the
fully automated mapping between objects in EcoSpace and data in the database table is
realized with these components at runtime.

But EcoSpace can be used in more ways than this.

     •     All interactions between objects, for example the linking of objects by means of
           associations, are realized in EcoSpace.
     •     When using several EcoSpaces for one application pooling and synchronization
           mechanisms are provided.
     •     If EcoSpace gets implemented in the framework of an ECO-Web-Service, flexible
           caching methods can be installed to optimize access time.
     •     EcoSpace provides a complete Undo/Redo and Version function, Transaction
           handling plus a Subscriptions-method for automatically notification of objects if
           data gets changed in other objects.
     •     Finally EcoSpace provides the developer with interfaces for code based access to
           EcoSpace; plus an OCL evaluation and query functionality.

The xxxEcoSpace-Unit itself provides a first level of configuration the EcoSpace. For this
unit the object inspector provides (among others) the following global properties for the
EcoSpace:

Property                   explanation
Optimistic Locking         activation of the Optimitic Locking method,
                           see chapter 4.7.3
UpdateWholeObjects         When saving changed objects, the whole objects gets saved,
                           not only the changed attributes, see chapter 4.1.6.
AllowDeactivateDirty       Modification of the DirtyObjectList-Handling, see chapter 4.1.6.
EnforceStringLength        The string lengths set by the model are mandatory
PersistenceMapper          Properties of the PM-component, see chapter 2.2.5.




                                                                                    Page 49
                                   2. Modeling with ECO



2.2 EcoSpace – Persistence and databases
In the Eco world you will very often stumble across the term Persistence-Mapping, from now
on abbreviated with PM. PM in ECO as a whole consists of multiple components which we
will have a look at one by one.


2.2.1 Choosing of a PersistenceMapper-component
The basic components of the PM system is the so-called PersistenceMapper, which we
already used in our basics-application.
ECO provides a total of 5 different (alternative) PersistenceMapper-components:
      •   PersistenceMapperXML
      •   PersistenceMapperBDP
      •   PersistenceMapperSQLServer
      •   PersistenceMapperSharer
      •   PersistenceMapperMultiDB

The XML-Mapper is only useful for special applications, for example small example programs
or test applications. Its advantage is that it doesn’t need any database support, so such an
installation works on any .Net computer.

The BDP-Mapper can be used with any BDP-Database-component. So it scores high on
flexibility, but has its disadvantages regarding performance and the use of database-specific
structures.

The SQLServer-Mapper can only be used in association with a MS SQL-Server database,
either SQL Server or SQL Client, but offers the best performance and support in return.
In contrast to the BDP-Mapper, with the SQLMapper e.g. the SQL setup offers, among other
things, alternative support of ANSI or unicode (MCBS-Setup).

The Sharer-Mapper is only used in association with so-called PersistenceMapper Provider
Units. More on that in chapter 2.2.9.

In Eco-III a new component was added, the PersistenceMApperMultiDB. It can be used to
distribute the persistence of a model to several databases. More about that in the next
chapter.

The following analyses refers in general to the PersistenceMapperBDP, since it is the most
flexible way of database integration for our examples. Whenever we will differ from this rule,
you will see an according note.




                                                                                      Page 51
                         2.2 EcoSpace – Persistence and databases


2.2.2 Installing a PersistenceMapper-component
To equip EcoSpace with a persistenceMapper-component, the designated Mapper-
component is placed on the design tab of the xxxEcoSpace-Unit and – except the XML-
Mapper – connected to an adequate database component via the property Connection. A
BdpConnection works with the BDPmapper, a SQLconnection with the SQL-Server-Mapper.
After that the PersistenceMapper-component has to be initialized using the mapper´s context
menu. The SQL setup is selected according to the chosen database. This setup takes care
of the correct property settings of the PersistenceMapper, so that there’s usually no need to
optimize property settings.
If only one PersistenceMapper is placed on EcoSpace, the EcoSpace-Property
PersistenceMapper usually already features the PersistenceMapper-component. Otherwise
this property has to be set manually.

These settings result to the following diagram:




Still missing is the configuration of the connection component, which is done with the
component’s context menu. There the parameters for database access, like DB name,
password, etc. are set.

The use of multiple databases for one model is also possible. In this case a set of PM/DB
components is placed like shown above for each database. In addition a
PersistenceMapperMultiDb component has to be used. Now the EcoSpace property
PersistenceMapper has to be connected to the PMMultiDB component. With the PMMultiDB
property PersistenceMappers all PM components can be added to the list editor.




Page 52
                                   2. Modeling with ECO


2.2.3 Create and enhance a database schema
Now we are familiar with all components which are needed to create the db schema, suitable
for a UML class model (Package_1). For this the design tab of the xxxEcoSpace-Unit
provides the following buttons at designtime of an application:

       Validate model


      Genererate schema


      Evolve schema


       Generate Default Mapping XML


With Valliidate Modell modelling errors like, for example illegal parameters within an
     Va date Mode
association, incorrect OCL/EAL expression etc. can be found.

With Generate Schema table structures in the database are created. Existing tables will be
     Generate Schema
deleted! Before executing this function a dialog will open up and show which tables will be
affected by the operation.

With Evollve Schema an existing ECO database schema can be adjusted to the edited UML
     Evo ve Schema
class model.
This function can be critical and has been a continuous source of errors and problems in
former ECO versions! With ECO-II and the available updates the situation has improved
dramatically, nevertheless it’s still wise to save the database before executing this function

Next to this „one-click-version“ of scheme development the alternative way of developing a
scheme with the help of explicit XML allocation data exists. Multiple steps are required for
this.
First a XML mapping file has to be created based on the class model – before editing. This
can be done with the button Generate deffaullt mappiing XML . The created file has to be
                              Generate de au t mapp ng XML
saved implicitly, best in a separate subfolder, where all development steps should be saved
in general.
After editing the model another xml mapping file has to be created and saved.
Next we need two FileMappingProvider-components. Those get linked to the
PersistenceMapper-component          with     the   property    OldMappingProvider       and
New/RuntimeMappingProvider.
In the FileMappingProvider-component „Old“ the Property Filename is set to the file name of
the xml mapping file „before editing“, in the component „New“ Filename is set to path and file
name of the “new” xml mapping file.
Now changes to the class model can be transferred to the database tables with the button
Generate Schema .
Generate Schema




                                                                                      Page 53
                         2.2 EcoSpace – Persistence and databases


Notes:
  For further steps of db development only the xml mapping file name has to be replaced.
  The „Old-component“ gets the XML-Filename of the „New-component“ and the „New-
  component“ gets the path and file name of the xml mapping file that is to be generated.
  The functions to create and enhance a db schema can also be accessed with code. More
  about that in chapter 4.1.7.


  The symbol     Convert model to ECO-III is used to convert an ECO-II model to ECO-III.
  You can find more on that in the Delphi on-line help in the chapter ‘convert ECO
  Framework projects in Developer Studio 2006’.


2.2.4 Wrap existing database with ECO
ECO can – under certain conditions – be used with an existing relational database.
The IDE provides an assistant.


       Wrap existing database with ECO

The process of such a converting action looks like this:

   •    Placing a connection- and a PM component and creating a connection to the default
        DB (see chapter 2.2.2)
   •    Starting the assistant
   •    Determining identifiers and selecting the tables that are to be converted

As a result the assistant creates an OR-Mapping file (XML-file) that contains the complete
class structure an a UML package (diagram and code).

If the Eco objects modelled this way should also be saved in the default DB in the future, the
Eco specific OR-information has to be added to the DB structure.

The function         ‘Generate default mapping file’ takes over this task.


2.2.5 Properties of a PersistenceMapper-component
After having a look at the standard way of selecting and setting up a PersistenceMapper-
component, we now want to examine the various options outside of the standard settings.

We already mentioned the properties for the setting of the MappingProviders, that we need
alternatively for the enhancement of a db schema. These are the Properties New-, Old-, and
Runtime-MappingProvider. In general these properties are also used to influence the
Standard-Mapping-behaviour with a DefaultOrMapping-component. You can find an example
for this in chapter 2.2.7.

The next group of properties relates to SQL-Templates and SQL-Scripts, which serve as
patterns for certain SQL-Operations of the database. Among these are templates for
DropColumn, DropIndex and DropTable and the Scripts CommentStart, CommentStop,
CommitTransaction, RollBackTransaction, StartTransaction, Separator and Terminator.
Co




Page 54
                                   2. Modeling with ECO

For the adjustment of general DB-Parameters the following properties exist:
 Property                   Explanation
DateTimeFormat              defines the Format of the Function DateTimeToString
DefaultDateTime             the Default Date, which is set when creating date-time fields in
                            the db
DefaultStringLength         used for the default setting of the size of VarChar fields
                            (default=255); also see chapter 2.2.6.
FetchBlockSize              the max number of objects that can be loaded with a sql
                            statement
MaxDBIdentifierLength       max length of the identifier
MaxParamsInIdList           max number of parameters in the id list of a sql statement. If this
                            number is exceeded, parameters are transferred as text.
ReservedWords               the list of words reserved for the database, that can’t be used as
                            table name, field name, field identifier etc.


The following properties are used to activate certain db functionalities:
 Property                              Explanation
AllowMetaData                          The db allows the editing of Meta data within a
                                       transaction
SupportConstraintsInCreateTable        ECO generates primary key conditions for the
                                       generated tables
UseTimeStampTable/Column               adds a timestamp column to the table XFiles
UseClockLog                            automatically adds tables that protocol the time to
                                       each timestamp entry


Notes:
  Usually you don’t set the properties manually, but by selecting a database in the right-click
  context menu of the PersistenceMapper-component.
  You can find detailed information for the use of timestamps in chapter 4.7.3.
  The properties of the PersistenceMapper-component which are placed in the sections
  ‘Pooling and Synchronization’ are explained in chapter 4.7.2.

The meaning of the properties KeyMappers and PersistenceMappers will be explained in
the following chapters.




                                                                                       Page 55
                        2.2 EcoSpace – Persistence and databases


2.2.6 Mapping of Non-key-Attributes
For all non key attributes of a class a connection between the attribute and the
corresponding mapper is established by the property PMapper on the class.
Usually the entry <Default> in the attribute PMapper is sufficient for all “trivial” attribute
types like String, Integer, Boolean etc. In all other cases individual mappers can be used.
In our introductory example [     Basics] we already made use of this. We replaced the
PMapper value <Default> with the value AutoInc (see chapter 1.4.5) in the attribute iID
: Integer. As a result the value of the attribute iID is automatically created by the
database and increased gradually (default value = 1, increase = 1).

Which mappers are at our disposal by default?
The Property PersistenceMappers, in the PersistenceMapper-component informs us about
that. Here you can find all generic mappers and among others also our autoInc mapper.
Of course the number and kind of mappers depends on the kind and the configuration of the
PersistenceMapper-component. A PersistenceMapperBDP-component with DB2-Setup
provides other Mappers a SQL-Server-component.
Please note: Only the AutoInc-Mapper can be set up in a way that the database
automatically generates the values.

If we don’t want to leave the choice of mappers to Eco, even for trivial attribute types, we
have to replace the <Default> entry in the property PMapper with the name of the mapper
of our choice.

Another example for this [      PM1]:

We define two attributes sShortDesc and sDescription for a class CL_Job like shown in the
table below.

                    Object              sShortDesc       sDescription
                    inspector
                    Type                String           String
                    PMapper             <Default>        StringAsText

Both attributes use the same type String (max. string length 2 GB).
Because of the <Default>-setting of the Property PMapper the db-type varchar with a
max length of 255 byte is set for the field sShortDesc in the database table. The attribute
type string is mapped as a CharArry with a max length of 255 characters by default. In
contrast to that the type text (= Blob-Field) is set for the field sDescription, for which we
have set the PMapper StringAsText explicitly, thus using the max string length to full
capacity.

Notes:
  The db identifiers above and the max field length specifications vary with each database.
  In the example above a sql sever database was used.
  Instead of using a blob field the length of the type String (=varchar in the DB) can also
  be set with the Attribute-Property Length, with a max string length of 8000 characters for
  the sql server.
  The default string length of 255 characters can be changed with the property
  DefaultStringLength in thePersistenceMapper-component.




Page 56
                                    2. Modeling with ECO

If the PersistenceMapper-component in the Property PersistenceMappers doesn’t offer a
mapper suitable for the attribute, we can also define other mappers and add them to the list
of mappers.

For this we upgrade our example [        PM1]:
We want to add two more attributes in the form of enumeration types in the class CL_Job:

The attributes eJobType and eCompanyType, that should have the following characteristics:

  ADT_JobType = (jt_FullTime, jt_PartTime, jt_Freelancer);
  ADT_CompanyType = (ct_Industry,ct_Service,ct_Consulting,ct_Media);

Notes:
  For each of both data types we’ll define its own mapper subsequently. The required
  source code (Data type + Mapper) will be placed in a unit.
  The prefix ADT is used to indicate the deposit in the interface-part of both units
  ADTStr.PAS and ADTInt.PAS.

Of course a mapper doesn’t exist yet for the enumeration types above. So first we have to
create two custom mappers with the following details:

                    Attribute       Database value     display/input
                    value
                    jt_Fulltime             1          full time
                    jt_PartTime             2          part time
                    jt_Freelancer           3          freelancer

                    ct_Industry             I          industry
                    ct_Service              S          service
                    ct_Consulting           C          consulting
                    ct_Media                M          media

That means the enumeration type ADT_JobType is mapped onto an Integer, in contrast to
that an ADT_CompanyType is mapped onto a String with length 1.




                                                                                    Page 57
                        2.2 EcoSpace – Persistence and databases




An Integer-Mapper
To complete this task we first create a new unit ADTInt.PAS. In this Unit we first define the
structure and data for the data type JobType.

  type
  ADT_JobType = (jt_FullTime, jt_PartTime, jt_Freelancer);

  TJobTypeData = Array[ADT_JobType] of
    record
      iDBVal : Integer;
      sName : String;
    end;

  const
  CJobTypeData : TJobTypeData =
    ((iDBVal:1; sName:'Fulltime'),
     (iDBVal:2; sName:'Parttime'),
     (iDBVal:3; sName:'Freelancer'));


Next   is  the  definition of  a    mapper           class,   derived    from    the   class
AbstractNumericSingleColumnAttribute.

  ADT_JobTypeAsInt = class (AbstractNumericSingleColumnAttribute,
  ISingleColumnAttributemapping)
    private
      // Usually, here you would place the const struct defined in
  the implementation section, but the Delphi enum-bug…

    public
       function ColumnType (length : Integer) : String;
       procedure ValueToParameter (value : System.Object; parameter :
  IDataParameter);
       procedure StringToParameter(value : String; parameter :
  IDataParameter);
       function ColumnToValue(columnValue : System.Object) :
  System.object; override;
       function IsEqual(value, columnValue : System.Object) :
  Boolean; override;
  end;

The class AbstractNumericSingleColumnAttribute is defined in the               BDS-folder,
\Source\ECO\Persistence in the Unit DefaultAttributeMappers.cs. A mapper that maps
any data type onto an Int32 database value can be defined with a mapper class derived from
this class.
In our example we mapped the type ADT_JobType onto the Integer array 1..3 and defined
the class ADT_JobTypeAsInt for this.




Page 58
                                    2. Modeling with ECO

In this class we have to provide 5 methods:

        •   ColumnType returns a string that indicates onto which database type our attribute
            should be mapped ( „INTEGER“ in our example).
        •   ValueToParameter transfers an attribute value (ADT_JobType) into the
            corresponding DB value (Integer).
        •   StringToParameter transfers the String representation of the attribute value into
            the corresponding DB-value.
        •   ColumnToValue executes the retransformation of the db value into the attribute
            value
        •   IsEqual compares if two db values are identical (the implementation of this
            method is optional here)

Note:
  In the source code of [   PM1] you will find the unit ADTInt.PAS with the complete
  source code. That´s why we didn’t find it necessary to print the source code here.

The realization is made easier by using the structured constant CJobTypeData. Besides this
we can avoid direct access to our attribute-values within our methods. Customizing the
mapper to other enumeration types is now possible simply by expanding the structurized
constant.

Note:
  In this source code the record-structure and the constants were placed in the
  implementation-section of the unit, because these files don’t have to be exported.
  A better solution would be to place these files in the class itself (that’s where they belong
  to). The reason for this extraordinary measure is that Delphi –due to a bug- cannot handle
  structured constants containing enumeration types within a class.


Note to the note:
  The bug mentioned above has now officially been fixed (Borland QC). The example
  source code though hasn’t been updated yet.

After the mapper class has been defined we can use it. For this we set the property
PMapper for our attribute eJobType in the object inspector to ADT_PMJobType. We define
this new Pmapper as follow.
We switch to the design page of the xxxEcoSpace-Unit and search for the entry
PersistenceMappers in the Property SQLDatabaseConfig of the PersistenceMapperBDP-
component.




                                                                                      Page 59
                         2.2 EcoSpace – Persistence and databases




The Editor displays a list of all known PM-Definitions. With the Button Add we can add our
                                                                        Add
new mapper to the list. Enter ADT_PMJobType as the name and for the mapper enter the
full name of the mapper class which we just coded in the ADTInt.PAS Unit, in other words
ADTInt.ADT_JobTypeAsInt.

Note:
  Sometimes the list editor faces troubles accepting the entered class identifier. In this case
  just switch to the source code page of the xxxEcoSpace-Unit and enter the mapper class
  name directly in the InitializeComponent-Procedure:
  …
  PersistenceMapperDefinition120.Mapper :=
                                            TypeOf(ADTInt.ADT_JobTypeAsInt);
  PersistenceMapperDefinition120.Name                 := 'ADT_PMJobType';
  …


A String-Mapper
The mapping of ADT_CompanyType goes the same way. First we create a new unit
ADTStr.PAS. In this Unit we first define the structure and data for the data-type
CompanyType.

  type
  ADT_CompanyType=(ct_Industry, ct_Service, ct_Consulting,ct_Media);

  TCompanyTypeData = Array[ADT_CompanyType] of
    record
      sDBVal : String;
      sName : String;
    end;

  const
  CCompanyTypeData : TCompanyTypeData =
    ((sDBVal:’I’; sName:'Industry'),
     (sDBVal:’S’; sName:'Service'),
     (sDBVal:’C’; sName:'Consulting'),
     (sDBVal:’M’; sName:'Media'));




Page 60
                                   2. Modeling with ECO

Next is again the definition of a mapper class, this time derived from the class
Ab
AbstractStringSingleColumnAttribute.

  ADT_CompanyTypeAsChar=CLASS (AbstractStringSingleColumnAttribute,
  ISingleColumnAttributemapping)
    private
      // Usually here you would place the const struct defined in
  the implementation section, but the enum-bug…

    public
       function ColumnType (length : Integer) : String;
       procedure ValueToParameter (value : System.Object; parameter :
  IDataParameter);
       procedure StringToParameter(value : String; parameter :
  IDataParameter);
       function ColumnToValue(columnValue : System.Object) :
  System.object; override;
       function IsEqual(value, columnValue : System.Object) :
  Boolean; override;
  end;

The class AbstractStringSingleColumnAttribute is also defined in the BDS-folder,
\Source\ECO\Persistence in the Unit DefaultAttributeMappers.cs. A mapper that maps
any data type onto a string-database-value can be defined by a mapper-class derived from
this class.
In our example we mapped the type ADT_CompanyType onto Strings, and therefore defined
the class ADT_CompanyTypeAsChar.

After the mapper-class has been defined we can use it again. To do this we first set the
property PMapper for the attribute eCompanyType to ADT_PMCompanyType in the object
inspector. Then we add this new PMapper to the PersistenceMappers list (Property
SQLDatabaseConfig) of the PersistenceMapperBDP-component.

The implementation of this class proceeds exactly the same way as the one before.
In the example application [    PM1] you can find the Unit ADTStr.PAS .
The user interface of this example is kept very simple. You can add or delete files and save
your changes. The attribute sShortName can administrate and save up to 255 characters
only. The attribute sDescription can manage more.
The only entry accepted in the columns of both enumeration types are enumeration types in
the form of text. How to connect enumeration types to a list control in the user interface, you
can see in chapter 5.3.2.




                                                                                      Page 61
                        2.2 EcoSpace – Persistence and databases




A Guid (Globally Unique Identifier)-Attribute
In our next example [    PM2] we want to use a simple attribute of the Guid type.

Note:
  When using guids with SQL Server you definitely have to take the following into
  consideration:
  If you use a PersistenceMapperBDP instead of a PersistenceMapperSQL in your
  application or if you use SQL Server instead of the SQL Client, ECO-Guids aren’t mapped
  onto the SQL-file type UNIQUEIDENTIFIER, but onto a varchar(32)! This happens due
  to a bug in the BDP.

Back to our example [  PM2].
We define a class CL_Basis and therein we place an Attribute sGuid with the following
parameters.

                             Object             Attribute
                             inspector
                             Name               sGuid
                             Type               Guid
                             PMapper            <Default>
                                                or
                                                System.Guid

Since a PMapper for Guids already exists, System.Guid, we can use here the default
settings. When creating new objects we could see – unlike our AutoInc example – that the
Guid values are not provided by the DB and because of this they are „0“ by default.
Not even the entry SaveAction=DBAssign as Attribute-Property will help here.
So we have to set the Guid values explicit. At best this is done in the class constructor when
creating a new object:

  constructor CL_Basic.Create(serviceProvider: IEcoServiceProvider);
  begin
    inherited Create;
    Self.Initialize(serviceProvider);
    try
      // If you add user code here, please remove the …
      // from the declaration in the interface section

          Self.sGuid := System.Guid.NewGuid;

    except
       …
    end;
  end;

The line manually added to the class constructor is highlighted. The .NET Method NewGuid
of the Namespace System.Guid provides a Guid.
This way any instance of the class CL_Basis created newly in this application automatically
receives a Guid.




Page 62
                                   2. Modeling with ECO


2.2.7 Primary key and key attributes
The property KeyMappers of the PersistenceMapper-component offers 4 different mapping
classes for primary keys: DefaultEcoIdMapper, AutoIncKeyMapper, AttributeKeyMapper
and GuIDKeyMapper (GuID = Globally Unique Identifier).
A primary key always has to be used with one of the keymappers above.
DefaultEcoIdMapper is used by default.
In combination with a DefaultOrMappingBuilder-component one can modify the primary
key creation.


A Guid-PrimaryKey instead of the ECO_ID Integer
By default ECO uses a 32-Bit Integer (ECO_ID) as internal Primary Key for the objects saved
in the DB. This behaviour can be changed with a DefaultORMappingBuilder-component.

An example [      PM3]:
We want to replace the internal ECO_ID Key with a Guid-Key. For that we place a
DefaultOrMappingBuilder-component on the design page of the xxxEcoSpace-Unit, that
we configure as follows:

                       Object            DefaultOrMappingBuilder1
                       inspector
                       IDKeySignature System.Guid
                       IDMapperName Guid
                       IDColumnName (optional)

The reference of IDKeySignature and IDMapper to Guid ensure that ECO uses a Guid-value
as Primary Key. The column name of the Primary Key (default: ECO_ID) can optionally be
changed.
As mentioned in the example above, ECO normally wouldn’t automatically generate guid
values or have them generated by the db. But since we are talking here about the primary
key and not about a standard attribute, Eco – to be more exact – the GuidKeyMapper
creates in this case the Guid values, as a required behaviour of a keymapper.
To activate the DefaultOrMappingBuilder, we have to publish this component to the
PersistenceMapper-component.
To do this we set the following values in the PersistenceMapperBDP or
PersistenceMapperSQL:

    Object inspector                                      PersistenceMapperBDP/SQL
    NewMappingProvider                                    DefaultOrMappingBuilder1
    RuntimeMappingProvider                                DefaultOrMappingBuilder1

When we start the application and create some objects we won’t notice any changes in the
user interface compared to the former example (PM2).
The reason is that ECO_ID isn’t visible to the outside. But we can examine the table
structure with a db tool like the Enterprise Manager for SQL Server, and we’ll discover that
the ECO_ID is now defined as varchar (32) and contains a Guid.
Delphi as well offers access to the table structure of the db. Just activate the data explorer
tab in the project window and look for the DB in use.




                                                                                      Page 63
                         2.2 EcoSpace – Persistence and databases


                           In the context menu of the table entry dbo.CL_Basis we can find
                           the option open data ffrom tablle and ediit tablle , which we can
                                      open data rom tab e           ed t tab e
                           use to display format and content of the ECO_ID-Key.




A standard attribute used as a primary key
Instead of the default ECO-ID we can use our own attributes as primary key too. Within the
example [     PM4] we use a class CL_Basis with a single attribute iMyOwnPKey that
should work as a primary key.

In such a situation we normally use an AttributeKeyMapper and therefore set the property
pMapper (ORMappingBuilder) to the value attribute. The connection between the
ORMappingBuilder component and the original attribut (iMyOwnPKey) is done by the
property IdColumnName.

But in our example we want to use an AutoInc attribute again, which will get ist values
directly from the database.

To achieve this, we use the following configurations:

                 Objectinspektor Attribute iMyOwnPKey
                 Type               AutoInc
                 PMapper            AutoInc
                 SaveAction         DBAssign

                       Objectinspektor DefaultOrMappingBuilder1
                       IDColumnName       iMyOwnPKey
                       IDIsAutoInc        True
                       IDKeySignature     AutoInc
                       IDMapperName       AutoInc

              Objectinspektor                   PersistenceMapperBDP/SQL
              NewMappingProvider                DefaultOrMappingBuilder1
              RuntimeMappingProvider            DefaultOrMappingBuilder1


Note:
  Since ECO-III a DefaultORMappingBuilder component also contains two additional
  context menu items:
  AutoInc-Key and setup-Guid-Key.
  With these menu items the configuration of the components as shown above can be
  executed automatically.
  Changing the keymapper requires to regenerate the database!




Page 64
                                    2. Modeling with ECO


2.2.8 Using a PersistenceMapper Provider Unit
Other than using a PersistenceMapper-component on the Design-page of the xxxEcoSpace-
Unit, the PM of an EcoSpace can also be done with a PersistenceMapperProvider-Unit.
The structure of a PersistenceMapperProvider-Unit corresponds to that of a xxxEcoSpace-
Unit, however it doesn’t define an EcoSpace by itself, but is only in charge of pm. In this case
connection to EcoSpace has to be done manually.

The advantage of a PersistenceMapperProvider-Unit is that it can be used by several
EcoSpace-Instances; so several EcoSpaces are sharing the Mapper-Unit and thus also the
DB.

Depending if the EcoSpace instances are executed in one or more processes the following
configurations result:

All EcoSpace-Instances are within one Process:
In this case we have to place a PersistenceMapperSharer-component on the design page of
the xxxEcoSpace-Unit and configure it as follows:

 Object inspector       xxxEcoSpace-Design                PersistenceMapperSharer
 PersistenceMapper PersistenceMapperSharer
 MapperProviderType                        PersistenceMapperProvider-
                                           Unit



The EcoSpace-Instances are in different Processes:
In this case we have to place a PersistenceMapperClient-component on the design page of
the xxxEcoSpace-Unit and configure it as follows:

 Object inspector            xxxEcoSpace-Design                PersistenceMapperClient
 PersistenceMapper           PersistenceMapperClient
 URL                                                           URL       of       the
                                                               Persistence-Server

Please take into account the Method RegisterTCPServer in the PersistenceMapperProvider-
Unit when using PersistenceMapperClients!

An example for the usage of a PersistencemapperClient-component is located in chapter
4.7.2.

An example for the usage of a PersistencemapperSharer-component is located in chapter
6.1.4.




                                                                                       Page 65
                                   2. Modeling with ECO



2.3 EcoSpace – Service overview
Eco provides a lot of services that enable direct access to EcoSpace by coding. The table
below provides an overview.

Service                    Usage                                   Further information in...
StateService               Provides information about which        chapter 4.5.3
                           objects or attributes have changed
                           in EcoSpace (DirtyObjectList).
PersistenceService         Explicit loading and saving of          chapter 4.5.2, 4.5.3, 4.7.2
                           objects, synchronization of multiple
                           EcoSpaces
DirtyListService           Administers all objects that already    chapter 4.5.3
                           have their new/edited value in
                           EcoSpace but still have their old
                           value in the db
ExtentService              Subscription when adding and            chapter 2.4.3
                           deleting objects
ObjectFactoryService       Generic methods of creating objects     chapter 4.5.2
                           in EcoSpace using the UML-Type
                           system
VariableFactoryService     Creation and administration of          chapter 3.4, 4.6
                           VariableLists for IOCLService
TypeSystemService          Information of the types in the model   chapter 4.2
                           and validation of the model
OCLService,                Local      evaluation     of    OCL-    chapter 2.4, 2.6.5
OCLTypeService             expressions
OCLPsService,              Evaluation of OCL expressions on        chapter 3.3
OCLPsTypeService           the DB server
UndoService                Execute             undo/redo-action,   chapter 4.7.4, 4.8
                           transaction-handling
VersionService             administration of object versions       chapter 2.5
ActonLanguageService       Execution of EAL-Code                   chapter 3.2
ActionLa nguageTypeS
ExternalIDService          provides unique Ids for objects in chapter 6.1.4
                           EcoSpace; mainly used in ASP.NET
                           applications

Chapter 4.1 explains how to activate these services by code.
Those services are best explained with example programs. Because of this the table above
has links to the corresponding chapters.




                                                                                        Page 67
                                   2. Modeling with ECO



2.4 EcoSpace – the subscription mechanism
ECO contains a publish- and subscribe-mechanism. Changes made on objects in EcoSpace
are published and forwarded automatically to subscribers.
This mechanism is used internally by ECO, for example to valuate OCL expressions. Result
lists from an OCL expression are always updated automatically, for example from an
ExpressionHandle or a derived attribute.

Example [       Subscription1]:
We define the attributes iPrice and iQuantity in a class CL_Product. In addition we add a
derived attribute iTotal, whose value being defined by the OCL expression iQuantity *
iPrice.
As soon as we change one of the two basic attributes iPrice or iQuantity in a CL_Product-
Instance, the derived attribute iTotal of this instance is adjusted automatically due to the
internal subscription mechanism.

This subscription mechanism can also be used explicitly by coding.
To create an example we want to use the IOCL-Service provided by ECO. To evaluate any
OCL expression, the IOCL-Service-Method EvaluateAndSubscribe is used:

  s   := ’any OCL expression’
  rRet:= EcoSpace.OclService.Evaluate(NIL, s);

  or

  rRet:= EcoSpace.OclService.EvaluateAndSubscribe(NIL, s, NIL, NIL);

Depending on the OCL expression, the return value of this function can differ (Boolean,
Integer, Object, List of Objects etc.). For example if the OCL expression is a Constraint, the
return value will usually be a Boolean type.

As the name EvaluateAndSubscribe indicates, this method can not only be used to evaluate
OCL expressions. The last two parameters of the method – set in the example above as NIL
– can be used as so-called subscriber-parameters. The complete definition of the method
reads as follows:

  EvaluateAndSubscribe
     (root : iElement;
     expression : String;
     reevaluateSubscriber : ISubscriber;
     resubscribeSubscriber : ISubscriber) : IElement;


Notes:
  For the benefit of completeness it is to be said that there are 4 kinds (overloaded
  functions) of the EvaluateAndSubscribe-method. The only difference between them is the
  evaluate-parameter, the last two subscriber-parameters are always identical.
  Please note that using subscription via code requires to include the
  Borland.Eco.Subscription unit!




                                                                                      Page 68
                                     2. Modeling with ECO

The two subscriber-parameters represent the two different subscription methods,
reevaluation and re-subscription, used by ECO. So in general only one of the two subscriber-
parameters is used.


2.4.1 The Reevaluate-process
In the reevaluate process a subscription has to be assigned to those basic attributes, in
which expressions have to be recalculated when these attributes are edited.

Here another example, slightly modified from the one before [        Subscription2]:
The derived attribute iTotal no longer receives a OCL-derivative expression, instead we
define a custom way of calculating, iTotalDeriveAndSubscribe.
With this method we want to calculate the attribute value ‘by code’.

   function CL_Product.iTotalDeriveAndSubscribe(..) : system.Object;
   begin
     result := system.&Object (iPrice * iQuantity);
   end;

This implementation is sufficient to calculate the attribute value iTotal once – only when
creating the object -, but if one of the two underlying attributes, attributes iPrice or iQuantity
gets changed, it won´t be calculated a second time!

To make this happen we first have to activate the reevaluation, that ECO automatically
provided with the use of OCL based calculation, when calculating „manually“. For that we
insert the first of the two D subscriber-parameters.

   function CL_Product.iTotalDeriveAndSubscribe
   (reevaluateSubscriber,
    resubscribeSubscriber:ISubscriber) : system.Object;
   begin
     self.AsIObject.Properties['iPrice'].SubscribeToValue
   (reevaluateSubscriber);
     self.AsIObject.Properties['iQuantity'].SubscribeToValue
   (reevaluateSubscriber);
     result := system.&Object (iPrice * iQuantity);
   end;

With SubscribeToValue we register the ReevaluateSubscriber for both basic attributes. Each
change of one of the basic attributes will then lead to another call of the calculation method
above.




                                                                                         Page 69
                        2.4 EcoSpace – the subscription mechanism


2.4.2 The Resubscribe-process
The difference between the resubscribe-process and the reevaluate-process is, that the
resubscribe-process – in addition to the recalculation – will also place new subscriptions.

A modified example [        Subscription3]:
In addition to the class CL_Product above we define the class CL_Summary. An instance of
this class should contain the cumulative values of a group of CL_Product-Instances. For
example products could be combined into product groups and for each product group a sum
object could be generated.

In our example an object of the class CL_Summary should only receive a derived attribute
iSumTotal, whose value is the equivalent of the sum value of alld iTotal-values of all related
iS
CL_Product-Instances.




To fit both ways (OCL- and Code-based) into one example, we also use a
iSumTotalByCode derived attribute, that serves for the same purpose as iSumTotal – only
Code-based.

If we assign the following OCL-expression to the derived attribute iSumTotal,

  self.CL_Product.iTotal->Sum

Eco will use the required subscription automatically, in this case the ReSubscribe-process.

This means that the subsequent editing of iPrice and iQuantity in an existing association
between a CL_Product-Instance and a CL_Summary-Instance will lead to a recalculation of
iTotal and iSumTotal- just like until now.
Now in addition, in the Resubscribe-process, the corresponding subscription is also added
automatically when creating a new CL_Product-Instance and removed automatically when
deleting the CL_Product-Instance !




Page 70
                                  2. Modeling with ECO

When using a code based calculation method we have to proceed as follows:

  function CL_Summary.iSumTotalByCodeDeriveAndSubscribe
  (reevaluateSubscriber,
   resubscribeSubscriber:ISubscriber) : system.Object;
  var iSum : Real;
       i     : Integer;
  begin
    iSum := 0; i := 0;
    while (i < self.CL_Product.Count) do
       begin
         self.CL_Product.Item[i].AsIObject.Properties['iTotal'].
             SubscribeToValue(reevaluateSubscriber);
         inc (iSum, self.CL_Product.Item[i].iTotal);
         inc (i);
       end;
    self.AsIObject.Properties['CL_Product'].
          SubscribeToValue(resubscribeSubscriber);
    result := system.&Object (iSum);
  end;

With the first SubscribeToValue we register – just as before – all changes in existing
CL_Product-Instances. With the second SubscribeToValue we additionally register the
ResubscribeSubscriber (not the ReevaluateSubscriber), this not for an attribute of a
CL_Product-Instance, but for the whole group of CL_Product-Instances that are associated
with a CL_Summary-Instance. If any change within this group occurs, also when adding to or
removing instances from the group, the reevaluation is executed again.

Note:
  Furthermore this example shows, that subscriptions can also be used encapsulated. The
  method iSumTotalDeriveAndSubscribe uses the iTotal-Attribute, whose value is again
  evaluated by another DeriveAndSubscribe-Methode.

  When starting this example application, please note that you can only create a new
  CL_product object after creating or selecting a CL_summary object.




                                                                                  Page 71
                         2.4 EcoSpace – the subscription mechanism


2.4.3 Custom-made Subscriptions
Besides the possibility of accessing the subscription chain via code, like in the example
above, ECO allows you to create your own subscriptions.

There are two general ways to do this:

1. Implementing the interface ISubscriber directly, or
2. Create a new class of AdapterSubscriberBase



Implementing a ISubscriber-Interface
The ISubscriber-Interface provides the following two methods:

   function IsAlive(): Boolean;
   function Receive(sender: TObject; e: EventArgs): Boolean;

The job of the function IsAlive is to report to the subscription mechanism – on query- if the
corresponding subscriber can receive messages (meaning messages about object changes)
at all. Is Alive will return FALSE, if deactivated or if the subscriber is deleted by garbage
collection.
Receive is the designated receiver of those messages and should react in an appropriate
way to the received messages. The return value of Receive should – just as in IsAlive –
change to FALSE, when the subscribers are not supposed to receive any more messages.

Example [    Subscription4]:
We define three classes CL_Customer, CL_Order and CL_Product, like shown in the
image below.




We implement the ISubscriber in an separate Unit (MySubscriber.PAS).




Page 72
                                   2. Modeling with ECO

  unit MySubscriber;

  interface

  Uses Borland.Eco.Subscription;

  type
    IMySubscriber = Interface (ISubscriber)
    end;

     CL_MySubscriber = class (System.Object, IMySubscriber)
       private
          function IsAlive(): Boolean;
          function Receive(sender: TObject; e: EventArgs): Boolean;
     end;

  implementation

  Uses System.Windows.Forms, // because of MessageBox
       Borland.Eco.ObjectRepresentation, // ElementChangedEventArgs
       CoreClassesUnit; // access to model classes

  function CL_MySubscriber.IsAlive(): Boolean;
  begin
    result := TRUE; // replace with a cancel condition
  end;

  function CL_MySubscriber.Receive(sender: TObject; e: EventArgs):
  Boolean;
  VAR s : String;
  begin
    s := ElementChangedEventArgs(e).Element.
           AsObject.ClassType.ClassName;
    s := 'An object of class ' + s + ' has been created!';
    MessageBox.Show (s);
    result := TRUE; // replace with a cancel condition
  end;

The class CL_MySubscriber is just a utility class to host ISubscriber.
We will use an instance of this class in the WinForm.

The Receive-Function is designed in a way that it can generally be used by several callers.
For this the function analyzes the EventArgs-Parameter, which contains – in the element
field- the objects whose change lead to this message.
The Attributes ClassType.ClassName return the name of the object.

In the example above creating a new object of the class CL_Customer, CL_Order or
CL_Product should result in one message only.

In this example ISubscribers is activated with a OnClick-event of the WinForm.




                                                                                   Page 73
                        2.4 EcoSpace – the subscription mechanism


  procedure TWinForm.BtnActivate_Click(sender: System.Object;
                                       e: System.EventArgs);

  VAR MyExtentService : IExtentService;
      MySubscriber : IMySubscriber;
      aClassifier : IClassifier;
      aClass : IClass;
  begin
    // Create a subscriber
    MySubscriber := CL_MySubscriber.Create As IMySubscriber;
    MyExtentService := IExtentService (EcoSpace.
                         GetEcoService(typeof(IExtentService)));

     // access by class metadata
     aClassifier := EcoSpace.TypeSystem.
                      GetClassifierByType(typeof(CL_Customer));
     aClass := IClass (aClassifier);
     MyExtentService.SubscribeToObjectAdded(MySubscriber, aClass);

     aClassifier := EcoSpace.TypeSystem.
                      GetClassifierByType(typeof(CL_Order));
     aClass := IClass (aClassifier);
     MyExtentService.SubscribeToObjectAdded(MySubscriber, aClass);
     …

First a Subscriber-Instance is created.

ECO offers several ways of activating a subscription. In our example we use the
ExtentService, which offers two subscribing-methods: SubscribeToObjectAdded and
SubscribeToObjectDeleted.
Su

In our example, every time an object (of any class) is created, we want to receive a message
by the subscriber. Because of that we use a Subscriber for three classes.
The Method SubscribeToObjectAdded receives our Subscriber-Interface as first parameter
and the class for which the creation of a class ought to be reported, as second parameter.
In our example we register all the three classes, one after the other, with the subscriber.

If you have another look at the code of the unit MySubscriber above, you may want to
analyze EventArgs-Parameter of the receive-method even more, to be able to access the
newly created instance directly. For example like this:

  NewCustomer := CL_Customer (ElementChangedEventArgs(e).
                                Element.AsObject);

While this idea is correct in general, in the moment of the receive-call the new instance
hasn’t been initialized completely! So you can only retrieve the class of the object here.

Which other Subscription-activations do exist?




Page 74
                                   2. Modeling with ECO

The table below offers an overview:

Service / Element           Subscription                           Use
IExtentService              SubscribeToObjectAdded                 class-specific        object
                            SubscribeToObjectDeleted               creation     and      object
                                                                   deletion
EcoSpace                    SubscribeToActive                       EcoSpace
ElementHandle               SubscribeToActive                      activation/deactivation of
                                                                   the ElementHandle
IElement.                   SubscribeToValue                       changes in an object
ExpressionHandle            SubscribeToElement,                    changes in the binding-
                            SubscribeToStaticContent               context of the ECO handle
CurrencyManagerHandle       SubscribeToElement,                    changes in the binding-
                            SubscribeToStaticContent               context of the ECO handle
PropertyCollection          SubscribeToPropertyChanged             changes in the property-
                                                                   list


Notes:
  Please note that you have to include the unit Borland.Eco.Subscription here as well!

  In principle the ISubscriber-Interface can also be connected to a model class of the
  CoreClasses-Unit. To do this the interface has to be included in the class declaration of
  the corresponding class. But this interference usually messes up the automatic model-
  code-adjustment, thus „destroying“ the CoreClassesUnit!

  In the integrated help file you can read, that the second parameter (IClass) of the
  SubscribeToObjectAdded –method can be set to NIL by default, which should cause the
  subscription to react to the creation of objects in all classes. This doesn’t seem to work in
  a reliable way though.


Deriving a custom class from SubscriberAdapterBase
In addition to implementing ISubscriber directly, we can also derive a custom class from
SubscriberAdapterBase, that contains a ISubscriber-Interface by default. The example
application [  Subscription5] contains a button to activate the subscription. Each addition
of a CL_Product-Instance then causes a message, which is displayed as a screen message.

Note:
  Since SubscriberAdapterBase is a class „without accessible“ default constructor, it’s not
  possible to simply us this class within Delphi-Pascal:
  „...[error] E2253 The type 'SubscriberAdapterBase' doesn’t have an accessible default
  constructor...“
  Because of this the AdapterSubscriberBase example is coded in C#.




                                                                                      Page 75
                       2.4 EcoSpace – the subscription mechanism


  namespace MySubscription
  {
    class MySubscribingClass : object {

          private class MySubscriberAdapter:SubscriberAdapterBase {

              protected override void DoReceive(object sender,
                                  EventArgs e, object actualSubscriber) {
                // ActualSubscriber is a property of SubscriberAdapterBase
                (ActualSubscriber as MySubscribingClass).RespondToEvent();
              }
              public MySubscriberAdapter(object subscriber):
                                         base(subscriber)
              { }
          }

       private void RespondToEvent() {

          // event handling
          MessageBox.Show ("Hallo Subscription !");
       }
       // add a field for the Subscriber-Adapter.
       private MySubscriberAdapter myAdapter = null;
  }

The key method here is called DoReceive , which reacts to corresponding events just as the
Receive-method from the example before. In the code above the Event handling was
outsourced into an extra RespondToEvent-Method.

The subscription gets activated the same way as before:

  public void SubscribeToObject(IExtentService extentService,
                                IClass subscribeToClass) {

       // delete old subscription if it exists
       // Deactivate is a method of SubsciberAdapterBase.
       if(myAdapter != null)
         myAdapter.Deactivate();

       // create an instance of the private Subscriber-Adapter
       myAdapter = new MySubscriberAdapter(this);

       // place the subscription
      extentService.SubscribeToObjectAdded(myAdapter,subscribeToClass);
  }

Unlike ISubscriber, SubscriberAdapterBase provides a deactivate-method, that simplifies the
“logging off” a subscription.




Page 76
                                     2. Modeling with ECO


2.5 EcoSpace – Versioning
This chapter is about the use of so-called versioned objects.
If desired, ECO can equip objects with version management. The various object versions are
administrated in the db. The service IVersionService provides the required administrative
functions.


2.5.1 Requirements
There are two requirements for the activation of versioning:

a) General
The UseTimeStampTable and UseTimeStampColumn Property in the PersistenceMapper-
component of the application has to be set.

b) Class-specific
The Versioned-Property has to be set in the corresponding class.


2.5.2 Technical realization
Versioning of class objects is realized technically as follows:

      •    To each current class instance in a database table an infinite number of „historic“
           versions of this instance can be saved
      •    In each database table that saves versionised objects, the additional columns
           TimeStampStart, TimeStampStop and ECO_Timestamp are administrated,
           those contain the version number (Type Integer) of the historic objects,
           respectively their chronological linking.
      •    The current Object always has the TimeStampStop-value of MaxLongInt.
           However the historic versions contain an ascending value – depending on their
           „age“-, starting with 1.
      •                                                                     _
           The current object and all historic objects have the same ECO_ID, because of
           this the Primary Key of a „versioned“ table is a key combined from the ECO_ID
           and the TimeStampStart-Attribute!


2.5.3 Creating versioned objects
To demonstrate the use of „historic“ objects we can follow the example application
[   Versioned]. This application –again- consists of only one class CL_Person, with only
one attribute sFirstname:String.

In the class CL_Person the Versioned-property is set and in the PersistenceMapper-
component the UseTimeStampTable/Column-Properties are set.

First we add some new entries in the datagrid of the user interface and save those to the
database. As soon as we edit and save one of those new entries, the present version
becomes a historic entry and the changed object is added to the table as „current object“.




                                                                                      Page 77
                                  2.5 EcoSpace – Versioning


In our example application the right window displays the historic versions of the current entry
in the datagrid.




In general the following rules apply to the historic versions of an object:

      •    Historic versions are always marked as Read-only
      •    Historic versions are not loaded into EcoSpace automatically, but have to be
           loaded manually.
      •    The IVersionService-Method to load a historic version is GetVersion


2.5.4 Access to versioned objects
To get access to historic objects, ECO provides the Service IVersionService mentioned
above.

You can reach this service in two ways, either directly via EcoSpace, with

IVersionService (EcoSpace.GetEcoService(TypeOf(IVersionService)))

or via a class instance, for example oPerson : CL_Person , like this:

IVersionService (oPerson.AsIObject.ServiceProvider.
                 GetEcoService(TypeOf(IVersionService)))




Page 78
                                   2. Modeling with ECO

This service offers the following methods

Method                       Parameter                Function value
MaxSavedVersion              -                        Version number of the last update in a
                                                      class
GetVersion                   Version        number,   The versioned object with the specified
                             current object           version number that belongs to the
                                                      specified current object
CurrentVersion               -                        Version number of the current object
ElementVersion               Versioned object         Version number of the specified object
TimeForVersion               TimeStamp                Creation time of the version (DateTime)
VersionAtTime                DateTime                 Timestamp of the version
GetChangedPointCondition     Versionized object or    Returns a condition that can be used
                             object list, starting    with the method GetAllWithCondition
                             version-   and   end     (IPersistenceService), in order to find
                             version number           the different vetrsions on an object
                                                      within a specified version range.

The    use    of    the     IVersionService    is               demonstrated      in      the
TWinForm.dgPerson_CurrentCellChanged(...) process             of the example      application
[   Versioned].

Notes:
  Unfortunately the IVersionService doesn’t offer (until now) a way to find all historic
  versions of a specified object.
  After starting the program, the method MaxSavedVersion will return correct values only
  after the db gets changed/updated for the first time (UpdateDatabase). Before such a db
  change, the method always returns –1!
  Developing a versioned table with ECO also provides several other problems.




                                                                                     Page 79
                                   2. Modeling with ECO


2.6 Modelling of classes
In chapter 1.4 we created a first ECO application and modelled a first UML class diagram in
the process. Generally the class diagram contains the classes with their attributes as well as
generalisation- and associative relations.
In this chapter we will analyze the class- and generalization element of a UML class diagram
in detail.


2.6.1 An Attribute-Properties overview
When adding attributes to classes, first attribute-name and attribute-type are determined. Of
course the object inspector offers a huge number of properties for each attribute, which will
be explained below.

Base-Properties
Object inspector     Explanation
Name                 Attribute name
Alias                Optional alias-name, shown in the diagram instead of the name
Initial              Initial value when creating objects in EcoSpace
Stereotype           A further classification of the attribute type according to the UML-
                     standard, no futher usage by ECO
Visibility           Protected, private, public...
Former Names         Important for envolve database schema
Length               Attribute length (Strings only) see chapter 2.2.5
Has User code        The get/set methods of the attribute can contain user defined code, see
                     next section
IsStateAttribute     A state attribute, see chapter 2.8

PersistenceMapping-Properties
Object inspector     Explanation
Allow Null           The respective db field can be NULL
Column Name          An optional db field name differing from the attribute name
Default DB Value     Initial db value, useful to assign a value to a new attribute for existing
                     objects when evolving database
Delayed Fetch        When loading an object automatically, a „delayed fetch“ Attribute is not
                     loaded automatically. for example in Blob- or Memo-fields.
SaveAction           Freeze: a value once assigned can’t be changed afterwards; typically
                     for PrimaryKey-Attributes.
                     DBAssign: the attribute value is set by the db; usually in connection
                     with a AutoInc-Pmapper.
                     see chapter 2.2.5
Persistence          Usually derived attributes are transient, see chapter 2.2
PMapper              The mapping class assigned to the attribute, see chapter 2.2.5




                                                                                      Page 81
                                  2.6 Modelling of classes


Derivation-Properties
Object inspector    Explanation
Derived             Definition of a derived attributes, see chapter 2.6.4
Derivation OCL      The OCL expression that defines the value of the derived attribute, see
                    chapter 2.6.4
Derived Settable    Setting back of a recalculated value to the initial attributes, see chapter
                    2.6.4

In general we have to keep in mind that only the following types can be used as class
attributes:

     •    Simple types: integer, real numbers, characters, boolean, enumeration types
     •    Strings
     •    Array of simple types or strings


Attribute get/set-methods and UserCode
To each class attribute set/get-methods are assigned automatically. ECO enables the
addition of user-defined source code to these get/set-methods. The default attribute entry in
the source code (Package_1Unit) and its get/set-method are replaced with an entry of the
same name with new get/set-methods that can contain UserCode. The default property is
renamed (underscore-prefix) and moved to the protected part of the unit.

An attribute sLastName : String, where Has user code is false can be displayed with the
following source code:

  // within the public section

  function get_sLastName: string;
  procedure set_sLastName(Value: string);
  [UmlElement(Id='cd2bb46…', Index=Eco_LoopbackIndices.sLastName)]
  property sLastName: string read get_sLastName write set_sLastName;

An Attribute sLastName : String, where Has user code is true can be displayed with the
following source code:

  // within the strict protected section

  function get__sLastName: string;
  procedure set__sLastName(Value: string);
  property _sLastName: string read get__sLastName
                              write set__sLastName;

  // within the public section

  function get_sLastName: string;
  procedure set_sLastName(Value: string);
  [UmlElement(Id='cd2bb46e…', Index=Eco_LoopbackIndices.sLastName)]
  property sLastName: string read get_sLastName write set_sLastName;

In this case the implementation part of the get/set-methods contains a note for implementing
UserCode.




Page 82
                                   2. Modeling with ECO

                                                                        _
As we can see, only the get/set-methods of the default attribute entry (_sLastName) are
called by default.

  function CL_Customer.get_sLastName: string;
  begin
    // user code
    Result := Self._sLastName;
  end;

  procedure CL_Customer.set_sLastName(Value: string);
  begin
    // user code
    Self._sLastName := Value;
    // user code
  end;



2.6.2 An overview of the class properties
Every class has various properties available, which can be divided the following:

Basic Properties
Object inspector                Explanation
Name                            Class name
Alias                           Optional Alias-Name
DefaultStringRepresentation     An OCL expression that defines the function value of the
                                OCL-Operation Name.AsString
Abstract                        An abstract class doesn´t have any instances (objects)
Sealed                          A class can’t be expanded by inheritance
interfaces                      Here the object interfaces that the class should implement in
                                addition to ILoopBack are listed
Stereotype                      A more detailed classification of the class type according to
                                UML-Standard, for example Container, Entity, Factory,
                                Interface, Metaclass...
Filename                        The complete class name (read-only)
Namespace                       The complete Namespace of the class (read-only)
FormerNames                     Important for envolve database schema
Versioned                       Activate version management

PersistenceMapping-Properties
Object inspector                Explanation
Persistence                     Classes that are not be saved in the database are transient
Optimistic Locking              Activate optimistic locking, see chapter 4.7.3
TableMapping                    Own: saving class instances (objects) in an extra table
                                Parent: saving in the table of the parent class
                                Child: saving in the table of the child class
Table Name                      Name of db table (optional)




                                                                                     Page 83
                                   2.6 Modelling of classes


Constraints/dependency-Properties
Object inspector                Explanation
Constraints                     Define list of class constraints, see chapter 2.6.5
GenerateDefaultRegion           Activate dependency regions between the class attributes,
                                see chapter 2.9
Derivation Expressions          Are used to get “virtual” derivation of derived attributes or
                                association-ends in OCL.


2.6.3 Meta-Attributes and TaggedValues

Meta-Attributes
In .Net classes, attributes and methods can be equipped with so-called Meta-Attributes. In
the source code Meta-Attributes are placed in front of the element that is to be marked, in the
form [Meta-Attribute-identifier]. Those Meta-Attributes can be queried at runtime.

ECO also uses Meta-Attributes, predominantly in the CoreClasses-Units. Typical Meta-
attributes are  for    example     [UmlElement],       [UmlMetaAttribute]         or
[UmlCollection].

Usually Meta-Attributes serve to define additional properties of model elements. For certain
model elements though, for example constraints, the meta attribute represents the complete
definition of the element.

  [UmlMetaAttribute('constraint', 'MyConstraint=sLastName<>''''')]

ECO     classifies the   Meta        attributes,   which      it   defines   in   NameSpace
Borland.Eco.UmlCodeAttributes.

     •    UmlMetaAttributeAttribute
     •    UmlElementAttribute
     •    InnerLinkAttribute
     •    LinkRoleAttribute
     •    UmlTaggedValueAttribute
     •    StateMachineAttribute
     •    UmlCollectionAttribute
     •    EcoSpaceAttribute
     •    EcoSpacePackageAttribute
     •    EcoAutoGeneratedAttribute
     •    EcoAutoMaintainedAttribute
     •    EcoCodeGenVersionAttribute

Some examples below.

  // Defines the property „derived” for the class attribute iNo
  [UmlTaggedValue('derived', 'False')]
  Property iNo: Integer read…

  // Defines the property „Multiplicity” für an association end
  [UmlMetaAttribute('multiplicity', '0..*')]




Page 84
                                   2. Modeling with ECO

We can also define our own meta attributes, and either choose their names by ourselves or
use an attribute type predefined by ECO.
The rules for adding our own meta attribute in the source code are identical for all attribute
types. The difference between the attribute types is how these values can be read at runtime.
ECO offers extra ways of access for its special attribute types.

Ways of accessing the various meta-attribute-types
  Meta-Attribute             Reading methods                      Example
  All Meta-Attributes      .NET Reflection                        see chapter 4.2.3
  UmlTaggedValues          TaggedValue-Property                   see chapter 4.2.2
                           of the TypeSystemService
  UmlMetaAttribute       – Constraint-Property                    see chapter 4.2.2
  Constraints              of the TypeSystemService
  UmlMetaAttribute       – Feature-Property                       see chapter 4.2.3
  Assoziationen            of the TypeSystemService


TaggedValues
The group UmlTaggedValues is a subgroup of TaggedValues.
ECO administers most properties of model elements as TaggedValues. TaggedValues are
organized hierarchically, which means they exist on the highest Model level (EcoModelRoot)
as well as on class- and attribute-level.

Example for properties that are saved as tagged values
          Model level           Properties
          EcoModelRoot          GenerateMultiplicityConstraint,
                                OptimisticLocking, RegionDefinitions…
          classes               TableName, TableMapping,
                                DefaultStringRepresentation, Versioned...
          class attributes      Length, ColumnName,DelayedFetch,
                                DefaultDBValue...

For classes the IDE supports the entry of so called derivation expressions (see chapter
2.6.2) in the form of TaggedValues

  // a user defined derivation expression “Test“ for a class
  [UmlTaggedValue
    ('Eco.DerivationExpressions', 'Test=self.sFirstName=''Jan ''')]

The contents of TaggedValues in the various model levels can be queried at runtime. For
details have a look at chapter 4.2.2.




                                                                                      Page 85
                                    2.6 Modelling of classes


2.6.4 Derived attributes
Besides the standard class attributes ECO also supports the so-called derived attributes.
These are attributes that are not saved in the database and whose value results from a
calculation.

There are two ways of calculating values:
     •    calculation by OCL-expression
     •    calculation by function (Coding)

The typical property settings for both kinds of derived attributes are:

 Objectinspektor      Derived attribute by OCL-                 Derived attribute by Coding
                      expression
 Derived              TRUE                                      TRUE
 DerivationOCL        valid OCL expression                      field has to be empty
 DerivedSettable      no                                        Optional
 Persistence          usually transient                         usually transient

Both ways will be explained with an example.


An example of derived attributes with OCL-expression
[  DerivedAttribute1]
We define two classes, CL_Product and CL_ProductType, which are connected to each
other by a 1:n.




The class CL_ProductType contains only the attribute sName, the class CL_Product
contains the standard attributes sName, iPrice and iQuantity as well as the derived
attributes iTotal and sMyType.
If you add both derived attributes of the class CL_Product and configure them in the object
inspector according to the table above, you will notice that ECO puts a “/“ symbol in front of
the name of each derived attribute. This „/“ Symbol is part of the UML-specification.

                                            D
We still have to define the OCL expression (DerivationOCL) for both derived attributes:

   Object              /iTotal                                    /sMyType
   inspector
   DerivationOCL       Self.iQuantity * self.iPrice               Self.HasType.sName

/iTotal calculates the value of a product (quantity multiplicated with price), /sMyType returns
the product to the class CL_ProductType via navigation over the association end HasType .




Page 86
                                   2. Modeling with ECO

With each change of quantity and/or price of a product, the total price gets recalculated. ECO
takes care of re-evaluation of the OCL expressions. More information about the underlying
subscription mechanism you will find in chapter 2.4.

For the attribute sMyType it applies that, each time a link between a CL_Product-Instance
and a CL_Producttype-Instance is created or removed, or the afterwards change of the
attribute sName in a linked CL_ProductType-Instance is edited, the value of the sMyType
gets changed automatically.

Of course both derived attributes are read-only , that means their value is determined by
automatic evaluation only. So when we run the example application [         DerivedAttribute1],
we will see that we can edit the iPrice and iQuantity, but not sMyType or iTotal.
Besides you can recognize the „Read-only“ setting by the fact that the otherwise usual
method set_xxx is missing in the source code of both attributes of the unit CoreClasses.PAS.

Note:
  In this example the prefix self is obsolete, but it improves distinctiveness in more complex
  OCL expressions, thus avoiding equivocal OCL-expressions.
  Self indicates the starting point of the OCL-navigation, in our example an instance of the
  class CL_Product.


An example of derived attributes with function value
[  DerivedAttribute2]
Starting from the example before, we add the attribute iDiscount to the class
CL_ProductType and add the derived attribute iDiscountPrice to the class CL_Product .
This way we add a product-type-specific discount (percentage), that leads to a reduced total
price of the product.
IDiscountPrice is declared as derived and transient with the object inspector. The
Property DerivationOCL is left empty on purpose.
To assign a value to this attribute, we have to define an appropriate class method in the unit
CoreClasses.PAS. To do this we add the method iDiscountPriceDeriveAndSubscribe to the
class CL_ProductType in the context .
For code-based derived attributes the name of the evaluation method always consists of the
attribute name and the fix string „DeriveAndSubscribe“.
In our example this results in iDiscountPriceDeriveAndSubscribe.




The definition of the method is not complete yet. For a DeriveAndSubscribe-method the
calculated attribute value always has to be defined as a return value of the type
System.&Object, besides the following parameter values are required.

  (reevaluateSubscriber, resubscribeSubscriber:ISubscriber)




                                                                                      Page 87
                                   2.6 Modelling of classes


The Parameter reevaluateSubscriber provides a subscription method that has to be
assigned to those attributes, whose value is based on the calculation of the derived attribute.
This makes sure that each change of the calculation-base automatically leads to a
recalculation of the derived attribute. In contrast to the OCL expression method, we have to
explicitly activate here the automatic reevaluation.

Back to our example. The complete definition of the method is

   Function CL_Product.iDiscountPriceDeriveAndSubscribe
   (reevaluateSubscriber,
   resubscribeSubscriber:ISubscriber):System.&Object

You can complete these method definitions either on the CoreClasses-Diagram page in the
object inspector or directly in the source code of the Unit CoreClasses.PAS. It’s definitely
easier to edit in the source code editor.
But adding a class method on the CoreClasses-Diagram page with the context menu has the
advantage that both, the method interface and the implementation frame are already set in
the source code.

But now to the implementation part of our function.

   function CL_Product.iDiscountPriceDeriveAndSubscribe
   (reevaluateSubscriber,
    resubscribeSubscriber:ISubscriber) : system.Object;

   var iRet : Double;
   begin
     try
        AsIObject.Properties['iTotal'].SubscribeToValue
   (reevaluateSubscriber);
        IF Assigned (self.HasType) THEN
           BEGIN
             self.HasType.AsIObject.Properties['iDiscount'].
   SubscribeToValue(reevaluateSubscriber);
             iRet := (1 - self.HasType.iDiscount) * self.iTotal;
           END
        ELSE
           iRet := 0;
        result := system.&Object (iRet);
     except
        result := system.object (0);
     end;
   end;

Some explanations:
For the calculation and returning of the attribute value we only need the following lines

   iRet := (1 - self.HasType.iDiscount) * self.iTotal;
   …
   result := system.&Object (iRet);

Discount indicates the discount in percentage, so 1 - Discount is the price factor that is still
to pay. The reduced price results from the multiplication of price factor and gross price.




Page 88
                                   2. Modeling with ECO

The fact that iTotal itself only is a derived attribute, whose value is calculated by OCL
expression, is of no importance here. Cascading evaluation is possible in ECO without any
constraints.
The following lines are required to ensure that this DeriveAndSubscribe-Methode can be
executed at each change of one of the both underlying attributes.

  AsIObject.Properties['iTotal'].SubscribeToValue
  (reevaluateSubscriber);
  self.HasType.AsIObject.Properties['iDiscount'].
  SubscribeToValue(reevaluateSubscriber);

With this we assign the reevaluateSubscriber-method, that is provided via function
parameters, to both attributes iTotal and iDiscount.
Since iDiscount is not located in the instance of our starting class (CL_Product), but in the
associated CL_ProductType-Instance, we have to navigate to the association-end again.
The self-prefix is obsolete here as well, but it improves the readability.

Note:
  The access to class attributes in the AsIObject.Properties[’...’] allows three
  ways of indexing, via attribute name – like in the example above -, via attribute index
  (0,1,2...) and via structural feature.
  Access by index is possible since, as shown in chapter 1.4.3, each class attribute receives
  a distinct index.
  Identification of an attribute via structural feature is done rather rarely.

The security check is here absolutely necessary

  IF Assigned (self.HasType) THEN

The reduced price can’t be calculated without entering the discount in percent, and we can’t
guarantee that a CL_Product-Instance really gets linked to a CL_ProductType-Instance
every time. Since our DeriveAndSubscribe-Method already gets called when a new product
gets created, and at that moment a link to a product type surely doesn’t exist in our example
application!

As soon as you create new instances of the class CL_Product, link these to instances of the
class CL_ProductType and set the default attributes iPrice, iQuantity and iDiscount, the
derived attributes iTotal and iDiscountPrice are updated automatically.




Here – just like in the example before – the derived attribute iDiscountPrice should be read-
only, meaning that the field can’t be edited in the data grid; the set_xxx Method is missing in
the Unit CoreClasses.PAS as well.




                                                                                      Page 89
                                   2.6 Modelling of classes


An example of a reverse derived attribute [                    DerivedAttribute3]
In the third example of this chapter we want to have a look at another variation of this topic.
As mentioned in the two examples before, derived attributes are read-only by default.
However ECO offers a way of diverging from this setting.
To do this we have to activate the Attribute Property Derived Settable, which hasn’t been
used so far.
As soon as you set this property to TRUE for a derived attribute, ECO automatically adds a
set_xxx Method to the CoreClasses-Unit.

The example application [     DerivedAttribute3] demonstrates a possible use for this.
Starting from the last example, we add two standard attributes, iFinalDiscount : Double and
bManually : Boolean to the class CL_Product.




iFinalDiscount is supposed to display the final discount granted for a product.
This final discount can be calculated with the following function.

  iFinalDiscount := (iTotal – iDiscountPrice) / iTotal.

At first iFinalDiscount can’t offer many improvements, since the same discount is already
contained in the associated object CL_ProductType as iDiscount.
But we will go one step further. We set the property Derived Settable of our attribute
iDiscountPrice to TRUE and add an additional Textfield iFinalPrice and a button named
SetFinalPrice to our WinForm interface.

The desired result is this:
So far each product automatically receives its total price (iTotal) as soon as price and
quantity are entered or edited, and it receives its discounted price (iDiscountPrice), if the
product is linked to a product type with valid discount rate.
Now we want to enable the seller to change the calculated discounted price manually, for
example to meet a certain price limit. For example he could change the calculated price of
4025,80 to 3999,- manually.
This results to a discount rate that differs from the default rate. Our new attribute
iFinalDiscount is supposed to display this rate.
To make this manual correction valid permanently, we have to add a flag to those products
whose final price has been changed manually. For this we use the attribute bManually.




Page 90
                                     2. Modeling with ECO

With all these additions our winform interface will look like this:




The source code is affected by these changes in 3 areas.
To set iDiscountPrice manually we defined the following OnClick-Event for the button
SetDiscountPrice in the Unit WinForm.


   procedure TWinForm.BtnSetDiscountPrice_Click(sender:
   System.Object; e: System.EventArgs);
   var oProduct : CL_Product;
        iP         : Double;
        iOk        : Integer;
   begin
     try
        if (Assigned (cmhProduct.Element.AsObject)) and
            (cmhProduct.Element.AsObject Is CL_Product) then
           begin
             oProduct := CL_Product (cmhProduct.Element.AsObject);
             val (TBDiscountPrice.Text, iP, iOk);
             IF ((iP >= 0) and (iOk = 0)) then
                 oProduct.set_iDiscountPrice (iP);
           end;
     except
        …
     end;
   end;

First we check if any product is existing and selected. Then we reset the price for this
product, which we get from the text field, via set_iDiscountPrice.

This leads us straight to the second code editing.
We updated the method set_iDiscountPrice , that is created automatically by ECO because
of the activated derivedSettable-Flag, as follows.




                                                                                Page 91
                                  2.6 Modelling of classes


  procedure CL_Product.set_iDiscountPrice(Value: System.Double);
  begin
    // If you add user code here, please remove the
    // [EcoAutoMaintained] attribute
    // from the property declaration in the interface section
    Self.bManually := TRUE;
    IF (iTotal > 0) then
        Self.iFinalDiscount := (iTotal - value) / iTotal;
  end;

Each manual setting of the price has to activate the flag bManually automatically. After that
we calculate the real discount rate with iFinalDiscount.
Now we should set the attribute iDiscountPrice as well, but this isn’t possible, since
                                                   r
iDiscountPrice is a derived attribute and thus is „read-only“.
So how can we set this value?
Have a look at the adjusted DeriveAndSubscribe- method in the next code section.

  function CL_Product.iDiscountPriceDeriveAndSubscribe
  (reEvaluateSubscriber,
  reSubscribeSubscriber : ISubScriber): system.object;

  var iRet : Double;
  begin
    try
       AsIObject.Properties.Item['bManually'].
         SubscribeToValue(reEvaluateSubscriber);
       IF self.bManually THEN
          begin
            AsIObject.Properties.Item['iFinalDiscount'].
               SubscribeToValue(reEvaluateSubscriber);
            iRet := iTotal * (1 - self.iFinalDiscount);
          end
       else
          begin
            AsIObject.Properties.Item['iTotal'].
               SubscribeToValue(reEvaluateSubscriber);
            if ASSIGNED (self.HasType) then
                begin
                  self.Hastype.AsIObject.Properties.
                     Item['iDiscountRate'].
                       SubscribeToValue(reEvaluateSubscriber);
                  iRet := iTotal * (1 - self.HasType.iDiscountRate);
                end;
          end;
       result := system.&Object (iRet);
    except
       …
    end;
  end;

Now iDiscoutPrice gets recalculated depending on the value of the flag bManually, either
as until now by using iDiscountRate or if bManually is set, using the iFinalDiscount
discount rate.




Page 92
                                   2. Modeling with ECO

With that the calling of the method set_iDiscountPrice didn´t result in the direct changing of
the attribute, it only adjusted the discount rate.
To change the attribute iDiscountPrice itself, we have to go the long way, meaning the
automatic recalculation.

Summary:
  ECO supports class modeling not only with the UML class designer but also by providing
  EcoSpace-Services and other methods like the subscription mechanism.
  The behavior of objects can be controlled with a large number of class- and attribute-
  properties.
  OCL expression, coding or both simultaneously can be used to calculate values of derived
  attributes. The subscription mechanism, either fully automatic or activated by coding,
  takes care of the required re-calculation.

  But using code based derived attributes also has a side effect.
  In OCL-expressions derived attributes of a class can be accessed, but not class methods.
  OCL is defined as language without side effects according to the OMG definition.
  But if you use a code-based derived attribute in an OCL-expression, this broadens the
  possible uses of OCL in ECO; although side effects now cannot be excluded when
  executing the code!!!



2.6.5 Constraints

Definition
Constraints (assurances, constraints) are a vital part of UML class models. They enhance
object properties by rules, which for example constrain the range of values of attributes or
define pre- and post conditions for executing methods etc.

Examples of „common“ constraints are
    •    An abstract class doesn’t have any instances
    •    Before executing a job all partial stages have to be planned
    •    A room can only be occupied by one guest

In UML diagrams constraints can be defined in natural language or formally, for example with
an OCL statement. From here on only the later way, constraints in the form of OCL
expressions, is significant.
ECO provides the class property Constraints in form of a collection for the display of
constraints.
Each constraint consists of a user–defined identifier and the so-called Body. The Body itself
consists of the attribute Body.Language, which only allows the entry „OCL“ in the current
ECO version, and the attribute Body.Body, containing the real constraint-expression in form
of an OCL statement.




                                                                                      Page 93
                                     2.6 Modelling of classes




The rules for this Constraint-Collection-Property are:

      •    Entries can only be set with the object inspector or explicitly in the code (Unit
           CoreClasses).
      •    Constraints are a part of the model – they get placed in the source code as UML
           meta attributes - , but they are not saved in the db.
      •    A „read-only“ to the Constraint-Collection via Code is possible.
      •    An automatic analysis of constraints by ECO is not provided.
      •    But a syntactic check of constraint expressions, as well as a check if class
           attributes are used correctly within the expressions, already takes place during
           development when validating the model (see chapter 2.2.3).
      •    To some model elements (associations) ECO automatically adds constraint entries
           to the collection. Those entries can be queried by code, but are not visible in the
           object inspector (see chapter 2.7.2).

All in all the support of constraints by ECO is rather basic. Besides an automatic provided
container (in the form of constraint collection), which oneself can define,(with little effort), all
other steps towards a full constraints support have to be taken manually, like for example
saving constraints in a db or evaluating constraint statements.

So the example application of this chapter [       Constraints] mainly is about creating some
form of generic constraint support for any class. Luckily this can be done with little effort.

But first some general details of the property Constraints, which each class is automatically
provided with by ECO.




Page 94
                                    2. Modeling with ECO



Access to Constraints-Elements of a class
In the Unit CoreClasses access to a Constraint-Collection of a class xxx with a class method
can be reached the following way:

   function xxx.GetConstraintText (sConstraintName : String): String;
   var oConstraint : IConstraint;
   begin
     oConstraint := self.AsIObject.UmlClass.Constraints.
                      GetItemByName(sConstraintName);
     if (Assigned (oConstraint)) then
      result := oConstraint.Body.Body;
   …

This function returns the constraint expression based on the constraint name. Here Self
represents the class instance.

If for example we want to iterate all constraints within a class to the constraints collection of
this class, we can use the following code:

   i := self.AsIObject.UmlClass.Constraints.Count;
   while (i > 0) DO
     begin
       sName :=
   self.AsIObject.UmlClass.Constraints.Item[PRED(i)].Name;
       sLanguage :=
   self.AsIObject.UmlClass.Constraints.Item[PRED(i)].Body.Languange;
       sBody :=
   self.AsIObject.UmlClass.Constraints.Item[PRED(i)].Body.Body;

        IF (sName <> '') and
           (sLanguage = 'OCL') and
           (sBody <> '') then
           …
        DEC (i);
        …


Note:
  The ECO-internal Constraints-Collection isn’t organized very well.
  That means for example if you add new constraint elements with the object inspector and
  later delete some elements, there will be „gaps“ in the collection, those are the constraints
  that have been deleted. In this case the parameter Collection-Count displays more entries
  than really exist.
  So in the example above we check – before processing further – if each constraint
  element of the collection is valid.




                                                                                        Page 95
                                   2.6 Modelling of classes




Evaluating Constraint-expressions
As you can see, we can access the model elements of our class model at runtime with the
namespace UmlClass.
To evaluate a constraint expression we use the IOCLService, which is part of ECO-Services.
IOCLService provides the method EvaluateAndSubscribe, with which any OCL statement
can be evaluated, of course also our constraint expressions.

  function xxx.IsConstraintOk (sConstraintName : String): Boolean;
  VAR bOk            : Boolean;
      s              : String;
      MyOCLService : IOCLService;
      rReturn        : iElement;
      oConstraint : IConstraint;
  begin
    oConstraint := self.AsIObject.UmlClass.Constraints.
                       GetItemByName(sConstraintName);
    if (Assigned (oConstraint)) then s := oConstraint.Body.Body;
    if (s <> '') then
        begin
          MyOCLService := &self.AsIObject.ServiceProvider.
                   GetEcoService(typeof(IOclService)) as IOCLService;
          rReturn := MyOCLService.EvaluateAndSubscribe
                   (self.AsIObject.CloneValue(TRUE), s, NIL, NIL);
          if (rReturn.AsObject.GetType.Name = 'Boolean') then
              bOk := Boolean (rReturn.AsObject)
          else
              bOK := FALSE;
        end;
    result := bOk;
    …

In this example the function IsConstraintOk returns the evaluation result of a constraint
element, whose name was sent to the function.
The return value of EvaluateAndSubscribe can be – as is usual for OCL expression- of
various natures, starting from simple boolean up to complex object lists. In our case the
analysis of our constraint statement has to return a boolean return value. If this is the case,
we can proceed with the return value otherwise IsConstraintOk shall return FALSE.

Notes:
  If –unlike the example above- the nature of the return-values is not specified when using
  the EvaluateAndSubscribe-Method, it is wise to use rReturn : iElementCollection
  instead of rReturn : iElement.
  If the return value consists of only one object (rReturn.Count = 1), this object can be
  accessed with rReturn.Item[0].

  In ECO II the method Evaluate can also be used instead of EvaluateAndSubscribe. This
  method doesn’t require Subscription-Parameters.

Since there are many possible uses of the EvaluateAndSubscribe-Method, a lot of
overloaded methods with different parameter settings exist.
In the case of constraint evaluation we need the version with the parameters below.



Page 96
                                   2. Modeling with ECO

  function EvaluateAndSubscribe
    (root: IElement, expression: String,
     reevaluateSubscriber : ISubscriber,
     resubscribeSubscriber: ISubscriber): IElement;

We only need the first two parameters from the code above, since we just want to evaluate
an OCL expression without using a subscription mechanism (see chapter 2.4).

The first parameter root is the starting point of the OCL expression.
                                                                                   s
If the call for the method comes from a class-method, the current class instance (self) is the
starting point. But since we don’t need the instance itself, but the IElement assigned to this
instance, the version self.AsIObject is necessary here (more on IElement and other
EcoSpace-Interna in chapter 4.1).
When calling EvaluateAndSubscribe outside of a class, for example with an OnClick-Event
in the Unit WinForm, the value NIL is passed as root parameter. To access the model
elements via the global EcoSpace-Object we use the ECO service TypeSystemService. In
this case typical accesses to constraints in the class xxx look like this.

  //Anzahl der Constraints-Elemente ermitteln
  i := EcoSpace.TypeSystemService.TypeSystem.
         AllClasses[xxx].Constraints.Count

  //Ein Constraint-Element aus der Collection laden
  oConstraint := EcoSpace.TypeSystemService.TypeSystem.
                   AllClasses[xxx].Constraints.Item[x]

  //Den Constraint-Ausdruck s evaluieren
  rRet:= EcoSpace.OclService.EvaluateAndSubscribe(NIL, s, NIL, NIL);

The second parameter of the EvaluateAndSubscribe-Method is our Constraint expression
itself. In this case the third and fourth parameter is set to NIL.




                                                                                      Page 97
                                  2.6 Modelling of classes




A Constraint example application [                  Constraints]
Now follows a more complex constraint example, in which we will use the
DeriveAndSubscribe-Method (see chapter 2.6.4) in addition to handling constraints.
In this case we defined an abstract class CL_Base, that is supposed to provide us with a
basic constraint management that will be used on the basis of derived classes as an
example.




On the one hand the base class exports the method IsConstraintOk. Only the name of the
constraint that is to be evaluated has to be passed to this function, and then it returns the
check result.
Besides that CL_Base provides the derived attribute bConstraintsOk. With this attribute the
current status of all constraints of a derived class can be called, with the help of the ECO
subscription mechanism (DeriveAndSubscribe-Method), that we already know from chapter
2.4.
To get this result it is required that each derived class implements a reevaluation method, in
order to forward the subscription (message) to the class-specific attributes on which the
evaluation is based.

We derived the abstract class CL_Person from the class CL_Base , which is also abstract.
This class implements only two attributes: sFirstName and iAge.
Here the ReEvaluation-Method doesn’t have its own code – just like in the class CL_Base.
For adults and childs one class each has been derived from CL_Person. A further
subdivision into drivers licence owners is possible for adult persons.




Page 98
                                    2. Modeling with ECO

Each of the three non-abstract classes defines a constraint in its constraint collection.

 Objektinspector CL_Child                CL_Adult              CL_Driver
 Constraint-Name CheckChildAge CheckAdultAge                   CheckDriverLicence
 Constraint-     Self.iAge<=17 Self.iAge>=18                   Self.bDriverLizenz=true
 Ausdruck

This leads to a SubscribeToValue-call in the corresponding reevaluation method of a class
for the following attributes:

 Classenattribute CL_Child              CL_Adult               CL_Driver
 iAge                Yes                Yes                    Yes
 bDriverLicence      No                 No                     Yes

The implementation of the method IsConstraintOk is very simple and basically is the same
as the code section from the Evaluating Constraint expressions section above.
The realization of the DerviveAndSubscribe-Method for the attribute bConstraintsOk a little
more complex.




                                                                                            Page 99
                                   2.6 Modelling of classes


   function CL_Base.bConstraintsOkDeriveAndSubscribe
                (reevaluateSubscriber,
                 resubscribeSubscriber:ISubscriber) : system.Object;
   VAR bOk                 : Boolean;
        s                  : String;
        sColConstraint : ADT_ConstraintCol;
        MyOCLService       : IOCLService;
        rColReturn         : IElementCollection;
        aObjList           : IObjectList;
        i                  : Integer;
   begin
     ReEvaluation(reevaluateSubscriber);
     i := self.AsIObject.UmlClass.Constraints.Count;
     bOk := (i = 0); // no constraints? -> everything is fine!
     if (NOT bOK) then
          begin
            bOk := TRUE;
            MyOCLService := &self.AsIObject.ServiceProvider.
               GetEcoService(typeof(IOclService)) as IOCLService;
            while (i > 0) DO
               begin
                 s := GetConstraintTextAt (i);
                 rColReturn := MyOCLService.EvaluateAndSubscribe
                          (self.AsIObject, s, NIL, NIL).GetAsCollection;
                 if (rColReturn.Count = 1) THEN
                     begin // exact one result
                       if (rColReturn.Item[0].AsObject.GetType.Name =
                             'Boolean') THEN // and result is Boolean
                           bOk := Boolean (rColReturn.Item[0].AsObject)
                       else
                           bOK := FALSE; // only boolean expressions !
                     end;
                 if (NOT bOK) then BREAK; // That’s it....
                 dec (i);
               end;
          end;
     if (not bOk) then self.AsIObject.Delete;
     result := system.&Object (bOk);
   end;

First the reevaluation method of the current class is called, in order to make sure that the
constraint expression gets reevaluated when subsequently editing an attribute that is
required for the evaluation of a constraint.

Then the number of entries in the constraints collection of the class is detected. If there are
no constraints, the total evaluation is completed successfully.

In the other case an OCL Service is provided and iterated over all constraint entries.
The method GetConstraintTextAt, implemented in CL_Base, provides the constraint
expression of the i-th element, taking into account possible „empty entries“ in the constraint
collection (see the note in the section „accessing Constraint-Elements of a class“ above).
The constraint expression is evaluated and the evaluation result is analyzed.
If the check of one of the constraint expression leads to a negative result, the total evaluation
is not successful.




Page 100
                                   2. Modeling with ECO

Before the returning of the result the current instance of the class is deleted if the total
evaluation fails. You will see soon why we take this rather harsh action here.

Here it is very important, that the evaluation of the Constraints- property of a class takes
always into account the constraints of the higher classes.
In our example this means, that the evaluation of the constraints collection of the class
CL_Driver also includes the constraint expression CheckAdultAge of the class CL_Adult.
Because of this the constraint element CheckDriverAge is sufficient for the class CL_Driver !
But for subscriptions by relevant attributes the SubscribeToValue call has still to be set for
those relevant attributes. In our example this means, that the reevaluation method of the
class CL_Driver needs two SubscribeToValue-calls.

  function CL_Driver.ReEvaluation
             (reevaluateSubscriber:ISubscriber) : BOOLEAN;
  begin
    self.AsIObject.Properties['iAge'].
       SubscribeToValue(reevaluateSubscriber);
    self.AsIObject.Properties['bDriverLicence'].
       SubscribeToValue(reevaluateSubscriber);
  end;

To complete our example application we implement the user interface now.




With the OnClick-Method of the Button AddPerson new persons can be added, whose age
and driver´s licence status are taken over from the input fields.
AddPerson tries to find the class that matches the input parameters by constraint evaluation
of the various classes.




                                                                                    Page 101
                                  2.6 Modelling of classes


  procedure TWinForm.BtnAddPerson_Click(…);
  var oAdult : CL_Adult;
      oDriver : CL_Driver;
      oChild : CL_Child;
      i, iOk : INTEGER;
  begin
    val (TBAge.Text, i, iOk);
    if ((iOk <> 0) OR (i < 0) OR (i > 1000)) then EXIT;

     oDriver := CL_Driver.Create (EcoSpace);
     oDriver.iAge := i;
     oDriver.bDriverLicence := cbDriverLicence.Checked;
     if oDriver.bConstraintsOk then EXIT;

     oAdult := CL_Adult.Create (EcoSpace);
     oAdult.iAge := i;
     oAdult.bDriverLicence := FALSE;
     if oAdult.bConstraintsOk then EXIT;

     oChild := CL_Child.Create (EcoSpace);
     oChild.iAge := i;
     if oChild.bConstraintsOk then EXIT;

    MessageBox.Show ('The parameters are invalid!');
  end;

If the function bConstraintsOk of a possibly matching class returns TRUE, the total process
is completed successfully, if not the search is continued with the next class.
Here you can see why we need the self.AsIObject.Delete call in the method
bConstraintsOk. This is how we make sure that an object, that may be created prematurely
and then doesn’t fit, gets deleted from EcoSpace.

Beside that we wanted to test the reevaluation ability by subscription with this example.
To do this you only have to start the application, enter some persons and then change a
subscribe parameter, meaning iAge or bDriverLicence, in the datagrid. If this change results
in the person not belonging to the class anymore, this person automatically gets removed
from the corresponding datagrid.




Page 102
                                    2. Modeling with ECO


2.6.6 Operations and Triggers
The following methods can be assigned to a class
          • Constructors
          • Operations
          • Triggers

Unlike to constructors, operations and triggers contain additional properties that can be set in
the object inspector.

Property         Explanation
body             An action language expression that is executed when the method is called.
precondition     A boolean OCL expression that has to be fulfilled in order to execute the
                 method.
Is Trigger       Marks the method as a triger method
IsQuery          Marks the method as query method, meaning a non-object-changing-
                 method.

With the ECO Action Language (EAL) class methods can be defined that contain an EAL
            b
expression (body) instead of code (see chapter 3.2).

Trigger-Methods are used as triger-operations for state transitions in state diagrams (see
chapter 2.8.2).

The property IsQuery marks a method as query method that doesn’t change any object data.
Such methods can also be used in EAL.




                                                                                      Page 103
                                      2. Modeling with ECO



2.7 Modelling of Associations
After the analysis of the class element in the last chapter we want to look at association
elements in UML class diagrams in this chapter.

An association creates a relation between classes. In ECO an association can be produced
either between two classes, or recursive to the same class. UML-class models allow
associations between more than two classes, however this is not supported by ECO.

Basically each association consists of two names, two ends and a direction.
Each association-end has a name (= role), a cardinality (multiplicity) that indicates how many
instances of the opposite class can be associated with one instance of this class, and an
aggregation value which classifies the association type in detail.
An association, where you can navigate from one association-end to the other and vice
versa, is called non-directional.
Directional associations only allow navigating into one direction. The direction of navigation is
determining if an instance of one side of the association can access an instance of the other
side.

When creating an association in the CoreClasses-Diagram with Drag&Drop you implicitly
determine the direction of the navigation, unless you create a non-directional association.

Associations are quite similar to relations in a relational DB-System and are used just like
them in ECO. The configuration of associations in an ECO class model defines in the
assigned DB, which PrimaryKeys of other tables are included in a table (1:n Relations), and
which additional tables with key value pairs are created as a realization of n:m relations in
the DB.
So the direct handling of Primary-Keys is not required in an ECO-application at all. The class
model, most of all the associations define the links between tables automatically.

A connection between two instances at runtime can be created using the integrated
Drag&Drop-mechanism of the AutoForm (see chapter 1.4), but is usually done by coding.

For example setting a connection between a certain university and a certain student in a 1:n
Association between a university and its students can be done either based on the university

   oUniversity.HasStudent.Add (oStudent)

or based on the student.

   oStudent.Visits := oUniversity

In this case it’s sufficient to set the connection in only one direction.




                                                                                       Page 104
                                  2. Modeling with ECO


2.7.1 An Association-Properties overview
Since many different kinds of associations can be modelled, each defined by its properties,
we first need an association properties overview.

Basic Properties
 Object inspector            Explanation                             Chapter link
 Name                        Association name
 Association class           Assignment of a class to an see chapter 2.7.5
                             association
 former names                Important    for  envolve   database
                             schema
 derived                     Derived associations                  see chapter 2.7.6
 persistence                 Usually only derived associations are
                             transient


Association-end-Properties
 Object inspector            Explanation                             Chapter link
 Name                        Name of the association-end
 Aggregation                 None, aggregation or composition    see chapter 2.7.3
 Multiplicity                0..1, 1, 1..n, ...                  see chapter 2.7.2
 visibility                  Public, Protected...
                             Excluding neighbouring objects from
                             the use of the navigation
 Has User code
 Stereotype                  classification  of    the association
                             according to UML standards
 Navigable                   TRUE on both ends stands for a bi-
                             directional association

Additional Association-end-Properties
 Object inspector            Explanation                                Chapter link
 column name                 Used if the column name in the DB
                             should differ from the association end
                             name
 save action                 None = default,                            see chapter 1.4
                             DBAssign = assignment of the value by
                             the db,
                             Fix = value can’t be changed after first
                             assignment
 standard region mode        Use only in association with regions       see chapter 2.9
 former names                Important for envolve database schema
 sorted                      Takes care that the position of the        see chapter 3.1.1
                             elements is maintained permanently
 embedded                    In association with multiplicity           see chapter 2.7.2
 delete action               Enable cascading deletion                  see chapter 2.7.4
 derivation-OCL              Only for derived attributes                see chapter 2.6.4




                                                                                    Page 105
                                2.7 Modelling of Associations


2.7.2 Multiplicity
The entry Multiplicity on both ends of an association enables various association types. We
will have a detailed look at each of those variations.
The following explanations refer to the example application [    Associations].


1:1 Association
In a 1:1 Association the connection between an instance of the base class and an instance of
                                                  E
the opposite class is created using a PrimaryKey (ECO_ID).
To which table the primary key of the opposite class gets saved depends to which direction
the association gets dragged when it gets created.
Subsequently this value can be defined at both association-ends with the object inspector, in
the field Embed.




The PrimaryKey of the instance, on whose association-page Embed was set to TRUE, is
saved to the table of the opposite class.
In our example application the Property Embed is set at the association end CL_PassID, so
the PrimaryKey of a CL_PassID-Instance is saved in the table CL_Person as ForeignKey.

If the property Embed gets set on both ends of a 1:1 Association, the model validation (see
chapter 2.2.3) will result in an corresponding error message.
If Embed is set to FALSE on both sides, the associated PrimaryKey won´t be entered, ECO
will generate its own key table instead.


1:n Association
In a 1:n association the connection between an instance of the base class and n instances of
the opposite class is usually implemented by saving the PrimaryKey of the instance on the
„1“-Side of the association to the table where the „n“ Instances are located.




So the property Embed is set at the association-end with cardinality „1“. Setting this property
at the association-end with cardinality „n“ would have no effect here, but a warning will
appear when we call the model validation function (see chapter 2.2.3). If this property isn’t
set at any association-end, ECO automatically generates its own link table.


n:m Association
In a n:m Association the connection between the associated instances is always created via
a key table. The Property Embed is of no significance here. A set embed flag however will
cause a warning again.



Page 106
                                   2. Modeling with ECO


Strict 1:1 Association
Unlike the first 1:1 example, where strictly speaking we had a 0..1:0..1 association, we now
have to link each instance to exactly one object of the opposite class.




The handling of such associations is a bit difficult, because in principle at the moment of
creating an instance, the matching associated instance already has to exist and be linked to
the fresh object immediately, and vice versa. This resembles the question of who came first,
the hen or the egg?.
ECO complies with this „theoretical“ condition with an automatic creation of a constraint
element, if an association-end cannot have a „0“-multiplicity. This constraint element looks
like this:

  Constraint-Name       = Classxxx multiplicity constraint
  Constraint-Expression = self.Classxxx->size >= n

So the constraint expression requires, that at least one object of the class has to exist, on
whose end no „0“-multiplicity is allowed. Of course, if –like in the example above- strict 1-
multiplicities are set on both association-ends, two constraint elements are generated, one
for each class.

Note:
  The automatic adding of such constraints can be deactivated with the following entry in
  the unit xxxEcoSpace (in front of the xxxEcoSpace-class definition) of your application:
  [UmlTaggedValue(’Eco.GenerateMultiplicityConstraints’, ’False’)]




                                                                                   Page 107
                               2.7 Modelling of Associations


2.7.3 Aggregation
With the Property Aggregation, that can be set at each association-end, further association
types are possible.

The Option Aggregate displays, that an instance - in this example of the class
CL_Community – results from the sum of its partial instances – in this case the member
instances. This is called a total-partial-hierarchy.
A member can be member of multiple clubs, that means if the club instance is deleted, its
assigned members mustn’t be deleted automatically (also see the next section: cascading
deletion).




ECO marks the association end of an aggregation with a non-filled rhombus.

The option composition differs a little from the Option Aggregate, here partial objects can
only be assigned to one main object.




For the above composition example the following is true: If an instance of the class
CL_Circle gets deleted, all associated CL_Point-Instances have to be deleted as well. A
composition is displayed as a filled rhombus.




Page 108
                                    2. Modeling with ECO


2.7.4 Cascading deletion
As mentioned in the predecessing chapter, in certain situations deleting an instance that is
associated to other instances should also lead to the deletion of the associated instances.
This automatic cascading deletion can be set in ECO with the property delete action.
The property delete action can accept four different options:

      •   The default value causes a behavior that has to be interpreted according to the
          association type.
      •   The value ‘Prohibit’ prohibits cascading deletion in any case
      •   The value ‘Allow’ accepts cascading deletion in this association
      •   The value ‘Cascade’ accepts cascading deletion, covering multiple associations

The default behavior of an association concerning cascading deletion depends on the
association type. Usually the default value prohibits automatic cascading deletion.

If the aggregation property on an association-end is set to Aggregate, ECO interprets the
default setting of the delete action just like in the option „Prohibit cascading deletion“. This
goes according to the UML requirements for aggregations. In this case deleting a main object
doesn’t lead to an automatic deletion of the partial objects. Those have to be deleted
manually if required.

If the aggregation property on an association-end is set to composition, ECO interprets the
default setting of the delete action just like in the option „Cascade”. This goes according to
the UML requirements for compositions. In such a case deleting the main objects
automatically leads to the deletion of the partial objects.


2.7.5 Association classes (attributed association)
ECO realizes associations on the database page by entering the corresponding key values
into the tables or by the creation of an extra key table.
Furthermore a class can already be assigned to an association as soon as the association
model gets designed. Thus the association itself receives its own attributes and methods. In
the UML this is called association classes and the instances are called link objects.

Example application: [     AssociationClasses].
A class CL_Person is connected to the class CL_Session with an association ASS_Test.
The association should determine which person participates in which session (n:m relation).




                                                                                      Page 109
                                2.7 Modelling of Associations


If the participation in a session is supposed to be described with custom attributes, like for
example with bConfirmed, that contains the confirmation of each person for each session, it
won’t be sufficient to only define an association.
This additionally required attribute can’t be placed in the class CL_Person, since a person
can participate in multiple sessions. Vice versa usually multiple persons participate in a
session, so the class CL_Session isn’t an adequate place for this attribute either.
The only option left for us to display this example is to define a new class, for example
CL_Participancy and place the attribute bConfirmed there.
Now two associations would be required though. One between CL_Person and
CL_Participancy , the other between CL_Participancy and CL_Session.
In this case the association classes can be helpful.

In our example we assign the class CL_Participancy to the association ASS_Test via its
Property Assoziationsklasse in the object inspector.
When you follow this example you will notice, that after assigning the association class, the
initial name of the association ASS_Test, has been changed to the name of the association
class CL_Participancy.
(this explains why you can’t see an association called ASS_Test in the image above).

The use of association classes has the following advantages:
     •    With each linking of two instances (here CL_Person and CL_Session) an
          association object (here CL_Participancy) with all its attributes is created
          automatically
     •    With OCL statements very flexible navigations are made possible

OCL-examples for the example above:
 OCL-Statement                    Explanation
 Person.CL_Session                Returns all sessions a person participates in
 Session.CL_Person                Returns all persons participating in a session
 Session.CL_Participancy          Returns participancy of all persons of a session
 Session.CL_Participancy          Returns participancy of all persons, who are confirmed to
 -> select (bConfirmed)           participate in a session




Page 110
                                     2. Modeling with ECO


2.7.6 Derived associations
Parallel to an existing association, further connections between two classes can be modelled
with ECO – with derived associations.
Derived associations create additional ways of access to the class they are directed to. The
following property settings are typical for derived associations:

 Property                      Value                        Explanation
 derived                       TRUE                         Per Definition
 Persistence                   usually FALSE
 Navigable                     usually FALSE                Usually directional associations
 derivation-OCL                A valid OCL                  For example CL_Session_1
                               expression                   -> select(bConfirmed)

Another example with persons and sessions:




This time the attribute bConfirmed is not supposed to confirm the participation of a person in
a session, but the taking place of the session itself. As a result we place this attribute directly
in the class CL_Session.
In addition to our standard association ASS_Participancy we now also defined a derived
association ASS_Confirmed with the following derivation-OCL-expression:

   ASS_Session -> select(bConfirmed)

A Navigation via this derived association like

   Person.CL_Session_1

Returns all confirmed sessions a person participates in.

With the use of a derivation-OCL-expression the use of the derived association gets
determined to a large extent. Because of this, derived expressions are usually directional.
This can be recognized in the diagram by the arrow-heads.

Note:
  To be more exact, it is not the association that is derived, but each association end.




                                                                                         Page 111
                                2.7 Modelling of Associations


2.7.7 Associations, recursion and generalization
Of course, when generalizing classes, associations can be inherited. This is especially useful
for associations between abstract classes.

Another example:
Both abstract classes CL_Base and CL_BaseType are connected by the association
ASS_HasType. So a basetype instance is assigned to each base instance.
For example we can derive a class CL_User or CL_UserType from this abstract class
construct.




Instances of the class CL_User can be linked to a UserType-Instance with the inherited
association ASS_HasType.
The determination of TypeName or of the SecurityLevels of a oUser-Instance is usually
done with the following expressions:

  sTypeName := oUser.ThisType.sName
  iSecurityLevel := CL_UserType(oUser.ThisType).iSecurityLevel

If the attribute iSecurityLevel is not defined in CL_BaseType, but in the derived class
CL_UserType, a TypeCast is required when navigating via the inherited association
ASS_HasType.

As mentioned at the start of chapter 2.7, associations can also be used on only one class.
This is called a recursive relation. Also using the association via generalization is possible,
as shown in the example below:




The abstract class CL_Tree creates a common tree structure with support of its recursive
associations. The class derived from that, CL_NewsItem, makes use of this hierarchy.
A NewsItem-Object can for example navigate upwards and downwards in this hierarchy.




Page 112
                        2. Modeling with ECO

var oNewsItem,
      oCapitalNewsItem,
      oSonItem : CL_NewsItem;
…
oCapitalNewsItem := oNewsItem.FatherNode;
for i := 1 TO oNewsItem.SonNode.Count do
    oSonItem := CL_NewsItem (oNewsItem.SonNode.Item[PRED(i)]);
  …




                                                             Page 113
                                     2. Modeling with ECO


2.8 State diagrams
Starting with ECO-III another UML diagram exists in addition to the class diagram, the state
diagram (also called : State machine...).

UML-state diagrams display squences of states of class instances. So the are biund to a
class explicitly. A class can contain multiple state diagrams.
A state diagram can contain the following components:


      •                       initial state


      •                       state (Vertix)
      •                       transition

      •                       final state

A state node can contain regions with sub state diagrams (hierarchic structure).

State diagrams are primarily used to display “life cycles” of class instances, to display dialog
steps, etc.




2.8.1 The structure of a state diagram
the following rules apply for placing the components of a state diagram.

      •   To each state diagram a so-called state attribute is assigned, which is used to
          store the current state in the object.
      •   Each state diagram requires exactly one initial state. The initial state doesn´t
          represent any object state, it just points at the state the object will start in.
      •   From a initial state one or multiple transitions to one or multiple states are
          possible. A guard-consdition, but no trigger can be assigned to such a transition.
      •   Each state can have one or multiple transitions to other states or to the final state.
      •   The final state is optional. If a class instance reaches the final stateit gets deleted
          automatically (except in sub diagrams).




                                                                                       Page 115
                                       2.8 State diagrams


The following class and state diagram shows a basic display of a medication sale in a
pharmacy.




2.8.2 The components of a state diagram
A initial state doens´t have any special properties except for descriptions (name, description,
stereotype...).


State
States have the properties enter- and exit-action, end nodes of course only the property
enter-action.
For each of these actions a ECO Action Language (EAL) expression can be entered that is
executed as soon as this action gets activated (more on EAL in chapter 3.2).
The state transition of an instance that is connected with entering a node can be logged in a
memo field for example with an EAL expression placed in the property enter-action.

   self.sLog := self.sLog+'\rhere you find a log entry'


Transitions
Transitions have the properties effect, guard and trigger.
The trigger of a transition is a method of the class that initiates the execution of the transition.
In order to enable a trigger method to be assigned to a property first it has to be defined like
a conventional method, usually in the context menu of the class in the class diagram (more
on trigger methods in chapter 2.6.6).

In the interface section of the Package_1Unit the trigger method is marked with an
corresponding UmlTaggedValue.

   [UmlTaggedValue('Eco.IsTrigger', 'True')]
   procedure TrFinished;




Page 116
                                    2. Modeling with ECO

the code implementation consists of the call of the trigger method only .

  procedure CL_Service.TrFinished;
  type
    TArrayOfobject = array of &object;
  begin
    Self.AsIObject.Invoke('TrFinished', New(TArrayOfobject, 0));
  end;

This code implementation ensures that the trigger method can´t just be called by EAL but
also from a program code.
This raises the question, if we can add custom code to the implementation section.
Technically this is possible, but it wasn´t designed that way by the eco programmers and isn’t
a proper solution.
The line manually entered in the example below is executed when the trigger gets called by
code (not by EAL), but as soon as the complete program code gets regenerated by ECO,
this line gets deleted automatically!

  procedure CL_Service.TrFinished;
  type
    TArrayOfobject = array of &object;
  begin
    MessageBox.Show (’Trigger call has happened’);
    Self.AsIObject.Invoke('TrFinished', New(TArrayOfobject, 0));
  end;

With the call of the trigger method by code or EAL expression the transition of the
corresponding class instance is initiated.
When a transition doesn´t have a trigger method, this means that the transition from the pre
node to the post node is always initiated immediately.
A trigger method can also contain parameters that can be used in the EAL edtior for guard-
or effect-expression.
In the example application [     State1] in the next chapter the trigger TrAccepted contains a
string parameter sTyp, that is used in the effect expression self.sType := sTyp.

The optional guard expression defines a condition in ocl that has to be fulfilled in order to
enable the transition to happen.
If a trigger method gets called without ist guard expression being fulfilled, an exception is
caused. If the guard expression is missing, the condition is always fulfilled.

The effect expression (also optional) enables us to start additional actions by EAL expression
when the transition is executed. Instead of the “hard” code interference shown above we
should rather use an appropriate effect expression. Since it also uses EAL syntax, this
expression can also contain the call of further customized methods.




                                                                                    Page 117
                                      2.8 State diagrams


The following actions in the given sequence are executed during the transition from a pre
state to a post state started by the trigger TR.

      •    (the state of the class instance is PRE)
      •    the guard expression of the TR is checked and, if the condition isn’t fulfilled, the
           whole action is cancelled (exception)
      •    the exit action of the PRE state is executed
      •    the effect expression of the TR is executed
      •    the state of the class instance is set to POST
      •    the enter action of the POST state is executed

If the POST state is a final state, the class instance is deleted as a last action (except in sub
diagrams).


2.8.3 An example
After this rather theoretical explanations here is an example.
Our example application [        State1] is supposed to display the treatment of service calls
for a industry sector solution. We only use one class CL_Service with the following attributes
as class model:

 Attribute                    Data type      explanation

 rStart, rFinished            DateTime       Start and end of the process of one case
 sType                        String         Query type (subject or technology)
 sLog                         Text           Logs the process steps (state and point of time)
                                             of a case
 /rNow                        Datetime       Support attribute (derived attribut) for the
                                             determiation of the current time BY code or
                                             OCL.
 sStatus                      String         State attribute for saving the current state
                                             corresponding to the state diagram



Class model

                                    Each service call is forwarded by the reception either to
                                    the technology hotline (common computer problems) or to
                                    the subject hotline (questions on the subject). Wrong calls
                                    are sorted out.
                                    For each service case the case state, starting point of
                                    time, each processing and waiting point, ant the point of
                                    completion are recorded.
                                    Multiple process steps are necessary due to the options
                                    of ReturnToPool and GetFromPool.




Page 118
                                     2. Modeling with ECO


State diagram
As a next step we assigned an ECO state machine to the class CL_Service with the context
menu. The following diagram shows its structure.




The diagram itself has two properties, name and state attribute, which we can put on the
diagram level with the object inspector.
The state attribute is important here. This is the state attribute of a class, where the current
state (name of the node) of a class instance is saved, as soon as the instance is located in
this state.
Whenever we create a state diagram, the IDE checks if the class already has a state
attribute, if so, we have to assign such a state attribute to the property state attribute, if not,
such an attribute is created and assigned automatically.

Note:
  a class can have multiple state diagrams and a diagram can contain sub diagrams. So a
  class can have multiple state attributes.
  While you see different diagrams in this case, please notice, that ECO will handle all these
  diagrams as one state machine with multiple regions.

In order to create transitions betweeen states we use the transition component in the
component selection window (lower right). Except for the initial transition from initial state to
the state receiption, to all transitions trigger methods are assigned that we added to the class
CL_Service in the class diagram with the context menu of the class.




                                                                                         Page 119
                                     2.8 State diagrams


Notes:
  State symbols are also available in the context menu of a diagram or region and in the
  component selection window. Only state symblos from the context menu can be added to
  sub diagrams.
  The transition symbol is only availabe in the the component selection window, since
  transitions can span over hierarchies.
  Trigger-Methods can also be added to the class in the context menu of the state diagram.

All trigger methods in our example are designed as processes. Only the method TrAccept
contains an input parameter sTyp:String, that contains the call type of the service case.
Since this call type is important for the further process, we additionally assigned the effect-
EAL-code self.sType:=sTyp, that implements the input value into a class attribute
(sType).

The Trigger TrGetFromPool, that is used to continue „parked“ service cases is used by both
hotline sections. For the sake of case differentiation two guard expressions are used:
self.sType=“subject“ and self.sType=“technology“ .

Note:
  Guard- and Effect-expressions are set in the state diagram with the object inspector and
  contain EAL code (see chapter 3.2)
  Possible parameters of a trigger method are set in the class diagram with the object
  inspector or in the source code.

We assigned appropriate identifiers to each state. In addition the three middle states use
EAL expression in their enter-actions to save the state and status of the process in the log
attribute.

  self.sLog := self.sLog + '\r\nWaiting: ' + self.rNow.asString

The receiption state sets the starting time in its exit action, the Finished state sets the
completion point in its enter-action.

Note:
  Starting with ECO-III String constants in OCL-expression can contain Escape-character
  strings like \r, \n, \t usw. more information on that in chapter 3.1.1.

The following process of our example application results from this configuration:

The starting point of a service case, generated for example because of a telephone call, is
saved in the state receiption. Also the hotline section in charge is determined here and the
case is added to the pool by the trigger TrAccept.

Each sending to the pool is recorded, the employees of both hotline sections can fetch single
cases from the pool with the trigger TrGetFromPool to process them further. A
corresponding guard expression takes care that each hotline section only gets the cases it´s
in charge of. Also the transition to processing state is recorded in the enter action here.

With the TrReturnToPool-Trigger a case can sent back to the pool for later reprocessing.
the Trigger TrFinish marks the case as closed. The entry action of this state only sets the
point of completion.




Page 120
                                    2. Modeling with ECO



GUI
The interface of our example is pretty basic.




In order to visualize the case instances we use a datagrid with the usual datasource
connection via expression handle (Expression = CL_Service.allInstances).
It’s important here to activate the AutoForm-Property of the Grid.

For the visualization of sLog-Text entries we use a RTF-Textbox, that we connect to the
sLog-Attribute of the expression handle with simple databinding.
Besides we need a button to create case instances (ECO-ListAction = Add) and a button to
save data (ECO-GlobalAction = UpdateDatabase).
For saving this time a PersistenceMapperXML-component is enough.

After having created a new service case with the button new call, we use the AutoForm-
Option to activate the various trigger methods.




                                                                               Page 121
                                      2.8 State diagrams


The tab Methods contains an activation button for each class method, so also for the trigger
          Methods
events, with only those buttons activated that are possible in the current status of the case
instance.
The tab State only shows those trigger activation buttons that can currently be activated.
          State
Besides it contains the hierachical structure of the states and the possible activation buttons,
just in case hierachical state diagrams exist.
This way the complete application can be imlemented without delphi code and with minimal
interface design.


2.8.4 Hierarchical state diagrams
A state again can contain regions with sub state diagrams. This way hierarchical state
diagrams can be built.

The realization of sub diagrams / sub states happens within regions. Each state node can
have one or multiple regions. In each of these regions a sub diagram/sub state can be
placed.
If a state contains several sub diagrams, thus several regions, we call this concurrent sub
states.

In our example application from chapter 2.8.1, the detailing of the state check can for
example result in the following sub diagrams.




The image shows two concurrent sub diagrams in the state check.




Page 122
                                    2. Modeling with ECO

Note:
  As stated several times before, a class can have multiple state diagrams. Iin this case
  these diagrams behave like concurrent sub diagrams, only on the top hierearchy level.
  So when a class instance is created, it is located in all state diagrams of the class. In this
  case each state diagrams should have its own state attribute!



Entering sub diagrams
to create a first sub diagram we use the entry <Add> in the context menu on the „body“ of
                                                 <Add>
the node check. The menu entry provides the three components State , Initial State , and
                                                                    State Initial State
Final State . With this we can add all states to the sub diagram above.
Final State
The image above also contains another subdiagram in the state check. As we know already,
a reagion is assigned to each sub diagram.
Our first sub diagram was added to the default region of the super state automatically. To
create a second sub diagram we have to create another region in the state first. To do this
we use the menu entry <Add> -- <Region> of the context menu, but this time directed at the
                         <Add> <Region>
head of the state.
Within this new region the local states are entered with the context menu etc.

In chapter 2.8.3 we explained the assignment of a state attribute to the property state
attribute of a diagram. The same goes for the sub diagrams we just created. That means the
sub diagrams use the same state attribute as the super diagram by default. However we can
vary this with the state attribute property of a subdiagram and assign a custom state attribute
to a sub diagram.
Please note here that the state attribute has to be defined in the class before, then activate
the region of the sub diagram and execute the assigmnent with the object inspector.


Composite states
A class instance that enters a state that contains one or more sub diagrams is located in the
initial node/s of the sub diagram/s automatically.

                                        Accordingly the state/s of these initial state/s is
                                        assigned to this instance.
                                        The result of this is, particularly when multiple sub
                                        diagrams are used, that the complete state within
                                        such a state cannot be displayed with only one state
                                        attribute.

                                        Here a state attribute should be assigned to each sub
                                        diagram / region. The complete state then results from
                                        the amount of all state attributes.

                                        If the data of our example are displayed in a datagrid
                                        at runtime for example, the AutoForm-Editor (State
                                        tab) depicts the diagram hierarchy of the selected
                                        class instance, the current value of the state attributes
                                        and the trigger methods currently available.

Unlike to a top level diagram, in a sub diagram the transition to the final state does not result
in the deletion of the class instance.




                                                                                       Page 123
                                       2.8 State diagrams




Transition in a state with sub diagrams
In a transition from a pre state to a state with sub diagrams several entry scenarios are
possible.

The transition can be tied directly to the composite state (like in the case without sub
diagram) or directly to a state of a sub diagram.

If the transition is tied to the composite state a initial state has to exist in the sub diagrams in
order to enable a distinct transition to the sub diagrams.
In a direct tie no intital state is required for this sub diagram.

In each case the entry actions of the composite states are triggerd at the entry of a class
instance in the composite state, as well as the entry actions of the sub states that are
activated directly or indirectly (via initial state) by this initial transition.


Exit from a state with sub diagrams
Here we have several scenarios as well.
The exit can happen with a transition starting from the composite state or directly from the
state of a sub diagram. Very often both way appear together.

A transition on the super level is usually used if multiple states in the sub diagrams require
this exit option (main exit).
In the example above this is true for all states of the sub diagrams. Alternative exits however,
like canceling the process usually take place as a direct transition.

An additional option is to equip the transition on the super level with additional trigger
methods.
In this case a triigger method on the super level forces the exit from the composite state,
even if the local final state hasn´t been reached yet in the sub diagrams.
If the trigger methofd is missing, such a transition is only executed if the final state has been
reached in all sub diagrams. This behavior is displayed in the example above. The
(automatic) transtition to the state sale only takes place after the end state has been reached
in both regions.

The exit from the composite state then leads to a call of the exit action of the sub states
currently active and afterwards to the call of the exit action of the composite state.




Page 124
                                    2. Modeling with ECO


2.8.5 An example with sub diagrams
The second example application in this chapter [      State2] is an extension of the first
example. The main difference is that the state subject hotline is displayed more detailed
with a sub diagram.




Within the state subject hotline a service case goes through an evaluation, that either
forwards the case to the finishing test with a suggested solution (TrSolutionFound) or
realizes that the case should be handled by the technology hotline and returns the case to
the pool after reassigning it accordingly (TrTechnicPool).
Independent of this direct forwarding to the pool, a case can be parked in the pool at any
point of the process with the trigger (TrReturnToPool). What was added here is the trigger
effect to save the current status (analysis or test) in an additional class attribute
(sSaveStatus). This enables the correct assignment to the sub state active before pooling
when recalling (TrGetFromPool) the process. The differentiation is done by two guard
conditions that are connected to the two transitions that come from the initial state of the sub
diagram.
The two transitions of the state test are realized by the two options TrSolutionFailed and
TrFinish.




                                                                                      Page 125
                                    2. Modeling with ECO


2.9 Regions
When modelling business logic, you often come across attributes with interdependent values.
In a multi user environment the problem is, that a parallel change of attributes which depend
on each other can lead to a violation of the business logic.

Example:
For a product of a trading company the rule shall apply, that the retail price (iRP) always has
to be bigger than the buying price (iBP).
User A changes the retail price of a product from 100,- to 80 ,- and parallel, user B changes
its buying price from 75,- to 85,-.

To prevent such violations of business rules, ECO enables the creation of so-called regions.
A region is a group of interdependent attributes, whereas simultaneous changing of these
attributes by different users can be prevented.
Please notice, that the regions mentioned here are only used with Optimistic Locking and do
not relate to the regions used in state diagrams.


2.9.1 Defining a region
A region is defined with the EcoPackage-Property region definition in the object inspector.

So first we have to select the EcoPackage for the object
inspector. Activate the tab Modell Viiew in the project
                             Mode V ew
management window and click the upper core classes
package symbol.

Now the object inspector displays the properties of the
Eco package.

The property region definition provides a list editor, with
which you can add the entries required for the definition
of the region.
For each attribute group of a region you need one entry
in the list editor.

Each entry consists of a text string, called body.

The text string is structured like this:
      •    The region name
      •    The class the region refers to (in squared brackets and followed by a colon)
      •    A list of the affected attributes, separated by commas

Example:

   Pricerule[CL_Product]: iRP, iBP

With this region-definition the attributes iRP and iBP of an instance of the class CL_Product
can only be changed by one user simultaneously.




                                                                                     Page 127
                                          2.9 Regions


2.9.2 The Region Definition Language
The Region Definition Language (RDL) allows also subregions within a region, with that you
can have hierarchically structured regions.

The basic syntax of a region string is:

Regionname[Class1]: Attribute1_1, Attribute1_2... | SubRegionName[Association1]
SubRegionName[Class2]: Attribute2_1, Attribute 2_2...

Example:
  Pricerule[CL_Product]: iRP, iBP |Buyingrule[ASS_Supplier]
  Buyingrule[CL_Supplier]: iFactor

Explanation:
 Element                      Explanation                           Example
 Regionname                   The region name                       Rule of price
 Class1                       The class the region refers to        CL_Product
 Attribute 1_1,1_2...         The to be grouped attributes of the   iRP, iBP...
                              class class1
 |SubRegionName               The name of a SubRegion; a            |rule of purchase
                              predecessing | indicates the
                              beginning of a SubRegion-
                              definition
 Association1                 An association between Class1       CL-Product
                              and another class (Class2)                ASS_Supplier
                                                                  CL_Supplier
 SubRegionName                The SubRregion name                 Rule of purchase
 Class2                       The class the sub region refers to CL_Supplier
 Attribute 2_1,2_2...         The attributes of class class2 that iFactor...
                              are to be grouped

With this method regions can span over multiple classes beyond associations.
In the example above the region rule of price would automatically include the SubRegion
rule of purchase , that means when editing an instance of the class CL_Product, not only
the attributes iEK and iVK but also attributes (like iFactor) from all instances of the class
CL_Supplier associated with this instance would be protected by a joint region.
This is also true for :n associations, that means for example when n CL_Supplier-Instances
are linked to one CL_Product-Instance.




Page 128
                                2. Modeling with ECO



2.10 Diagrams and UML-Packages
In chapter 1.4 we created a simple ECO-WinForms-application with only one UML-Diagram.
As we have seen there, as soon as we create a new ECO-WinForms-application, a default
UML-Package with the default name Package_1 (ECOII: CoreClasses) is automatically
created. This package also contains a so-called primary class diagram. That in addition
contains the name of the package.

For a better understanding of the following explanation we renamed this standard UML
package in our example [     Modelling1] in the model view to SummaryModel with the
context.




Notes:
  The renaming of the UML package in the model view unfortunately doesn’t get adopted
  completely in the corresponding source code. The missing adjustment is mainly in the
  meta-data entries in the source code.

  For ECO II only:
  That´s why after renaming in the CoreClassesUnit the following line has to be adjusted
  like shown below
                                             S
  [assembly: RuntimeRequiredAttribute(TypeOf(SummaryModel))

  For ECO-II and ECO-III:
  In the Unit xxxEcoSpace in the list of uses the entry
  Package_1Unit has to be replaced with the entry SummaryModelUnit.
  Besides that the meta attribute-order that is directly in front of the EcoSpace-class-
  definition has to be adjusted as follows
                                                    S
  [EcoSpacePackage(TypeOf(SummaryModelUnit.SummaryModel)]

  If you rename a UML package that already contains model elements, you may have to
  make manual corrections on several positions.




                                                                               Page 129
                            2.10 Diagrams and UML-Packages


2.10.1 Secondary class diagrams
A way to subdivide a model „graphically for starters“ is, to place additional diagrams, so-
called secondary class diagrams in a UML package and to divide the model on to several
diagrams (within one package).

To do this you activate the default UML package and select
<Add> – <Add ECO cllass diiagram>
<Add> – <Add ECO c ass d agram>
in the context menu.

Now we name this new class diagram PersonModel.
Then we add another diagram and name it UniversityModel.




As a next step we place some class symbols on both secondary diagrams in our example
[   Modelling1].

First in the diagram PersonModel.




Then in the diagram UniversityModel.
                                                                  P
In this diagram we also create a connection to the first diagram (PersonModel) by using a so
            S
called link(ShortCut) (more information on working with links/ShortCuts follow below).




Page 130
                                   2. Modeling with ECO




Note:
  In ECO-II all class symbols that were not placed on the primary class diagram were
  marked with a little arrow in the lower right corner, the so called ShortCut-Symbol.
  In ECO-III only those symbols are marked that were imported from another package.

Class symbols of non-primary diagrams are only an additional display of the class, a kind of
copy of the original class symbol. The original symbol of all classes are placed in the primary
       S
class (SummaryModel). So this diagram contains all model components of all secondary
diagrams and only on this diagram the generation of the code is based.




So secondary diagrams in a package are only used for optical reasons, to improve the
display. They don’t have any effect on the generation of the code. Because of that shortcuts
don’t generate their own code.

In general Shortcuts are used, when in a diagram the connection to a class, which was
„defined“ in another diagram, is supposed to be displayed. With that it’s possible to realize
association- and generalization arrows beyond diagram boundaries.
To place a shortcut, use the menu item ‘add shortcut’ in the context menu of a diagram.




                                                                                     Page 131
                            2.10 Diagrams and UML-Packages




In our example we added –based on the diagram UniversityModel – the CL_Professor-
Element from the diagram PersonModel.
In the diagram UniversityModel this element is then displayed as a shortcut (see image
above) and can be connected to the existing class models of the diagram with an
association.
The example [      Modelling1] doesn’t have any interface, it’s just for the benefit of the
demonstration of secondary class diagrams!

Note:
  Of course the short cut method also works with diagrams that are placed in other UML-
  packages. See the next chapter 2.10.2.




Page 132
                                  2. Modeling with ECO


2.10.2 Multiple UML-Packages
A far more important way of structuring large ECO applications is the use of additional UML
packages.

We want to clarify the general proceeding with an example [       Modelling2].
We divide the two class groups person and university from the last example into two UML
packages. To do this we rename the default UML package in our new example
[    Modelling2] to PersonPackage. Don´t forget to adjust the meta data in the source code!
We place the three classes CL_Person, CL_Student and CL_Professor in the primary class
diagram of this example.

In the Modell Viiew we can add additional UML packages , so-called sub-packages, with
       Mode V ew
the menu item <Add>--<ECO Package> on application level as well as within the package.
               Add> <ECO Package>
In our example we add the new package on application level (Modelling2). We name this
new package UniversityPackage, the Package-Unit gets saved as UniversityPackageUnit or
gets renamed accordingly in the tab Modelling2. The new package gets the classes
CL_Subject, CL_Room and CL_Course.




We create the connection between the two diagrams/packages by adding a ShortCut-Symbol
for the class CL_Professor to the UniversityDiagram and connect it via ASS_CourseHead
to the CL_Course-Symbol.




                                                                                  Page 133
                           2.10 Diagrams and UML-Packages




One action is still missing though. The additional UML package has to be reported to
EcoSpace. This is done with the button Sellect Packages on the design page of the Unit
                                         Se ect Packages
xxxEcoSpace. In the following dialog we have to add the UniversityPackage to EcoSpace.




Using multiple packages simultaneously on application level as well as using them as sub-
packages within a package, is an effective means of keeping down the size and complexity
of an application by subdivision into class groups.
The example [      Modelling2] doesn’t have any interface, it’s just for the benefit of
demonstration of UML-Packages!




Page 134
                                  2. Modeling with ECO


2.10.3 Outsourcing of UML-Packages into a ECO-Package
If the reuse or shared usage of UML-packages is the main issue for you, ECO offers a way of
packing UML packages into a ECO-Package, thus making them available for other/multiple
ECO-functions.

Example [         Modelling3]:
     •      First create a Delphi package with
    <Fiille – New – Other -- Dellphii ffor..Net--Projjects – ECO Package iin Package> .
     F e – New – Other De ph or Net Pro ects – ECO Package n Package>
   In our example we save this package and name it ModelPackage.
     •      Switch to the model view and add a UML package to the ModelPackage with the
            context menu.
     •      Rename the UML package to PersonModel
     •      Now you can add the usual classes to the UML diagram.




With that you can outsource the complete model information – subdivided into as many UML
packages as you want – into a ECO-package and make it accessible for other .Net
applications (also non-ECO-applications).
Please note: theUML-Packages don’t contain an EcoSpace by default!
The example [     Modelling3] doesn’t create an EXE but a DLL!




                                                                                  Page 135
                               2.10 Diagrams and UML-Packages


2.10.4 Referencing UML-Packages in an application
An ECO-application, that is supposed to access model structures from a UML package (in an
ECO package), has to
     •  Reference the ECO-package in the application and
     •  Select the contained UML-package for the EcoSpace of the application

Like any other package, a ECO-package is
referenced in the form of its DLL.

Activate the application entry in the
standard view of the project management
and select the menu item Add Refference
                         Add Re erence
in the context menu.

You can also select the entry references in
the project management and select the
menu item Add in the context menu
           Add


This makes the        dialog    for   adding
references appear.




You can select the desired package (DLL) with the menu item ‘search’ in the lower part of the
dialog, it will then be shown in the list of new references. After that close the dialog.




Page 136
                                    2. Modeling with ECO


Now you have to report the new package to EcoSpace. This is done with the Button Sellect
                                                                                   Se ect
Packages on the design page of the unit xxxEcoSpace. More on that in chapter 2.10.2.
Packages

Notes:
  The class model of a referenced UML package can’t be changed in the ECO application.
  But you can make a connection to a referenced model with shortcut symbols (see chapter
  2.10.2).

   You can also reference UML-packages within a UML package, whereas the same rules
   apply as for ECO applications.

A typical scenario for the use of shared packages would be for example the development of
multiple ECO-WinForms-applications, e.g. one for customer administration and one for
controlling, with both using a shared class model.
One would have to create the shared class model (customers, jobs...) and integrate it into an
ECO-package. Now every ECO-WinForms-application can integrate this package.

Of course the usage of multi-user requires some kind of access coordination. For ECO-
applications there are the following possibilities:

      •   Each ECO-Client-application implements its own EcoSpace.
      •   An additional ECO-Server-application, that also implements the model package,
          implements a central EcoSpace and persistence mapping.
      •   An additional Synchronization- and conflict management-mechanism takes care of
          data adjustment between the clients.

A multi client example is in chapter 4.7.2.




                                                                                   Page 137
                                      2. Modeling with ECO



2.11 Patterns
With Delphi 2006 the use of patterns was integrated into the IDE.
Patterns describe in general a problem and its solution in a structured way. Because of this
Patterns consist of three components, the Pattern-Name, the problem description and the
solution.
In reference to software development, patterns provide a template that can be used to solve
a typical application-problem in various contexts.

In books the following classification of pattern can be found:

          •   BasicPatterns
          •   DesignPatterns
          •   ProcessPatterns
          •   ArchitecturalPatterns

The most well-known patterns are GRASP-Patterns and the 23 design patterns of the GoF
(Gang of Four). The GoF patterns are also available in Delphi for the three project groups:
Delphi, C# and Design.

It’s important to know that the provided GoF-patterns are not implemented for ECO-classes,
which means we can’t use these patterns for ECO-diagrams. Within an ECO-project the
GoF-patterns can only be used in a code-visualized-diagram, with that they can only be used
for non-ECO-classes (see Chapter 1.4.1).

Furthermore the Delphi pattern-library contains also code templates, which e.g. contain
binary operators (compare-operators and arithmetic operator) as a pattern.
Particular patterns can be saved in the section ‘custom patterns’.


2.11.1 Patterns in Delphi - overview
The Delphi pattern-library classifies and sorts the patterns based on the following hierarchical
construction:

Folders             Sub-folder / Pattern
Bundled Patterns GoF                   Creational, Structural,
(Delphi / C#)                          Behavioural
                 Standard              Stub implementation,
                                       Implementation link and stub
                    TCC Code templates Class
                    TCC Code templates Members                              Binary and Unary
                                                                            Operators
                    TCC Code templates Links
Bundled Patterns GoF                        Creational, Structural,
(Design)                                    Behavioural
                 Standard                   Implementation Link and stub
Custom Patterns unrestricted




                                                                                      Page 139
                                          2.11 Patterns


For me it seems to be important to have a separation of the patterns based on the method of
their usage. Patterns, which are managed by Delphi, can be differentiated by three criterions:

Criterion                   Form-Process        Explanation
Implementation level        Diagram-level,      Patterns, which e.g. contain complete classes
                            class-level         or patterns within phase diagrams can only be
                                                implemented on diagram-level.
                                                Pattern, which e.g. contain attributes and
                                                methods of a class can only be implemented
                                                within a class.
Usage      of     existing Yes, No              During the implementation of the single
elements                                        elements (attributes, methods....) of a pattern
(Option: Use Existent),                         into a receiver class, only elements out of the
see Chapter 2.11.3                              pattern will be added, which are not already
                                                available within the receiver class.
Save as FCC-Pattern         Yes, No             To differentiate between development- and
                                                FCC-pattern, please see the paragraphs later
                                                in this chapter under the same name.

Out of the combination of these criterions result various implementation-options, which can
be used based on the various model-context. During the import of patterns out of the library,
only already pre-defined and self-developed patterns are available, which fit into the actual
context.

Context                                  Available Patterns
Delphi-Unit,       Code-visualization, Bundled patterns (Delphi) - GoF-patterns,
Context is the diagram                 suitable custom patterns

Delphi-Unit,       Code-visualization, Bundled patterns (Delphi) – standard,
context is a class                     Bundled patterns (Delphi) – TCC code templates,
                                       suitable custom patterns
C#-Unit, Code-visualization, context Bundled patterns (C#i) - GoF-patterns,
is the diagram                         suitable custom patterns

C#-Unit, Code-visualization,    context Bundled patterns (C#) - standard
is a class                              Bundled patterns (C#) - TCC code templates,
                                        suitable custom patterns
Design-project,                         Bundled patterns (design) - GoF-patterns,
context is the diagram                  suitable custom patterns
Design-project,                         Bundled patterns (design) - standard
context is a class                      suitable custom patterns
ECO-class diagram                       suitable custom patterns
ECO-state diagram                       suitable custom patterns

In Delphi online-help you will find the following separation of the patterns:

Separation                               Pattern group
Source code-templates                    Bundled Patterns - TCC Code templates
Design pattern                           Custom Patterns
FCC (FirstClassCitizens)-patterns        Bundled Patterns - GoF-Patterns
Stub-Implementation-pattern              Bundled Patterns – Standard




Page 140
                                   2. Modeling with ECO


Source-Code-Templates
As already mentioned, source-code-templates offer patterns, e.g. binary operators, which
can be integrated into existing classes.
These templates are implemented in form of:
   • Class-templates
   • ClassMember-templates and
   • Link-templates

Such a pattern exists of a source-code-file and a macro-file. The following code shows the
contents of these files for the template of the group ‘Member – Binary Operator – Equal’


  public
    class operator Equal(oper1,oper2: %Class_Name%): Boolean;
    class operator NotEqual(oper1,oper2: %Class_Name%): Boolean;

  #Fri Jun 08 15:07:45 GMT+04:00 2001
  singleOccurrencePerClass=false
  patternDescription=<HTML> <H3>Equal and Not Equal Operators
  pattern </H3>Creates the overloaded equal comparison (==) and not
  equal (!=) operators. </HTML>
  defaultName=operator1
  defaultType=Integer
  containerMetaclasses=Class,Struct,Association Class

These files are physical saved into the following folder:
..\Borland\BDS\4.0\Objrepos\Patterns\Templates\...


Design-pattern
All self developed patterns are part of the design- or FCC-patterns.
Design patterns contain diagram elements (classes, class attributes, associations...), which
will either be integrated on diagram level or in an existing class.
The option Use Existent (see above) is available.
All self developed patterns, also the ones with activated FCC-option (see Chapter 2.11.3) will
be saved as a XML-file within the following physical directory (depending on the
configuration):
\Documents and Settings\Userx\Local Settings\
Application Data\Borland\BDS\4.0\Patterns\templets


First-Class-Citizen (FCC)-Pattern
FCC-patterns are design pattern of ‘highest quality’. They are represented with an additional
oval-element, which has the name and information of the members (=elements) containing
the pattern. The context-menu of the oval-element offers also the possibility to add additional
members to the pattern.
Each of the pattern exists of a XML- and a property-file (exception: self defined patterns).
These files will be saved in the following physical folder:
..\Borland\BDS\4.0\Objrepos\Patterns\templets\...




                                                                                     Page 141
                                        2.11 Patterns


Stub-Implementation-Pattern
These patterns automate the transmission of elements between two abstract classes, which
are connected with each other through an inheritance relation, respectively between a class
and an interface.

Therefore the following example:
The next picture shows a class and an interface. The interface receives the function
AnyFunc:Integer.




To implement the interface and also the function of the class, we will use the implementation
link and stub pattern:

   •    Choose class AClass
   •
   •    Activate the context menu entry Node by Pattern
                                        Node by Pattern
   •    Choose pattern implementation link and stub
   •    Place the property proposer to AInterface

The link between class and interface is now shown in the diagram. Furthermore the
automated takeover of the interface-function AnyFunc into the class can be recognized.




In parallel to that also the source code has been adjusted.

       AClass = class(TObject, AInterface)
       public
         function AnyFunc: integer;
       end;

The files of the stub-implementation-patterns are saved the same way as the FCC-patterns
in the following physical folder:
..\Borland\BDS\4.0\Objrepos\Patterns\templets\...

Note:
  When saving of a self created pattern, every pattern-category can be used as a folder for
  the new pattern. With that we don’t mean the physical place of storage, but a virtual folder,
  which only contains a reference to the pattern (see next chapter).
  Self developed patterns are usually saved in the folder Custom Patterns. Patterns, which
  are directly created out of elements in ECO-classes- or ECO-state-diagrams, can not be
  saved with the FCC-option and can only be implemented again into ECO-classes.
  FCC-patterns can not be implemented into ECO-classes.




Page 142
                                     2. Modeling with ECO


2.11.2 Pattern management
In the previous chapters the physical storage places for the various pattern-groups have
been listed. Thereby self created patterns are saved in form of a XML-file.
The pattern administration consists of a virtual order hierarchy, in which only connections to
the physical stored pattern-file are inserted.
This virtual hierarchy itself is saved in a registration file, the so-called pattern registration.




With the module Pattern Organizer , available via the Tooll-Menu, the pattern registration
                 Pattern Organizer                        Too
can be edited. Here folder and links can be created, referenced, copied or deleted.
Design-patterns contain diagram elements (classes, class attributes, associations...),




                                                                                        Page 143
                                      2.11 Patterns


2.11.3 Creating patterns
Pattern can be saved out of an existing diagram in form of a design pattern. Therefore we
mark the elements (or only the one) which should belong to the pattern and choose the
context menu-input Save as Pattern .
                   Save as Pattern

                                  Next the dialog appears for the ‘Expert to create patterns’

                                  Here you have to add the file- and show name and
                                  optional you can add a description for the pattern.
                                  The option Pattern Object in the bottom-left-dialog
                                  enables the storing as FCC-pattern.



The next step in this dialog allows again changes to the name and the description of the
pattern, as well as the activation of the option ‘use existent’, with this we can decide if
existing model-elements should be considered during an implementation of this pattern (see
chapter 2.11.1)




                                  In the last step of the dialog we choose the storage place
                                  for our pattern, more exact the folder, in which a first
                                  connection to our new pattern should be stored.
                                  You will find more details to the topic ‘Folders and
                                  Connections’ in Chapter 2.11.2.




Page 144
                                    2. Modeling with ECO


2.11.4 Using patterns
Pattern can be implemented in ECO-class diagrams, in ECO-state diagrams and in the code-
visualization diagrams via the context-menu-input Node by Pattern..
                                                      Node by Pattern
With the call of this function the pattern-expert dialog opens.




Choose the pattern you want and accept with Ok.

Note:
  The pattern-expert-dialog shows only the pattern, which are allowed in the current context
  (see Chapter 2.11.1)
  Alternatively for the call over the context-menu-input, both of the inputs in the tool-palette
  Node by Pattern and Liink by Pattern can be used
  Node by Pattern           L nk by Pattern

   You will find more information to their usage in the Delphi Online-Help under Together –
   Instruction for Pattern.




                                                                                      Page 145
3. ECO and the OCL
The Object Constraint Language (OCL) was added to the UML-Specification in 1997 by
OMG.
In chapter 1.3 we glanced at OCL for the first time. Possible uses for OCL in ECO were
explained, as well as the fundamental syntactic and functional aspects of OCL.

In this chapter we want to have a detailed look at the use of OCL in ECO applications.



3.1 General information for using OCL
OCL can be used in ECO when modelling an application or at runtime.

Just as SQL is used for work with relational databases, OCL is used for work with objects.
Unlike SQL, OCL in ECO applications doesn’t access the database directly. Instead it only
accessed objects located in EcoSpace. If an object is not available in the EcoSpace, it will be
“loaded on demand” when it is needed. This “load on demand”, which saves memory, is
called Lazy Fetching in ECO.

In addition ECO provides a subscription method (see chapter 2.4), with which OCL
expressions automatically get re-evaluated whenever a parameter on which the expression
is based gets changed. A typical example: using an OCL expression to calculate derived
attributes.

Just like the ECO modeller realizing only a part of the UML specification (see chapter 1.2),
ECO doesn’t use the complete range of OCL language as specified by OMG.


3.1.1 Structure, uses and syntax
An OCL expression in ECO can have the following components:

     •    Class identifier
     •    Class attribute
     •    Association end
     •    Association attribute
     •    OCL-Operator
     •    Iterators
     •    String, numeric and datetime literals
     •    Enum and state literals


Example [       OCL1]:
                                 C                           C
In this class diagram customers (CL_Customer), their orders (CL_Order), the single order
        C                                     C
items (CL_OrderLine) as well as the products (CL_Product), the order items refer to, are
displayed.




                                                                                     Page 147
                            3.1 General information for using OCL




From this model the following OCL expressions can be derived:

OCL-expression                                                Explanation
CL_Customer.allInstances.HasOrders          List of all orders of all customers
CL_Customer.allInstances.HasOrders.iOrderNo List of all order numbers of all
                                            orders of all customers
self.HasOrders.iOrderValue->sum             Total order value of all orders of
                                            one customer
self.HasOrderLine.HasProduct.sName          List of all product names of the
                                            selected order
self.HasProduct.sName.length                Length of the product name of a
                                            selected order line
CL_Customer.attributes                      List of all attributes of the class
                                            CL_Customer (Metadata)

In these examples the following basic OCL rules can be recognized:

     •     The result list of an OCL expression can consist of a single value, an object, a
           value list or an object list.
     •     Besides the application data, an OCL expression can also provide metadata,
           which means model structure data.
     •     The starting point (context) of an OCL statement can be the total model, a class or
           a class object. The context results from the situation the OCL expression is started
           from.
     •     The context is always refered to with a self in front of it, besides the case that the
           context is the EcoSpace.
     •     OCL expression can navigate beyond class borders via association ends.
     •     A dot connects the elements of an OCL expression.
     •     OCL-Operators, that are used on collections (object lists), are connected to the
           expression not by a dot, but by ->.

To be able to test OCL-expressions better, the example application contains a button, which
starts the in ECO-III integrated ECO-debugger.




Page 148
                                        3. ECO and the OCL




The ECO-debugger offers a lot of functions for the visualization and for the change of the
ECO-objects, and especially it offers also the possibility to input and evaluate OCL-
expressions.


Uses and context
As already mentioned, OCL can have multiple uses in an ECO application. An overview is
provided in the table below.

Uses for OCL-expressions

use                                  context (self)   example                         OCL-Editor
class, Property Default String Class instance         this OCL-expression is          Yes
representation                                        evaluated                when
                                                      “....AsString“ gets called
class,                               Class instance   Used to override the            Yes
Property derivation expression                        Derivation ocl for an
                                                      inherited derived attribute
                                                      see chapter 2.6.3
Class,                               Class instance   Constraint-evaluation, see      Yes
Property constraints                                  chapter 2.6.5
Class, attribute,                    Class instance   Derived Attributes,             Yes
Property derivation-OCL                               see chapter 2.6.4
Associations,                        Class instance   Derived Associations,           Yes
Property derivation-OCL                               see chapter 2.7.6
ExpressionHandle,                    context of the   Data selection,                 Yes
Property Expression                  RootHandle       see chapter 5.1.2
Property Column in                   context of the   Data selection,                 Yes
ElementHandles                       ElementHandle    see chapter 5.2
IOCLService:                         any              general OCL-Evaluation at       No
Methode         Evaluate         /                    runtime,
EvaluateAndSubscribe                                  see chapter 2.4



                                                                                           Page 149
                            3.1 General information for using OCL


The OCL editor provided by Delphi displays the context in the header. The parser window
checks the syntax of the OCL expression and displays at the same time the result type of the
expression.




Note:
  In general almost every model element, or every classifier, to be more specific, can be the
  starting point and thus the context of an OCL expression. With the specific implementation
  of the OCL usage within ECO, the possible contexts are limited to those listed in the table
  above.


Calling Metadata / Structure data
With the OCL implementation in ECO, it’s possible to request structure data of a model of an
application.
Based on the model level the OCL expression EcoModelRoot.AllSubClasses returns a
list of all classes of the model.
Within a class a list of all attributes can be queried with the OCL operator allAttributes , or
the association-ends of a class with the operator AssociationEnds. You can find a complete
list of all metadata operators in chapter 3.6.


Comments and special characters in OCL-expressions
OCL allows the implementation of comments, preceded by a „—“. ECO does not support this
functionality.

The apostrophe used in Delphi to delimit string literals is used the same way in OCL
expressions. To code an apostrophe that is part of such a string, it has to be preceded by a
backslash.

Base string    OCL-String Example
„John“         ’John’         CL_Customer.allInstances->select(sName=’John’)
„Simon’s“      ’Simon\’s’     …->select(sFirstName=’Simon\’s’)




Page 150
                                      3. ECO and the OCL

For the indication of date and time values, the symbol „#“ is used in OCL. A date must
always be entered in the form #YYYY-MM-DD, a point of time in the form #HH:MM:SS or
#HH:MM.
One-digit values require a preceding zero.

  Base value          OCL-value      Example
  5.1.2005            #2005-01-05 CL_Customerr.allInstances-
                                  >select(Birthday=#2005-01-05)
  9:1:00              #09:01:00   …->select(Starttime<#09:01:00)
                      #09:01
  5.1.2005 9:1:00     #2005-01-
                      05T09:01:00
                      #2005-01-
                      05T09:01

Other special characters in OCL expressions are the pipe symbol „|“ and the colon „:“, both
are used in iterators. More on iterators in the next section.


Iterators in OCL-expressions
When using OCL operators, which allow conditions in the form of boolean expressions as
parameters like ->select, ->reject, ->forall or ->exist, iterators (loop variables) can be used in
the conditional expression, that assign the value of the checked element for each iteration, in
which the condition gets checked.

  Variante          OCL-expression
  without           CL_Customer.allInstances->select(sFirstName=’John’)
  Iterator
  with Iterator     CL_Customer.allInstances->
                      select(p | p.sFirstName=’John’)
  with Iterator     CL_Customer.allInstances->
                      select(p : CL_Customer | p.sFirstName=’John’)

All three ways in the table above lead to the same result.
When evaluating the select command, each CL_Customer object in the list will in turn be
assigned to the iterator p. The pipe symbol separates the iterator from the condition.

Optional the type of the iterator can be declared, separated by a colon. However, ECO does
not support this.

Optional the class can be entered in addition to the iterator, separated by a colon. However,
ECO does not support the showing of the class.

Using iterators has two advantages:
     •     In more complex expressions an iterator can provide a more distinct presentation
           of the condition
     •     the Iterator, the current element of the collection, can be used as parameter in the
           OCL expression itself.




                                                                                        Page 151
                               3.1 General information for using OCL




Regular Expressions
The OCL-Operator regExpMatch checks, if a string meets the conditions of the specified
regular expression.
For example the expression name.regExpMatch(’A[CST]’) returns TRUE for elements,
whose attribute name begins with “A“ and whose second letter is “C“, “S“, or “T“.
Regular expressions use uses the same syntax as the .net class RegEx to define character
string patterns.

More examples of regular expressions:

Regular             Explanation                                     Result
Expression
J.n                 The point represents any character              Jan, Jon, Jin…
A[cst]              After the “A” either a “c”,”s” or “t” follows   Access, Aspect, At…


Escape-Sequences
In ECO-III the following escape sequences are supported in OCL expressions (string
constants):

          \0      null
          \a      alert (#7)
          \b      backspace
          \t      tab
          \r      CR
          \v      vertical quote (#11)
          \f      formfeed
          \n      newline
          \'      quote
          \\      backslash

In the following example code a new entry that contains a preceding CR/LF (\r\n) is added to
a text field (sLog) text field.

   self.sLog:=self.sLog + '\r\nThis text gets a new section'


Collection types
Very often the result of an OCL expression is a list of objects or values.
In general OCL differentiates between the following collection types:

      •        Bag
      •        Sequence
      •        Set




Page 152
                                     3. ECO and the OCL

A bag is a simple unsorted list of elements that can also contain duplicates. A bag is created
by this simple call:

   CL_Customer.allInstances.sFirstName

This bag contains an unsorted list of the first names of all customers.

A sequence permanently keeps the order of the list elements, even when elements are
added or edited. It is a sequence if, at the access via an association end, the option Ordered
has been set for this association end (see. chapter 2.7.1).

   oCustomer.HasOrders.OrderDate

Based on a customer, the list of orders of this customer is referenced via the association end
HasOrders and the attribute OrderDate is fetched from each order instance.

A set is a collection that doesn’t contain duplicates. To create a set, the OCL operator asSet
is used.

   CL_Customer.allInstances.sFirstName->asSet

Unlike the bag example, in this set no string values appears twice.


3.1.2 Structure elements
OCL provides branching structures as well as operators for getting access to collections and
to pass through collections:
      •    if - then - else - endIf
      •    first, last, at
      •    forAll

The if-then-else branch is used just as in Delphi, with the important difference that the else-
clause is not optional.
First, last and at provide selective access to elements of a collection.
ForAll executes a pass through all elements of a collection and returns TRUE only, if all
elements satisfy the entered condition.

Examples:

   if iPrice>100 then
     ’Product is expensive’
   else
     ’Product is cheap’
   endif

   CL_Customer.allInstances->first
   CL_Customer.allInstances->last
   CL_Customer.allInstances->at(6)

   CL_Cusomer.allInstances->forAll(iAge>=18)




                                                                                     Page 153
                            3.1 General information for using OCL


OCL-expressions also can be recursive, example:
The class CL_Person shall have a recursive association to itself (more on recursive
associations in chapter 2.7.7).
Via the association end Father access to the parent instance shall be possible.

The derived attribute sAllFirstNames of the class CL_Person shall contain a character
string, where the first name of a person and the first names of all of its ancestors are listed.
The OCL derivation expression for sAllFirstNames then could be as follows:

   iF self.Father->IsEmpty then
      sFirstName
   else
      sFirstName + ‘-‘ + self.Father.sAllFirstNames
   endif



3.1.3 Additional Notes
With the isNull Operation in the OCL can be queried if a value is not defined or NULL.

The null-value will be converted to a default value when it is required:

      •    Integer    -0
      •    Decimal    -0
      •    String     - ’’
      •    Boolean    - FALSE
      •    DateTime   - 01.01.0001
      •    TimeSpan   - TimeSpan.Zero

This will also be the case when you navigate relations that are empty.
If there is no Order for a certain customer than an expression like
self.Orders.sProductname will be an empty string.




Page 154
                                   3. ECO and the OCL


3.2 EAL (ECO Action Language)
With ECO-III, a new language was introduced, the Eco Action Language (EAL). It is primarily
used to define effects inside statemachines, but can also be used as a general purpose
scripting language. EAL is a superset of OCL. It contains all features and operations of OCL
and in addition it adds an assign-operation, list-manipulation operations, object
creation/deletion and sequencing of statements (see Chapter 1.3.4).


Calling Class Methods
Now an EAL expression can reference next to their attributes of a class also their methods.
To reference a method by OCL too, it is necessary that the method-property IsQuery is
activated (see Chapter 2.6.6).

In the example [    EAL1] we have defined two classes CL_Order and CL_Orderlines
which are connected with each other via association.




The class CL_Orderline provides the line price of an order line via the function
GetLinePriceByCode. The function GetLinePriceByCode multiplys only the amount and
the price.

  function CL_Orderline.GetLinePriceByCode: System.Double;
  begin
    result := iAmount * iPrice;
  end;

The derived attribute /iValue in the class CL_Order uses the following OCL-expression for
the investigation of the total order value of an assignment:

  self.TheOrderLine.GetLinePrice->sum


Class methods with body
The behaviour of a class method can alternatively be defined using the method-property
body.
In our example we have in parallel to the method GetLinePriceByCode also a method
GetLinePriceByEAL defined, which determines the line price alternatively via the EAL-
expression:

  self.iAmount * self.iPrice

The derived attribute /iValue2 in the class CL_Order uses this method.




                                                                                  Page 155
                              3.2 EAL (ECO Action Language)


Because of their implementation, Class-methods with body can be compared with trigger-
methods. As we have seen in Chapter 2.8.2 (state-diagrams), for every defined trigger-
method a special Delphi-code wrapper within the class-unit (Package_1Unit) is
automatically created, which we should not modify or extend.
For the implementation of the above listed class-method GetLinePriceByEAL the following
code has been generated in parallel:

  function CL_Orderline.GetLinePriceByEAL: Double;
  type
    TArrayOfobject = array of &object;
  begin
    Result := (Double(Self.AsIObject.Invoke('GetLinePriceByEAL',
               New(TArrayOfobject, 0))));
  end;

Also in this case this code-implementation ensures that this method can be executed not
only via EAL but also out of a program code.


Button controls with ActionExpression
With ECO-III there are additional ECO-properties (in WinForms with an
EcoListActionExtender component) available for the button controls. We can assign e.g. an
EAL-statement to the property ActionExpression, which is optional executed to a coded
OnClick-event.
But similar to every OCL/EAL-expression, the placement of the property ActionExpression
demands a first defined context. This context is created via the button-properties RootHandle
and BindingContext. The property EcoListAction is set to ActionExpression.

Within the example we have placed a button Action Add Plus whose ActionExpression
should create and configure a new CL_Orderline Object.
For that we have configured the properties of this button the following:

Property           Value
RootHandle         exphOrderLine
BindingContext     dgOrderLine
EcoListAction      ExecuteAction
ActionExpression   let o=CL_Orderline.Create in
                   (o.sProduct:='SuperTool';o.iPrice:=12345;o.iAmount:=1)

The let-command within the ActionExpression is part of the OCL 2.0 specification and allows
the creation and configuration of local variables. In connection with ECO you can create
ECO-objects with that.




Page 156
                                      3. ECO and the OCL



Make buttons active and visible
When the EcoListActionExtender component is present the button controls consist of two
additional ECO-properties.
The property EnabledOCL can be set to a Boolean OCL-expression. The value of the
expression will control the enabled-attribute of the button.
e.g. with this OCL-expression

   self.iValue > 10000

a button for additional credit-check could get activated, as soon when the order amount is
above € 10.000

In parallel to this, you can manage the visible-attributes of a button via the property
VisibleOCL.
Also here it applies, that for a usage of these properties the OCL-context has to be set
(Properties RootHandle and BindíngContext).

In our example application we have give the button Add (of CL_Order Instances) an
EnabledOCL–property.

State diagrams offer a typical usage area for this functionality.




In general a state transition is executed via a trigger (TrSaleOk). This trigger can only be
used if:

      •    The object state has reached the PRE-node (check) and
      •    Possible Guard-conditions of the trigger are fulfilled

If you now connect the call of a trigger function with a button, you can place the VisibleOCL-
or EnabledOCL-property of the button to the automated available Trigger-Query-Method
(TrSaleOk?).
With that this button is only than ‘enabled’ if the prerequisite for the call of the trigger-method
is given.




                                                                                         Page 157
                              3.2 EAL (ECO Action Language)




EAL and state diagrams
The most important result achieves the EAL in connection with the state diagram. The nodes
and transitions in this diagram are configured via EAL-expressions.
In chapter 2.8 you find more information to the topic state diagrams and also both of the
example applications [ State1 und State2].
Within the example application you will also find a modified example application
[    State1b], which we now want to explain further.

The modification within this example is that next to the class CL_Service another class
CL_Log has been implemented, in which every state change of a service-case with the help
of an explicit CL_Log-Instance is written down.

The until now integrated sLog-textfield within the CL_Service class is no longer needed.




These changes have now especially effect on the entry-actions of the state.
Until now every state change has been added to the local sLog-textfield with an EAL-
expression of the form:

    self.sLog := self.sLog + '\r\nWaiting: ' + self.rNow.asString

Now the modified EAL-expression

    let oLog=CL_Log.Create in (oLog.sLog:='Busy';oLog.MyConnect(self))

takes care that a new CL_Log-Instance gets created, configured and with the method
MyConnect also gets tied to the actual CL_Service-Instance.

Note:
  A more elegant way would be to replace the MyConnect-PascalMethod with an EAL-
  expression in order to get a „pure“ EAL expression:
  let oLog=CL_Log.Create in (oLog.sLog:=’Busy’; oLog.TheService:=self)
  unfortunately this doesn´t work that way but it will be in the next Delphi version (promised
  by Jonas H.).




Page 158
                                  3. ECO and the OCL


ActionLanguageService
In a similar way to ocl expressions that can be executed with coding via the Evaluate /
Execute-Function of the OCL- / OCLPsService, (see chapter 2.6.5 and chapter 3.3), EAL
expressions can be executed with the so-called ActionLanguageService of EcoSpace.

The ActionLanguageService can be called for example with:

    GetEcoService(TypeOf(IActionLanguageService)

It provides various methods, the one used most often is the process Execute. Execute is
provided in several (supercharged) versions and executes the eal expression passed to it.

  var myEALS : IActionLanguageService;
  begin
    // get ActionLanguageService
    myEALS := EcoSpace.GetEcoService(TypeOf(IOCLPsService))
                 AS IOCLPsService;
    // or
    myEALS := EcoServiceHelper.GetActionLanguageService (EcoSpace)

    // execute an EAL expression
    myEALS.Execute('let oLog=CL_Log.Create in (oLog.sLog:= …)');
  end;




                                                                                Page 159
                                         3. ECO and the OCL


3.3 OCLPsHandle and OCLPsService
Since OCL statements can only be executed in EcoSpace (see chapter 3.1), OCL-
Statements that process batch data are very critical concerning their memory use. An OCL
expression like

    CL_Customer.allInstances->select(sFirstname=’Jonas’)

Loads all instances of the class CL_Customer into EcoSpace and executes there the select-
order.

The OCL Operation is transferred into two SQL statements:.

   Select ECO_ID, ECO_TYPE From CL_Person

The first select-query provides a list of object identifiers: aList.

   Select ECO_ID, ECO_TYPE, sFirstName, sLastName ...
     Where ECO_ID in aList

The second select query loads all default attributes of each identifier from aList.
After that the first names are checked in EcoSpace with a filter function.

Note:
  The expression „default attributes“ and the topic loading of object Ids and attributes will be
  dealt with in chapter 4.5.2.


OclPsHandle
Using an OclPsHandle (OCLPersistentStorageHandle) can improve this drastically. Similar to
an ExpressionHandle an OCLPsHandle is placed and configured (RootHandle, OCL-
Expression...) in the non-visual WinForm-ECO-components.

Unlike an expression handle, the OCL expression of an OclPsHandle is not evaluated
automatically, but has to be evaluated explicitly by calling the Execute-method.

Example:

   MyOCLPsH.Expression := ’CL_Person.allInstances->select(iAge>17)’;
   MyOCLPsH.Execute;

In order to realize this OCL expression, an corresponding sql statement is executed on the
database server. This SQL-Statement returns only those object Ids to EcoSpace that meet
the select criteria.

   Select ECO_ID From CL_Person Where (iAge > 17)

The first select order returns a list if object identifiers: aList.

   Select ECO_ID, ECO_TYPE, sFirstName, sLastName ...
     where ECO_ID in aList




                                                                                      Page 161
                             3.3 OCLPsHandle and OCLPsService


The second select order loads all ‘default attributes’ of each identifier from aList.


However, using a OCLPsHandle has some limits concerning functionality:

      •    The OCLPsHandle.Execute method only returns data from the database, and
           doesn’t take into account new or edited objects in EcoSpace (see DirtyObjectList
           in chapter 4.5.3)!
      •    The OCL-Statement can only access persistent attributes; which means derived
           attributes are usually not available.
      •    Typecast functions are not supported by the OCL statement.
      •    More on the limitations in the Delphi-help under „using ECO-Handles “


These limitations lead to, that in practice the usage of OCLPshandle is much more difficult as
in comparison to ExpressionHandles. The example application [    OCLPs] shows some
possibilities, how you can still use OCLPsHandle effectively.
Within this example the instances of the class CL_Customer should be represented in a
data-grid and edited.

To reach a certain ’persistence-effect’ of the OCLPsHandle, 1000 test entries, with different
names have to be created via a button-click. The datagrid should only consider the instances
with the last name exactly 6 characters long, the selection of the data should happen via the
db, which means via OCLPs.

If we now use as for the Grid an ECO-data source with an OCLPsHandle with the
expression:

   CL_Customer.allInstances->select(sLastname.length = 6)

we will get the wanted customer entries, but we will notice that the deletion and adding of
entries – in comparison to the usage of ExpressionHandle – is not shown immediately in the
datagrid, but additional actions are needed, as the saving of data and the again evaluation of
the OCLPs-expression.
This is not surprising, as the OCLPsHandle only represents the objects, which are within the
db and leaves all not saved objects (DirtyObjectList) out.

The solution of this problem is within the combination of OCLPs- and ExpressionHandle.
Here I’d like to give a special thanks to Peter Morris, who has published the solution to this
problem within his EcoSpace-article (http://www.myecospace.net)!

Because of that in the example application, the datagrid will be combined with an
ExpressionHandle, which by itself is again connected with the OCLPsHandle using the root-
property.
To ensure that entries out of the db and also new added and respectively deleted entries are
shown immediately, the ExpressionHandle is using the following expression:

   CL_Customer.allLoadedObjects->select(sLastName.length=6)

The OCL-operator allLoadedObjects delivers all objects located within EcoSpace, also the
ones which have first been loaded through the OCLPsHandle and also the current changes.
The select-statement filters the current changes, which don’t fit to our generic choice
criterion.




Page 162
                                   3. ECO and the OCL


OCLPsService
OCL-expressions can also be evaluated with direct coding, by using the OCLService /
OCLPsService. You can find an example in chapter 2.6.5. There we demonstrated how to
evaluate constraints with the OCLService-Function Evaluate.

  EcoSpace.OclService.Evaluate (’Constraint-Ausdruck’)

Even when using these ecospace service functions directly, the restrictions stated above
concerning memory use and performance on the the one hand and the functional restrictions
of the OCLPsService on the other hand are still valid.

The OCLPsService can be called with GetEcoService(TypeOf(IOclPSService) for
example. It provides various functions, of which the Execute method is used very often as an
equivalent to the OCLService-Evaluate.
Execute is provided in various (supercharged) versions and returns the results in form of an
IObjectList.

  var myPs        : IOclPSService;
      oResultList : IObjectList;
      oObj        : IObjectInstance;
      oPerson     : CL_Person;
  begin
    // get OCLPsService
    myps := EcoSpace.GetEcoService(TypeOf(IOCLPsService))
                 AS IOCLPsService;
    // or
    myps := EcoServiceHelper.GetOCLPsService (EcoSpace);

     // load all adults
     oResultList := myps.Execute
                     ('CL_Person.allInstances->select(iAge>17)');
     i := oResultList.Count;

     // if there are more than 100 ad. then just load the first 100
     if (i > 100) then
        oResultList := myps.Execute
                 ('CL_Person.allInstances->select(iAge>17)', 100, 0);

    // typecasting for each entry
    for oObj in oResultList do
       begin
         oPerson := oObj.AsObject AS CL_Person;
         …
       end;
  end;




                                                                                  Page 163
                                    3. ECO and the OCL



3.4 OCL-Variables
To increase the flexibility of OCL expressions at runtime, OCL variables can be used in ECO.
An OCL variable replaces the static part of an OCL expression in an OCL statement. When
this variable gets modified, the OCL expression gets changed and re-evaluated
automatically.

Example:
The OCL expression

  CL_Person.allInstances->select(sFirstName.RegExpMatch(’ian’))

returns a list of persons, whose first name contains the character string ‘ian’.
We can replace this string with an OCL-String-Variable vFirstName. The OCL-expression is
then:

  CL_Person.allInstances->select(sFirstName.RegExpMatch(vFirstName))

In an OCL expression any number of variables can be used. Each OCL variable is of a
certain type: Integer, String, Object, Date/Time, ObjectCollection etc.

A VariableHandle is required for each variable. The VariableHandle are part of the so-called
non-visual WinForm-Eco-components. In the example to this chapter [       OCLVariables] two
VariableHandles, vhAge and vhFirstName are used.




For each placed VariableHandle we then set the EcoSpaceType-Property in the object
inspector, analogue to RootHandles (see chapter 1.4). Besides that a manual entry in the file
WinForm.PAS is required to assign the EcoSpace to the VariableHandle and to initialize the
handle.

  constructor TWinForm.Create;
  begin
    inherited Create;
    …
    FEcoSpace := TOCLVariablesEcoSpace.Create;
    rhRoot.EcoSpace := FEcoSpace;
    vhFirstName.EcoSpace := FEcoSpace;        //                      Assignment
    vhAge.EcoSpace := FEcoSpace;              //                      Assignment
    …
    vhFirstName.Element.AsObject := '';       //                      Initializing
    vhAge.Element.AsObject:= System.Int32(0); //                      Initializing
    …
  end;

Next we assign the corresponding file type (e.g. string) to the variable handle in the object
inspector with the property StaticValueTypeName.

The assignment of values to a VariableHandle is done with Code.



                                                                                   Page 165
                                     3.4 OCL-Variables


In our example [      OCLVariables] we implemented a search function, that is activated by a
button-click–event. In this method we assign the content of a textbox, in which the user has
first entered the search string, to the VariableHandle vhFirstName.

     vhFirstName.Element.AsObject := TBFirstName.Text;

Through this assignment automatically starts the reevaluation of the OCL expression.

However the connection between the VariableHandle and the Variable itself in the OCL
expression is still missing.

  vFirstName            vhFirstName
  vAge                  vhAge

This connection is created with another non-visual ECO-WinForm-component, the
OCLVariable-component.
We also place this component on the WinForm and set the Property
OCLVariableCollection. A Collection-Editor is assigned to this Property. Using this editor we
enter the two variables vFirstName and vAge and assign the corresponding VariableHandle
to them. An OCLVariable-component can administer any number of OCL-Variables.




In order to be able to use the desired OCL expression

  CL_Person.allInstances->select(sFirstName.RegExpMatch(vFirstName))

in an ExpressionHandle, the OCLVariable-component is assigned to the ExpressionHandle
with its Property Variables. This way the ExpressionHandle knows the OCL-Variables in this
Expression.

In our example we assigned the following expressions to the ExpressionHandle
ehSelectedPersons:




Page 166
                                     3. ECO and the OCL

  CL_Person.allInstances->select(sFirstName.regExpMatch(vFirstName)
  and (iAge = vAge))

After entering a search string for the first name and entering a value for the age, the
VariableHandle gets reset by activating the select button, which leads to the evaluation of the
OCL expression in this expression, which again leads to an updating of the datagrid view.




Note:
  More information to the topics GUI and ECO Handles in chapter 5.1.


Databinding instead of an event method
Instead of editing a VariableHandle with an event method, the databinding concept of .Net
can be used.
For example one could connect the property Databinding-Text of the FirstName-Textbox to
vhFirstName.Self in the example above. This way the textbox permanently displays the
current content of the variable vFirstName. Then each change in the textbox leads to a re-
evaluation of the expression.

Note:
  More information to the topic Databinding in chapter 5.1.3.


Dynamic integration of OCL variables
OCL-Variables can also be used dynamically, without using static components on a
WinForm. To do this we need the IVariableFactoryService to register the OCL-Variable, and
the Evaluate- or EvaluateAndSubscribe-Method of the IOCLService to execute our OCL-
Expression.

The following code shows the basic procedure.
We need variables for:
      •   Access to the IVariableService of EcoSpace (vs)
      •   a dynamic OCLVariable-component (ov)
      •   both OCL-Variables from the example above (iAge and sName)
      •   the integration of the evaluation result in form of an object list (rRet)
      •   the casted access to an instance (e.g. a person) from the result list (oCust)




                                                                                     Page 167
                                      3.4 OCL-Variables


  VAR vs : IVariableFactoryService;
      ov : IModifiableVariableList;
      i,
      iAge : Integer;
      sName : String;
      rRet : IElementCollection;
      oCust: CL_Person;
  begin
    vs := EcoSpace.VariableFactoryService;

     sName := 'John';
     iAge := 66;

     ov := vs.CreateVariableList('vFirstName', sName);
     ov.AddConstant('vAge', iAge);

     rRet := EcoSpace.OclService.Evaluate
       ('CL_Person.allInstances->select
        (sFirstName.regExpMatch(vFirstName) and
        (iAge=vAge))',ov).GetAsCollection;

    i := rRet.Count;
    while (i > 0) DO
       begin
         oCust := CL_Person (rRet.Item[PRED(i)].AsObject);
         ... // further operations follows here
         dec (i);
       end;
  end;

First we set the connection to the IVariableFactoryService and initialize both search variables
with the search strings.
After that the VariableList-component is created by passing the first variable, then the second
variable is added.
To start our OCL query it now follows the evaluate call.
In the finishing loop, the individual elements are cast as CL_Person, they are now ready to
be processed further.




Page 168
                                    3. ECO and the OCL



3.5 User-defined OCL-Operations
The Update 2 for Delphi 2005 enables the user to implement custom OCL operators in ECO.


An example
Again the procedure will be explained with a little example [     CustomOCL]. Our model
example consists of only one class CL_Person, that contains the attribute rDateOfBirth and
the derived attribute iAge.

The OCL function CalcAge, which is to be implemented new in our example, should contain
the date of birth of a person as an input parameter (DateTime) and with that to calculate the
age of that person, based on date of birth and the current system date.
To make this happen, we created a unit AdditionalOCL in our example, that contains the
implementation of the new OCL function.

First we define a new class in the Unit AdditionalOCL, that has to be derived from
OclOperationBase (Namespace: Borland.Eco.Ocl.Support ).
Such a class always contains the code for one OCL Function and implements the methods
Init and Evaluate for it.

  TOCLCalcAge = Class (OclOperationBase)
    strict protected
       procedure Init; override;
    public
       procedure Evaluate(Params:IOclOPerationParameters); override;
  end;

The method Init determines the name, the input parameters and the return value of our OCL
operation (integer).

But please take care that the instance that is supposed to call the new OCL operation later
on, is always passed as the first parameter.
So if we call oPerson.CalcAge (self.rDateOfBirth)for an instance oPerson of the
class CL_Person in our example, two parameters are passed, oPerson and
self.rDateOfBirth!

  procedure TOCLCalcAge.Init;
  var aParams : Array OF IOCLType;
  begin
    SetLength (aParams, 2);
    aParams[0] := Support.ObjectType; // the calling Person himself
    aParams[1] := Support.DateTimeType; // the DateOfBirth-Param
    InternalInit ('CalcAge', aParams, Support.IntegerType);
  end;

The method evaluate calculates the return value based on the input parameters. Which is
implemented in our example with Support.MakeNewInteger.




                                                                                   Page 169
                             3.5 User-defined OCL-Operations


  procedure TOCLCalcAge.Evaluate (Params : IOclOPerationParameters);
  var dtNow,
       dtBirth : DateTime;
       iAge    : Integer;
  begin
    dtNow := DateTime.Now;
    dtBirth := Support.GetAsDateTime(Params.Values[1]);
    iAge := dtNow.Year - dtBirth.Year;
    Support.MakeNewInteger(Params.Result, iAge);
  end;

At last the new OCL operation has to be reported to the Eco system at runtime.
In our example we coded a button-click-event, that registers the new OCL operation with
InstallOperation, a method of the IOCLService.

  procedure TWinForm.BtnInitOCLOperation_Click(sender:
                                               System.Object;
                                               e: System.EventArgs);
  var MyOCLCalcAge : TOCLCalcAge;
  begin
    MyOCLCalcAge := TOCLCalcAge.Create;
    EcoSpace.OclService.InstallOperation(MyOCLCalcAge);
    …
  end;

When we start our small application, we first have to activate the operator registration with
the button. After that we can add persons to the list.
As soon as we enter or change the date of birth of a person, the column iAge displays the
corresponding age.




Page 170
                                  3. ECO and the OCL


OCLOperation – Programming interface
The Namespace Borland.Eco.Ocl.Support provides classes and interfaces for the
handling of OCL-Operations. The base class of an OCL-Operation is OCLOperationBase, its
Standard-Interface is IOCLOperation.
IOCLOperation provides the following properties and methods:

Name               explanation
Name             Name of the OCL-Operation
DeduceMethod     Classifies   the  result   type   of  the   operation
                 (OCLResultTypeDeduceMethod): ExplicitType,
                 TypeOfSource,     TypeOfFirstParam,      SourceAsBag,
                 MetaType…
FormalParameters List of parameters of the operation
RepeatParameters always = 0
ResultType       Results data type of the operation
IsDotNotation    FALSE = collection-Operator “->” instead of “.” (see
                 chapter 3.1.1)
IsTypeOperation  always = FALSE
ModifiesSource   always = FALSE
SemanticCheck    Evaluation method
Evaluate         Evaluates the result of the operation
Initialize       Initializes the operation

By default the Evaluate-Method uses a Parameter-Object                   of   the   type
IOCLOperationParameters, that contains the following properties.

Name              Explanation / examples
Values            Contains the list of passing parameters of the ocl
                  operation
Result            Contains the result of the operation (IOCLType). The
                  the   key    value   of  Result  is administrated  in
                  Element:IElement (see chapter 4.1). the assignment
                  happens either with one of the methods of Result (for
                  example SetOwnedElement), or Result is passed as
                  parameter to a support function like for example
                  MakeNewInteger (see next table).
SubscriberBlock   Option     of    implementing    a  subscription.   a
                  ValueChangeSubscriber and a ResubscribeSubscriber are
                  provided.

If we derived an extra class from OCLOperationBase, the interface IOCLOperationSupport is
provided via the Property Support.




                                                                                Page 171
                              3.5 User-defined OCL-Operations


This interface provides the following functions:

Name                Explanation / examples
All data types      BooleanType,    ByteType,          StringType,     ObjectType,
that can be used    ObjectListType…
in OCL
TypeCasting         GetAsBoolean, GetAsString, GetAsList…
Access         to   Property Model (see chapter 4.2)
EcoTypeSystem
Zugang zu ECO-     OCLService,   ObjectService,    VariableFactoryService,
Services           UndoService,       ExtentService,       VersionService,
                   ExternalIDService
Creation    of a CreateNewConstant,                     CreateNewVariable,
new         object CreateNewSimpleVariable
(IElement)
Value            MakeNewInteger, MakeNewBoolean, MakeNewString...
assignment to an
OCL-Parameter

ECO supports the implementation of custom OCL-Operations with the EcoSpace-Service
TypeService / OCLService. This provides the following functions.

Name                  explanation
InstallOperation    Installs a new OCL operation
InstalledOperations Provides a list of all installed             ocl   operations
                    (108).




Page 172
                                          3. ECO and the OCL


    3.6 OCL-expressions: overview
    Arithmetic
Name             explanation              Parameter result              example
+                Addition                 number      number            Quantity + 6
-                Substraction             number      number            Price – 9.95
*                Multiplication           number      number            Quantity * price
/                Division                 number      number            Quantity / 10
abs              Absolute                             Positive number   Value.abs
round            rounded                              Integer           Value.round
floor            Integral part                        Integer           Value.floor


    String-Operators
Name             explanation              Parameter          result     example
+                Connection                                  String     text + more
                 between two strings
asString         Stringrepresentation     any                String     Price.asString
concat           Connection               String             String     text.concat(more)
                 between two strings
length           Number              of                      Integer    name.length
                 characters of a
                 string
pad              Filling a string from
                                    length:Integer,          String     name.pad(10,’-’)
                 the left side      filling
                                    character:String
postPad       Filling a string from length:Integer,          String     name.postPad(10,’-’)
              the right side        filling
                                    character:String
subString     Substring of a string Start:Integer,           String     name.subString(5,8)
                                    End:Integer
toLower       Transformation to                              String     name.toLower
              lower case
toUpper       Transformation to                              String     name.toUpper
              upper case
regExpMatch Match check             Regular                  Boolean    name.regExpMatch
                                    expression:String                   (’[ABC]’)
sqlLike       Match check           Ansi-SQL-Like            Boolean    name.sqlLike(’%ian%’)
                                    String:String
sqlLikeCase- Match check            Ansi-SQL-Like            Boolean  name.sqlLikeCase-
Insensitive                         String:String                     Insensitive(’%ian%’)
strToDateTime Transformation of a                            DateTime SDate.StrToDateTime
              string to a date-
              time-value
strToDate     Transformation of a                            DateTime SDate.StrToDate
              string to a date-
              value




                                                                                       Page 173
                               3.6 OCL-expressions: overview


 Boolean-Operators
Name           explanation             Parameter            result    example
=              Equal to                any                  Boolean   Name = ’Alpha’
<>             unequal                 any                  Boolean   Name <> ’Alpha’
>              Greater than            any                  Boolean   Quantity > 100
<              Less than               any                  Boolean   Quantity < 10
>=             Greater than or equal   any                  Boolean   Quantity >= 100
               to
<=             Less than or equal to   any                  Boolean   Quantity <= 10
or             or                      Boolean              Boolean
and            and                     Boolean              Boolean
not            not                     Boolean              Boolean
xor            Exclusive or-link       Boolean              Boolean
implies        Condition a implies     Boolean              Boolean   (sum > 0) implies
               condition b                                            (price > 0)


 Date-and-time-Operators
Name             explanation       Parameter      result      example
dateTimeAsFloat Transformation                    number      Mydate.DateTimeAsFloat
                ofd a date or
                time into a
                number
IiDateRange     Check if date      Upper limit:   Boolean     Mydate.InDateRange
                is within a        number,                    (firstdate.DateTimeAsFloat,
                certain    date    lower limit:               secDate.DateTimeAsFloat)
                span               number
iiTimeRange     Check if time      Upper limit:   Boolean     MyTime.InTimeRange
                is within a        number,                    (firstTime.DateTimeAsFloat,
                certain    time    lower limit:               secTime.DateTimeAsFloat)
                span               number
sumTime         Addition      of                  DateTime worktime.sumTime
                times
formatDateTime Formatting a        Formatstring String     MyDate.FormatDateTime          (dd
                date-time-                                 mmm yyyy)
                value                                      -> 01 Januar 2001
strToDateTime   Transformation                    DateTime SDate.StrToDateTime
                of a string into
                a    date-time-
                value
strToDate       Transformation                    DateTime SDate.StrToDate
                of a string into
                a date- value




 Page 174
                                        3. ECO and the OCL


     Access to class instances
Name                 explanation     Parameter           results       example
allInstances       All objects of a                  Object            MyClass.allInstances
                   class                             list
allLoadedObjects All objects of a                    Object            ….allLoadedInstances
                   class already                     list
                   loaded      into
                   ECoSPace
allInstancesAtTime All objects of a TimeStamp:number Object            ....allInstancesAtTime
                   class already                     list
                   loaded      into
                   ECoSPace,
                   with a certain
                   version
                   number
atTime             All objects of a TimeStamp:number Object            …allInstances.atTime(x)
                   certain version                   list
                   number
exisiting          ExistenceState                    Boolean           if oPerson.existing ...
                   eines Objektes
emptyList          Empty list                        Object            MyClass.EmptyList
                                                     list


     Elementary collection-Operators (use “->“ instead of “.“!)
Name                explanation         Parameter            result       example
first               First element of a                       Element      CL_Person.
                    list                                                  allInstances->first
last                Last element of a                        Element      CL_Person.
                    list                                                  allInstances->last
at                  Nth element of a Position:Integer        Element      CL_Person.
                    list               (1,2,3…)                           allInstances->at(5)
size                Number of list                           Integer      CL_Person.
                    elements                                              allInstances->size
count               Number of copies Element:Object          Integer      CL_Person.
                    of a list element                                     allInstances-
                                                                          >count(x)
sum                 Sum of all values                        number       CL_Product.
                    in a number list                                      allInstances.Price-
                                                                          >sum
minValue            Smallest value in                        Number       CL_Product.
                    a number list                                         allInstances.
                                                                          Price->minValue
maxValue            Largest value in                         number       CL_Product.
                    a number list                                         allInstances.
                                                                          Price->maxValue




                                                                                     Page 175
                                     3.6 OCL-expressions: overview


   Collection-Operators for checks (use “->“ instead of “.“!)
Name            explanation          Parameter            result      example
isEmpty         Checks if list is                         Boolean     CL_Person.allInstances
                empty                                                 ->select(sFirstName=…)
                                                                      ->isEmpty
isNotEmpty      Checks if list                            Boolean     CL_Person.allInstances
                contains        at                                    ->select(sFirstName=…)
                least         one                                     ->isNotEmpty
                element
exists          Cheks if a list      condition:Boolean    Boolean     CL_Person.allInstances
                element meets                                         ->exists(sFirstName=…)
                the      specified
                condition
includes        Cheks if the         Element:Object       Boolean     CL_Person.
                specified                                             allInstances
                element exists                                        ->includes(x)
                in a list
includesAll     Checks if all        MasterList:Collection Boolean    CL_Person.allInstances.
                elemnts of a list                                     sFirstName->includesAll
                exist in the                                          (AllNames.allInstances)
                specified list
forAll          Checks if all        Bedingung:Boolean    Boolean     CL_Person.allInstances
                elements in a                                         ->forAll(iAge>18)
                list meet the
                specified
                condition


   Collection: Sorting, Grouping and Selection ((use “->“ instead of “.“!)
Name              explanation            Parameter result            example
orderBy         Sorts a list , Sorting       collection              CL_Person.allInstances
                values increasing field:                             ->OrderBy(sLastName)
                                  expression
orderDescending Sorts a list , Sorting       collection              CL_Person.allInstances
                values decreasing field:                             ->OrderDescending(…)
                                  expression
collect         Combines lists    any        collection              CL_Customer.allInstances
                                                                     ->collect(Orders->size)
select            Selection of list      condition:   collection     CL_Customer.allInstances
                  elements      that     Boolean                     ->select(Firstname=’Jo’)
                  meet the specified
                  condition
reject            Extraction of list     condition:   collection     CL_Customer.allInstances
                  elements      that     Boolean                     ->reject(Firstname=’’)
                  meet the specified
                  condition




   Page 176
                                        3. ECO and the OCL

   Collection: comparison- or -amount-Operators (use “->“ instead of “.“!)
Name            explanation            Parameter result         example
difference      Selection of Base      ParamList: collection    CL_NewCustomer.
                list.ParamList         Collection               allInstances->difference
                elements, that are                              (CL_Customer.allInstances)
                not part of the
                ParamList.base
                list
symetric-       Selection         of   ParamList: collection    CL_NewCustomer.
Difference      elements that are      Collection               allInstances
                either part of the                              ->symetricDifference
                ParamList or part                               (CL_Customer.allInstances)
                of the Base list
Iitersection    Selection         of   ParamList: collection    CL_NewCustomer.
                elements that are      Collection               allInstances->intersection
                part of ParamList                               (CL_Customer.allInstances)
                AND base list
                (intersection)
union           Addition          of   ParamList: collection    CL_NewCustomer.
                parmaList              Collection               allInstances->union
                elements         and                            (CL_Customer.allInstances)
                Base list elements
                (double      entries
                possible!)
excluding       Selection of all       Element:    collection   CL_NewCustomer.
                base list elements     Object                   allInstances->excluding
                except the passed                               (ThisCustomer)
                element
Iicluding       Selection of all       Element:    collection   CL_NewCustomer.
                base list elements     Object                   allInstances->including
                plus the passed                                 (ThisPerson)
                element
subsequence     Selection of base      Start,      collection   CL_NewCustomer.
                list elements from     End :                    allInstances->subsequence
                position start t       Integer                  (15, 30)
                oposition end




                                                                                 Page 177
                                3.6 OCL-expressions: overview



  Metadata: Type-Operators
Name           explanation               Parameter       result    example
oclType        Element type                              OclType    CL_Person.allInstances
                                                                    ->first.oclType
typeName       Name        of      the                   String     CL_Person.allInstances
               element type                                         ->first.typeName
filterOnType   Filters     a      List   Filter value:   collection CL_Customer.allInstances
               according            to   Metatype                   ->filterOnType (TStatus)
               characteristics of an
               OclType
oclIsTypeOf    Checks       if      an   Check value: Boolean      If ThisObject.isOclTypOf
               element is of the         Metatype                  (Person) then...
               specified OCL type
               (100%         identical
               types only)
oclIsKindOf    Checks       if      an   Check value: Boolean      If
               element is of the         Metatype                  ThisObject.isOclKindOf
               specified OCL type                                  (Person) then...
               (with the supertype
               identical as well)
oclAs Type     Transformation into       New             Element, ThisObject.oclAsType
               the specified OCL         OclType:        collection (Person)
               type (can only be         Metatype
               transformed        into
               supertype)
saveCast       Transformation into       New             Element, ThisObject.saveCast
               the specified OCL         OclType:        collection (Person)
               type (result= NIL,        Metatype
               OclType is illegal)




  Page 178
                                       3. ECO and the OCL

  Metadata: Structure-Operators
Name              explanation              Parameter result   example
superTypes      Supertype of an                      Metatype CL_Person.superTypes
                element
allSuperTypes   List        of       all             Metatype- CL_Person.allSuperTypes
                supertypes of an                     collection
                element
allSubClasses   List        of       all             Metatype- CL_Person.allSubClasses
                subclasses of an                     collection
                element
attributes      List of all class                    Metatype- CL_Person.attributes
                attributes       (even               collection
                those        of     the
                supertypes)
associationEnds List        of       all             Metatype- CL_Person.associationEnds
                association ends of                  collection
                a class (even those
                of the supertypes)
constraints     List of all constraints              Metatype- CL_Person.constraints
                of a class (even                     collection
                those        of     the
                supertypes)




                                                                               Page 179
4. ECO at runtime (EcoSpace-Coding)
At runtime only the “current” instances of classes of an ECO application are located in
EcoSpace and only there they can be edited.
Which instances get loaded into or deleted from EcoSpace, is mainly decided by user activity
in the interface. The visualization and editing of object data in datagrids, text- and listboxes
etc. is done automatically via EcoSpace, so in theory no EcoSpace methods have to be
explicitly called.

Of course in practice there are lots of scenarios, where explicit coding in EcoSpace is
required, which is intended this way in ECO. Some scenarios are:

      •   Redo- and Undo-Handling
      •   Creating and editing objects without GUI interaction
      •   Automatic notification of objects in case of value changes: subscription
      •   Coordination of multi user access: synchronization
      •   Maintenance of data consistence: transactions and locking methods
      •   Performance: caching and pooling

In chapter 2.1 to 2.9 we primarily dealt with EcoSpace properties concerning the modelling of
an ECO application. In this chapter we will provide the basics and some examples of working
with EcoSpace at runtime.

In the chapters 4.1 and 4.2 we will try, to get an overview of the structure of the EcoSpace,
ist services and methods.



4.1 Access levels of EcoSpace
The chapter 2.3 gives an overview of all services available through EcoSpace.

You have three possibilitites to access the separate services, this will be shown in the
following example of the TypeSystemService

   var myTSS : ITypeSystemService;

   // direct (not available for all services!)
   myTSS := EcoSpace.TypeSystemService;

   // using the getter function (available for some services only!)
   myTSS := Ecospace.GetTypeSystemService;

   // using the common GetEcoService function
   myTSS := ITypeSystemService
              (Ecospace.GetEcoService(TypeOf(ITypeSystemService)));

   // using the common EcoServiceHelper class
   myTSS := EcoServiceHelper.GetTypeSystemService(EcoSpace);




                                                                                      Page 181
                               4.1 Access levels of EcoSpace


                                                                    ,
EcoSpace provides 3 levels for object access, the ECO-Object-level, the IElement-level and
the ICache-level.
In this chapter we will deal with the ECO-Object- and the IElement-level. The ICache-level is
explained in detail in chapter 4.4.


ECO-Object
The Eco-Object-level is model-based. An Eco-object can be e.g. an instance of the class
CL_Person or the attribute sFirstName of such an instance.

Starting from an Eco-class instance you can reach the IElement level using the function
AsIObject.

  // To delete a class instance, you use the delete method at the
  // IElement-level.

  oPerson.AsIObject.Delete;


IElement
The IElement-level provides an access which is not type-dependent. Here object access
takes place without knowing the corresponding UML model information.
This level is used for example by ECO-handles like the Root-, Expression- or
CurrencyManager-Handle, in order to make them applicable for all purposes, see. chapter
5.1.1.

  //   The property Element provides the access to the IElement level
  //   for all eco handles.
  //   A specific SubInterface of IElement (i.e. IObject) then
  //   provides a model specific handling.

  (cmhCustomer.Element AS IObject).Delete;

You can always switch from an IElement-Object to the Eco-object level with the AsObject-
Function.

  //   the type independent CurrencManagerHandle cmhCustomer points
  //   to the currently selected CL_Customer instance in the datagrid.
  //   AsObject provides a model based version of that object
  //   Then an additional typecast enables direct assignment to a
  //   Customer object

  oCustomer := cmhCustomer.Element.AsObject As CL_Customer;

  // Starting at the IElement level of the instance oCustomer,
  // we can convert the IElement (=IProperty) of an attribute of
  // this instance back to an ECO object of type Integer.

  iProperty := oCustomer.AsIObject.Properties.Item['iCustNo'];
  iCustNo := iProperty.AsObject;




Page 182
                            4. ECO at runtime (EcoSpace-Coding)

An IElement can stand for a class instance or the instance of a statemachine, which is
connected to the class, as well as for an attribute or association end of an class instance. It
can also represent class-independent values like strings or collections .
Depending on the object type a sub interface of IElement, for example IObjectList, IObject,
IobjectStateMachine, IPrimitive etc. is used. The Property ContentType of an IElement
determines the corresponding type.

A class instance on the IElement level is represented by an IObject. The components of the
instance, its attributes, embedded association ends etc. are represented in the IObject by a
property list.
Each property of this list is an IElement itself, for example an IPrimitive, if the component is a
class attribute.
To represent a component in form of an association end with an n-multiplicity, a property in
form of an IObjectList is required. Of course for each object (=instance of the associated
class) of this IObjectList a property list for its attributes exists etc...

The new added IObjectInstance with ECO-III offers compared to IObject a new broadened
interface, which contains in addition the Property StateMachine.
Along with the change to ECO-III the previous type IObject has been replaced through
IObjectInstance within a few EcoSpace-functions (see list below), which as a parameter or
as a function value expects or deliver a class-instance on IElement-level.

   IObjectFactoryService.CreateNewObject
   IObjectList.Item
   IExternalIdService.ObjectForId
   IVariableFactoryService.NullReference
   …

IObjectInstance is as a property within the IObject-level available.

The following code section displays – with an example of the class CL_Person with two
            s
attributes (sFirstName and sLastName : String) the common properties and methods for
reading the structure and content of an ECO object (class instance) on IElement level.

note:
  You will find detailed information on the analysis of UML structure information at runtime
  of an ECO application in the next chapter 4.2.




                                                                                        Page 183
                              4.1 Access levels of EcoSpace


  //   An IObject ist the IElement counterpart to a class instance.
  //   IObject.Properties represents the list of all components of a
  //   class instance (for ex. both attributes).
  //   An IProperty as special kind of an IElement can also be an
  //   IObject, IPrimitive, IObjectList etc.
  //   The attributes sFirstName and sLastName are IPrimitives.
  //   StructuralFeature.Name provides the name of the property.
  //   UmlDataType provides the complete datatype of the property.
  //   UmlDataType.ObjectType provides the datatype without namespace.
  //   We have read and write access to the propertys value.

  var oPerson    : CL_Person;
      iObj       : IObject;
      iProp      : IProperty;
      sPropValue,
      sPropName : String;
  …
  iObj := oPerson.AsIObject;
  for i := 1 TO iObj.Properties.Count do
    begin
      iProp := iObj.Properties.Item[Pred(i)];
      sPropName := iProp.StructuralFeature.Name;
      if (iProp.ContentType = ContentType.Primitive) THEN
          begin // Attribute: sFirstName, sLastName
            if (iProp AS IPrimitive).UmlDataType.ObjectType =
               TypeOf(String) THEN
               sPropValue := (iProp AS IPrimitive).AsObject.ToString;
            if (sPropName = ’sFirstName’) THEN
               (iProp AS IPrimitive).AsObject := ’Peter’;
          end;
  …

In case an IElement doesn’t only represent an single ECO object but an ECO object list, the
function GetAsCollection can be of use.

  // When evaluating any kind of constraint expression the result
  // type is unnknown. The maximum return type is a collection.
  // That’s why we use GetAsCollection here.

  var rColReturn : IElementCollection;
  …
  s := ’any Constraint expression’;
  rColReturn := MyOCLService.Evaluate (NIL, s).GetAsCollection;
  if (rColReturn.Count = 1) THEN
      begin // Eavluating OCL exactly provides one result
        if (rColReturn.Item[0].AsObject.UmlDataType.ObjectType =
            TypeOf (Boolean)) THEN // and this is a boolean
           bOk := Boolean (rColReturn.Item[0].AsObject)
    …




Page 184
                           4. ECO at runtime (EcoSpace-Coding)


4.2 The model structure at runtime (UML-RT)
In .Net-applications data- and object structures can be accessed with the so-called
reflection. With those classes, attributes, operators etc. of an ECO UML model can be
examined at runtime.
A reflection example can be found in the section method-analysis with reflection in chapter
4.2.3.

ECO also provides access to meta data respectively the type information of the model
 I
(IEcoTypeSystem) with the namespace Borland.Eco.UmlRt.


4.2.1 UML- and ECO-Interface
The NameSpace Borland.Eco.UmlRt defines the interfaces for all model element types like
IClass, IAttribute, IAssociation etc. we can see in the online help, that for some model
element types two specifications exist, a UML version and an ECO version.

          UML-Version                           ECO-Version
          IClass                                IEcoClass
          IStateMachine                         IEcoStateMachine
          IMethod                               IEcoMethod
          IPackage                              IEcoPackage
          IClassifier                           IEcoClassifier
          IAssociationEnd                       IEcoAssociationEnd
          IStructuralFeature                    IEcoStructuralFeature
          IEnumerationLiteral                   IEcoEnumerationLiteral

The reason for this division into two parts is, as mentioned in chapter 1.3, that an ECO class
model contains additional properties compared to a UML model. These additional properties
can only be accessed with the according ECO interface.
We can always access the ECO versions of an interface type directly from the UML interface.

  var MyClassifier    : IClassifier ;
      MyEcoClassifier : IEcoClassifier;
      MyFeature       : IStructuralFeature;
      MyEcoFeature    : IEcoStructuralFeature;
      MyClass         : IClass;
      MyEcoClass      : IEcoClass;
  …
  MyClassifier := oPerson.AsIObject.UmlType;
  MyEcoClassifier := MyClassifier.EcoClassifier;

  MyFeature := IStructuralFeature (MyClassifier.Features.Item[1]);
  MyEcoFeature := MyFeature.EcoStructuralFeature;

  MyClass := oPerson.AsIObject.UmlClass;
  MyEcoClass := MyClass.EcoClass;




                                                                                    Page 185
                        4.2 The model structure at runtime (UML-RT)


IClass / IEcoClass
On the IElement-level the Property UMLClass or more general UMLType AS IClass
provides access to the IClass-Interface. In IClass we find the ‘common’ elements of the
model element type Class.

Properties and Methods of IClass
Access: MyClass:=oPerson.AsIObject.UMLClass

  Name               explanation                            example: class CL_Person
  Name               Name of the class                      ’CL_Person’
  EcoClass           Further ECO-specific Properties        see next grid
                     see next table IEcoClass
  Association        Parameter of an association            AssociationEnd
  IsAssociationClass attributed Association?                TRUE/FALSE
  SubTypes           sub Elements                           CL_Customer
  SuperTypes         super Elements                         EcoModelRoot
  ObjectType         the CLR-Type of the Classifier         Package_1Unit.CL_Person
                     (fully qualified type name)
  Features           Collection of the Ifeature             see chapter 4.2.3
                     elements of the Classifier
  StateMachine       Link to the statemachine of the        see section
                     class                                  IStateMachine
  Constraints        List of Constraints                    MyNameConstraint =
                                                              sLastName <> ’’
  Features             Collection of IFeature-Elements      see next grid
                       of the Classifier (see next table)
  TaggedValues         List of TaggedValues                 ECO.TableName
  Package              The ECO-Package, where the           see chapter 4.2.2
                       class is modelled


Properties and Methods of IEcoClass
Access: MyClass:=oPerson.AsIObject.UMLClass.EcoClass

  Name                            explanation               example: class CL_Person
  DefaultStringRepresentation     Defines the AsString-     self.sFirstName +
                                  value of an object        ’ ’ + self.sLastName
  Versioned                       Activate versioning       see chapter 2.5
  Persistent                      Activate persistence      Persistent/Transient
  IsLinkClass                     Association class         see chapter 2.7.5
  InternalIndex                   Internal class ID         see chapter 4.3
                                  (Integer)
  ID                              UML-ID of the class       [UmlElement(Id='be94261…
                                  (String)
  GenerateDefaultRegion           Activate regions          see chapter 2.9
  OptimisticLockingMode           Activate opt. locking     see chapter 4.7.3
  SuperClass                      IClass of Superclass
  AllMethods                      List of class methods     see section IMethod
  AllStructuralFeatures           Struktural information    see chapter 4.4.2
                                  of class elements




Page 186
                            4. ECO at runtime (EcoSpace-Coding)


IStateMachine / IEcoStateMachine
If one or multiple state diagrams (sd) are assigned to a class, IStateMachine provides the
Properties and components of this sd. The list of sds of a class is a collection of regions,
where each node in a sd can contain other sub diagrams (regions) (hierarchic structure, see
chapter 2.8).

Properties and Methods of IStateMachine
access: MyStateMachine := oService.AsIObject.UMLClass.StateMachine

  Name                    explanation                         Example: class CL_Service
  Name                    Class name                          ’CL_Service’
  EcoStateMachine         Contains the                        GetTriggerByName...
                          FullStateMachineName, a
                          collection of all StateAttributes
                          (AllStateAttributes) and various
                          access functions
  Regions                 Collection of regions.              Regions.Item[0].
                          With each region comes a state      Transitions.Item[x].
                          diagram.                            Trigger
                          Region.Item[0] = the first state
                          diagram of a class.
                          (see next table)
  Constraints             Not in use
  TaggedValues            List of TaggedValues                ECO.StateAttribute
  Package                 ECO-Package                         see chapter 4.2.2


Properties and Methods of IRegion
access: MyEcoRegion := oService.AsIObject.UMLClassStateMachine.Regions.Item[x]

  Name                      explanation                              Example: class
                                                                     CL_Service
  Name                 Name of the region in the state               ’ZD_Service1’
                       diagram
  Vertexes             Collection of nodes                           Vertexes.Item[x].
                       (IVertexCollection). Each node                Incoming...
                       contains entries and exits, various
                       parameters (IEcoVertex) and a
                       region container.
  Transitions          Collection of transistions                    Transitions.Item[x].
                       (ITransitionCollection). Each                 Guard...
                       transistion contains a link to the
                       source and target node, a guard-
                       and effect expression, etc.
  Container            Link to the super StateMachine
                       (see previous table)
  FullStateMachineName identifier                                    ’ZD_Service1’
  EcoRegion            State-Parameter of the Region                 IsTopLevel = TRUE
                       (StateAttribute, InitialState,
                       AllStates...)
  Constraints          Not in use
  TaggedValues         List of TaggedValues                          ECO.StateAttribute
  Package              ECO-Package                                   see chapter 4.2.2




                                                                                      Page 187
                        4.2 The model structure at runtime (UML-RT)


IMethod / IEcoMethod
The methods of a class are administrated in a collection (IMethodCollection) that can be
accessed with the property AllMethods of the IEcoClass Interface.

Properties of IMethod
access: MyMethod := oPerson.AsIObject.UMLClass.EcoClass.AllMethods.GetItemByName(...)

  Name                          explanation                 example: class CL_Person
  Name                          Name of the method          CurrentAge
  Parameters                    Parameter
  ReturnType                    Result value
  IsQuery                       IsQuery-Property            see chapter 2.6.6
  Visibility                    visibility                  Private, Protected,
                                                            Public, Package
  OwnerScope                    Instance- or class          Instance, Classifier
                                method
  EcoMethod                     Additional eco-specific     see next grid
                                properties
  FeatureType                   Association, Attribute or   always method
                                Method
  EcoFeature                    ID of the method
  Owner                         owner (IClassifier of the
                                class)
  Constraints                   Not in use
  TaggedValues                  List of TaggedValues        ECO.IsTrigger…
  Package                       ECO-Package                 see chapter 4.2.2


Properties of IEcoMethod
access: MyMethod := oPerson.AsIObject.UMLClass.EcoClass.AllMethods.GetItemByName(...).EcoMethod

  Name                          explanation                        Example:class
                                                                   CL_Person
  Implementation                EAL-Code of a method               see chapter 3.2
                                (Property body)
  Trigger                       Trigger-Name and IMethod-Link      see chapter 2.8
                                to the Trigger method
  PreCondition                  OCL-precondition                   see chapter 3.2
  MethodInfo                    provides all details of a method   ReturnType,
                                and an invoke function             GetParameters,
                                                                   Invoke (...), …
  ID                            ID of the method
  IsTrigger                     Method is a Trigger method       TRUE/FALSE
  IsImplementedAsActivity       Is used as an effect method in a TRUE/FALSE
                                transition
  IsEcoCallable                 ?                                TRUE/FALSE




Page 188
                          4. ECO at runtime (EcoSpace-Coding)


4.2.2 Basic components
In almost all elements (Class, Statemachine, Method...) of the EcoTypeSystem we’ll stumble
upon the 3 base components Packages, TaggedValues and Constraints. The structure of
these base components can be displayed as follows:




TaggedValues
In an ECO-Model some ECO-Properties of the model or the model elements are saved as
TaggedValue. It’s also possible to make custom TaggedValues, although they cannot be
defined in the UML diagram but only directly in the code (CoreClasses.PAS). For the
definition of TaggedValues see chapter 2.6.3 and chapter 4.1.2.

TaggedValues are always organised as a collection. Each TaggedValue consists of a Tag
and a Value, both of the type string.

On the top model level the following ECO-TaggedValues can be found.

  ECO.GenerateMultiplicityConstraints = True
  ECO.OptimisticLocking = Off
  ECO.GenerateDefaultRegions = True

  // Access:
  EcoSpace.TypeSystemService.TypeSystem.TaggedValues[x].Tag…

On the class level ECO administers the following TaggedValues.




                                                                                 Page 189
                        4.2 The model structure at runtime (UML-RT)


  ECO.TableName
  ECO.Versioned
  ECO.DerivationExpressions…

  // Access using UMLClass:
  oPerson.AsIObject.UmlClass.TaggedValues.Item[x].Tag…

On the class attribute level we can find the following TaggedValues.

  ECO.Length
  ECO.DelayedFetch
  ECO.AllowNull…

  // Access using iFea = IFeature of an IClassifiers of a class:
  oPerson.AsIObject.UmlClass.Features.Item[0].TaggedValues.Item[x]…


Constraints
A Constraint consists of the name (String) and a body structure. The body consists of the
property Language (String), that has the default value „OCL“ in ECO models, and the
property Body (String), that represents the constraint value.
Like with taggedvalues, we distinguish constraints set by ECO automatically from user-
defined constraints. More about the use and the differences between both constraint types in
chapter 2.6.5.

Like TaggedValues, constrains exist in general on the top model level as well as on the
element level of a UML model
However, as far as I know, constraints are used in ECO only on the class level. There you
find the automatically generated constraints, which can be used to check the multiplicity
constraint of association ends with multiplicity 1 as well as user defined constraints.

  // Created automatically (siehe example below)
  Owner Multiplizitätsbedingung = self.Owner->notEmpty

  // Created by user input (siehe example below)
  MyNameConstraint = sLastName <> ’’


Packages
ECO-Models are divided into packages (see chapter 2.10). A package administrates a
certain number of model elements and has the following properties.

  Name                         explanation                         example
  Name                         identifier                          ’Package_1’
  OwnedElements                Collection of all model elements
                               (IModelElement)
  EcoPackage                   UML_ID of the Package and list of   EcoPackage.ID=
                               classes, associations and Sub-      ’be94261...’
                               Packages
  Constraints                  Not in use
  TaggedValues                 List of TaggedValues                ECO.IsTrigger…
  Package                      ECO-Package




Page 190
                             4. ECO at runtime (EcoSpace-Coding)


4.2.3 Access to a model element
The central base for accessing the model structure at runtime is the Property TypeSystem of
the Eco-Service TypeSystemService. Here we can find the following components:

  Name                           explanation
  AllClasses                     Clooection of all classes
  AllAssociations                Collection of all associations
  AllDataTypes                   Collection of datatypes
  Packages                       List of packages of the model
  Constraints                    Constraints on the top model level
  TaggedValues                   TaggedValues on the top model level

AllClasses and AllAssociations provide the IClass / IClassifier-value for each entry. In
addition TypeSystem provides direct access to each individual model element with the
functions GetClassifierByName, GetClassifierByType and GetClassByType.


Classifier
With the IClassifier-Interface, called a Super-Interface for all types, all information on a
concrete element or element type of a model (e.g. of a class) can be queried. A Classifier
can possess constraints and Tagged Values.

There are 5 types of classifiers: Class, Collection, Primitive, Enumeration and Tuple.
In an application a sub interface, e.g. IClass, ICollection, IPrimitive etc. is used instead of the
common IClassifier-Interface. The Property ClassifierType of the IClassifier-Interface
determines the corresponding type.
Depending on the sub-interface used, different interface properties are available.

We can determine the classifier of an element in the following ways:

a) With the class identifier or the class type from the model

   MyClassifier :=
     EcoSpace.TypeSystemService.TypeSystem.GetClassifierByName (’…’);
            or
   MyClassifier :=
     EcoSpace.TypeSystemService.TypeSystem.GetClassifierByType (’…’);

b) With a class from the class collection of the model

   MyClassifier :=
     EcoSpace.TypeSystemService.TypeSystem.AllClasses.Item[x];

c) With the Ielement level of a class instance

   MyClassifier := oCustomer.AsIObject.UmlType;

d) With the IElement level of the components of a class instance (IPropertyList)

   MyClassifier := oCustomer.AsIObject.Properties.Item[x].UmlType;




                                                                                         Page 191
                       4.2 The model structure at runtime (UML-RT)


e) With a RootHandle or rooted Handle

  MyClassifier := rhRoot.Element.UmlType;    //Root-Handle
  MyClassifier := exphPerson.Element.UmlType;//Expression-Handle
  MyClassifier := cmhPerson.Element.UmlType; //CurrencManager-Handle

Notes:
  the access to model elements with the TypeSystem is read-only!
  Using classifiers requires to include the Borland.Eco.UmlRt.
  The method GetClassifierByName () usually requires a fully qualified identifier with
  preceding namespace. However this is not true if a class name is used. In this case the
  namespace prefix is not needed.
  The collection AllClasses contains all classes of the model. The pseudo-class
  EcoModelRoot is always at the index position 0.

We use the model of the example application [     EcoSpaceCoding] as base for the model
analysis that follows.




The example application itself only enables you to execute 3 kinds of model evaluation and
to display the results in a listbox.
In the WinForm of this application we evaluate the model data with a button-click-method.
The tables below show the evaluation results as an example.




Page 192
                               4. ECO at runtime (EcoSpace-Coding)

Properties and Methods of IClassifier
access: MyClassifier:=EcoSpace.TypeSystemService.TypeSystem. GetClassifierByName (‘CL_Person’)

Name                     explanation                                 example: class CL_Person
ClassifierType           Classifier type : Class, Collection,        Class
                         Primitive…
CollectionType           The collect. type of this Classifier        Collection (CL_Person)
ObjectType               the CLR-Type of this Classifier             CoreClassesUnit.
                         (fully qualified Type name)                 CL_Person
SubTypes                 sub Elements                                CL_Customer
SuperTypes               super Elements                              EcoModelRoot
(MyClassifier As IClass) UML-Properties of the class                 IsAssociationClass
(MyClassifier As         ECO-Properties of the class                 Persistent, Versioned
IClass).EcoClass
Constraints              List of Constraints                         MyConstr=sLastName<>’’
TaggedValues             List of TaggedValues                        ECO.TableName
EcoClassifier            additional ECO-specific Prop: IsA           IsAbstract = FALSE
                         (), ConformsTo (), IsAbstract…
Features                 Collection of IFeature-Elements             See next table
                         of the Classifier (see next table)

Most important in the table above are the entries EcoClass, EcoClassifier and Features.
EcoClass returns class-specific Eco-Properties only, EcoClassifier returns a IEcoClassifier
for the general access to eco specific properties.


Features
A so-called Featurecollection can be assigned to a classifier. A Feature can be either an
attribute, an association end or an operation. Accordingly ECO differentiates between
IStructuralFeature (IAttribute, IAssociationEnd) and IBehavioralFeature.
In our example the Feature-Collection for the class CL_Person has the entries for the two
attributes sFirstName and sLastName. The Feature-Collection for the class CL_Customer
consists of the attribute iOrderNo and the association end Owner. Again a Feature can also
contain Constraints and TaggedValues.
In addition to UML Features also ECO-features that contain ECO specific properties are
administrated, just as in classifiers. Access can be achieved with the element
EcoStructuralFeature.

Properties and Methods of IFeature (Attribute)
access: MyFeature := MyClassifier.Features.Item[x] As IStructuralFeature As IAttribute

Name                      explanation                                       example: Attribute
                                                                            CL_Person.sLastName
Name                 Name of the Feature                                    sLastName
InitialValue         Initial value                                          ’’
FeatureType          Attribute, AssociationEnd, Operator                    Attribute
_Type                Data type of the Feature                               String
Visibility           Public, Protected…                                     Public
EcoAttribute         Additional eco-spec. attributes: AllowNull,            IsDerived = FALSE
                     Persistent, IsDerived, Derivation-OCL…
EcoStructuralFeature like EcoAttribute                                      CanHaveOldValues =
                                                                            TRUE
OwnerScoper               Instance or Classifier                            Classifier




                                                                                         Page 193
                          4.2 The model structure at runtime (UML-RT)


Properties and Methods of IFeature (AssociationEnd)
access: MyFeature := MyClassifier.Features.Item[x] As IStructuralFeature As IAssociationEnd

  Name                    explanation                           example: Association end
                                                                Owner
  Name               Name of the Feature                        Owner
  Multiplicity       Parameter of the multiplicity:             Multiplicity.Lower = 0
                     Lower, Upper, IsSingle…
  FeatureType        Attribute, AssociationEnd,                 AssociationEnd
                     Operator
  _Type              Data type of the Feature                   CL_Customer
  IsNavigable        Boolean                                    TRUE
  AssociationEndKind Normal, ToLinkObject, InnerLink            Normal
  EcoAssociationEnd Additional eco-specific attributes:         IsDerived = FALSE
                     AssociationClass,
                     DeleteAcCtion, IsDerived,
                     Persistent…
  OppositeEnd        The feature that represents the            Feature: TheOrder
                     other association end
  OwnerScoper        Instance or Classifier                     Classifier


Structure information on the IElement-level
As we have seen in the preceding chapter 4.1, the IElement-level provides a type-
independent access to class instances and their components at runtime. This access also
allows the reading of structure information.

As seen before, we can achieve the same effect on an instance level using IClassifier or the
IClass/IEcoCLass interface.

   MyClassifier := oCustomer.AsIObject.UmlType;
   MyIClass     := oCustomer.AsIObject.UmlClass;
   MyIEcoClass := oCustomer.AsIObject.UmlClass.EcoClass;

Within a class instance we can access the components (attributes, association ends...) with
properties/StructuralFeatures or by using the property AllStructuralFeatures of the EcoIClass
interface.

   MyProperty := oCustomer.AsIObject.Properties.Item[x];
   MyFeature := MyProperty.StructuralFeature;

   MyFeature       := oPerson.AsIObject.UmlClass.EcoClass.
                        AllStructuralFeatures.GetItemByName(x);
   // or
   MyFeature       := oPerson.AsIObject.UmlClass.EcoClass.
                        AllStructuralFeatures.GetItem[x];




Page 194
                            4. ECO at runtime (EcoSpace-Coding)



Method analysis with Reflection
As we have seen in chapter 4.2.1, we have access to the structural informations of the class
methods in runtime using the IMethod interface. An alternative way to those informations is
also offered by .NET Reflection.

In our example application the code that is required for the method analysis finds itself on the
Winform as a button-click-method.

Note:
  This Button-Click-Method searches all methods of the class CL_Order for methods that
  only belong to the UML model or that are marked in the source code with a taggedValue.
  With that the for example “elementary” class models, inherited from the super class are
  not displayed.
  The name, parameters and method type of each appropriate method is displayed in a
  listbox.
  In this example we use an instance of the class CL_Order as starting point.

First we need the list of the namespaces required and of the significant variables of our
method.

   Uses
     Borland.Eco.ObjectRepresentation,
     Borland.Eco.UmlRt,
     Borland.Eco.Services,
     Borland.Eco.UmlCodeAttributes,
     System.Reflection;

   procedure TWinForm.BtnReflection_Click(…)
   var BaseType,
       AttrType : System.&Type;
       mInfo     : MethodInfo;
       pInfo     : ParameterInfo;
       aObj      : TObject;
       mList     : ARRAY OF MethodInfo;
       pList     : ARRAY OF ParameterInfo;
       aList     : ARRAY OF TObject;
       oOrder    : CL_Order;

With the On-Click-Method we first determine the .Net-Type of the class, or to determine the
.Net-Type of a class-instance we use the .Net-function GetType. Based on this type we get
the list of methods with GetMethods.

   BaseType    := CL_Order.ClassInfo;
      // or
   oOrder      := CL_Order.Create (EcoSpace);
   BaseType    := oOrder.GetType;
   mList       := BaseType.GetMethods;

In order to display only certain methods, we determine the attribute list (list of meta
                             G
attributes) for each method (GetCustomAttributes).




                                                                                      Page 195
                       4.2 The model structure at runtime (UML-RT)


Then we check all meta attributes of a method on their type. This way we can select for
example only the methods that have set an attribute like [EcoAutoGenerated] or
[UmlElement] or – like in our example – our custom meta attribute
[UmlTaggedValue('MySpecialMarker', 'TRUE')].

Note:
  You find more information on using meta attributes in chapter 2.6.3.

  for mInfo in mList do
    begin
      bMarked := FALSE;
      aList := mInfo.GetCustomAttributes(FALSE);
      for aObj in aList do
          begin
            AttrType := aObj.GetType;
            //if (AttrType = TypeOf(EcoAutoGeneratedAttribute)) then
            //if (AttrType = TypeOf(UmlElementAttribute)) then
            if (AttrType = TypeOf(UmlTaggedValueAttribute)) then
                begin
                  IF (((aObj as UmlTaggedValueAttribute).
                        Tag = 'MySpecialMarker') and
                       ((aObj as UmlTaggedValueAttribute).
                         Value = 'TRUE')) then
                      bMarked := TRUE;
                end;
          end;
      if bMarked then … // analyse this methods only
      …

The method-specific properties like IsSpecialName (meaning for example getter and setter
methods of class attributes) or the check of ReflectedType are other ways of differentiation
between methods.

  if ((NOT mInfo.IsSpecialName) and
      (mInfo.ReflectedType = BaseType)) then …

                                      G
Now we determine the parameters (GetParameters) for each appropriate method and
create a parameter string (ss) from them. The complete display string (s) consists of the
method name, the parameter string and the function type.

  pList := mInfo.GetParameters;

  ss := '(';
  for pInfo in pList do
     ss := ss + pInfo.Name + ':' + pInfo.ParameterType.Name + ';';
  if ss[LENGTH(ss)] = ';' then Delete (ss, Length(ss), 1);
  ss := ss + ')';

  s := mInfo.Name + ' ' + ss;
  if (mInfo.ReturnType.Name <> '') then
     s := s + ' : ' + mInfo.ReturnType.Name;




Page 196
                           4. ECO at runtime (EcoSpace-Coding)



4.3 Object-Identification in EcoSpace
The following identifiers are assigned to an object, or to be more precise to a class instance
administrated by the ECO system:

      Name         explanation
      ObjectID     Initial object ID, corresponds with the BOLD-ID
      ECO_ID       Distinct ID for the identification of an object in the DB
      Locator      Key to objects in the Eco-Cache

As soon as a class instance is created in ECO space, a transient distinct ObjectID gets
assigned. With the first saving of the class instance in the DB the transient ObjectID is
replaced with a persistent version, the so-called ECO_ID.
Class instances located in the Eco-Cache can also be identified there with Locator.

Note:
  Access to ObjectIDs, Locators, as well as properties and methods of the Eco-Cache
  requires to include the following NameSpaces:
  • Borland.Eco.ObjectRepresentation
  • Borland.Eco.DataRepresentation
  • Borland.Eco.Cache


ObjectID
An ObjectID consists of two values, a Key, of type TObject and a ClassID, of type Integer.

The ClassID is a consecutive number, that identifies the corresponding class in the overall
model. In a database generated and administrated by ECO this classID is saved in the table
ECO_Type as Bold_Type. Because of this the class ID of an Object ID has exactly this
value, of course with the constraint that the values of the initially created objectIDs are
replaced with the values from the DB as soon as the class instances are saved for the first
time.

The key of an ObjectID contains an integer that can be interpreted as consecutive number of
a class instance within a class. The final value of this key also is determined as soon as the
instance is saved for the first time. The key value equals the value in the column ECO_ID in
the corresponding dataset in the according class table.

The ObjectID also provides the following properties:

      Name       explanation
      IsStorable TRUE, except for transient classes
      Timestamp Timestamp-value of the class instance , see chapter 4.4.2


Locator
All objects located in the cache of the EcoSpace are identified with a locator. The methods
provided by the ICache-Interface are mainly based on locators.
A Locator-Object doesn’t provide any properties or methods. Access happens with the
ICache-Interface, with which we will deal with in the next chapter.




                                                                                    Page 197
                                      4.4 Eco-Cache



4.4 Eco-Cache
In chapter 4.1 we had a look at the Eco-Object- and IElement level used to access objects in
EcoSpace. In this chapter we want to deal with the access to objects in EcoSpace using
locators and with properties and methods provided by the ICache-Interface.

Note:
  The Cache is part of the internal operations of ECO and is a very advanced topic. This
  section can safely be skiped by novice users.


4.4.1 FrontSidePolicy-component
In addition to the various services analyzed in the preceding chapters EcoSpace provides
another component, the so-called FrontSidePolicy.
In this component you can find the interface IObjectRepresentationProvider, which is the
„official“ gate to the locator level.

Like already mentioned in chapter 4.1, we can switch from an ECO object (class instance) to
the IElement level of the object with AsIObject. The method LocatorForIObject of the
IObjectRepresentationProvider now provides the locator for our IObject and thus the access
to the EcoSPaceCache.

  ObjectRepresentationProvider.LocatorForIObject(oObject);

We only have access to this FrontsidePolicy-component within a method of the
xxxEcoSpace-class, that means the access to locators always has to be implemented in the
form of methods of our EcoSpace class. In order to get the locator for every IObject we
define the method GetObjectLocator as a method of the xxxEcoSpace-class in our
xxxEcoSpace-Unit.

  function TxxxEcoSpace.GetObjectLocator (oObject:IObject): Locator;
  begin
    result := self.FrontsidePolicy.ObjectRepresentationProvider.
                LocatorForIObject(oObject);
  end;

From the winform we can for example determine the locator for the currently selected object
from a datagrid with our custom EcoSpace method.

  procedure TWinForm.BtnSingleUpdate_Click(…);
  var oPerson : CL_Person;
      ILocator : Locator;
  begin
    // get the currently selected person
    oPerson := CL_Person (cmhPerson.Element.AsObject);

    // get the locator for that object
    iLocator := EcoSpace.GetObjectLocator (oPerson.AsIObject);
  end;




Page 198
                          4. ECO at runtime (EcoSpace-Coding)

We can go the reverse way, from the locator to the Eco-Object with the method
IObjectForLocator of the IObjectRepresentationProvider. Now we first implement an
corresponding method in our xxxEcoSpace-class, called GetObjectByLocator.

   f. TxxxEcoSpace.GetObjectByLocator(iLocator:Locator):IObject;
   begin
     result := self.FrontsidePolicy.ObjectRepresentationProvider.
                IObjectForLocator(iLocator);
   end;

With the help of this method we can code the retransformation to an ECO-Object based on a
locator.

   oPerson := EcoSpace.GetObjectByLocator(iLocator).
                AsObject AS CL_Person;

Note:
  The access to ObjectIDs, Locators as well as properties and methods of EcoCache
  requires to include the following namespaces :
  • Borland.Eco.ObjectRepresentation
  • Borland.Eco.DataRepresentation
  • Borland.Eco.Cache


4.4.2 ICache interface
The Interface ICache can not be used – as in the ECO services we´ve see nso far- in the
form ...GetEcoService (TypeOf (ICache)) AS ICache..., but only with the
FrontSidePolicy-component of EcoSpace, thus only with custom methods in the EcoSpace
class.


Basics
The properties and methods of the ICache-Interfacecan be grouped as follows.

Methods to create and delete class instances
Method                Parameter/result            explanation
CreateNewObject       Parameter: IClass           Creates , Based on the specified class, a
                      result: Locator             new object (class instance) in the cache
                                                  and returns its locator
DestroyObject         Parameter: Locator          Deletes the object of the specified locator
                                                  from the cache




                                                                                   Page 199
                                       4.4 Eco-Cache


Methods to administrate Locators and ObjectIDs
Method                Parameter/result              explanation
GetAllLocators        result: Array of Locator      Creates a list of all locators currently in
                                                    the cache
GetIdByLocator        Parameter: Locator            returns ObjectID of a Locator
                      result: ObjectID
GetLocatorById        Parameter: ObjectID           returns Locator of a ObjectID
                      result: Locator
SetObjectId           Parameter: Locator,           Resets the object ID of the specified
                      ObjectID                      locator

The Method GetUmlClass in the following table returns an IClass, thus providing an
alternative IClassifier-access to the structure information of a class instance (see chapter
4.2.1).

Structure information based on a Locator
Method                Parameter/result              explanation
GetUmlClass           Parameter: Locator            Returns an IClass-Classifier for the
                      result: IClass                specified Locator


Attributes and association ends
The next table lists the methods that enable access to attributes and association ends of a
class instance with the locator.
On the ICache-level we have to differentiate between two kinds of values. The current value
of an attribute or association end (CurrentValue) and the value in the database
(FetchedValue). The two values always differ from each other, if object changes haven’t
been saved in the database (see chapter 4.5.3).

Methods for access to attributes/association ends of a class instance
Method            Parameter                  explanation
GetCurrentValue   Parameter: Locator,        Fetches the attribute/association end at the
                  Memberindex                specified index position of the object identified
                  result: IObject            with a locator
SetCurrentValue   Parameter: Locator,        sets Attribute/association endwith the specified
                  Memberindex, IObject       object value at the specified index position
GetFetchedValue   Parameter: Locator,        Fetches the attribute/association end at the
                  Memberindex                specified index position of the object identified
                  result: IObject            with a locator
SetFetchedValue   Parameter: Locator,        sets Attribute/association endwith the specified
                  Memberindex, IObject       object value at the specified index position

We want to demonstrate the use of ICache-Methods with the example application
[    Cache].




Page 200
                             4. ECO at runtime (EcoSpace-Coding)




In this example application we first create some CL_Customer- and CL_Order-Instances
and then link a CL_Customer-Instance to some of the CL_Order-Instances. Since the
EcoAutoForm- and the Drag&Drop-Properties for both Datagrids are already set in the
WinForm, the instances can be linked with Drag&Drop (see chapter 1.4).
The process TWinForm.BtnLocator_Click(), that we defined as an OnClick-event for
the TestLocator-Button, contains some ICache-accesses that makes a good example.
Activating this process doesn’t result in a screen output, but when we follow the procedure
step by step with the integrated debugger, the handling of ICache-access will come
immediately clear.

When the ICache interface is used, class instance attributes are accessed with an indicated
attribute list. The indication of the attributes equals the attribute order defined by the classifier
property AllStructuralFeatures.
If we have received a IClassifier (iCl), or to be more precise an IClass for the instance
oCustomer of the class CL_Customer with the GetUmlClass-Method stated above, we can
determine the index position of a certain attribute, for example sFirstname with the following
call.

   iPosition := iCl.EcoClass.AllStructuralFeatures.
                  GetItemByName ('sFirstName').EcoStructuralFeature.
                  IndexInAllStructuralFeatures;

With the index position (iPosition) of the attribute we can now fetch the attribute of the
instance using the ICache-Method GetCurrentValue. To do this we code an corresponding
         G
method (GetAttributeByLocator) in our xxxEcoSpace-class.

   function TxxxEcoSpace.GetAttributeByLocator
             (iLocator : Locator; iPosition : Integer) : TObject;
   begin
     result := self.FrontsidePolicy.Cache.
                 GetCurrentValue(iLocator, iPosition);
   end;

A call of this method, for example to fetch the sFirstName-Attributes as string variable of a
oCustomer-Klassen-Instance for which we determined the locator, would then look like this.

   VAR iCl   : IClass;
       iPos : Integer;
       sAttr : String;…
   iCl := EcoSpace.GetUmlClassByLocator (iLocator);
   iPos := iCl.EcoClass.AllStructuralFeatures.
            GetItemByName ('sFirstName').EcoStructuralFeature.
            IndexInAllStructuralFeatures;
   sAttr:= EcoSpace.GetAttributeByLocator(iLocator,iPos) As String;…




                                                                                           Page 201
                                        4.4 Eco-Cache


Of course this example requires that we already know at runtime, which classes and class
attributes we’ll have to deal with.

But if our analysis methods are supposed to work „blind“, we have to check some structure
contents before the explicit access to the attributes of a class instance.

Note:
  The required procedure was already explained in chapter 4.2.3, so the following method
  description will only be brief.

If we don’t know the name of an attribute, we use the AllStructuralFeatures-Method
GetItem instead of GetItemByName and iterate over all class entries.
In order to be able to differentiate between attributes and association-ends we check the type
              F
of the entry (FeatureType).

   // FeatureTypes: AssociationEnd, Attribute
   if (iCl.EcoClass.AllStructuralFeatures.GetItem[x].
        FeatureType = FeatureType.Attribute) then…

If the entry is an attribute we usually come across elementary Data types. The ICache-
Method GetCurrentValue only returns a TObject, that we have to cast into a string or Int32
etc, according to the data type.

   if (iCl.EcoClass.AllStructuralFeatures.GetItem[x].
         Type_.ObjectType = TypeOf (String)) then
      begin
        iPos := iCl.EcoClass.AllStructuralFeatures.GetItem[x].
                  EcoStructuralFeature.IndexInAllStructuralFeatures;
        s:= EcoSpace.GetAttributeByLocator(iLocator, iPos) As String;

If the entry isn’t an attribute but an association-end with multiplicity 0..1, the result of the
GetCurrentValue-Method is a Locator. This can be transformed into an Eco-Object, like the
example below will demonstrate.

In our example application Cache, only one CL_Customer-Instance can be assigned to a
CL_Order-Instance via the association end TheOwner.

   iPos := iCl.EcoClass.AllStructuralFeatures.
            GetItemByName ('TheOwner').EcoStructuralFeature.
            IndexInAllStructuralFeatures;
   MyLocator := EcoSpace.GetAttributeByLocator(iLocator, iPos) As
                  Locator;
   oCustomer := EcoSpace.GetObjectByLocator (MyLocator).AsObject As
                  CL_Customer;

However multilink-Association-ends (Multiplicity = 0..n) will have a result in the form of iList
of Locator for GetCurrentValue.
So let´s have a look at the association between CL_Customer and CL_Order from the
Customer-perspective. To each CL_Customer-Instance several CL_Order-Instances can
be assigned via the association end TheOrders.




Page 202
                         4. ECO at runtime (EcoSpace-Coding)

  iPos := iCl.EcoClass.AllStructuralFeatures.
            GetItemByName ('MyOrders').EcoStructuralFeature.
            IndexInAllStructuralFeatures;
  MyList:= EcoSpace.GetAttributeByLocator (iLocator, iPos) As iList;
  for MyLocator in iList do
    begin
      oOrder := EcoSpace.GetObjectByLocator (MyLocator).AsObject As
                  CL_Order;
    end;


        S
With theSetCurrentValue-Method the ICache-Interface also allows you to change attributes
and association ends. First we implement an corresponding EcoSpace method.

  Procedure TxxxEcoSpace.SetAttributeByLocator
             (iLocator: Locator; iPosition: Integer; oObj: TObject);
  begin
    self.FrontsidePolicy.Cache.SetCurrentValue
       (iLocator, iPosition, oObj);
  end;

Write-access is achieved the same way as read access. Below you can find the code to
change the sFirstName-Attribute of a CL_Customer-Instance.

  iCl := EcoSpace.GetUmlClassByLocator (iLocator);
  iPos := iCl.EcoClass.AllStructuralFeatures.
           GetItemByName ('sFirstName').EcoStructuralFeature.
           IndexInAllStructuralFeatures;
  sAttr := ’Peter’;
  EcoSpace.SetAttributeByLocator (iLocator, iPos, sAttr);

The procedure is exactly the same for read and write access to FetchedValues (instead of
CurrentValues ).

Note:
  Write access is immediately visible in the datagrid of our example application
  [    Cache]. However it’s interesting that in this case the UpdateDatabase-Button, which
  is usually „activated“ automatically whenever a change in the datagrid happens, somehow
  doesn’t notice this object change and stays “grey”.




                                                                                 Page 203
                                       4.4 Eco-Cache




ExistenceState and PersistenceState
The following table shows the methods for the access to the property ExistenceState and
PersistenceState.

Methode                      Parameter              Bedeutung
GetExistenceState            Parameter: Locator     returns the ExistenceState of a
                                                    class instance, which is identified
                             Ergebnis: ExistenceState
                                                    via a locator
SetExistenceState         Parameter: Locator,       places the ExistenceState for the
                          ExistenceState            class instances identified per
                                                    locator
GetPersistenceState       Parameter: Locator        Returns the PersistenceState of a
                          Ergebnis:                 class instance, which is identified
                          PersistenceState          via a locator
SetPersistenceState       Parameter: Locator,       Places the PersistenceState for the
                          PersistenceState          class instances identified per
                                                    locator
GetMemberPersistenceState Parameter: Locator,       Returns the PersistenceState of
                          Memberindex               the identified attribute of a class
                          Ergebnis:PersistenceState instance identified via a locator
SetMemberPersistenceState Parameter: Locator,       Places the PersistenceState for the
                          Memberindex,              identified attribute of the class
                          PersistenceState          instance identified per locator

To each class instance in the cache the property ExistenceState is assigned, which can have
the following characteristics.

             ExistenceState          explanation
             Existing                Default Status of an object
             Deleted                 object was deleted
             NotCreated              this status is not in use

The methods for reading / editing this property can be implemented as xxxEcoSpace-class
methods

   Function TxxxEcoSpace.GetExistenceState
              (iLocator: Locator) : ExistenceState;
   begin
     result:=self.FrontsidePolicy.Cache.GetExistenceState (iLocator);
   end;

   Procedure TxxxEcoSpace.SetExistenceState
              (iLocator: Locator; iEState : ExistenceState);
   begin
     self.FrontsidePolicy.Cache.SetExistenceState(iLocator, iEState);
   end;

To each class instance and to all attributes and association ends of a class instance located
in the cache the property PersistenceState that can have the following characteristics, is
assigned.




Page 204
                            4. ECO at runtime (EcoSpace-Coding)

PersistenceState      explanation
Current               FetchedValue is identical to CurrentValue
Modified              FetchedValue is different than CurrentValue
Transient             a FetchedValue doesn’t exist; the object is not saved in the DB
Invalid               The object value hasn’t been fetched from the DB or set yet

There exist 4 methods for reading / editing this property, which are listed in the table above.
These methods can be implemented in the xxxEcoSpace-Unit just like the persistence
methods.

The next table will explain the various combinations of Existence- and PersistenceStates of
an object.

ExistenceState PersistenceState explanation
Existing       Modified         The object has been created, but has not been saved
                                yet.
Existing       Current          The object hasn’t been changed since the last save in
                                the DB (default case)
Deleted        Modified         The object has been marked as deleted, but the
                                deletion hasn´t taken place in the DB yet
Deleted        Current          The object has been marked as deleted and has been
                                deleted in the DB. It still exists in the cache though.


Timestamp
Each cache object has a timestamp value, existing as an attribute of the object ID. This
attribute only gets used if we activate Optimistic Locking for an ECO application. More on
Optimistic Locking in chapter 4.7.3.

The ICache-Interface provides the following methods for reading and changing the
timestamp attribute.

Methode                Parameter                    Bedeutung
GetTimestamp           Parameter: Locator           Fetches the timestamp value of the object
                       result: Integer              identified with the specified locator
SetTimestamp           Parameter: Locator,          Sets the timestamp value of the object
                       Timestamp                    identified with the specified locator

Here we have to note that the timestamp value is set by the DB. A timestamp value records
the latest change in the DB, not changes in the cache.


Events
The ICache-Interface also provides two event handlers.

Property                 Parameter                       explanation
ValueChangedDelegate     Parameter: Locator,             Each value change in a class
                         StructuralFeature               instance activates this event handler
ExistenceChangedDelegate Parameter: Locator              Each changing of the ExistenceState
                                                         of a class instance activates this
                                                         event handler




                                                                                     Page 205
                                        4.4 Eco-Cache


The event ValueChangedDelegate always gets called when the current value of an attribute
or an association end changes.
In order to be able to react to such a message we have to assign an event handling method
to the Property ValueChanged.
In the WinForm of our example application [    Cache] we placed a ActivateEventButton ,
who’s OnClick-Method registers a custom coded event handler MyValueChangedEvent .

   function TCacheEcoSpace.InstallValueChangedEvent : BOOLEAN;
   begin
     Include (self.FrontsidePolicy.Cache.ValueChanged,
              MyValueChangedDelegate);
   end;

Our event handler is supposed to react to each change in Customer- or Order-Instance and
to display all string attributes of the changed instance as a current value characteristic and as
a FetchedValue.

   procedure TCacheEcoSpace.MyValueChangedDelegate
                 (oLocator : Locator; oFeature : IStructuralFeature);
   var oObj           : IObject;
        sPre, sPost : String;
        iCl           : IClass;
        i, iFeatures : Integer;
   begin
     oObj := GetObjectByLocator (oLocator);
     iCl := self.GetUmlClassByLocator (oLocator);
     iFeatures := iCl.EcoClass.AllStructuralFeatures.Count;
     sPre := ''; sPost := '';
     for i := 0 TO PRED (iFeatures) do
        begin
          if GetCurrentAttributeByLocator (oLocator, i) IS String then
              sPre := sPre + GetCurrentAttributeByLocator
                                 (oLocator, i) As String + ' ';
          if GetFetchedAttributeByLocator (oLocator, i) IS String then
              sPost := sPost + GetFetchedAttributeByLocator
                                   (oLocator, i) As String + ' ';
         end;
     MessageBox.Show('Current:' + sPre + ' --- Fetched:' + sPost);
   end;


Note:
  The following rule applies for working with objects in ECO cache:
  The cache doesn’t administrate derived features, since they can’t be reloaded from the
  database.




Page 206
4.5 Object-Handling
After these rather theoretical explanations of structure and properties of the ICache-Interface
in EcoSpace, this chapter will deal with more concrete examples of working in EcoSpace.


4.5.1 Creating and deleting objects
Objects (class instances) can be created in EcoSpace with the class constructor or the
IObjectFactoryService. The following code section displays the various ways, shown on the
example CL_Person.

   var oPerson : CL_Person;
       IClf    : IClassifier;
   …
   // using ths class constructor without an object reference
   CL_Person.Create (EcoSpace);

   // using ths class constructor and an object reference
   oPerson := CL_Person.Create (EcoSpace);

   // using the IObjectFactoryService
      // using the class name
   EcoSpace.ObjectFactoryService.CreateNewObject('CL_Person');
      // or the class type
   EcoSpace.ObjectFactoryService.CreateNewObject(TypeOf (CL_Person));
      // or IClassifier (IClass)
   iClf := EcoSpace.TypeSystemService.TypeSystem.
           GetClassifierByName ('CL_Person');
   EcoSpace.ObjectFactoryService.CreateNewObject(iClf AS IClass);

We can use the delete method on the IElement level of an object for deleting objects in
EcoSpace. In order to delete all objects physically from the cache it’s sufficient to deactivate
EcoSpace temporarily.

   var oPerson : CL_Person;
   …
   // IElement:Delete-Methode
   oPerson := CL_Person.Create (EcoSpace);
   oPerson.sFirstName := ’Jonas’;
   oPerson.AsIObject.Delete;
   IF oPerson.AsIObject.Deleted then
     MessageBox.Show(’Object ’+oPerson.sFirstname+’ was deleted’);

   // global deletion of all objects by deactivating the EcoSpace
   EcoSpace.Active := FALSE;
   EcoSpace.Active := TRUE;

Using the delete method doesn’t lead immediately to a physical deletion of an object. First
the references to other objects linked with this object are deleted. Besides that, when re-
evaluating OCL expressions those lists are cleared that would contain the deleted object.




                                                                                      Page 207
                                       4.5 Object-Handling


In the next DB update the “deleted” object is removed from the DB. It gets removed from
EcoSpace as soon as no further references to this object exist.

Deactivating EcoSpace deletes all objects fully, of course the data in the DB remains
untouched .

On the EcoCache level we also have the Unload-Method of the persistence service for
deleting. Unload is used primarily to cause EcoSpace to reload an „old“ object from the DB.
With unload only the locator for the object remains for now in the cache.
Unload needs a IObject or a Iobjectlist as parameter.

   oPerson := CL_Person.Create (EcoSpace);
   EcoSpace.PersistenceService.Unload (oPerson.AsIObject);

The unload method is not available for transient objects. Besides that unload can’t be used
on objects from the DirtyObjectList.


4.5.2 Basic load strategy
ECO favours the late fetching method, that means data is only loaded when needed. To
make the effects of this method clear we first have to note that ECO knows 3 “load-areas” for
loading objects (instances).

      •    IDs (ECO-ID / ObjectID)
      •    Default Attribute
      •    Delayed fetched Attribute

The ID of an instance to load is always loaded first. If another instance is assigned to an
instance with a so-called embedded SingleLink, meaning an association-end with a max
multiplicity of 1 and a set embed-flag, it’s ID is also loaded.

The default attributes of an instance are loaded completely, as soon as at least one of the
default attributes of the instance is referenced explicitly.
This can be triggered by an editing function or by displaying data in a GUI control on the
winform.

Attributes marked as delayed fetch in an instance are loaded – one at a time – as soon as
they are referenced in the program. among delayed fetch. All attributes of the associated
„embedded“ instances, as well as all data – also IDs- from associated instances with multilink
belong to the delayed fetch attributes.

For example if an expressionhandle with an expression in the form of
CL_Customer.allInstances is assigned to a datagrid used to display customer data, all
Ids of all CL_Customer-Instances are loaded as soon as this expression is executed .
In addition the default attributes are loaded for all instances that currently can be displayed in
the grid. If the grid also displays delayed fetch attributes of the instances or data from
associated instances, than these are loaded as well, one at a time.




Page 208
                           4. ECO at runtime (EcoSpace-Coding)



Explicit Prefetching
The late fetching method has the advantage of conserving memory, but can lead to database
queries of less quality, concerning performance.

For example if we have to process all oOrder-Instances associated to an oCustomer-
Instance in a processing function, it would make sense – concerning the performance – to
replace the SQL loading orders generated automatically by ECO for each oOrder-Instance
with one SQL operation covering all instances .

ECO provides exactly this in the PersistenceService, see the table below.

Methods of Prefetching objects in the PersistenceService
Methode              Parameter                     explanation
EnsureRange          Parameter: ObjectList,        Loads all objects of the specified list from
                     FromIndex, ToIndex            the specified area with a SQL operation
EnsureRelatedObjects Parameter: ObjectList,        Loads all objects linked via the specified
                     AssociationEndName            association end to the base object wit ha
                                                   SQL operation


4.5.3 Administrating and saving object changes
In this chapter we will show the basic structures and methods ECO uses to administrate and
save changed objects (instances ).
In multi user environments synchronizatiion of data changes plays a vital role. We won’t deal
with this here but in chapter 4.7.2.


DirtyObjectList
Each object in EcoSpace, whose attribute values differ from the last saved values in the DB
is administrated by ECO in the so-called DirtyObjectList.

Among these are
    •    Objects that are created new in EcoSpace but haven’t been saved to the DB yet
    •    Objects that were changed or edited in EcoSpace after loading them from the DB,
         but whose deletion /editing hasn’t taken place yet in the DB

ECO provides the DirtyListService for working with these objects.
We can use this service in the common way, directly in the global EcoSpace object or in a
class instance.

   EcoSpace.DirtyListService
      //or
   EcoSpace.GetEcoService(IDirtyListService) AS IDirtyListService
      //or
   (oPerson.AsIObject.ServiceProvider.
      GetEcoService(IDirtyListService) AS IDirtyListService)




                                                                                     Page 209
                                    4.5 Object-Handling


Properties and Methods of the IDirtyListService
           Name                explanation
           HasDirtyObjects     are there any DirtyObjects?
           AllDirtyObjects     returns all DirtyObjects as a list with access via a
                               IObjectList-Interface
           Subscribe           Subscription interface

Each list object has the IObject-Interface and can be displayed, analyzed and transformed in
to an ECO object, like shown in chapter 4.1.

  for iObj in EcoSpace.DirtyListService.AllDirtyObjects do
    begin
      // access to properties of the Object
      s := IObj.UmlClass.Name;            // access by IClass
      s := IObj.UmlType.ObjectType.Name; // access by IClassifier

        // typecasting to the right ECO object
        if (IObj.UmlType.ObjectType = TypeOf (CL_Person)) then
           oPerson := IObj.AsObject As CL_Person;
  …

In order to get more information on why an object was added to the DirtyObject-List, we can
use the Property Deleted of the IObject-Interface and the IStateService provided by ECO.

  iSS := EcoSpace.GetEcoService(TypeOf (IStateService)) as
                                 IStateService;
  for iObj in EcoSpace.DirtyListService.AllDirtyObjects do
    begin
      if iSS.IsNew (IObj) then…      // New object
      else if IObj.Deleted then…     // Objekt was deleted
      else…                          // else Objekt was modified
    end;

The IDirtyList-Service also provides a subscription interface. With this we can get a
notification each time there is a change or new entry in the DirtyObjectList.
The implementation of this subscription is done as shown in chapter 2.4.

We code our own Subscriber-Interface (IMySubscriber), best in an extra unit
(MySubscriber.PAS) and place the part of the code that is supposed to react to the
notification in the receive method of the ISubscriber.

In order to activate the subscriber, we placed an activation button on the winform of our
example [    DirtyObjectList]. The activation happens with the passing of an instance of our
IMySubscriber-Interface to the Subscribe-Method of the IDirtyListService.

  procedure TWinForm.BtnActivateSubscription_Click(…);
  var MySubscriber : IMySubscriber;
  begin
    MySubscriber := CL_MySubscriber.Create As IMySubscriber;
    EcoSpace.DirtyListService.Subscribe(MySubScriber);
  end;




Page 210
                           4. ECO at runtime (EcoSpace-Coding)


Collective saving
EcoSpace provides the Method UpdateDatabase for saving all changed objects, meaning all
entries in the DirtyObjectList.
UpdateDatabase also exists as a predefined ECO-Action-Method for implementing an
UpdateDatabase-Button.

Besides that EcoSpace defines the global property UpdateWholeObjects, with which it gets
determined if changes are saved in the form of saving complete objects (class instances) or
in the form of saving only the changed attributes of the instances.
We can set the value of this property at development time with the object inspector (see
chapter 2.1) or at runtime with the global EcoSpace object.


Selective saving
As an alternative to the general UpdateDatabase the PersistenceService provides the
possibility of saving single objects from the DirtyObjectList.

In the example application [     PersistenceService] we created a Button-Click-Method
                                                                         C
SingleUpdate, that updates only the currently selected data grid object (CL_Person) in the
DB.

  procedure TWinForm.BtnSingleUpdate_Click(…);
  var oPerson : CL_Person;
  begin
    // get the currently selected person
    oPerson := CL_Person (cmhPerson.Element.AsObject);

    // update the person data in the database
    EcoSpace.PersistenceService.UpdateDatabaseWithList
     (oPerson.AsIObject.GetAsCollection AS IObjectList);
  end;

The method UpdateDatabaseWithList requires IobjectList as parameter.
Because of this we transform the ECO object (Instance oPerson) to an IObject (see chapter
4.1) with AsIObject. The GetAsCollection-Method interprets the IObject as IElementList,
theTypeCast AS IObjectList transforms it to the required IObjectList.
The example application [   PersistenceService] was modified in the way that we now have
modelled three classes instead of one We can switch between them with a SwitchClass-
Button. Basically the switch is done by modifying the Expression of the central
ExpressionHandle.

Of course the IObjectList-Parameter in the Method UpdateDatabaseWithList can also
contain objects of multiple classes. To get this result we use the method
CreateUntypedObjectList of the IVariableFactoryService. This method returns a type-
independent IObjectList. We can add all kinds of objects to the instance of such a list (for
example oMyList) and allow the list to be saved.

  oMyList.Add (oCustomer.AsIObject);
  oMyList.Add (oOrder.AsIObject);
  ...
  EcoSpace.PersistenceService.UpdateDatabaseWithList (oMyList);




                                                                                  Page 211
                                  4.5 Object-Handling


In ECO-III the PersistenceService also provides the method UpdateDatabase (oObj :
IObjectInstance), that only saves the element passed in the form of an IObjectInstance.

  EcoSpace.PersistenceService.UpdateDatabase
     (oPerson.AsIObject);
  EcoSpace.PersistenceService.UpdateDatabase
     (cmhCurrencyManager.Element AS IObjectInstance);




Page 212
                           4. ECO at runtime (EcoSpace-Coding)



4.6 Uses for EcoSpace-Coding
In general we can differentiate between 3 kinds of coding in EcoSpace:

     •    Access to methods and services of EcoSpace from a class-instance
     •    Access to methods and services via the global EcoSpace-object
     •    Custom functional extensions of the Eco-runtime-system

The Code can be placed in the following areas (units) of a ECO-WinForms-application:

     •    xxxEcoSpace-Unit
     •    Package_xUnit
     •    WinForm-Unit
     •    Additional custom units


xxxEcoSpace-Unit
In the xxxEcoSpace-Unit always the application specific EcoSpace-class is defined, that is
derived from the class DefaultEcoSpace.

  TMyAppEcoSpace = class(Borland.Eco.Handles.DefaultEcoSpace)

The only instance from this EcoSpace-class is placed by default in the MainForm of the
application (class TWinForm) and is initialized there in the constructor.

In this unit the class of EcoSpace itself is the gateway to EcoSpace. With that direct access
to EcoSpace services is granted.

This application-specific EcoSpace-class contains furthermore the persistence components
of the application that were placed on the design page of xxxEcoSpace. Typically these are
persistence mappers and DB connections.

Because of this, functions are coded in the xxxEcoSpace-Unit, which modify or enhance the
range of functions of the application-specific EcoSpace. Among these are especially
functions that relate to persistence components.

Some examples:

  // This function extends the EcoSpace-Interface with a method to
  // recreate the databaseschema

  function TMyAppEcoSpace.CreateDatabaseSchema : Boolean;
  begin
    try
       PersMapper1.CreateDataBaseSchema (TypeSystemService);
       result := TRUE;
    except
       result := FALSE;
    end;
  end;




                                                                                   Page 213
                             4.6 Uses for EcoSpace-Coding


  // This function checks, if there is a DB-Connection available and
  // the returns the name of the DB and the connection state

  function TMyAppEcoSpace.TestDatabase (VAR sDBName:String):Longint;
  VAR bDatabase,
      bDBOpen,
      bTables    : Boolean;
      MyState    : System.Data.ConnectionState;
      MyTable    : DataTable;
  begin
    try
      // First get the DBConnection params:
      MyState := self.BdpConnection1.State;
      sDBName := self.BdpConnection1.Database;

         // Analyse state:
         bDBOpen := (MyState <> System.Data.ConnectionState.Closed);
         if (NOT bDBOpen) then
            begin // does the DB exists ?
              try
                self.BdpConnection1.Open;
                self.BdpConnection1.Close;
                bDatabase := TRUE;
              except
                // 1. case: ther is no DB
                bDatabase := FALSE;
                bTables    := FALSE;
              end;
            end
         else
            bDatabase := TRUE;

         if bDatabase then
            begin
              try
                 // test for any table:
                 MyTable := self. BdpConnection1.GetMetaData.GetCol…
                 bTables := (MyTable.Rows.Count > 0); // any columns?
              except
                 // 2. case: DB without a table
                 bTables := FALSE;
              end;
            end;

         if bDatabase and bTables then
           result := 3 // 3.case: DB is complete
         else
    …
  end;

As shown in chapter 4.4 we only have access to the FrontSidePolicy-component of
EcoSpace within our EcoSpace class. With that access to the ICache-Interface only exists
there.




Page 214
                           4. ECO at runtime (EcoSpace-Coding)

  // This function returns the object locator

  function TMyEcoSpace.MyGetLocatorService (anIObject : IObject) :
  Locator;
  begin
    result := self.FrontsidePolicy.ObjectRepresentationProvider.
              LocatorForIObject (anIObject);
  end;


  // This function returns the FetchedValue of a locator

  function TMyEcoSpace.MyGetFetchedValueService
            (oLocator : Locator; iIndex : Integer) : system.Object;
  begin
    result := self.FrontsidePolicy.Cache.
                GetFetchedValue (oLocator, iIndex);
  end;

The use of EcoSpace-Coding in the xxxEcoSpace-Unit is limited to coding within the
EcoSpace-class. Class instances of the model or the global EcoSpace object itself don’t exist
here.


Package_xUnit
In the Package_xUnit mainly extensions of the business model are coded.
Among these are modifications of the automatically generated methods, like for example
class constructors.

  //   Every instance of the root class gets a Timestamp attribute
  //   (dt_Create) to save the creation date
  //   Within the construktor this attribute will be initialized with
  //   the current system date using the set method

  constructor CL_Root.Create(serviceProvider: IEcoServiceProvider);
  begin
    inherited Create;
    Self.Initialize(serviceProvider);
    try
       // ...
       self.set__dtCreate(DateTime.get_Now);
    …
  end;

Besides that extra methods are added to the classes of the model.
A typical example are the DeriveAndSubscribe-Functions for code-based calculation of
derived attributes. You can find a detailed example in chapter 2.6.4.

You can also find a detailed example of the use of EcoSpace-Codings in our Constraint-
application (see chapter 2.6.5). There methods for constraint management were added to the
abstract base class CL-Base.




                                                                                   Page 215
                               4.6 Uses for EcoSpace-Coding


  // Test of a Constraint expression named sConstraintName

  function CL_Base.IsConstraintOk (sConstraintName:STRING): BOOLEAN;
  VAR s             : STRING;
      MyOCLService : IOCLService;
      rReturn       : iElement;
      oConstraint : IConstraint;
  begin
    oConstraint := self.AsIObject.UmlClass.Constraints.
                      GetItemByName(sConstraintName);
    if NOT (Assigned (oConstraint)) then
        result := TRUE // Constraint not found ->no broken constraint
    else
    begin
        s := oConstraint.Body.Body;
        MyOCLService := &self.AsIObject.ServiceProvider.
           GetEcoService(typeof(IOclService)) as IOCLService;
        rReturn := MyOCLService.Evaluate (self.AsIObject, s);
  …

As we can see in the examples above, the starting point of EcoSpace-Coding in this Unit is
                                          s
usually the corresponding class instance (self). The instance Self represents the Eco-object,
Self.AsIObject provides us access to the IElement-level of the class instance. With
self.AsIObject.ServiceProvider.GetEcoService(), we can access all Services of
EcoSpace.


WinForm-Unit
In the MainForm of our application the global EcoSpace exists in the TWinForm-class.
The example application [    Association] provides an example of the use of the EcoSpace
object (see chapter 2.7.2). The On-Click-Method of the ShowConstraint-Button uses the
TypeSystemService of EcoSpace to list all constraints of all classes.

  // Lists all Constraints of all classes within the model
  ...
  i := EcoSpace.TypeSystemService.TypeSystem.AllClasses.Count;
  while (i > 0) do
    begin
      sClassName := EcoSpace.TypeSystemService.TypeSystem.
                       AllClasses[PRED(i)].Name;
      iCCount     := EcoSpace.TypeSystemService.TypeSystem.
                       AllClasses[PRED(i)].Constraints.Count;
      while (iCCount > 0) do
          begin
            sCName := EcoSpace.TypeSystemService.TypeSystem.
            AllClasses[PRED(i)].Constraints[Pred(iCCount)].Name;
            sCBody := EcoSpace.TypeSystemService.TypeSystem.
            AllClasses[PRED(i)].Constraints[Pred(iCCount)].Body.Body;
  …

Besides this direct use of the EcoSpace object coding can also be done via the class
instances that are in EcoSpace at runtime and are visualized with the various GUI controls.




Page 216
                          4. ECO at runtime (EcoSpace-Coding)

In this case the important role comes to the Root- and ExpressionHandle and most of all to
the CurrencyManagerHandle of a Winform.
As stated in the preceding chapter 4.1 , ECO-Handles are implemented class-independent,
in order to be able to be used more flexible.
So these handles provide a direct access to the IElement-level and return via AsObject and
TypCast the corresponding ECO-Object (e.g. the class instance).

A common example application is the active linking between two class instances , referenced
by the according CurrencyManagerhandle, based on the association defined in the model.

  // Implements the link between a product object and a
  // product type object

  procedure TWinForm.BtnLinkProductType_Click
             (sender: System.Object; e: System.EventArgs);
  var oProduct     : CL_Product;
      oProductType : CL_ProductType;
  begin
    IF (assigned (cmhProduct.Element.AsObject) and … then
    begin
      oProduct := CL_Product (cmhProduct.Element.AsObject);
      oProductType:=CL_ProductType(cmhProductType.Element.AsObject);
      oProduct.CL_ProductType := oProductType; // Linking
  ...

The next lines of program code show the direct creation editing and deletion of objects in
EcoSspace without connection to ECO-Handles.

  oPerson := CL_Person.Create (EcoSpace);
  oPerson.sFirstName := ’Jonas’;
  oPerson.AsIObject.Delete;

Another typical coding example within a winform is the dynamic creation of ECO components
As shown in the [   OCLVariable]-example (see chapter 3.4).
There a OCL variable component is created dynamically with the IVariableFactoryService of
EcoSpace after that it is filled with variables which afterwards get evaluated in an OCL
expression.




                                                                                  Page 217
                              4.6 Uses for EcoSpace-Coding


  …
  var is : IVariableFactoryService;
      ov : IModifiableVariableList;
      iAge : Integer;
      sName : String;
      rRet : IElementCollection;
  begin
    sName := 'John';
    iAge := 66;

      vs := EcoSpace.VariableFactoryService;
      ov := vs.CreateVariableList('vFirstName', sName);
      ov.AddConstant('vAge', iAge);

      rRet:= EcoSpace.OclService.Evaluate
            ('CL_Person.allInstances->select
            (sFirstName.regExpMatch(vFirstName))',ov).GetAsCollection;
  …


Also in chapter 2.5.2 you can find the example [    Versioned]. There the code was placed
in the WinForm in the Datagrid-Event „CurrentCellChanged“.


Additional Units
We also want to have a look at the implementation of EcoSpace-Coding in additional Units
with the help of some examples.

In chapter 3.5 the example application [                 CustomOCL] contains the Unit
AdditionalOCL.PAS,which was implemented into the WinForm. In this unit an OCL-Operator-
class, derived from OCLOperationBase, that implements a custom defined OCL-Operator
was implemented.
In this Unit only class methods of the new OCL operator are defined. Access to class
instances of the model or EcoSpace itself is not provided and not necessary.
So the unit only has to include the Namespace Borland.Eco.Ocl.Support necessary for OCL
handling.

The example application [       PM1] in chapter 2.2.5 is similar.
Here we implemented custom PersistenceMapper-Methods for integrating application-
specific enumeration types into the OR-Mapping of the PersistenceMappingSystem.
Also an extra class with all methods was coded for each mapping component and was
placed in extra units (ADTInt.PAS und ADTStr.PAS)
In this case most of the units are implemented by the xxxEcoSpace-Unit.

In chapter 2.4.3 we dealt with the implementation of custom subscriptions . In the example
applications [    Subscription4 and Subscription5] custom units were used for the
implementation of an ISubScriber-Interface. Here these units were implemented through the
WinForm.




Page 218
                           4. ECO at runtime (EcoSpace-Coding)



4.7 Securing data integrity
Database-oriented applications require strategies to secure data integrity. For that there are
several ways in ECO-applications available, which we are going to have a look at in this
chapter.


4.7.1 Overview
ECO provides the following methods for securing data integrity

Variation            explanation
EcoSpace-            Several ECO-WinForms-applications with local EcoSpace
Syncronising         communicate via .Net- Remoting with a central EcoSpace application.
Optimistic Locking   Recognizes integrity violation by competing/paralel acccess to DB data.
Transaktionen        Ensures that a group of processes within EcoSpaces is executed
                     without interruption.


4.7.2 EcoSpace-Syncronising
In this MultiUser-Version multiple ECO-WinForms-applications (Clients), each containing a
local EcoSpace, are connected to a central ECO application (Server).
The EcoSpace of a client application contains a PersistenceMapper(PM)-Client- or PM-
Sharer-component and communicates with it via the PM-Provider-component of the server
application. The server application provides database access via a PM-SQLServer or a PM-
BDP. A PM-XML-version as a replacement for a database is not possible in such a
configuration .

Usually the communication between client application and the central PM-Provider happens
via .NET-Remoting. The parameters for .NET-Remoting can be set in a template that is
generated automatically in the source code (see next section).
Alternative a communication within one .Net process is possible, for example if client- and
server application are used on the same computer.
In a remoting case with multiple processes we use a PM-Client–component for the client, if
not we use a PM-Sharer-component.


Example application SyncServer/SynClient [                       SyncModelPackage,
SyncClient, SyncServer]
We want to demonstrate EcoSpace-Syncronising with the help of an example application,
consisting of an ECO server application (SyncServer) and an ECO client application
(SyncClient) based on a collective class model(SyncModelPackage).

First we define a simple class model CustomerModell, which will be the base for our multi
user application and save this as an UML package named SyncModellPackage (more on
working with UML-Packages in chapter 2.10.2).

The model exists of only one class CL_Customer with the attributes sFirstName,
sLastName and iCustNo.



                                                                                    Page 219
                                  4.7 Securing data integrity


SyncServer [          SyncServer]
Next we create an server application named SyncServer. In our example application we
choose a basic ECO-WinForms-application.
If the server application only should work as a „dedicated Server“, that means not having any
other function than providing the service itself, a simple console application would be
sufficient. More on that in the text below.

We create a ECO-WinForms-application named SyncServer. we import the collective class
model into this application by adding the package to the reference list of the application. The
required steps for importing a package are explained in chapter 2.10.4 in detail.

After that we have to announce the imported package to EcoSpace. This can be done wit
hthe button select packages on the design page of the unit SynServerEcoSpace.




The dialog for the selection of packages shows us two facts:

First the Customer-Model, which we add to the list of selected UML packages using the >
button, is provided within the imported SyncModelPackage.
Second, our new SyncServer-application contains the Default-Package Package_1Unit, that
contains no entries and is of no use four our goals in this case. So we can remove this
package from the list of selected packages.

The crucial difference between a server application and a basic WinForms-application is
revealed in the following steps.


SyncServer: Server-Part
We add a special ECO-Unit, a ECO-PersistenceMapperProvider-Unit to our SyncServer.
We find this in the object gallery under <Fiille> -- <New> -- <Other> -- <Dellphii ffor ,,NET--
                                         <F e> <New> <Other> <De ph or NET
Projjects> -- <New Eco Fiilles> .
Pro ects> <New Eco F es>




Page 220
                            4. ECO at runtime (EcoSpace-Coding)




We rename this new unit to SyncServerPersistenceMapperProvider.

A PersistenceMapperProvider-Unit (PMProvider-Unit) serves alternative to a
xxxEcoSpaceUnit among others the reception of the usual PM components.
The difference to a xxxEcoSpaceUnit is, that it doesn’t have it’s own EcoSpace . This can be
recognized by some missing buttons on the design page of the PMProvider-Unit, for example
the Button select Eco-Package.
Because of that we have to set the required connection from the PMProvider-Unit to the
EcoSpace of the application manually with the PMProvider-Property EcoSpaceType, that we
set to SyncServerEcoSpace.

Because of this we don’t place the persistence components in the xxxEcoSpace-Unit, but in
the PMProvider-Unit. As usual we use a BDPConnection and a PersistenceMapperBDP-
component. We create the database structure with the Generate Schema -Button.
                                                     Generate Schema
And we add a SyncHandler-component for server-side activation of the synchronization.




We establish the connection from the SyncHandler to the PersistenceMapperBDP-
component with its Property SyncHandler.

The last thing missing is the activation of.Net-Remoting. In the source code of our
PMProvider-Unit you see two entries which are commented out. One entry is in the interface
part, in the class definition of the provider component.

//class procedure RegisterTcpServer(Port: integer); static;

The other entry is in the implementation part.




                                                                                  Page 221
                                  4.7 Securing data integrity


   (*
   //       Examplecode...
   //       System.Runtime.Serialization.Formatters,
   //       System.Runtime.Remoting, System.Runtime.Remoting.Channels,
   //       System.Runtime.Remoting.Channels.Tcp;

   class procedure TEcoPersistenceMapperProvider.
                       RegisterTcpServer(Port: integer);
   var
      provider: BinaryServerFormatterSinkProvider;
      props: IDictionary;
      chan: TcpChannel;
   begin
      provider := BinaryServerFormatterSinkProvider.Create;
      // Necessary for serializing
      provider.TypeFilterLevel := TypeFilterLevel.Full;
      props := Hashtable.Create;
      props['port'] := Port;
      chan := TcpChannel.Create(props, nil, provider);
      ChannelServices.RegisterChannel(chan);
      RemotingConfiguration.RegisterWellKnownServiceType(
        typeof(TEcoPersistenceMapperProvider),
        'TestServer1',
        WellKnownObjectMode.Singleton);
   end;
   *)

All we have to do in our example application is to activate both code sequences through
changing the de-commends back and to extend the uses list in the implementation part of the
unit like mentioned in the comment.

We chose the following values as communication parameters for remoting via tcp in our
example application, differing from the defaults:

        •     Host:           localhost
        •     Port:           1234
        •     Service name:   SyncServer

To activate the TCP-Server we best call the method we just activated, from the constructor
method of EcoSpace; thereby passing the port number.

   constructor TSyncServerEcoSpace.Create;
   begin
     inherited Create;

        TEcoPersistenceMapperProvider.RegisterTcpServer(1234);

     InitializeComponent;
   end;

With this the coding of the server part of our SyncServers is finished.




Page 222
                            4. ECO at runtime (EcoSpace-Coding)

Notes:
  The behaviour of a server application can be modified with additional parameters.
  Among these are the properties of the PersistenceMapper-components in the section
  ECO-Pooling and ECO-Synchronisation, for example MaxOpenConnections and
  HistoryLength.


SyncServer: Client-Part
As mentioned above our SyncServer is based on a traditional ECO-WinForms-application
thus offering the opportunity of playing the server part as well as the client part. We will
implement this client part now.

To be able to add, delete and save Customer-entries we create a little user interface on the
design page of the WinForm unit .




We follow the usual ECO-WinForms-process:

      •   Connect the Roothandle (rhRoot) to EcoSpace
      •   place an ExpressionHandle (exphCustomer), connect it to the RootHandle and set
          the Property Expression to CL_Customer.allInstances
      •   place a Datagrid (dgCustomer) and set the Datasource-Property to the
          ExpressionHandle
      •   place a CurrencyManagerHandle (cmhCustomer) and connect it to the
          ExpressionHandle and the Datagrid
      •   place buttons with the ususal ECO actions like add, delete and save

The Client-Part in our SyncServer-application requires one last step, establishing the
connection to the server part.
To do this we have to place a PersistenceMapperClient-component on the design page of
the SyncServerEcoSpace-Unit. This way we get a local EcoSpace in our SyncServer-
application that can communicate with the PM-Provider of our application via .Net-Remoting.
You will probably look for this PersistenceMapperClient-component without success. The
reason is that this component is not part of the tool range by default. First we have to include
this component in the tool range.




                                                                                      Page 223
                               4.7 Securing data integrity


To do this we use the menu item installed .NET-components in the context menu of the tool
range.




This will lead us to the according dialog where we can add the PMClient-component to the
tool range.




Page 224
                            4. ECO at runtime (EcoSpace-Coding)

After finally having placed the PersistenceMapperClient-component on the design page of
the SyncServerEcoSpace-Unit, we only have to enter the URL of the server. With the values
from above the following URL results: ’tcp://localhost:1234/SyncServer’.
Now we can start the SyncServer and we will see that it works for a user like a simple single
user version of a Eco-WinForms-application.
On the inside of course the SyncServer behaves completely different. Each communication
of the local EcoSpace with the DB doesn’t take place directly, in between is a .NET-
Remoting-communication with an ECO-server. it doesn’t matter here that client- and server-
part are combined in one application.
If you doubt this, just change the port number and/or the server name in the URL property of
the PersistenceMapperClient-component. The errors caused by this when starting the
application should remove any doubts.


SyncClient [          SyncClient]
Next we want to create a pure ECO client application, also based on a traditional ECO-
WinForms-application.

To do this we create a ECO-WinForms-application named SyncClient. We import the
shared class model into this application by adding the package to the reference list of the
application. The steps necessary to import a package are explained in chapter 2.10.4.

Next we have to announce the imported package to EcoSpace. This is done with the button
select packages on the design page of the unit SyncClientEcoSpace. This is done exactly
the same as shown above for SyncServer.

For the sake of simplicity the SyncClient-application should have the same interface as the
client part of the SynServer-application. So we create the components in the winform unit just
like shown in the section SyncServer: Client-Part.

We also place a PersistenceMapperClient-component on the design page of the
SyncClientEcoSpace-Unit and set the same URL property for this component:
’tcp://localhost:1234/SyncServer’.

With this the client application is ready fortesting. Starting our SyncClient-application requires
an activated SynServer-application.
After starting SyncClient we can add, edit, delete and save Customer-entries, just like usual.


Synchronization and conflict management
But our example applications are not finished yet!

In our example applications SyncServer/SyncClient we created the base for multi-user use,
but what was left out so far – and what is very important in multi user applications – is the
data synchronization between the clients and conflict handling of competing accesses.

When we work parallel wit hseveral client applications at the current state of our example
application we will notice that:

      •    data changes of other clients are not displayed locally
      •    each save of changes can overwrite changes of other clients




                                                                                        Page 225
                                 4.7 Securing data integrity


in order to change this, we have to

     •     load and display changes made by other clients periodically or on demand
     •     when saving changes check for conflicts with changes from other clients and solve
           these conflicts

Thanks to ECO this can be done with little effort. The methods of the PersistenceService are
the base for that.

Some methods of the IPersistenceService
           Name                  explanation
           RetrieveChanges       Creates a list of objects that have been changed
                                 in other EcoSpaces
           GetChanges            Returns the list of changed objects as return
                                 value of the function in form of an Array of
                                 IChange
           ApplyAllChanges       The complete list of changed objects is enabled
                                 to be saved
           Refresh               Call RetreiveChanges, but will only care about
           (fetchValue: Boolean) “non conflict” changes. If the Boolean parameter
                                 is set to TRUE, the changes will be re-read at
                                 once.

With these methods changes can be loaded, evaluated and their saving can be controlled.
We should pay attention that in general for each object exist/are administrated 3 different
values/versions .

     •     The latest value loaded into EcoSpace from the db (LV)
     •     the current value in EcoSpace (AV)
     •     the current DB value (DV)

Various conflict- and solving- scenarios result from comparing these three values. The values
are administrated at each change., a change is defined as IChange, we can look up its
properties and methods in the Borland.Eco.Services.IChange Interface.




Page 226
                             4. ECO at runtime (EcoSpace-Coding)

Some Properties and Methods of IChange
Name               Version            explanation
Kind                                  defines the kind of change:
                   MemberChanged
                   ObjectCreated
                   ObjectDeleted
                   LinkConflict
                   All
Action                                Determines the action that has to be executed when
                                      saving the changes
                   Ignore             The change is not saved and is removed from the list
                                      of changes
                   Discard            The AV value is set to invalid and is replaced with the
                                      DV value on the next load
                   Reread             The AV value is replaced wit the DV value immediately
                   Keep               The LV value is set to the DV value., the AV value
                                      stays the same
                   Verify             A check for a conflict happens by comparing with the
                                      DV value, for example at a connection loss to a
                                      persistence server
                   Undecided          No changes happen, the change itself stays as it is
IsDirectConflict                      Shows if a conflict exists for this change
ChangedElement                        Enables access to the object that belongs to this
                                      change in form of an IElement.
                                      more on IElement in chapter 4.1
Apply                                 Enables the saving of this change with the defined
                                      action

Based on this information we can make the following adjustments to our example application.

We place a timer component in the WinForm of both applications and name it SyncTimer.
We set the timer interval to 3000 ms and define the following Timer-Tick-Method.

  procedure TWinForm.SyncTimer_Tick(…);
  var iAnyChange : IChange;
  begin
    // Retrieve all Changes from all the other EcoSpaces
    EcoSpace.PersistenceService.RetrieveChanges;
    // Iterate over all Changes
    for iAnyChange in EcoSpace.PersistenceService.GetChanges do
       begin
         if (not iAnyChange.IsDirectConflict) then
             begin //don’t look for conflicts but just for updates
               // refresh the ecospace-value with the db-value at once
               iAnyChange.Action := ChangeActionKind.ReRead;
               // or --- refresh the ecospace-value on demand
               //iAnyChange.Action := ChangeActionKind.Discard;
               iAnyChange.Apply;
             end;
       end;
  end;




                                                                                    Page 227
                                  4.7 Securing data integrity


Using this timer it first results in a periodical updating of the screen display. Each change of
Customer-objects by other clients is displayed in the WinForm of our applications within 3
seconds.

We only want to solve possible conflicts when saving our own changes. To do this we modify
the properties for the UpdateDatabase-Button in our WinForm.
Instead of the Default-ECO-Action used until now, we set a new Save-Method for the
OnClick-Event.

   procedure TWinForm.BtnSave_Click(…);
   var iAnyChange : IChange;
   begin
     // Retrieve all Changes from all the other EcoSpaces
     EcoSpace.PersistenceService.RetrieveChanges;
     // Iterate over all Changes
     for iAnyChange in EcoSpace.PersistenceService.GetChanges do
        begin
          // in the case of conflict
          if iAnyChange.IsDirectConflict then
              // other users may override my changes
              iAnyChange.Action := ChangeActionKind.Discard
              // or --- I’m the king
              // iAnyChange.Action := ChangeActionKind.Keep
              // or --- whatever…
              // iAnyChange.Action := ChangeActionKind.Ignore…
          else
          // in the case of update only
              iAnyChange.Action := ChangeActionKind.ReRead;
        end;
     EcoSpace.PersistenceService.ApplyAllChanges;
   end;

Our custom UpdateDatabase-Method checks each interim change for a possible conflict with
our own changes (DV-value <> LV-value). In case of a conflict we can decide between
various options. We also update the other (conflict-free) changes during this process.
                                                   A
This time all changes are allowed to be executed (ApplyAllChanges).

The IChange-Method ChangedElement provides a way of analyzing a change closer . It
returns an IElement for an corresponding change in the object.
This means for our example application, that we get an IChange-Element for each of our 3
            s
attributes (sFirstName, sLastName and iCustNo) of a changed customer object. To be
more precise that means that the method ChangedElement returns the IPrimitive-value of an
attribute. In order to get the concrete value of an attribute we can use the following
expression.

   (IAnyChange.ChangedObject As IPrimitive).AsObject.ToString

More on structure information and the IElement-level in chapter 4.1 and chapter 4.2.




Page 228
                           4. ECO at runtime (EcoSpace-Coding)



Remoting-Parameter
With the latest state of our example applications [     SyncClient, SyncServer] we can now
test the synchronization options for multiple-user-service. To do this we start a SyncServer-
application and multiple SyncClient-applications on our PC and change customer objects in
the various application windows .

However a multi-user test makes more sense when done in a network. But with the remoting
parameters used until now we can only execute the applications on one PC.

The changes required in the remoting parameters for use in a network are obvious. We only
have to change the hostname from localhost to the network name of the server, that means
to the name of the PC the SyncServer-application is executed on.

Another Option of configuration remoting is to assign an explicit application-name to the
server in the method RegisterTCPServer.

  RemotingConfiguration.set_ApplicationName ('MySyncServer');

In our example the URL string has to be adjusted accordingly.

  URL=tcp://localhost:1234/MySyncServer/SyncServer



4.7.3 Optimistic Locking
The conflict solving method shown in the preceding chapter is based on the recognition
and“processing“ of interim data changes of other users by comparing the local with the
central EcoSpace instance.

However Optimistic Locking (OL) is a method that can recognize possible integrity violations
due to competing accesses by comparing database entries directly.

An example for competing accesses: user a and b load the same object, for example a
person from the database, user a changes the first name from Jan to Jonas and saves the
object. User b, who still has the “old” object displayed on his screen, changes the first name
from „Jan“ to „Peter“ and also saves the object. With the save of user b the changes of user
a would get lost automatically.

In this case an OL method would recognize by reading the data object first, as soon as B´s
changes are saved, the old first name has been changed by user A from Jan to Jonas and
would stop and question the save of Peter.




                                                                                    Page 229
                                  4.7 Securing data integrity


In ECO OL is activated with the following settings:

     •     globally activating OL in the EcoSpace-Object
     •     class-specific configuration of OL

The global property Optimistic Locking of
EcoSpace can be set at development time with the
object inspector or at runtime in the global EcoSpace
object.




  EcoSpace.OptimisticLocking := TRUE;

Afterwards we have to set in all classes the class specific property Optimistic Locking, for
which the OL should be activated. This has the following characteristics:

characteristic       explanation
Off                  OL is deactivated for this class
Default              The OL settings of the super class is crucial.
ModifiedMembers      When an attribute is saved, ECO checks if the former value of this
                     attribute has been changed in the meantime by another user. In this
                     case ECO causes a runtime exception.
AllMembers           When an attribute is saved, ECO checks if the former value of any
                     attribute of the class instance has been changed in the meantime by
                     another user. In this case ECO causes a runtime exception.
Timestamp            ECO recognizes a possible competing access by comparing timestamp
                     values and in this case causes a runtime exception

The ModifiedMembers and AllMembers-Versions lead to the following, ECO reloads the
affected/all attributes of a class instance by SQL query when a class instance gets saved
and compares them with the fetched values in the cache for any changes in the meantime.

The timestamp version is the most efficient form of OL. Here ECO can recognize by an
additional timestamp entry if a class instance has been changed in the meantime by another
user. A precondition for that is, that the property UseTimeStampTable in the Property
SQLDatabaseConfig has been set in the PersistenceMapper-component (see chapter
2.2.4).

Independent of which form of OL has been selected in the class specific property Optimistic
Locking, ECO creates during saving of an object, which has been changed in the meantime
by another user, a runtime exception in the form of „OL failed for xxx objects“.

In the example application [    OL1] we chose the AllMembers-method. The application
contains only one class CL_Customer with 3 attributes. In the WinForm new CL_Customer-
entries can be changed, edited and deleted in a datagrid. An OnClick-event is assigned to
the UpdateDatabase-Button, which executes the following OL exception evaluation.




Page 230
                          4. ECO at runtime (EcoSpace-Coding)

  procedure TWinForm.BtnUpdateDatabase_Click(…);
  var eDialogResult         : System.Windows.Forms.DialogResult;
      eSelectedActionKind : ChangeActionKind;
      iAnyChange            : IChange;
  begin
    try
      EcoSpace.UpdateDatabase;
    except
      // optimistic failure?
      on ex: Exception do
        begin
           eDialogResult := MessageBox.Show('OL-Error: Save anyway?',
  ex.message, MessageBoxButtons.YesNoCancel);
           if (eDialogResult = System...DialogResult.Yes) then
              eSelectedActionKind := ChangeActionKind.Keep
                 // save changes even though
           else
           if (eDialogResult = System...DialogResult.No) then
              eSelectedActionKind := ChangeActionKind.ReRead
                 // retreat
           else
              eSelectedActionKind := ChangeActionKind.Ignore;
                 // cancel

             // Iterate over all Changes
             for iAnyChange in ...PersistenceService.GetChanges do
                begin
                  // in the case of conflict
                  if iAnyChange.IsDirectConflict then
                      iAnyChange.Action := eSelectedActionKind
                  else
                  // in the case of update only
                      iAnyChange.Action := ChangeActionKind.ReRead;
                end;
             EcoSpace.PersistenceService.ApplyAllChanges;
             EcoSpace.UpdateDatabase;
           end;
    end;
  end;

If the normal UpdateDatabase leads to an Exception (OL), the OL conflict is solved there.
The security dialog offers 3 ways of solving:

     •    The option „save anyway“ forces a save of the instance (Keep) thus overwriting
          the changes of another user.
     •    The option „don’t save“ discards the changes made by oneself (ReRead or
          Discard) and reloads the instance changed in the meantime from the DB.
     •    The Option „Cancel“ lets the DB remain unchanged (Ignore), but also keeps the
          local instance values, so that the second UpdateDatabase (in the end) again
          causes an exception, which is not solved in this example!

In the OnClick-Event above the IPersistenceService- and IChange-Methods are used again,
similar to the way we used them in chapter 4.7.2.




                                                                                Page 231
                                  4.7 Securing data integrity


To cause OL-Exceptions,first start the application one time, than add a new CL_Customer
Object and save your inputs. Now start a second instance of the application, change the
object just created in the other instance and save again. Switch back to the first instance and
make another change with the same object. When saving this object you will get an
exception message.

This Ol method supported by ECO rarely is sufficient. For example it still can happen, that, in
the short time span when ECO reloads data from the DB to compare them with the fetched
values, changes of another user are saved. In such cases the OL process has to be
additionally secured, for example by a transaction.


4.7.4 Transactions
With transactions a group of DB operations can be executed in a „block“, which ensures that
either all operations of the block are executed completely or the execution of the block is
discarded completely without any changes in the DB.

When saving objects, ECO uses transactions with the methods UpdateDatabase or
UpdateDatabaseWithList, in order to ensure that each call of such a method either gets
completed successful or, in case of an error, leads to an exception, in which case the DB and
the EcoSpace-IObject instances are set back to the state they had before calling the method.

Explicit Transactions are coded in ECO for processes within the EcoSpace respectively for
securing user actions and their effects on EcoSpace .
They are similar to the undo/redo mechanism in ECO and thus can be reached via the
IUndoService-Interface.

Method                explanation
StartTransaction      Marks the begin of recording of changes for a finishing Commit- or
                      RollbackTransaction.
CommitTransaction     Lists all changes made since the last StartTransaction.

RollbackTransaction Resets all changes made since the last StartTransaction.

A typical structure of an operation encapsulate by a transaction looks like this.

   EcoSpace.UndoService.StartTransaction;
   try
     ... // place here the “surrounded” actions
     EcoSpace.UndoService.CommitTransaction;
   except
     EcoSpace.UndoService.RollbackTransaction;
     // Exception handling because transaction failed
   end;

If the changes in EcoSpace created by this operation are supposed to be saved immediately,
the UpdateDatabase-call is added.




Page 232
                  4. ECO at runtime (EcoSpace-Coding)

EcoSpace.UndoService.StartTransaction;
try
  ... // place here the “surrounded” actions
  EcoSpace.UndoService.CommitTransaction;
  EcoSpace.UpdateDatabase;
except
  EcoSpace.UndoService.RollbackTransaction;
  // Exception handling because transaction failed
end;




                                                        Page 233
                            4. ECO at runtime (EcoSpace-Coding)


 4.8 Undo- and Redo-Operations
 In order to be able to reset user entries and –actions before saving them, ECO provides the
 IUndoService. This service offers the following methods.

Method                     explanation
StartUndoBlock (sName)     Marks the begin of a new undo block, that is placed at the
                           beginning of the undo block chain.
UndoLatest                 Resets all entries of the first undo block of the chain and deletes
                           this block.
UndoBlock (sName)          Places the specified undo block at the beginning of the chain and
                           executes a UndoLatest.
ClearAllUndoBlocks         Deletes all undo blocks from the chain
CanUndoBlock (sName)       Checks, if an undo block operation with the specified name would
                           be possible.
GetUniqueBlockName         Returns a distinct block name based on the specified name by
(sName)                    adding a counter.
UndoList                   Returns the complete chain of all undo blocks as IUndoBlockList.

 The Undo-Handling uses single Undo-bBocks, that form an Undo-chain (Stack). Each block
 gets a distinct name. The latest block created is at the beginning of the Undo-block-chain.
                                                    I
 the function UndoList returns the complete chain (IUndoBlockList).

 With the method StartUndoBlock (sName) a new Undo-Block is placed at the beginning of
 the chain with the specified (distinct) name.
 From now on all changes done in EcoSpace, for example user entries and –actions are
 added to this block .

 Deleting Undo-blocks is possible in the following ways:
       •   the Method UndoLatest resets the entries that belong to the top block of the chain
           and then deletes this undo block.
       •   the Method UndoBlock (sName) places the specified block on top of the chain
           and then executes the function UndoLatest.
       •   the method ClearAllUndoBlocks deletes Undo-Blocks of the chain.
       •   saving the changes EcoSpace with UpdateDatabase etc. deletes the whole undo
           block chain.

 The redo function in ECO enables to reverse an undo function right after executing it. Thus
 Undo- and Redo-Functions are related closely.
 The Method UndoLatest, that reverses the actions saved in an Undo-block, automatically
 creates a Redo-block identical in content and name thus creating the option of making the
 Undo operation invalid by executing a RedoLatest-Operation afterwards .
 The antigon function RedoLatest executes the actions contained in the Redo-block. There
 the Redo-block is deleted and an identical Undo-block is created. This can be repeated
 endless.




                                                                                     Page 235
                              4.8 Undo- and Redo-Operations


The Redo-Methods are also located in the IUndoService.

Method                  explanation
RedoLatest              Executes all entries of the first Redo-block in the chain and deletes
                        this Redo-block.
RedoBlock (sName)       Places the specified Redo-block at the beginning of the chain and
                        then executes RedoLatest.
CanRedoBlock            Checks if a Redo-block operation with the specified name would be
(sName)                 possible.
RedoList                Lists the complete chain of all Redo-blocks as IUndoBlockList.

The Redo-Handling and its underlying object structures are identical with the Undo-concept .
A list of Redo-blocks builds a Redo-chain (Stack). Each block gets a distinct name. The
latest created Redo-block is at the beginning of the chain. The function RedoList returns the
               I
complete list (IUndoBlockList).

                           U
The methods UndoLatest /UndoBlock automatically add new Redo-blocks to the Redo-
block-chain. Deleting of Redo-block can be done just as Undo-blocks with the methods
RedoLatest / RedoBlock, which on their part add similar Undo-blocks.

Note:
  Going back and forth in the Redo- and Undo-chain only works as long as no other
  interfering actions like UpdateDatabase are executed.
  The methods UndoBlock and RedoBlock are not available if these blocks contain entries
  that are also contained in blocks which are positioned before them.
  Even without a preceding StartUndoBlock new entries in the instance and instance
  changes are added as a standard Undo-block with the name „UnNamed“.

In the example application [      Undo] we defined a class CL_Person with the now familiar
sFirstName- and sLastName–Attributes. The winform provides the usual datagrid to enter,
edit and delete CL_Person-Instances.
In addition the winform displays the contents of the current Undo- and Redo-chains in a
listbox. Additional buttons allow the execution of the methods StartUndoBlock, UndoLatest,
RedoLatest and the Refresh of the listbox display.

In order to get distinct block names we use the .NET NewGuid-Method. For reading the
undo/redo-chains we code RefreshLB-Method.




Page 236
                           4. ECO at runtime (EcoSpace-Coding)

  procedure TWinForm.RefreshLB;
  var s                     : String;
      i, j, jCount, iCount : Integer;
      oItem                 : IUndoBlock;
      oPerson               : CL_Person;
  begin
    LBUndo.Items.Clear;
    iCount := EcoSpace.UndoService.UndoList.Count;
    for i := 1 to iCount do
      begin
        oItem := EcoSpace.UndoService.UndoList.Item[PRED(i)];
        s := oItem.Name;
        if TRUE then //oItem.ContainsChanges is not secure
            begin
              try
                jCount := oItem.GetChangedObjects.Count;
                s := jCount.ToString + ' - ' + s;
                LBUndo.Items.Add(s);

                 for j := 1 to jCount do
                    begin
                      oPerson:= CL_Person (oItem.GetChangedObjects.
                         Item[j-1].AsObject);
                      s := '     ' + oPerson.sFirstName +
                         ' ' + oPerson.sLastname;
                      LBUndo.Items.Add(' - ' + s);
                    end;
               except
                 // nothing to do here
               end;
             end
          else
             LBUndo.Items.Add(s);
        end; …

In the Method RefreshLB we first delete the „old“ contents of the listbox and then determine
the number of blocks in the chain.
Then we have to check each block of the chain for entries. Unfortunately the function
ContainsChanges always returns FALSE for deleted instances, even if a entry exists in this
block. Because of this we access all entries in our example and avoid such errors with
try..except.
Each entry represents an IObject as reference to the corresponding class instance. Our
example application only contains the class CL_Person, so here we can cast a oPerson-
Instance immediately (see chapter 4.1) and display its attributes.




                                                                                  Page 237
5. ECO and the GUI
The 5th chapter of this book deals with the design of the graphic user interface (GUI) in an
ECO-WinForms-application.



5.1 Basics
5.1.1 EcoSpace, WinForm and ECO Handles
The connection between EcoSpace and the GUI is established with special ECO handles.

We already dealt with the basic types and tasks of these handles in chapter 1.2.2, more
details will follow in this chapter.

EcoSpace in an ECO-WinForms-application is a single instance of the EcoSpace class
defined in the xxxEcoSpace-Unit. The ECO-WinForm-Unit, provided by default in an ECO-
WinForms-application creates this EcoSpace instance in the constructor of the TWinForm
and activates it.

  constructor TWinForm.Create;
  begin
    inherited Create;
    InitializeComponent;

     FEcoSpace := TxxxEcoSpace.Create;
     rhRoot.EcoSpace := FEcoSpace;

    FEcoSpace.Active := True;
  end;

If we use multiple WinForm-Units in an ECO-application, we have to pass this EcoSpace
instance to the other WinForm-Units. More on this topic in chapter 5.1.4.

The connection between the GUI controls of a WinForm and EcoSpace is established with
two kinds ECO handles. First we create one or more Root Handles and establish a
connection to the EcoSpace instance with the property EcoSpaceType. The second group of
ECO handles, the so-called Rooted Handles are linked to a Root Handle with the property
Root. As an alternative rooted handles can choose another rooted handle as connection
point.
This way chains of various lengths are built, on whose beginning a root handle is the
connection to EcoSpace and on whose end a rooted handle is placed as a direct datasource
for GUI controls.




                                                                                  Page 239
                                         5.1 Basics




In the default ECO-WinForm a Root Handle (a ReferenceHandle to be more precise) called
rhRoot already exists. All other Handles have to be explicitly added to the winform.
In the example application [   GUI1] we linked a rooted handle (an expression handle to be
                                                     rh
more precise) exphCustomer to the root handle rhRoot. ExphCustomer provides all
instances of the CL_Customer-class. Another Rooted Handle (a CurrencyManagerHandle)
cmhCustomer was linked to the exphCustomer Handle and serves as dataset indicator of
the current instance of the CL-Customer-class.
We linked two additional rooted handles, exphOrder and exphSupport, to the
CurrencyManagerHandle .

ExphOrders serves as datasource for all orders of the current customer, whereas
exphSupport administrates the support processes.
In accordance to that the 3 datagrids of our application contain the customer list, orders and
support processes of the currently selected customer.




Page 240
                                    5. ECO and the GUI




5.1.2 ECO Handle Properties
In chapter 4.1 we analyzed the IElement-level of EcoSpace. To each object in EcoSpace an
IElement provides a generic way of referencing the contents of an EcoSpace.
For example an a class instance can be referencesd as a IObject, an attribute of an instace
as iPrimitive , and a list of instances, such as an association-end of multiplicity >1 as an
IObjectList.


ECO Handle and IElement
Each handle has a value which an IElement. The value can be reached through the Element
property. The value is determined in different ways for different handles:

ECO Handle-Type              example application     object assignment
                             [   GUI1]
ReferenceHandle              rhRoot                  By calling the SetRoot() method.
ExpressionHandle             exphCustomer            As the result of evaluating
                                                     Expression, with RootHandle.Element
                                                     as the context
CurrencyManagerHandle        cmhCustomer             The element in RootHandle currently
                                                     selected in the GUI.




                                                                                  Page 241
                                             5.1 Basics


In our example application [      GUI1] the following element values of the ECO handles are
set.

 ECO Handle              Root resp.                Expression                    Type of
                         RootHandle resp.                                        Element-
                         EcoSpace-Property                                       Property
 rhRoot                  EcoSpace                  -                             -
 exphCustomer            rhRoot                    CL_Customer.allInstances      IObjectList
 cmhCustomer             exphCustomer              -                             IObject
 exphOrder               cmhCustomer               self.HasOrder                 IObjectList
 exphSupport             cmhCustomer               self.HasSupport               IObjectList

The root handle serves two roles, it is the connection to the EcoSpace for a chain of handles,
but it can also (optionally) hold a value. In this example the root handle rhRoot is not used to
hold a value, just to serve as a connection to the EcoSpace, so the element property of
rhRoot has not been set.
The second root handle in our example application [     GUI1] however, rhRoot2, is used to
hold a reference to a customer. We can ensure that it is not set to anything else bu setting
               St
the property StaticValueTypeName of the Root Handle to CL_Customer. With
StaticValueTypeName we can limit the data selection to a „certain area of objects“ of
EcoSpace, determined for example by class names.

The handle chain cmhCustomer->exphCustomer->rhRoot could then be replaced with
the chain cmhCustomer->rhRoot2.

Setting of the properties of an ECO handle cannot only be done during development but also
dynamically at runtime. you can find an example in chapter 5.1.4.


Property-overview
The following tables provide an overview of the basic properties of ECO handles.

ReferenceHandle-               explanation
Properties
EcoSpace                       connection to EcoSpace
StaticValueTypeName            object name from EcoSpace (optional)
Element                        the value as an IElement
Columns                        see chapter 5.2.1
Nestings                       see chapter 5.2.2
Variables                      Links to a OCL-Variable-component see chapter 3.4


ExpressionHandle-               explanation
Properties
RootHandle                      Connection to a handle that servers as the context (root) of
                                the expression.
Expression                      OCL-expression for data selection
Element                         the value as an IElement
Columns                         see chapter 5.2.1
Nestings                        see chapter 5.2.2
Variables                       Links to a OCL-Variable-component see chapter 3.4




Page 242
                                   5. ECO and the GUI


CurrencyManagerHandle- explanation
Properties
RootHandle             Handle that we want to extract the current element from
BindingContext         A control that serves as data indicator and whose .NET Binding
                       Context is supposed to be used, see chapter 5.1.3
CurrencyManager        the .NET CurrencyManager (read only), see chapter 5.1.3
Element                The element in RootHandle.Element selected in the
                       BindingContext
Position               Position of Element in RootHandle.
Columns                see chapter 5.2.1
Nestings               see chapter 5.2.2
Variables              Links to a OCL-Variable-component see chapter 3.4


IBindingList, IList, ITypedList
The ECO handles participate in the .NET databinding by implementing the interfaces IList ,
ITypedList and IBindingList. The IBindingList Interfaces offers various methods of
accessing the data-list of the handle. The Method ListChanged for example enables
accessing the ListChanged-Event, in order to be able to react to possible changes in the
datalist.
The ListChanged-Event provides for this purpose an EventArgument-Object, which has the
following properties.

 ListChangedEventArgs-        explanation
 Properties
 ListChangedType              ItemAdded, ItemDeleted, ItemChanged, Reset...
 NewIndex                     new set position
 OldIndex                     Old set position


5.1.3 Databinding
In the preceding chapters 5.1.1 and 5.1.2 we learned about the general connection between
EcoSpace and the Gui with ECO handles. In this chapter we will deal with the interactions
between the various GUI controls and the ECO handles.


.NET Data-binding and ECO
                                                            .
Since ECO applications are based on .NET, the so-called.NET-Databinding is here very
important.
A connection between a GUI control, for example a datagrid and an ECO handle, for
example an expression handle is usually established with the property Datasource of the
control. With the creation of the connection a so-called .NET Binding Context is created,
which ensures the synchronization of the datasource (usually an expression handle) and the
control. This binding context contains a .NET CurrencyManager, which takes over the task
of administrating the positions of the data list.
If multiple GUI controls are connected via its datasource property to the same expression
handle, these controls share the binding context and thus the currency manager.




                                                                                 Page 243
                                          5.1 Basics



Note:
  The .NET CurrencyManager and the ECO CurrencyManagerHandle are two
  completely different things! The ECO CurrencyManagerHandle is explained below .

The .NET Binding Context concept also applies to ECO applications. ECO Handles serve as
datasource and the „dataset indicator“ functionality of the.NET CurrencyManger can be
accessed with a explicit ECO CurrencyManagerHandle.

To achieve this we have to connect a ECO CurrencyManagerHandle to the datasource (for
example an expression handle) via the property RootHandle and to a control via the property
BindingContext. This automatically establishes the connection of the ECO
CurrencyManagerHandles to the .NET Binding Context and the .NET CurrencyManager.

In general there exist two ways of realizing databinding in an ECO-WinForms-application.


Complex databinding with a DataSource-Property
As mentioned above, a databinding context originates for example from the connection of an
expression handle and a control via the Datasource-Property of the control.
We have often used this option in the various examples of this book. Usually the instances of
a class (for example CL_Customer) are used as datasource. A datagrid control can display
multiple elements (attributes) simultaneously, so it suits well for this purpose.

All controls that can display „multiple“ elements, like list- and comboboxes, can be used that
way.
Whereas the assignment of the class attributes to the datagrid columns can happen
automatically, additional settings in the control have to be made if the structure of the
datasource does not match 1:1 the structure of the control.

We want to demonstrate this in the example application [       GUI2] with a listbox and a
combobox. Our base is the application GUI1, which we due to simplicity reduce to the class
CL_Customer but to which we add an additional listbox and combobox.
Both new controls get linked to the exphCustomer Handle via their datasource property.

After starting this first version of our application we will notice that new CL_Customer-entries
in both new controls are displayed by the expression Borland.Eco.Handles.Rendered-
Tuple , which is not very helpful.
Since a “non-structured” listbox/combobox does not match the “data structure” of our class,
we have to assign the concrete class attributes that are supposed to be displayed to the new
controls.
This is done with the Property DisplayMember. For the listbox we select the attribute
sFirstName, for the combobox sLastName.

As we now notice, every change of a display position of one of the three controls leads
always immediately to an update of the display of the other controls, because all three
controls are located within the same binding context and with that they also use the same
CurrencManager (see previous paragraph).

This new list and combobox can be used to display class attributes, but it can´t be used to
edit values (yet). This function will be added in chapter 5.3.2 .




Page 244
                                     5. ECO and the GUI


Simple Data-binding with the Property DataBindings
The control property DataBindings offers another way of using .NET Databinding with an
ECO-WinForm. This property provides a dialog in the field Extended , with which a single
element of a datasource can be assigned to each control property.




For example in a textbox control the data field sLastName of a CL_Customer-Instance
would be assigned to the property Text.

Just like in the first way of databinding it is also true for this case, that each change in the
binding context of the connected property immediately updates its display.
For demonstration reason we added another textbox control in the example
application[    GUI2] and linked its text field to the class attribute iCustNo via the
cmhCustomer-Handle. The customer number of the currently selected CL_Customer-
Instance is displayed simultaneously in the datagrid and this textbox, it can also be edited in
both places.

Hint:
  As mentioned before, in this example there is no real need for using a
  CurrencymanagerHandle too. As an alternative we can link the text field to the
  ExpressionHandle instead.




                                                                                      Page 245
                                       5.1 Basics


5.1.4 ECO-WinForms
As described in chapter 5.1.1, each ECO-WinForms-application contains a Standard-ECO-
WinForm, in whose constructor the central EcoSpace-Instance of the application is created
and activated.

With the menu item we can get additional ECO-WinForms in the Delphi-IDE
<Fiille> – <New> – <Other> -- <Dellphii ffor ..NET> -- <New ECO Fiilles> .
<F e> – <New> – <Other> <De ph or NET> <New ECO F es>




From the object gallery we select the entry ECOWinForm.

Each additional ECO-WinForm can be distinguished from the Standard-ECO-WinForm by its
changed constructor.
In the Standard-ECO-WinForm the central EcoSpace-Instance is created once and activated
(see chapter 5.1.1). However the constructor of an additional ECO-WinForm requires this
central EcoSpace-Instance as a passing parameter and assigns this instance to a local
EcoSpace-Variable.
When creating an additional ECO-WinForm, for example from a method of the Standard-Eco-
Winform, the central EcoSpace-Instance has to be passed to the constructor.

   TWinForm1.Create (EcoSpace);




Page 246
                                   5. ECO and the GUI



WinForm vs. ECO-WinForm
The TWinForm-class in an ECO-WinForm is derived from System.Windows.Forms.Form just
as in a common .NET- WinForm
However in contrast to a common WinForm-Unit an ECO-WinForm-Unit contains the
following entries:

     •    Inclusion of the Units Borland.Eco.Handles, Borland.Eco.Windows.Form and
          Borland.Eco.WinForm in the interface part of the Unit.
     •    Five additional invisible ECO components in the TWinForm-class (see next
          section).
     •    Additional local EcoSpace-Variable in the TWinForm-class (see previous section).
     •    Additional getter-method for access to the local EcoSpace-Variable in the
          TWinForm-class .
     •    Inclusion of the Units Borland.Eco.ObjectRepresenation and Borland.Eco.Services
          in the implementation part of the Unit.
     •    Initialization of the 5 ECO components in the InitializeComponent-Method.
     •    Assignment of the central EcoSpace instance passed in the constructor to the
          local EcoSpace-Variable (see previous section).

Thus with little effort a common WinForm can be transformed into an ECO-WinForm with.


The 5 Standard-ECO-components
Each ECO-WinForm contains by default the following 5 ECO components:

     •    a ReferenceHandle rhRoot for connection to EcoSpace (see chapter 5.1.1).
     •    an EcoActionExtender-component EcoGlobalActions, which adds the property
          EcoAction to all button controls.
     •    an EcoActionExtender-component EcoListActions, which adds the property
          EcoListAction to all button controls.
     •    an EcoAutoFormExtender-component EcoAutoForms, which adds the properties
          EcoAutoForm and EcoAutoFormReadonly to all listbox and datagrid controls
          (see chapter 1.4.5).
     •    an EcoDragDropExtender-component EcoDragDrop, which adds the properties
          EcoDragSource and EcoDropTarget to all listbox and datagrid controls (see
          chapter 1.4.5)

The Extender-components contain several properties, most of all properties to determine
names for the various actions. Besides that an individual button image can be assigned to
each action with the property ImageList.




                                                                                 Page 247
                                          5.1 Basics




Unit-spanning referencing of ECO Handles
With one or more rhRoot-components ECO-WinForms get access to the EcoSpace of the
application (see chapter 5.1.1). In most cases data that is displayed in the various ECO-
winforms is related somehow, for example have a master-detail-relation.

In the example application [     GUI3] we placed each, the visualization of a customer list
 C                                             C
(CL_Customer) and the orders of a customer (CL_Order) as well as its support processes
 C
(CL_Support) in an extra ECO-WinForm. If you select a customer from the list in the base
winform and then activate the second winform, the orders of the selected customer are
supposed to be displayed there, and the 3rd winform is supposed to display the according
support processes .
With that information about the selected customer has to be passed from the base winform to
the sub winforms.
To achieve this we can go 2 different ways.

The first solution is to include the appropriate ECO handle from the base winform as the root
of the handle chain of the sub winform. This automatically synchronizes all winforms. Each
change in a winform automatically updates the display in the other winforms.

As an alternative to this solution you can pass only the object referenced by the handle out of
the EcoSpace to the sub winform instead of the complete ECO handle (see chapter 5.1.2).
With this way for example the selection of another customer in the base winform doesn’t lead
to an update in the sub winforms.

The example application [     GUI3] uses the first method for displaying orders and the
second method for displaying support processes.

For the display of orders and SupportCalls we set the following „temporary“ ECO handle
chains:

rhRoot <-> exphOrder <-> Datagrid-Orders
rhRoot <-> exphSupport <-> Datagrid-SupportCalls

The final binding can only take place at runtime with the call to open the sub winform. In
order to be able to access the object structures at development time, we configure the ECO
handles temporarily using the StaticValueTypeName-Property of the Root Handle.

For the Order-WinForm we set the ValueTypeName-Property from rhRoot to CL_Order. So
for now the ExpressionHandle exphOrder doesn’t need any further settings.
For the Support-WinForm we set the ValueTypeName-Property from rhRoot to
CL_Customer.      The      ExpressionHandle       exphSupport       gets   the    Expression
self.CL_Support.
This way the datagrid already contains the final column entries at development time.

For the passing of information from the base winform to the subwinforms at runtime we code
the following methods.




Page 248
                                    5. ECO and the GUI

  procedure TWinForm1.SetSelectedCustomer_cmh
              (cmh : CurrencyManagerHandle);
  begin
    exphOrder.RootHandle := cmh;
    exphOrder.Expression := 'self.CL_Order';
  end;

With this the link between rhRoot and expOrder is at runtime deleted in the Order-WinForm.
Instead exphOrder gets linked to the CurrencyManagerHandle of the BasisWinForm thus
getting implemented into the Binding Context of the Basis-WinForm.

  procedure TWinForm3.SetSelectedCustomer_obj (iEL : IElement);
  begin
    rhRoot.SetElement (iEl);
  end;

For the Support-WinForm the IElement-Reference of the Root Handle is set to the currently
selected Customer-Instance.


Force or prevent a GUI-Update
In certain situations it is necessary to force an update of the IList implemented by the ECO
handles used by the databinding in order to update the resulting display in the controls.
Generally ECO executes corresponding updates only when the application is idle, in order to
improve performance and avoid screen flickering.
Besides that ECO doesn’t consider some state changes as (immediately) sufficient to cause
an update (an example in Chapter 5.3.1).

In such situations it can be helpful calling the handle method EnsureBindingList /
EnsureAllBindingLists, that forces a display update of the data of a concrete ECO handle /
all ECO handles .

Of course there is also the option of generally preventing updates of GUI controls. The call
WinFormDequeuer.Active := FALSE deactivates the                     GUI-Update, the call
WinFormDequeuer.Active := TRUE reactivates the Updating.




                                                                                  Page 249
                                     5. ECO and the GUI


5.2 Columns and Nestings
The columns implement by default by a handle depend on the type of the value in the
Element property.
In our example application [    GUI1] the instances of the class CL_Customer are assigned
as data area to the expression handle exphCustomer.
The result is that attributes of the class CL_Customer (iCustNo, sFirstName and
                                                                i
sLastname) automatically form the default columns of this handle.


5.2.1 Columns
In the Property-overview of ECO Handles in chapter 5.1.2 is among others the Property
Columns listed. This Property does not show the base columns, however, it allows creating a
list of additional columns as an extension for the base columns.
For this property the object inspector provides a list editor to add additional columns, called
Member. Each member receives a name and an OCL expression that defines its value.
The OCL-Editor can be used to edit the OCL expressions . The context (=origin ) of the OCL
expression is type of the items in the value of the handleitself.




The add-button of the list editor has two options, OCLColumn and EventDerivedColumn. In
this chapter we will only deal with OCL based columns. The other column type will be
described in chapter 5.2.3.

The use of the column property can be demonstrated very well with our example application
[    GUI1]. There we defined the expression handle exphCustomer as data source of the
display of customer instances.
Various orders can be assigned to each customer with the association ASS_Orders. In our
example we want to improve the customer display in a way that the number of orders is
displayed for each customer.
This can be achieved very easily by creating a new member OrderCount with the Columns-
Property of exphCustomer and assigning the OCL expression self.CL_Order->size.




                                                                                     Page 251
                                 5.2 Columns and Nestings


ExphCustomer contains, in addition to the base columns a custom defined column list,
whose members are immediately used by the controls connected to the handle (here:
datagrid). In our example the column order count was added automatically to the customer
datagrid after the definition of the ordercount member.


Hierarchic Columns
The result of an OCL expression of a member, defines the member type; in the example
above this is an integer. OCL-Expressions can have various result types (see chapter 1.3), in
accordance the member types of the column property can vary.
To have a closer look at this we extended the base model of the application [       GUI1] in
our next example application [     GUI6], so now we can, based on a CL_Customer-
Instance, receive the list of Orders of the customer and for each Order the list of
OrderLines.




In the WinForm we want to define a Datagrid dgCustomer that can represent this hierarchic
structure. In order to do this we have to extend the expression handle exphCustomer
accordingly via its column property.

Next to the already implemented Member OrderCount we add – with the column list editor-
                     H
two more members (HisOrders and SupportCalls), which will enable access to the orders of
a customer as well as to its support calls. An overview of the configuration:

   Properties in the list   1. Member                2. Member         3.Member
   editor
   Name                     OrderCount               HisOrders         SupportCalls
   Expression               self.CL_Order->size      self.CL_Order     self.CL_Support
   Nested                   FALSE                    FALSE             FALSE
   NestingName

Whereas the first member „only“ represents an integer, the other two members represent
object lists.




Page 252
                                     5. ECO and the GUI

In the Customer-Datagrid the three additional columns are displayed next to the attributes of
the CL_Customer-class. However, the datagrid only displays an integer for both object list
members, the number of orders / support call entries of a customer.




The individual order/support call lines are not displayed (yet). In order to achieve this we
have to set Nesting-Parameters.

The easiest way to do this is to activate the Nested-Property in the list editor for the 2nd and
3rd member.
This change causes an immediate adjustment in the datagrid. The two datagrid columns
HisOrders and SupportCalls are deleted automatically, each customer line receives a plus
symbol instead for switching the display to an orders / support call sub grid level.




Clicking the HisOrders-Subgrid-Link then results in the following display:




In the datagrid the attributes of the selected customer are moved to the header area. Instead
of the various customer instances the grid now displays all order entries of the current
customer. An additional back arrow in the header enables navigating to the super grid level.

The display of the order attributes complies with the default settings. Order instances in the
order datagrid are created exactly the same way.




                                                                                      Page 253
                                 5.2 Columns and Nestings


5.2.2 Nestings
Another entry in the property overview of ECO handles is the property Nestings. With this
property we define the “appearance” of the columns we defined earlier with the column list
editor. In general using an according nesting member is optional, but in certain situations
absolutely necessary, as we will see.

With the nesting list editor new entries, so called members, are created that have the
following properties.

  Properties                   explanation
  Name                         member name
  AddDefaultProperties         TRUE, if the default columns are supposed to be displayed
  AddDefaultNesting            TRUE, if the member is supposed to contain a sub grid
                               display
  Columns                      List of columns to display additionally
  TypeName                     Context of the OCL expression of the additional columns

Each member receives a name and – in the most simple case – the default property settings.
If the display type of this member is supposed to be changed, the additional columns can be
defined in the familiar way with the property columns. Besides that the display of the default
           A
columns (AddDefaultProperties) can be prevented.
In the example application [    GUI6] we defined Nesting-Member ShowOrderColumns and
configured it as follows.




With the column list editor we defined two column members for displaying OrderNo and
OrderInfo.

             Columns-Properties      1. Member                 2. Member
             Name                    OrderNo                   OrderInfo
             Expression              self.iOrderNo             self.sInfo

At last we link the new nesting entry to the corresponding column entry HisOrders with its
property NestingName = ShowOrderColumns . Then the display in the datagrid will look
like shown below.



Page 254
                                   5. ECO and the GUI




The default column CL_Customer is now missing. Instead each line contains a subgrid link
(Plus-Symbol) to the next sub level. This is caused by the activated AddDefaultNestings-
Parameter.

Now we can see that we need nesting entries every time we want to extend the subgrid
display to more than one level. In such cases we can create hierarchy of any depth by
combining columns and nesting members.
In our example application [   GUI6] the level order lines is added to the grid hierarchy.




To change the default display of the orderline columns, we have to add a 3rd column
member, for example OrderLines to the ShowOrderColumns-entry and assign the
expression self.CL_Orderline and a nesting name to it.
Then we could define a second nesting entry for the orderlines column etc.

Notes:
  In a hierarchical Datagrid you could for example adjust the button function for adding /
  deleting datagrid entries to the current grid level. Depending on the currently selected
  level a click on the add-button would create a new customer-, a new order-, or a new
  orderline instance in the datagrid.
  This would require to be able to determine the current level. For example implementing a
  navigate event would be the solution. This is coded (still incomplete) in the example
  application [    GUI6].




                                                                                     Page 255
                                 5.2 Columns and Nestings


5.2.3 Code Derived Columns
As stated in chapter 5.2.1, with the column property we can add two kinds of additional
columns to an ECO handle. The OCL based version and the code- or event-based version .

The example application [     GUI7] demonstrates the use of the second version.
There we defined a class CL_Customer with two attributes sFirstName and sLastName.
The visualization is done as usual, with a datagrid that is connected to an expression handle
exphCustomer via the datasource property.

We want to add an extra column CompleteName to exphCustomer, that is supposed to
combine the two names of the customer. This can be done easily with the OCL version, but
in this example we want to use the code version.

For the code derived column the list editor displays the OCL expression of the typename
entry instead of the expression property. Here we determine the column type. In our example
a string.




Next we implement the code for calculating the additional column CompleteName.
ECO provides 2 code templates. The method xxx_DeriveValue, to determine the column
value and optional the method xxx_ReverseDeriveValue, to be able to react to a change in
the column by the user.
Here xxx represents the name of the underlying ECO handle.

These two methods can be entered in the object inspector of the ECO handle with the event
tab. In our example applications we implemented the following xxx_DeriveValue-Method in
the winform unit.




Page 256
                                   5. ECO and the GUI

  procedure TWinForm.exphCustomer_DeriveValue (
                      sender : System.Object;
                      e      : Borland.Eco.Handles.DeriveEventArgs);
  var s          : String;
      oCustomer : CL_Customer;
  begin
    if (e.Name = 'CompleteName') then
        begin
          oCustomer := e.RootElement.AsObject AS CL_Customer;
          s := oCustomer.sFirstName + ' ' + oCustomer.sLastName;
          e.ResultElement :=
              EcoSpace.VariableFactoryService.CreateConstant (s);

           if assigned (e.ValueChangeSubscriber) then
              begin
                (e.RootElement AS IObject).Properties['sFirstName'].
                    SubscribeToValue(e.ValueChangeSubscriber);
                (e.RootElement AS IObject).Properties['sLastName'].
                    SubscribeToValue(e.ValueChangeSubscriber);
              end;
         end;
  end;

Since only one DeriveValue-Method can be assigned to each ECO handle it is in charge of
managing all Code Derived Columns of the Handle.
Because of this the method begins with the distinction between the individual columns.
The DeriveEventArgs-Parameter (e) passed to the method contains the following
parameters.

  Parameter of e             explanation
  Name                       Name of the Code Derived Column
  RootElement                IElement-value of the current object; in the example the
                             IElement-value of the corresponding customer instance
  ResultElement              IElement-value of the Code Derived Column
  ValueChangeSubscriber      the ISubscriber, that is supposed to trigger a recalculation of
                             the column.

First we determine the complete name of the customer (s) from the IElement of the
corresponding Customer-Instance. The VariableFactoryService then returns the IElement
for the assignment to the ResultElement.
In order to have the complete name recalculated after a subsequent change of first or last
name, we assign a subscriber interface to both attributes which in such cases causes an
additional call of the DeriveValue-Methode.

This procedure is similar to the one we chose for the use of DerivedAttributes (see chapter
2.4.1).

In the example application we also implemented a second method xxx_ReverseDeriveValue.
With this method we want to achieve that a direct change of the complete name leads to
corresponding adjustment of first and last name.




                                                                                     Page 257
                                5.2 Columns and Nestings


  procedure TWinForm.exphCustomer_ReverseDeriveValue (
                sender : System.Object;
                e      : Borland.Eco.Handles.ReverseDeriveEventArgs);
  var s : String;
       i : Integer;
       oCustomer : CL_Customer;
  begin
    IF (e.Name = 'CompleteName') then
        begin
          s := e.Value AS String;
          i := Pos (' ', s);
          if (i > 0) then
              begin
                oCustomer := e.RootElement.AsObject AS CL_Customer;
                oCustomer.sFirstName := COPY (s,1,PRED(i));
                oCustomer.sLastName := COPY (s,SUCC(i),Length(S));
              end;
        end;
  end;

First we have to distinguish the various Code Derived Columns. The passed
ReverseDeriveEventArgs-Parameter (e) contains the current value of the column in his value
property. If the complete name contains a blank as separation symbol, we split it into two
partial strings and assign these to the attributes of the customer instance.




Page 258
                                     5. ECO and the GUI


5.3 Datagrid, Listbox and Combobox
Controls from the control group Datagrid, Listbox and Combox can display several elements
from a datsource. With that they are suitable for more complex databinding and support the
datasource property (see chapter 5.1.3).

For such controls the sorting list entries, the positioning within a list and the enhanced ways
of display plays a very important role. In this chapter we want to have a look at how those
characteristics can be used in an ECO winform.


5.3.1 Datagrid - Sorting
The control datagrid contains a AllowSorting-Property, however using this property requires
the datasource connected to the grid to support sorting. But the IBindingInterface (see
chapter 5.1.2) implemented by the ECO handles does not support sorting.


Sorting with OCL-Expression of the ECO Handle
An alternative to integrated sorting is to sort with an OCL statement in the expression of the
ECO handle.
For this the sorting order OrderBy is added to an expression of the form
Classname.AlInstances :
Classname.allInstances->orderby(Columnname).

The example application [       GUI4] demonstrates this.
Again the instances of the class CL_Customer are displayed in a datagrid. Clicking a column
identifier now should lead to the data of this column being sorted.
So we implement the following Mouse-Down-Event into our datagrid .




                                                                                     Page 259
                           5.3 Datagrid, Listbox and Combobox


  procedure TWinForm.dgCustomer_MouseDown(…);
  var rHitTest : System.Windows.Forms.DataGrid.HitTestInfo;
       i         : Integer;
       s         : STRING;
       aICol     : IElementCollection;
  begin
    // Look for a click on a column header
    rHitTest := dgCustomer.HitTest
                     (MouseEventArgs(e).X, MouseEventArgs(e).Y);
    if (rHitTest.&Type =
         System.Windows.Forms.DataGrid.HitTestType.ColumnHeader) then
         begin // a column was hit
           i := rHitTest.Column;
           // direct access to the IElement level
           aICol := exphCustomer.Element.GetAsCollection;
           if (aICol.Count > 1) then
              begin // at least 2 objects within the datagrid
                if i<(aICol.Item[0] AS IObject).Properties.Count then
                    begin // the column index is valid
                      // get the column name
                s := (aICol.Item[0] AS
                   IObject).Properties.Item[i].StructuralFeature.Name;
                      // insert the sort order
                exphCustomer.Expression :=
                   'CL_Customer.allInstances->orderBy(' + s + ')';
                    end;
              end;
         end;
  end;

With the datagrid function HitTest we receive the number of the column that has been
clicked. Then we can access the model structure of the data shown in the data grid via the
IElement-level of the Expressionhandle (see chapter 4.1) and determine the corresponding
column name.
Then we add the corresponding sorting order to the expression of the expression handle
determined at development time.

Note:
  Instead of accessing the expression handle directly we can choose to access it via the
  datasource property of the datagrid:
  aICol := (dgCustomer.DataSource AS ...ExpressionHandle)...

  A switch between ascending and descending sorting was not implemented into this
  example.


Editing and positioning
By using the orderBy-Statement in the expression we receive a sorted list that unfortunately
doesn´t allow adding any new instances wit the add-button. However Editing attributes and
deleting instances is still possible and also leads to an update of the list display.




Page 260
                                     5. ECO and the GUI

Note:
  According to the ECO developers this constraint is due to each OCL list operation like -
  >orderby or ->select generating a „new“ list. The attributes of newly added instances
  can collide with the (select) criteria of the new list.

This constraint can be bypassed by replacing the default add-button with a button with
custom on-click-event. The OnClick-Method consists of only one line to create a new
customer instance.

  procedure TWinForm.BtnAdd_Click(…);
  var oCustomer : CL_Customer;
  begin
    oCustomer := CL_Customer.Create (EcoSpace);
  end;

With this, entries can be added to the sorted datagrid.

Another problem with sorted lists is, that a new entry or the editing of an existing entry can
lead to a new sorting of the list, where the focus on the edited / new entry usually gets lost.
The solution is a new explicit positioning of the CurrencyManagerHandle after adding /
editing the affected entry.

For a new entry we add the following to our BtnAdd-Method.

  procedure TWinForm.BtnAdd_Click(…);
  var oCustomer : CL_Customer;
  begin
    oCustomer := CL_Customer.Create (EcoSpace);
    exphCustomer.EnsureBindingList;
    cmhCustomer.set_Position((exphCustomer.Element AS IObjectList).
                               IndexOf (oCustomer.AsIObject));
  end;

The call of EnsureBindingList is necessary to bind the new entry immediately to the
datagrid, making the following positioning of the CurrencyManagerHandle to this entry
possible.

In order to keep the CurrencyManager-Position on the entry, even after a resorting of the list,
3 steps are necessary.

First we have to create a subscription that reacts to possible changes of the attributes that
cause a resorting of the grid. In the example application [ GUI4] this was realized e.g. for
the sLastname-Attribute.
The creation of a custom subscription was explained in detail in chapter 2.4.3. We created
the following subscriber class for our example.




                                                                                     Page 261
                            5.3 Datagrid, Listbox and Combobox


  CL_MySubscriber = class (System.Object, IMySubscriber)
    public
       iObj : IObject;
       cmh : Borland.Eco.Handles.CurrencyManagerHandle;
    private
       function IsAlive(): Boolean;
       function Receive(sender: TObject; e: EventArgs): Boolean;
  end;


  function CL_MySubscriber.Receive(sender: TObject; e: EventArgs):
  Boolean;
  begin
    iObj := cmh.Element AS IObject;
    result := TRUE; // use a cancel criterium here
  end;

The Receive-Method is called at each change of the attribute (here sLastName) and has
                                                       C
only the task of saving the currently selected object (Customer-Instance).

Next we need an event that notifies us as soon as the CurrencyManager-Position has been
changed, for example because of a resorting of the datagrid entries.
The.NET Framework offers the PositionChanged-Event, for which we define the following
delegates.

  procedure TWinForm.MyPositionChanged (…);
  var s : String;
  begin
    IF assigned (CL_MySubscriber (MySubscriber).iObj) then
        begin
          exphCustomer.EnsureBindingList;
          cmhCustomer.set_Position ((exphCustomer.Element as
    IObjectList).IndexOf (CL_MySubscriber (MySubscriber).iObj));
          CL_MySubscriber (MySubscriber).iObj := NIL;
        end;
  end;

Every time the current list position changes, our delegate process checks, if a saved object
exists in the subscriber (every time the position-change was caused by an attribute-change
with a following resorting).
In this case the currency manager is set to the new position of this object and the object is
deleted in the subscriber.

Now Subscriber and Delegate only have to be activated / initialized. To do this we place an
activation button in the winform and provide it with the following onclick-method.




Page 262
                                    5. ECO and the GUI

  procedure TWinForm.BtnActivate_Click(…);
  begin
    MySubscriber := CL_MySubscriber.Create As IMySubscriber;
    CL_MySubscriber (MySubscriber).cmh := cmhCustomer;
    CL_MySubscriber (MySubscriber).iObj := NIL;
    (cmhCustomer.Element As IObject).Properties['sLastName'].
                                     SubscribeToValue(MySubscriber);

    Include (cmhCustomer.CurrencyManager.PositionChanged,
             MyPositionChanged);
  end;

First the subscriber instance is created and initialized. Then the instance is assigned to the
sLastName-Attribute of the current entry .
The last entry is the registration of our PositionChanged-Delegate.


5.3.2 Data input Listbox/Combobox
The example application [       GUI2] introduced in chapter 5.1.3 is using in addition to the
normal data-grid a list-box and a combo-box to show the CL-Customer-Instances.
All controls in this example use a shared expression-handle within their data-source-
property. With the property DisplayMember an explicit class attribute is assigned to the list-
and the combo-box.

This method shows the synchronization of the display in the different controls with a shared
expressionhandle. But this example is not suitable to demonstrate the usage of list- or
combo-boxes for change of data.

The required steps for that you will find in the example application [ GUI5].
We have defined two classes CL_Customer and CL_CustomerType, which are combined
with an association. Each customer-instance can have assigned an entry out of the list of
customertype-instances.




Within the WinForm along to each class we have a data-grid and the known buttons for
adding and deleting of instances. An ExpressionHandle and a CurrencyManagerHandle will
be defined for each class. The assignment of a CustomerType-entry to a customer can again
be done via the drag&drop method (see chapter 1.4).
In addition to that we are using a combo-box, with which we want to perform an assignment
of a CustomerType-entry to a Customer.




                                                                                    Page 263
                           5.3 Datagrid, Listbox and Combobox




The combobox should perform the following task:

     •     Display the name of all CustomerType-entries in the PullDown-List.
     •     Synchronization of the input-field with the CustomerType-value of the actual
           selected customer in the data-grid.
     •     A new selection out of the PullDown-list changes the corresponding value in the
           actual selected customer-instance.
     •     The input of a new name in the input-filed creates a new CustomerType-instance
           and assigns this to the actual customer.

In order that the combobox as a selector can serve for the different CustomerType-values,
her datasource-property has to be connected with the expressionhandle of this class, with
the exphCustomerType (Expression=CL_CustomerType.allInstances).
On the display we will only see the name of the class instance, because of that we place the
displaymember-property to sName.
The combo-box-input-field synchronizes with the CustomerType-value of the actual customer
via the SelectedValue-Property. The actual customer is referenced via the
CurrencyManagerHandle cmhCustomer, but we need his Customer Type-value. Thus with
the help of the Columns-Property we add an additional column to the
CurrencyManagerHandle with the name ActualType, their expression will be placed to
self.CL_CustomerType (More details about ‘Working with Property Columns’ in chapter
5.2.1).
We have to place the CustomerType-value of the instance via the ValueMember-Property of
the combobox to ensure that changes in the input-field of the combobox succeed to the
actual customer-instance.




Page 264
                                     5. ECO and the GUI

The data base of this property is the expression handle exphCustomerType itself. But we
can´t link the ValueMember-Property to the handle directly, but only to a member of the
handle. Because of this we add a new entry MySelf, that gets assigned the expression
self, to the handle with the columns property.

Here is the summary of the used Combobox-Properties :

  Property                   value                        explanation
  Datasource                 exphCustomerType             Data source of the PullDown-List
  Displaymember              sName                        The name of the column to be
                                                          displayed. The default columns
                                                          have the same name as the
                                                          attributes.
  SelectedValue              position of                  Synchronization of current
                             cmhCustomer.ActualType       customer and Combobox
  ValueMember                MySelf                       Assignment of the combobox
                                                          value to the current customer

What’s still missing is the function to add customer type instances with the input field of the
combo box.
In order to react to the <enter> key after the text input we code the following KeyPress-
Event.

  procedure TWinForm.CBCustomerType_KeyPress(sender: System.Object;
  e: System.Windows.Forms.KeyPressEventArgs);
  var s    : String;
       oC : CL_Customer;
       oCT : CL_CustomerType;
  begin
    // Return key confirms the user input
    if (e.KeyChar = CHR(13)) then
        begin
          s := CBCustomerType.Text;
          if (s <> '') then
              begin
                // here one should test whether value already exists
                // create new instance
                oCT := CL_CustomerType.Create(EcoSpace);
                oCT.sName := s;
                // get current Customer instance
                if assigned (cmhCustomer.Element) then
                    begin
                      oC:= cmhCustomer.Element.AsObject AS CL_Customer;
                      // link new instance to current Customer
                      oC.CL_CustomerType := oCT;
                    end;
              end;
        end;
  end;




                                                                                     Page 265
                            5.3 Datagrid, Listbox and Combobox


5.3.3 Datagrid - TableStyles
The TableStyle-Property enables the Definition              of display-Templates, so-called
DataGridTableStyle-Objects. A list of DatagridColumnStyle-Objects, that define content and
design of the individual columns of the datagrid, is assigned to each TableStyleObject.

On the top level of the TableStyle- list editor the DataGridTableStyle-Objects are entered .




Each entry gets assigned a name. Optional additional Layout-Parameter like Grid-size, -
Layout and –colours can be set. The base for the following column assignment is usually the
Datasource of the datagrid. As an alternative we can assign a nesting member (see chapter
5.2.2) to the property MappingName.

The second list level can be accessed with the GridColumnStyle-Property.




Here the individual columns are defined. The add-button offers 2 kinds of column entries, a
text entry and a combobox for the display of boolean values.




Page 266
                                   5. ECO and the GUI

Each column gets a name, optional layout settings like HeaderText, Width etc. and the
assignment to an element of the datasource with the MappingName-Property.
Please note here that the MappingName-Property can also access the extra-Columns of an
ExpressionHandle (see chapter 5.2.1).

If we define individual columns within the GridColumnStyle-Property we get a layout that
differs from the settings of the ExpressionHandle columns. If we use the MappingName
property on the top level, then the settings of the Nesting-Member that is assigned to this
MappingName defines the layout instead.




                                                                                  Page 267
                                      5. ECO and the GUI


5.4 Autoforms
Listbox- and Datagrid-controls of an ECO-WinForm contain the ECOAutoForm-property
provided by the ECOAutoFormExtender-component (see chapter 5.1.4).

With an activated AutoForm-Property the doubleclicking of the selection column of a
datagrid line starts the so-called autoform editor, that can be used to edit the individual
attributes of the selected instance comfortably (see chapter 1.4.5).
This editor in general isn’t designed for the use of the end user, rather as a development
support. The developer gets an editor automatically adjusted to the attribute structure of any
ECO object – with no extra coding.


5.4.1 Using the IAutoContainer-Interface
As an alternative to the double click method stated above the autoform editor can also be
called with a simple button containing an ECOListAction-Property = ShowAutoForm or by
coding.
To demonstrate this we added an extra button BtnShowAutoForm with the following setting
to the example application [     GUI8] next to the familiar Customer-Grid.

                    Button-Properties          value
                    BindingContext             sgCustomer
                    ECOListAction              ShowAutoForm
                    RootHandle                 exphCustomer

Clicking this button starts the autoform editor for the selected Datagrid-Entry.

We realized the coding-alternative as an OnClick-Method for an additional button
BtnShowAutoFormByCode for the purpose of demonstration.

   procedure TWinForm.BtnShowAutoFormByCode_Click(…);
   var MyAutoContainer : IAutoContainer;
   begin
     if Assigned (cmhCustomer.Element) then
         begin
           MyAutoContainer := AutoContainerService.Instance.
              CreateContainer
                (cmhCustomer.Element,
                 AutoContainerArgs.Create (EcoSpace, FALSE,
                 AutoContainerMemberVisibility.AllMembers,
                 ContainerReusage.NeverReuse));
           if assigned (MyAutoContainer) then
               Form (MyAutoContainer).Show;
         end;
   end;




                                                                                    Page 269
                                         5.4 Autoforms


For the explanation of this code section, the following has to be said:

ECO defines an AutoForm-Editor as a so-called AutoContainerForm. This is an ECO-
WinForm, to which an IAutoContainer-Interface – defined in the Namespace
Borland.Eco.AutoContainers – has been added. With this interface the winform has extra
methods of providing the appropriate edit fields for the passed objects immediately when the
form is called.

For that IAutoContainer defines the method HookUpGUI. This method receives as
parameter the current EcoSpace instance and the IElement-value of the object. So
HookUpGui initializes the rhRoot-Handle of theAutoContainerForm, thus determining the
connection to the object to display.

An AutoContainerForm can be created with the IAutoContainerService-Interface. The
IAutoContainerService.Instance has the following methods for that:

Methods              Parameter                       explanation
CreateContainer      Basiselement : IElement,        Creates an AutoContainer with the
                     AutoContainer-control parameter specified controls suitable for the
                                                     base element
RetreiveContainer    Basiselement : IElement,        Checks if a suitable container already
                     AutoContainer-control parameter exist for reuse / creates a new
                                                     IAutoContainer control parameter

The AutoContainer-control parameters are passed in                 the    form   of   the   class
AutoContainerArgs , which contains the following properties:

  Properties                 value and explanation
  EcoSpace                   the current EcoSpace
  ForceReadOnly              True/False: ReadOnly-constraint of input fields
  MemberVisibility           AllMembers, ProtectedOrHigher, PublicOnly
  ContainerReusage           NeverReuse, ReuseForClass, ReuseForElement

Since an AutoContainer-Instance is nothing else than a special kind of ECO-WinForm, the
call of the casted show method is sufficient to get a display.

Note:
  The IAutoContainer interface could also be implemented on other elements like an
  container. In this case you need to register your own factory.


5.4.2 AutoForm Factories
The automatically generated input fields of an action, that can be used for instances of all
classes of an application, of course don’t have any design specific for object data, because
of this they usually are not suitable for end users.

However ECO enables us to transfer the AutoForm mechanism to any ECO-WinForms by
using the so-called AutoForm Factories.
As we have seen in chapter 5.4.1, AutoContainerForms are defined as extended ECO-
WinForm. We can make use of this fact and define custom winforms that regard class-
specific specialties to edit the instances of various classes of an application.




Page 270
                                     5. ECO and the GUI

Then we have to add the AutoForm-Mechanismto the winform and register it in the ECO
system, so that the common AutoFormEditor-call – by double click or code etc. –
automatically gets connected to the call of the class-specific winform.

In our example application [       GUI8] we defined a second WinForm CustomerEdit, that
enables a user friendly input of customer data.




To connect the contained controls to the attributes of the customer class we initialized the
rhRoot Handle (contained by default) as follows (see chapter 5.1.2):

                  Properties               value
                  EcoSpaceType             GUI8EcoSpace.TGUI8EcoSpace
                  StaticValueTypeName      CL_Customer

We create the connection of the individual controls to the attribute values with their property
databinding .

Next we add the autoform property to the code of the CustomerEdit-Unit. In the following
code sections the new parts are colored red, so they stand out better.
First we add the required namespaces to the uses list in the interact part of the unit.

   uses
     …
     Borland.Eco.AutoContainers,
     Borland.Eco.ObjectRepresentation, Borland.Eco.UmlRt;

Then the IAutoContainer-Interface with it’s functions is added to the winform class definition.




                                                                                      Page 271
                                       5.4 Autoforms


  type
    TCustomerEdit = class(System.Windows.Forms.Form, IAutoContainer)
    {$REGION 'Designer managed code'}
    strict private
       /// …
       Components: System.ComponentModel.Container;
       RHRoot: Borland.Eco.Handles.ReferenceHandle;
       …
       procedure InitializeComponent;
       …
    {$ENDREGION}
    strict private
       FEcoSpace: Borland.Eco.Handles.EcoSpace;
    strict protected
       /// …
       procedure Dispose(Disposing: Boolean); override;
    public
       //
       procedure BuildControls(element: IElement;
                               autoContainerArgs: AutoContainerArgs);
       procedure HookUpGUI(ecoSpace: EcoSpace; element: IElement);
       procedure set_EcoSpace(value: EcoSpace);
       // new with ECO-III !!!
       procedure Show(autoContainerArgs: AutoContainerArgs);

       constructor Create(anEcoSpace: EcoSpace); overload;
       function get_EcoSpace: Borland.Eco.Handles.EcoSpace;
       property EcoSpace: Borland.Eco.Handles.EcoSpace read
                          get_EcoSpace;
     end;

For the registration of this winform as an AutoContainerForm in EcoSpace we also need the
corresponding registration class IAutoContainerFactory.

  CustomerAutoContainerFactory = class(System.Object,
                                       IAutoContainerFactory)
    public
      function get_AutoContainer: IAutoContainer;
      function Matches(modelElement: IModelElement): Boolean;
    end;

The implementation part contains the realization of the IAutoContainer-Methods defined
above. There the rhRoot Handle is configured with the parameters of the objects currently to
edit.




Page 272
                                   5. ECO and the GUI


  procedure TCustomerEdit.set_EcoSpace (value: EcoSpace);
  begin
    if value <> FEcoSpace then
        FEcoSpace := value;
  end;

  procedure TCustomerEdit.HookUpGUI (ecoSpace: EcoSpace;
                                      element: IElement);
  begin
    FEcoSpace := ecoSpace;
    RHRoot.EcoSpace := self.EcoSpace;
    RHRoot.SetElement(element);
  end;

  procedure TCustomerEdit.BuildControls (element: IElement;
                             autoContainerArgs: AutoContainerArgs);
  begin
    // nothing to do
  end;

  procedure TCustomerEdit.Show (autoContainerArgs:
                                AutoContainerArgs);
  begin
    // nothing to do
  end;

The get_AutoContainer Method of the IAutoContainerFactory-class creates our special
winform. The Matches-Function, called by the ECO-System at each AutoForm-request,
checks if the element to be displayed is an instance of the class we coded for this winform
 C
(CL_Customer). In this case our special winform is used as AutoForm-Editor. In all other
cases the Standard-AutoForm-Editor is used.

  function CustomerAutoContainerFactory.get_AutoContainer:
  IAutoContainer;
  begin
    Result := TCustomerEdit.Create(nil);
  end;

  function CustomerAutoContainerFactory.Matches(
    modelElement: IModelElement): Boolean;
  VAR ic : IClass;
  begin
    ic := modelElement As IClass;
    Result := Assigned(ic) and (ic.ObjectType = CL_Customer);
  end;

This way an individual Edit-WinForm can be implemented and registered as an AutoForm for
each class. Then it is automatically provided for access with the doubleclick function (see
chapter 5.4).




                                                                                  Page 273
                                        5.4 Autoforms



Note:
  It is also possible to manipulate the list of registered factories. The factories are scanned,
  starting with the last added entry. The default autoform simply matches all IClassifier
  elements. It would be possible to either register another factory that does that to replace
  all autoforms, or remove the default form to get no autoform except for the ones you
  chose to plug in.




Page 274
                             6. ECO, ASP.NET and WebService


6. ECO, ASP.NET and WebService
Delphi and especially ECO supports the development of ASP.NET-applications and
Webservices. ASP.NET is a development model to create dynamic websites. ASP.NET ist
an integral part of the .NET Framework.

In a Web-application based on ASP.NET a call, coming from a web browser, is passed on
the server to an ASP.NET application. Then this application creates a dynamic website that
is sent back to the browser.

Webservices have a strictly functional orientation. A Webservice implements one or more
concrete tasks/functions. The communication between a client application and a webservice
is standardized, usually XML and http is used. ASP.NET Webservices are part of the
ASP.Net specification.



6.1 First step
This chapter provides the basics of ECO ASP.NET development, in order to enable us to
create a first simple ECO WebForm application.

6.1.1 ASP.NET components
An ASP.NET application consists of one or more web forms. Each webform contains a so-
called distinction file (ending aspx), that contains the basic structure of the website and a
codebehind file containing the program logic.

Note:
  The program logic can also be placed directly in the aspx file (Inline-version), but usually
  (ans especially in our example applications) codebehind files are used.

The aspx-file is a „normal“ textfile. It contains simple text, HTML elements and so-called
Server Controls.
The codebehind files contain the application logic of a webform and generate a dynamic html
output. From the combination of both components and html output compatible to all browsers
is generated. Depending on the configuration or which controls are used this output can
contain javascript. But ASP.NET can be configured in a way that it doesn’t need any
javascript.

A codebehind file can be written in any .net compatible language, that means C#, VB... and
of course Delphi. Like in a winforms application the language-specific source code is
transformed into .NET CLR-Codeby the IDE and then compiled to executable code by the
JIT compiler at runtime of the application.

Behind the web form is an individual class derived from the basic class Page. All functions of
the page are coded as methods of the class. At the first page call this class is created by the
ASP.NET Runtime-System and then compiled into a DLL file. Any subsequent calls are
served by the compilation.




                                                                                     Page 275
                                           6.1 First step


The so-called server controls are among the most important components of a webform. A
Server Control is a control whose program logic is defined in a codebehind file that is
executed on the server. More on the various kinds of controls in chapter 6.2.1.

The following files are part of an ECO-ASP.NET application ASP1:

file                                       explanation
ASP1.bdsproj                               Delphi-project file
Package_1Unit.pas                          contains the class model (domain model)
ASP1EcoSpace.pas                           Implements the EcoSpace class
EcoPersisistenceMapperProvider.pas         Implements the central persistence
EcoSpaceProvider.pas                       Administrates the session state
WebFormxxx.aspx                            Design of a Webform: Definition of Text-, HTML-
                                           and ServerControls
WebFormxxx.pas                             the Codebehind-file wit ha realization of the
                                           application logic of the webform
Global.asax                                Implements the global functions: Application_Start,
                                           Session_Start...
                                           Usually only contains a link to the corresponding
                                           codebehind file Global.pas, where these functions
                                           are coded
Global.pas                                 see Global.asax
Web.config                                 configuration filei: Debugging, error messages and
                                           authentification
bin/ASP1.dll                               the compiled application


6.1.2 ASP.NET process control
The first step of calling an ASP.NET application is entering the URL of the website.
Optionally the name of the selected (Start-)WebForm can be added, for example
http://www.MeineSeite.de/WebForm1.aspx.
With the project options of the application we can define which webform should be the
default page of the application. If we only enter the domain name when calling the site, this
default page will be displayed.

As a next step the ASP.NET runtime environment on the server analyzes the content of the
requested aspx file. If the page is requested for the first time, first the compilation (dll) of the
corresponding codebehind file is created and the global function ApplicationStart is
                                             S
executed. Then a new session gets started (Session_Start).

Special method calls are assigned to each application start, each session start and each
client request.




Page 276
                             6. ECO, ASP.NET and WebService


          level            Method                             Unit
          Application      Application_Start                  Global.asax/pas
             Session       Session_Start                      Global.asax/pas
              Request      Application_BeginRequest           Global.asax/pas
              Request      Application_AuthenticateRequest    Global.asax/pas
              Request      Page_Load                          WebFormxxx.pas
              Request      Page_Unload                        WebFormxxx.pas
              Request      Application_EndRequest             Global.asax/pas
             Session       Session_End                        Global.asax/pas
          Application      Application_End                    Global.asax/pas

At the first page request and with each further request the server response is created within
the request sequence as an html output, sent to the client and then deleted.

                                                                    S
If the page is left or the session has timed out, the session ends (Session_End). If no other
                                           A
session is active, also the dll is closed (Application_End).

A user action on a page, e.g .data input or a button click etc usually results in a so-called
roundtrip, that means the page is sent back from the client to the browser, is recreated there
and then displayed as new. The Flag IsPostBack marks if the page generation is a roundtrip
or the first page request (see chapter 6.2.2).


6.1.3 Sessions
An ASP.NET-application can administrate „any number“ of sessions. Each session usually
consists of multiple page requests. Each session is started wit hthe call of Session_Start and
ended with Session_End. A page request within the webform is started with Page_Load and
ended with Page_Unload.

In general page requests from the web are without state, that means the server application
that handles two successive page requests doesn’t know if these pages are part of one
sessions or of multiple sessions (users), since in general no data and thus no page status is
buffered.

However in practice certain data hasto be saved either central, as long as the lifecycle of an
application, or user-specific for the length of a session , in order to be able to identify for
example users and their actions in a session.

ASP.NET offers solutions for that in form of so-called Application-State and Session-State
Objects. more on that in chapter 6.2.3.




                                                                                     Page 277
                                         6.1 First step


6.1.4 A first ECO ASP.NET Web-application
For the development of ASP.NET Web-applications the Delphi IDE offers the following types:

                                   ASP.NET Web-application

                                   ASP.NET Webservice-application
                                   ECO ASP.NET Web-application

                                   ECO ASP.NET Webservice-application



We will explain ASP.NET-development with ECO with a first example, having
a special look at what is similar or different to the development of an ECO
WinForms-application.
First weselect the entry ECO ASP..NET Webapplliicatiion in the IDE under
                         ECO ASP NET Webapp cat on
<Fiille> -- <New> -- <Other> -- <Dellphii ffor ..Net> .
<F e> <New> <Other> <De ph or Net>

The following dialog for entering program options offers in addition to ‘program name’ or
‘save location’ the choice between the webervers IIS or Cassini.
Our new web application is registered automatically by the IDE on the local webserver. If IIS
was selected, you can find the most important website control parameters (alias name,
access permissions), also familiar from the windows internet service manager.

Note:
  Delphi2006 places all alias entries created that way in the IIS in a special IIS subfolder.
  Because of that the IIS-entries are more clear. If using a subfolder causes access
  problems with various Borland.ECO.... assemblies, maybe changing the default alias to a
  flat alias entry can help.

After having finished the webserver selection dialog the IDE creates several default project
files that differ from the project file list of a winforms application as follows:

      •    the xxxEcoSpace-Unit contains a PersistencemapperSharer-component
      •    a EcoPersistenceMapperProvider-Unit was created
      •    a EcoSpaceProvider-Unit was created
      •    instead of a WinForm-Unit a WebForm-Unit was created
      •    aGlobal.asax file was created
      •    a Web.config file was created

The purpose of these files will be explained in the following.


Modeling
Modeling of classes and associations is the same as in ECO WinForms-development. In our
example application [     ASP1] we only define one class CL_Customer with the usual
attributes iCustNo, sFirstName und sLastName.




Page 278
                            6. ECO, ASP.NET and WebService


Persistence
First we have to note that using a XMLPersistenceMapper is not possible in a ASP.NET
application. Parallel accesses to an ASP.NET application on a webserver always require a
database manager.

As we have seen in chapter 2.2.8, multiple EcoSpace-Instances require the use of a
PersistenceMapperProvider-Unit, to enable EcoSpace-Instances to share the database
access. This goes for ECO ASP.NET applications (parallel Sessions) as well as for ECO
WinForms applications (Multi-Client).
Analog to our SyncServer/SyncClient-application we therefore place the PersistenceMapper-
components in a PersistenceMapperProvider-Unit. Such a unit was –as stated above-
provided by the IDE at the creation of the project. In our example we use a
PersistenceMapperBDP- and a BDPConnection-component and configurate the database
access similar (see chapter 4.7.2).
We must not forget here to connect this unit to EcoSspace with the property EcoSpaceType
and to set the SyncActive-Property of the PM component.

Important note:
  Delphi2006/ECO-III uses an extra SyncHandler-component instead of the SyncActive-
  Property!

With that the persistence on the server is implemented, now we can create the database
schema the familiar way with the CreateDatabase-Button .


EcoSpace
Unlike an ECO-WinForms-application the ASP.NET-application doesn´t have a central
EcoSpace instance. Here EcoSpace instances usually are allocated only temporary for
building up a page or at max for one session, and released afterwards. The default Unit
EcoSpaceProvider.pas contains an corresponding Provider-class.

The allocation / release of an EcoSpace instance is executed in the Page_Load / Page-
Unload Event of a WebForm. More on that in the next section.

Since an ASP.NET application can have any number of parallel sessions at runtime, a
flexible „EcoSpace management“ is necessary, which offers for example the option of saving
EcoSpace instances during a session, or pooling EcoSpace instances to provide parallel
sessions.
Furthermore ECO provides in the EcoSpaceProvider-Unit the (changeable) constant MODE
of the type EcoSpaceStrategyHandler.SessionStateMode and the two Pooling-Parameter
MaxPool and MaxAge, which are saved in the file Web.config.

More on the use and the possibilities of this kind of EcoSpace-Management in chapter 6.2.3.


GUI
For the development of interfaces the IDE provides by default a first unit WebForm1.aspx. As
the IDE demonstrates, a WebForm.aspx provides 3 development levels. A graphic level
(HTML--Desiign ) for placing controls, the WebForm1.aspx-file itself and the corresponding
 HTML Des gn
CodeBehind-file WebForm1.pas.




                                                                                   Page 279
                                        6.1 First step


On the design page we can find the Root Handle rhRoot, for connecting the webform to the
EcoSpace. In the source code of the unit WebForm1.pas the following units are already
entered.

Region: Designer         Region: help methods               Basic methods
InitializeComponent      UpdateDatabase                     get_EcoSpace
Page_Load                IdForObject                        DoneWithEcoSpace
Page_Unload              ObjectForID
DataBind

The InitializeComponent-Method initializes the individual controls of the form, just like for
winforms.

The method Page_Load executes the following functions by default:
     •   Requesting and activating an EcoSpace from the EcoSpace provider
     •   Initializing the rhRoot-Handle by setting the IElement-value
     •   Databind-call in case of a first page request

Page_Unload only calls the basic method DoneWithEcoSpace, that deinitializes the rhRoot
Handle and returns EcoSpace to the EcoSpaceProvider.

In the DataBind-Method redefined by ECO first EnsureAllBindingLists is executed (see
chapter 5.1.4) and then the ASP.NET Databind Method of the page is called. This databind
call generally leads to a reevaluation of all databinding expressions of a webform. Imagine it
as kind of data refresh of controls on a webform page.

The EcoSpace-Method UpdateDatabase and the ExternalIDService-Methods IdForObject
and ObjectForId were redefined– unlike an ECO-WinForms application – because of a
missing central EcoSpace instance with help methods, that load a new EcoSpace instance if
needed.

The basic method Get_Ecospace requests a new EcoSpace instance from the EcoSpace
provider, DoneWithEcoSpace returns the current EcoSpace-Instance to the provider.

At last the Unit WebForm1.pas provides the interface entries for the 4 Datagrid-Events for
handling the standard datagrid entries Update, Edit, Delete und Cancel. The
implementation of those events also happens automatically, as soon as those events are
assigned to a concrete datagrid (see next section).


WebForm
We will proceed the familiar way for implementing our example application [     ASP1].

First we place an ExpressionHandle exphCustomer, bind it to the rhRoot Handle and set
the Expression from exphCustomer to CL_Customer.allInstances.
In an ASP.NET Datagrid the selection and editing of a line requires explicit referencing by a
key value – unlike a winform.
ECO automatically provides such a key via the expression handle, in the form of the property
ExternalID. As soon as we activate this property, it expands – like an additional column –
the data area of our expression handle.




Page 280
                            6. ECO, ASP.NET and WebService

The ExternalID equivals the ObjectID provided by ECO (see chapter 4.3). It is used for the
definite indentification of an object in EcoSpace. An ExternalID consists of two values, the
Class-ID and a Key-value. It is assigned first as an GUID value when an object gets created
in EcoSpace and is replaced with a final value pair (ClassID: Key) when saving the object in
the DB.

Next we position a datagrid control from the webcontrol group on the webform, as well as a
button to add new customer entries and a button to save changes to the DB.




For the placing of visual controls we use the so-called Fllow--Layout -input mode, where
                                                        F ow Layout
controls simply are placed on the webform one by one.
This input mode takes care that at runtime the position of the controls is automatically
adjusted to the size of the browser window.

Note:
  The design interface provides two ways of positioning controls. In the second way, the
  Griid--Layout , controls can be placed at any absolute position. This position is kept at
  Gr d Layout
  runtime at any browser window size.
  The layout of a webform can be determined in the object inspector of the document with
  the property PageLayout.

ECO-WebForms do have an EcoAspListActionExtender component, that – just like for ECO
winforms – is supposed to provide an Add-Function for standard buttons. However this
component is not reliable. Because of this the Add- and UpdateDatabase-Button receive an
explicit OnClick-Method.

  procedure TWebForm1.BtnAddCustomer_Click(…);
  var oCustomer : CL_Customer;
  begin
    oCustomer := CL_Customer.Create (Ecospace);
    UpdateDatabase;
    Databind;
  end;

  procedure TWebForm1.BtnSave_Click(…);
  begin
    UpdateDatabase;
  end;




                                                                                   Page 281
                                        6.1 First step


The only exception - compared to a winform application - in this code section is the
Databind call. It results in a display refresh (see previous section).
We don’t need to add a delete button here, since this function can be provided directly in the
grid, as we will see soon.

In order to be able to edit entries in the datagrid the grid has to be connected to EcoSpace –
                                                Da
just like in a winform. So we set the Property Datasource to our exphCustomer Handle. Now
the grid already displays the columns of the datasource, meaning our class attributes, and
the column of the ExternalID-value. But to ensure full functionality in the grid we need
additional settings in an ECO-ASP.NET application.

With that in the next step we activate the property generator dialog that can be accessed with
a link below the object inspector.




In the property generator dialog we make the following settings :

a)Basics tab:
set Datasource to the exphCustomer Handle and select the ExternalID as Data key field.




b) Columns tab:
Here we deactivate the automatic column assignment and instead add the individual data
areas explicitly to the list of selected columns. The explicit assignment takes care that the
data areas are bound “completely” to the attributes of the datasource. Only this makes
subsequent editing possible (see chapter 6.4.1).

Besides we place the edit and delete entry from the button columns area in the selected
columns list on the right hand.




Page 282
                             6. ECO, ASP.NET and WebService




This completes the settings in the datagrid dialog.

Note:
  More details to the contents of this dialog in chapter 6.4.1.

As a last step we have to implement the standard edit function in the object inspector by
assigning the predefined events.
For each action an appropriate event is already defined.




Now we can start our example application and create, edit and delete customer entries.




                                                                                  Page 283
           6.1 First step




Page 284
                              6. ECO, ASP.NET and WebService


6.2 Basics
After this introduction to ECO ASP.NET Programming we will deal in this chapter with the
basics. We will have a look at the individual aspects of ASP.NET technology and we will
recommend books for a broad information on ASP.NET.


6.2.1 Controls
For the development of the interface of an ASP.NET application four different kinds of visual
controls are provided in the toolbox of the Delphi-IDE, divided into three groups.

      •   HTML-Elements and server controls
      •   Web controls
      •   DBWeb Controls

For each control from the toolbox, which we place on the design page of a webform file,
Delphi automatically adds an appropriate element declaration to the aspx page, enclosed in
html tags.
The example application [      ASP2] demonstrates the use of the different controls. Each
kind is represented by display and input elements on a coloured panel. Again the application
is based on a simple CL_Customer-class, the WebForm is connected to EcoSpace with the
familiar RootHandle-/ExpressionHandle-combination.


HTML elements
HTML elements are controls, that are not executed on the client side. The properties of
HTML elements can’t be accessed with the program code (CodeBehind). If controls contain a
                 v
„data content“ (value) like for example html text areas or html buttons, this content is
displayed (without change) at each page update. So these controls are mostly suitable for
static displays.

Note:
                                          H
  By using a so-called html hidden field (HtmlInputHidden), data of HTML elements can
  be saved for the span of multiple page requests. The property value of a hidden field is
  saved in a Viewstate-field (see chapter 6.2.3).

An html textffield with value-entry “Testentry“ is declared by the Delphi IDE in the aspx file as
<input value="Testentry" style=...>.

HTML elements also contain event methods. However they are executed on the client side.
An event defined in the codebehind file can´t be used here.
In our example application [            ASP2] we assigned the on-click event
HandleOnClickEventAtClient() to the html button element in the object inspector and
defined an corresponding javascript method for that in the <head> area of the aspx file, that
simply displays a message box .




                                                                                       Page 285
                                         6.2 Basics


  <head>
    <title></title>
    <script type="text/javascript">
      function HandleOnClickEventAtClient()
       {
         alert("OnClick-Event at Client activated using Javascript!")
       }
    </script>


Server controls
Each HTML element can also be used as a server control. Two steps are needed:

     •     A distinct identifier has to be assigned to the element as id
     •     the attribute runat="server" has to be added to the aspx file within the control
           declaration.

An corresponding entry for a html text field in the aspx file would look like this
<input id="IDTextBox" value="Testentry" style=... runat="server">.

The context of such a textbox can only be edited by the user at runtime, the new content
remains after a page request. This form of value persistence is achieved by automatically
saving the value of this control in a ViewState-Field (see chapter 6.2.3) on each roundtrip,
thus passing it back and forth between client and server. Because of this server controls are
suitable for presenting dynamic contents.
With the manual addition of the runat="server" Attribute, Delphi automatically adds the
entry in the form of:
IDTextBox: System.Web.UI.HtmlControls.HtmlInputText;
to the member list of the webform class definition and announces this element to the
codebehind area.

Correspondingly server controls are executed on the server side, their properties can be
accessed in the code. In the WebForm.pas file we can access the value-property of the text
field via the id of the element with the expression IDTextBox.Value := 'Anything'.

Concerning the use of event methods the same rules apply as for HTML elements. Here
Client-side events can be defined as well. Server controls provide two ways to do that, either
the event method is defied directly in the aspx file like HTML elements, or the Attributes-
property of the control in the codebehind file is used.

Note:
  The second option is also possible for web and DBWeb controls explained later. There
  you will find a suitable example there.

In addition some controls contain event methods that can be executed on the server side in
the codebehind. In such cases the definition of a server-side event happens in the
WebForm.pas-file, however such an event assignment is not visible in the object inspector.
In our example application [         ASP2] we assigned the client-side on-click event
HandleOnClickEventAtClient() to the upper button element IDButtonClient and defined
the following on-click event method in the codebehind for the lower button element with the
id IDButtonServer .
id




Page 286
                             6. ECO, ASP.NET and WebService

  procedure TWebForm1.HandleOnClickEventAtServer (…);
  begin
    …
    Response.Output.WriteLine('A message....');
  end;

This event only displays some text on the top of the webpage. On the serverside this event is
known as serverclick-event, the assignment of the event is done in the Page_Load Method.

  Include (IDButtonServer.ServerClick, HandleOnClickEventAtServer);

Note:
  In the code example the event above also contains additional orders, for demonstration of
  the ViewState-Mechanism. More on ViewState in chapter 6.2.3.


Web controls
The display of web controls is also controlled on the server side. Like winform controls they
also have properties and event methods and their „data content“ is buffered automatically
with the ViewState-Mechanism (see chapter 6.2.3). What´s missing is the close connection
to the corresponding html tags familiar from HTML and server controls and the
corresponding properties in the object inspector like value, style and client-side events .

The corresponding entry to a web control, in the aspx file contains an additional tag prefix,
that is <ASP> for standard web controls. After the tag-prefix the class name of the control
follows.
So an entry in the aspx file for a textbox would look like this
<ASP:TextBox id="TBTextbox3" runat="server">Text</ASP:TextBox>.

Unlike to HTML and server controls web controls can use the databinding concept. So web
controls are your weapon of choice for the use in ECO. More on databinding in chapter 6.3.

In the example application [  ASP2] a button to add new Customer-Objects is defined in
the according panel in addition to a textbox and a datagrid with connection to the
CL_Customer-class, and another text-button, whose click event integrates the current time
into the button text.

  procedure TWebForm1.BtnTest_Click(…);
  var t : DateTime;
  begin
    t := DateTime.now;
    BtnTest.Text := 'Get Server-Time : ' + t.ToLongTimeString;
  end;

More details on the individual web controls in chapter 6.4.




                                                                                   Page 287
                                        6.2 Basics




DBWeb controls
DBWeb Controls are mostly used in association with ADO.NET and BDP.NET data
components. They contain a DBDataSource-Property with which they get connected to a
datasource, for example a Dataset. Similar to web controls they are controlled on the server
side. They also contain various properties and event methods that can be accessed with the
codebehind file.
The main difference to web controls is that here no properties for explicitly assigning
databinding exist. Databinding is done implicitly with the DBDataSource-component.

Note:
  In DBWeb Controls direct databinding is only possible by coding (overwriting the databind
  method).

Since DBWeb controls are designed for datasources based on a BDPDataAdapter or a
ADO.NET Provider, they are not suitable for use with ECO in general. To avoid this
constraint, Delphi provides the so-called EcoDataSource-component, that can be used as an
alternative to a dataset.
In the example application [ ASP2] we placed such an EcoDataSource-component and
integrated the exphCustomer Handle into it. In order to link a DBWeb-Datagrid we connect
the DBDataSource-Property to the EcoDataSource-component and select exphCustomer
     DB
as TableName. Now the DBWeb-Datagrid displays the same customer entries as the web
datagrid lying above.

The tag prefix for Delphi DBWeb Controls is <borland>, so the entry in the aspx file for the
DBWeb-Datagrid looks like this:

  <borland:DBWebGrid id="DBWebGrid1" runat="server"
   dbdatasource="<%# EcoDataSource1 %>" tablename="exphCustomer"
   width="208px" edititemindex="0" selectedindex="0"
   datasource="<%# exphCustomer %>" autogeneratecolumns="False">
   <Columns>
     <ASP:BoundColumn datafield="ExternalId"
      sortexpression="ExternalId" headertext="ExternalId">
     </ASP:BoundColumn>
     <ASP:BoundColumn datafield="sFirstName"
      sortexpression="sFirstName" headertext="sFirstName">
     </ASP:BoundColumn>
   </Columns>
  </borland:DBWebGrid>

Note:
  Connecting DBWeb Controls to EcoSpace with a EcoDataSource-component is not
  without problems. Is seems that Delphi needs some improvements here.




Page 288
                             6. ECO, ASP.NET and WebService



Properties and formatting
Whereas a vast list of properties is provided for web- and DBWeb controls that can be used
comfortably in the object inspector or the codebehind, the amount of properties and their way
of editing for Html elements and server controls is very restricted.
The values id, style and class are among the most important properties of HTML elements
and server controls.
Elements are identified with the id-value. On the one hand this is a requirement for the
transformation of a HTML element into a control, on the other hand a style can be assigned
in a stylesheet file with the id-value of an element .
The appearance of an element (Font., colour, size...) can generally be influenced in 4
different ways.

Style-assignment         explanation
Directly via Inline      Direct setting of style attributes within the style property
                         (only for html – and server controls)
Individual               Assignment of an element-individual style definition in a stylesheet
                         with the id property of the element
per class                Assignment of a class-specific style definition in a stylesheet wit
                         hthe class-property of an element
with     the      Object as for WinForm-Controls
inspector
with CodeBehind           as for WinForm-Controls (not for HTML-Elements)

In the example application [    ASP2] all 4 ways are used.
To be able to use an external stylesheet file, it has to be referenced in the <head> section of
the aspx file:
 <LINK REL="stylesheet" TYPE="text/css" HREF="StyleSheet.css">.

The Style-Definition of the panel in the section web controls for example is set with inline,
for the overlying panels an individual style definition (#IDHtmlPanel) and for all textbox
components a class specific style definition (.TextBoxStyle) was selected in the CSS file. The
appearance of the AddCustomerButton in the section web controls was defined with the
object inspector, the look of the test button below in the codebehind with the expression
BtnTest.BackColor := Color.Aqua.




                                                                                     Page 289
                                         6.2 Basics




Creating controls dynamically
With our usual procedure of placing controls statically on a webform an entry in the aspx file
and an corresponding object in the codebehind was created for each control (except for
HTML elements).

In ASP.NET there is also the option of creating controls dynamically, that means only in the
codebehind. Since in such a case no corresponding aspx control entries exist, we have to
recreate the dynamic controls in the codebehind with each page request. This means that an
corresponding „CreateControls“-Method has to be accessed with the Page_Load Event of
the WebForm with each page request.

In the example application [    ASP2] we demonstrate this option in the panel dynamic
controls. This panel contains only a CreateControls-Button on the first page request . the
OnClick-Method of this button primarily has the task of activating a “central button”, with
            Pa
which the Page_Load Event calls the CreateControl-Process. The value of the button
DynamicControlSwitch has to be saved for one roundtrip, for that we use a session
variable.


  procedure TWebForm1.BtnCreateControls_Click (…);
  var b : BOOLEAN;
  begin
    // switch value (sessionvariable)
    b := Session['DynamicControlSwitch'] As Boolean;
    Session['DynamicControlSwitch'] := TObject (NOT (b));
    // deactivate CreateButton
    BtnCreateControls.Enabled := b;
    // redraw page
    Server.Transfer ('WebForm1.aspx');
  end;

After the button has been set, a page reload is forced with the Server.Transfer Function.
This restarts the Page-Load Event, that can regenerate the controls.

note:
  You find more on Postback in chapter 6.2.2., and more on session variables in chapter
  6.2.3.

The CreateControls-Procedure is accessed in the Page_Load Event.




Page 290
                            6. ECO, ASP.NET and WebService

  procedure TWebForm1.Page_Load(…);
  …
    if not IsPostBack then
       begin // Initializing the system at first output
         …
         if Session.IsNewSession then
            Session['DynamicControlSwitch'] := TObject (FALSE)
         else
            if (Session['DynamicControlSwitch'] As Boolean = TRUE)
               then CreateControls;
       end
    else
       begin // Just at Roundtrip
         …
         if (Session['DynamicControlSwitch'] As Boolean = TRUE) THEN
            CreateControls;
       end;

At the first page request (Non-Postback) we have to differentiate between two cases. the
„regular“ first request that leads to a new session and the non-postback case caused by the
Server.Transfer Function .
In the first case we only initialize the button as session variable. In the second case we
activate the CreateControls-Method when the button is „on“.

The CreateControls-Method creates a textbox- and a button-control and adds these to the
panel with the add-method of the sub control list.

  procedure TWebForm1.CreateControls;
  var MyTextbox         : System.Web.UI.WebControls.TextBox;
      BtnRemoveControls : System.Web.UI.WebControls.Button;
  begin
    MyTextbox := System.Web.UI.WebControls.TextBox.Create;
    MyTextbox.AutoPostBack := TRUE;
    MyTextbox.Text := 'Here I am!';
    BtnRemoveControls := System.Web.UI.WebControls.Button.Create;
    BtnRemoveControls.Text := 'Remove Controls';
    Include (BtnRemoveControls.Click, BtnCreateControls_Click);

    DynamicPanel.Controls.Add(MyTextbox);
    DynamicPanel.Controls.Add(BtnRemoveControls);
  end;

We assign the ButtonCreateControlsClick-Method described above as an on-click method
to the RemoveControls-Button. The event deactivates our button and forces a page update,
this time without the dynamic controls.




                                                                                  Page 291
                                          6.2 Basics




Placeholders for controls
Among the web controls we can also find a so-called Placeholder-Control. This control is
also used in association with dynamic controls. This Placeholder-Control serves as a kind of
anchor for other (usually dynamic) controls, that can be added to the placeholder control with
the add-method.
Concerning the previous example, a placeholder control could replace our DynamicPanel-
Control.
A classic example of using placeholder controls can be found in the Web AutoForms in
chapter 6.4.5.


6.2.2 Postback and Roundtrip
As we now know, controls (except HTML elements) can keep their state during multiple page
requests. The so-called Roundtrip describes a page sequence that goes as follows:

     •     The server sends a requested page to the client browser
     •     The user enters / selects data and submits the page
     •     The page is sent to the server for data evaluation / processing

The so-called postback, sending back the page to the server can be triggered by various
actions (ButtonClick, <Enter>-key...). with each postback the following actions are triggered
on the server:

     •     First the Page_Load Method is called. A differentiation can be made between the
           two cases „first page request „ and postback with the IsPostBack-Flag.

  procedure TWebForm1.Page_Load (…);
  var
    Id: string;
  begin
    EcoSpace.Active := True;
    Id := Request.Params['RootId'];
    if Assigned(Id) and (Id <> '') then
       rhRoot.SetElement(ObjectForId(Id));
    if not IsPostBack then
       begin // only at the first call of the page
         DataBind;
       end
    else
       begin // in the case of roundtrip only
         ...
       end
    ... // always done
  end;

     •     Then the result, for example an ButtonOnClick assigned to the action causing the
           postback , is executed on the serverside.




Page 292
                            6. ECO, ASP.NET and WebService


This can be demonstrated rather quickly with the example application [    ASP2].

     •    A click on the upper button (HTML button) doesn’t lead to a Postback
     •    A click on the second button (HTML button with runat=“server“) leads to a
          Postback,      that     triggers   first   the     Page_Load     ,    then     the
          HandleOnClickEventAtServer-Method on the server. All buttons of the web
          control type react the same way.
     •    No on-click event is assigned to the bottom button of the examle application „Just
          a Roundtrip“, so here the postback only triggers the Page_Load Method.

The controls on an ASP.NET page can be structured the following way concerning the
assignment of server-side events and postback realization.
To some server controls an OnClick- / OnChange-event can be assigned, that gets executed
in case of a postback, but only text fields and buttons can trigger a postback themselves.

Server controls          explanation
HTML button              a ButtonClick triggers a postback each time a server-side on click
                         event is assigned to the button.
HTML Text area           the <Enter>-key always triggers a postback, a server-
                         sideOnChange-event (Serverchange) can be assigned
HTML CheckBox            a server-sideOnChange-event (Serverchange) can be assigned
HTML select box          a server-sideOnChange-event (Serverchange) can be assigned
HTML Dropdown            a server-sideOnChange-event (Serverchange) can be assigned
HTML List box            a server-sideOnChange-event (Serverchange) can be assigned

Usually multiple server-side events can be assigned to web controls with the properties page
of the object inspector.
Buttons and text areas (with the <Enter>-key) always trigger a postback. In the Controls
CheckBox, RadioButton, Textbox (at a focus change), Listbox and DropdownList this
property can be set with the AutoPostback-Attribute.

Note:
  The AutoPostback-property requires JavaScript to be activated in the Browser. An
  AutoPostback-Function can also be implemented manually for server controls with
  JavaScript.

DBWeb controls behave like web controls concerning server-side events and postback-
triggering.




                                                                                    Page 293
                                               6.2 Basics


6.2.3 Session strategies
As mentioned in chapter 6.1.3, page requests from the web are generally without any state.
So in theory for a server application no relation between two successive requests exists.

In practice of course ASP.NET administrates in the so-called page and application context, a
large number of information on the current application, the content of the URL, the state of
the current session, the browser in use, etc. .
This information can be accessed in the codebehind, for example with the Response-,
Request-, or Context-Object (see chapter 6.4.6).

This page and application context offers the option of saving any additional data spanning
page requests , either by

     •        Saving the data on the client page
         or
     •        saving the data on the server.

For client-side saving ASP.NET again offers 4 ways .

  method                      explanation
  Viewstate                   Saving of any data inan invisible, encrypted field (see
                              Viewstate).
  HtmlInputHidden             Saving of individual variables in an invisible field (see chapter
                              6.2.1).
  URL-Parameter               Adding information to the end of the URL (see Session-State).
  Cookies                     Saving any data as file in the client file system (see Session-
                              State).

For saving data on the server the framework offers the following options.

  method                      explanation
  Sessionstate                saving for the duration of a session
                              (see Session-State).
  Applicationstate            saving for the duration of an application
                              (see Application-State).
  Datenbank                   Permanent saving in a db


Viewstate
The current content of a control (except for HTML elements) is passed back and forth
between server and client at each roundtrip and thus remains.
ASP.NET uses hidden fields in the formular for that, which contain the current state of the
controls in the attribute value. If we have a look at the source code of such a page we can
find an entry of the form.

  <input type="hidden" name="__VIEWSTATE" value="dDwxMDkxMzQ4MjIz …

The technology this is based on is called viewstate. The viewstate is an instance of the so-
called StateBag-class and is defined as global property of the Page-class. Data of the
viewstate can also be accessed in the codebehind and be used to buffer custom values.




Page 294
                            6. ECO, ASP.NET and WebService

To demonstrate this option we improved the default Datagrid-Update-Event in the example
application [    ASP2] in a way that parallel to each update of a customer entry an entry in
the global viewstate is added or updated .

  procedure TWebForm1.DataGrid_UpdateCommand(…);
  var
    …
    iCustomer : IObjectInstance;
    sFirstName : String;
    vsItem      : TObject;
  begin
    …
    iCustomer := ObjectForId(Id);
    sFirstname := (iCustomer.AsObject as CL_Customer).sFirstName;
    vsItem := ViewState.Item[Id];
    if (NOT Assigned (vsItem)) then
        ViewState.Add(Id, sFirstName) // create Viewstate entry
    else
        ViewState.Item[Id] := sFirstname; // update entries
  end;

In addition we implemented code for the display of the viewstate entries in our
HandleOnClickEventAtServer-Method.

  procedure TWebForm1.HandleOnClickEventAtServer (…);
  var i         : Integer;
       s        : String;
       oEnum    : IDictionaryEnumerator;
       oElement : DictionaryEntry;
  begin
    oEnum := ViewState.GetEnumerator; //Enumerator for the entries
    oEnum.Reset; // put Enumerator on first position
    s := ''; i := 0;
    while oEnum.MoveNext do // as long as there are entries
       begin
         INC (i);
         s := s + oEnum.Key.ToString; // get entry key
         s := s + ':'+(oEnum.Value AS StateItem).Value.ToString+';';
              // concat it with with the entry value
       end;
    // show values
    Response.Output.WriteLine('OnClick-Event… : ' + i.ToString);
    Response.Output.WriteLine;
    Response.Output.WriteLine('Listing Viewstate-Entries : ' + s);
  end;

A disadvantage of the using viewstate is the higher transfer volume. All values saved in the
viewstate are passed back and forth between server and client on each roundtrip.
However we can influence this effect. The Page-class itself and each of the controls (except
HTML elements) contain the Boolean property EnableViewState. With this we can switch
on/off data saving in the viewstate for individual controls or the complete page.




                                                                                   Page 295
                                        6.2 Basics


This property can be set in the code behind or the page directive of the aspx file for the
whole page:
 <%@ Page language="c#" ... EnableViewState="false"...%>
The value can also be set in the codebehind for the individual controls. This property also
can be accessed with the object inspector for web and DBWeb controls.


Session-State
As we already mentioned in chapter 6.1.3 , ASP.NET contains functions to administrate data
within a session for example to be able to assign the actions of a session to a user.
The underlying class is called HttpSessionState and can be called with the codebehind via
the Page-Property Session. With the Session-Property a lot of tasks can be executed.

Session Variables are saved in a list as pair of values (Key, Value), with Key being any
distinct string and Value any object. As an alternative to access using the key, access with
the list position is also possible. The following properties and methods are provided in the
Session-Property for the administration of session variables.

Name            explanation
Count           number of Session Variables
Mode            Way of saving Session Variables:
                Off = no saving
                InProc = in the central memory of the Server (default-setting, problematic
                in multiserver systems !)
                State Server = custom saving process, communication with ASP.NET via
                TCP/IP
                SQL Server = saving on a MS SQL Server
Item            Access to Session Variable with an indicated number or a key expression
Keys            List of keys
Add             Save a new variable at the specified key
Remove          Delete a variable with the specified key
RemoveAt        Delete a variable at the specified position
RemoveAll/Clear delete all variables
Set             Set the value of a variable
Lock            Lock a variable
Unlock          unlock a variable

Note:
  If the State Server or SQL Server mode are used for saving objects, those objects have to
  be serializable (attribute [Serializable]).

Each session can be identified by a unique ID. For basic and handling of a session and user
identification the session property offers the following properties and methods.

Name           explanation
SessionID      Unique session ID
IsNewSession   = TRUE at first page request of a session
IsReadonly     Session is write-protected
IsCookieless   TRUE = embedding of the SessionID in the URL -> no cookie required
Abandon        Cancel current session Aktuelle Sitzung abbrechen
Timeout        Number of minuts after which a session is closed automatically




Page 296
                              6. ECO, ASP.NET and WebService

ASP.NET offers 2 ways of user identification. By default the version “with cookies” is
activated, that means at the first page request of a session ASP.NET saves the Session-ID
as a Cookie on the Client-PC. With each sending of a client request to the server the value of
the cookie is transferred and thus identifying the client.
The option without cookie is called Cookieless Session State. Here ASP.NET enters the
Session-ID as a virtual folder into the URL in front of the page name:
http://localhost/.../(w4sj5155xjmgjpmx5svzyq45)/Startup.aspx.

The property IsCookieless of the Session-Property indicates which way of user identification
the application uses. This variable is set in the Web.config file in the section SessionState
with the attribute cookieless.
The example application [            ASP3] offers a simple demonstration of saving session
variables. It consists of two pages, MainForm and Startup. At the request of the mainform
page, the method NavigateToPage checks if the session already exists. If so, the session ID
and the variable Username are displayed.
If not, then it first switches to the startup page. There the user has to enter his name, which is
saved as a session variable Username, then mainform gets requested again.

   procedure TMainForm.NavigateToPage;
   begin
     if Session.IsNewSession then
         // call Startup page
         Server.Transfer('Startup.aspx', FALSE)
     else // show username
         IDLabelHelloUser.Text := 'Welcome ' +
                                  Session.Item['Username'] as String;
     // show SessionID
     IDLabelSessionID.Text := 'Session-ID: ' + Session.Session.ID;
   end;

   procedure TStartup.IDButtonOk_Click(…);
   var s : String;
   begin
     s := TBInputName.Text.Trim;
     if (LENGTH (s) = 0) THEN // invalid (or no) input
         IDLabelWarning.Visible := TRUE // activate warning
     else
         begin
           Session.Add('Username',s);// save uUsername in session
           Server.Transfer('MainForm.aspx',FALSE);// call Mainform
         end;
   end;

Another way of administrating objects in a session is provided by the file Global.asax. with
object tags various objects can be defined that can be accessed by any page of the
application. In order to create e.g. an ArrayList-Object with the id TestArrayList, we enter
the following into Global.asax:

   <object id="TestArrayList" runat="server" scope="session"
           class="System.Collections.ArrayList"/>




                                                                                        Page 297
                                           6.2 Basics


Access from the codebehind level is achieved with the session property StaticObjects, that
administrates all object defined this way in a list. So the access to an element of the ArrayList
would look like this

   (Session.StaticObjects.GetObject('TestCollection') As
   System.Collections.ArrayList).Item[…];

The session state also provides the two events Session_Start und Session_End, that we can
fill with code in the Global.pas file. A typical use for these events is for example the
initialization/release of session-variables, the opening/closing of record files, the in-
/decreasing of a visit-counter etc. please note that Session_End is only called in the
Session.Mode InProc!

In general the session status of an application can also be deactivated, either in a single
page with the corresponding order in the aspx file:
<%@ Page language="c#" ... EnableSessionState="false"...%>
or in all pages of the application with the following entry in the web.config:
<pages enableSessionState="true" />.


Application-State
Analog to the session state, ASP.NET offers the option of saving objects for the „life cycle“ of
an application. For this so-called Application-State the same access concept applies as for
session variables, although objects can only be administrated in the memory of the current
ASP.NET process (InProc-Mode).
The instance Application of the base class HttpApplicationState is provided within the
Page-class. It offers the following properties and methods:

Name               explanation
Count              number of Application Variables
Item               access to the Application Variable with indicated number or key
Keys               key list
Add                Save a new variable with the specified key
Remove             delete a variable with the specified key
RemoveAt           delete a variable at the specified position
RemoveAll/Clear    Delete all variables
Set                Set the value of a variable
Lock               lock a variable
Unlock             unlock a variable

Objects used in the whole application can also be – like on the session level – defined in the
Global.asax file. In this case the example entry from above looks like this.

   <object id="TestArrayList" runat="server" scope="application"
           class="System.Collections.ArrayList"/>

Access from the codebehind level can be achieved with the Application-Property
StaticObjects , just like in the Session-State.

The Application-State also offers the Events Application_Start, _End, _Error,
_BeginRequest, _EndRequest and AuthenticateRequest, that can be filled with code in the
Global.pas file. Typical uses for these events are gathering and saving statistic values or a
central error management.



Page 298
                             6. ECO, ASP.NET and WebService


EcoSpace strategies
As we have already seen in the introductory example , there is no central EcoSpace instance
for an ECO application in ASP.NET. For each page request of a client in general an extra
EcoSpace is provided.

The lifecycle of an EcoSpace instance starts with the call of the Page_Load Event.
After that, in case of a postback, the event methods, triggered by previous user actions on
the page, are executed in the codebehind (ButtonClick, Textchanged...). Usually a
DataBind-call takes place as well. As a last step the Page_Unload Event is started, that
releases the EcoSpace instance. The html output created in this cycle is then sent to the
client.

Depending on which EcoSpace-object-changes are executed or saved within this life cycle in
the codebehind, the state of the EcoSpace instance is called clean or dirty before its release.

ECO provides 3 strategies to deal with this EcoSpace life cycle with the (changeable)
constant MODE (Type EcoSpaceStrategyHandler) in the EcoSpaceProvider-Unit.
The strategy Never releases the EcoSpace instance in any case. All changes that have not
been saved are lost, that means to each object change in EcoSpace an
UpdateDatabase(WithList)-call has to follow.
The default strategy IfDirty saves „dirty“ EcoSpace-Instance in the SessionState of a
session and only then releases it if the instance is clean again or the session is ended.
The third option Always keeps the EcoSpace instance saved in the session state during a
session.

The Never-Option requires in addition that no unsaved changes exist at the point of release
of the EcoSpace instance, or else an exception is caused.


EcoSpace pooling
Since a web application can be used by any number of clients at the same time, it is
reasonable to have a certain number of EcoSpace instances „in stock“, in order to minimize
the expenditure of time necessary to create new instances of the requested EcoSpaces.
For that ECO provides pooling, that can be configured with the two Webconfig-Parameters
MaxPool and MaxAge. MaxPool defines the max number of EcoSpace instances provided
by the pool , MaxAge defines the „dying“ age“ of an EcoSpace instance as seconds since
the generation of the instance. After this time runs out the EcoSpace instance is
automatically removed from the pool.

Another important characteristic of pooling is the automatic synchronization of the pooled
EcoSpace instances. If for example two EcoSpace instances are administrated in the pool,
and user A changes objects in EcoSpace 1, then, at the next page request from user B, who
for example requests the 2nd EcoSpace instance from the pool, the changes are transferred
from EcoSpace1 to EcoSpace 2.
To be more precise, the changed objects are marked as invalid in the second instance the
moment this second instance is requested and are reloaded later if needed.




                                                                                     Page 299
                                       6.2 Basics


From the combination of ECO strategy and pooling the following configuration options
emerge.

SessionStateMode      MaxPool explanation
Never                 =0      EcoSpace-data is not saved in the sessions state of a
                              session . with each roundtrip all unsaved changes get lost.
                              Each client request creates a new EcoSpace instance that
                              is released when sending the html output.
Never                 >0      EcoSpace-data is not saved in the sessions state of a
                              session. with each roundtrip all unsaved changes get lost.
                              A client request gets the EcoSpace instance (if in stock)
                              from the pool and returns it there.
Always                =0      EcoSpace-Data is saved in the session state of a session.
                              For the duration of the session the corresponding memory
                              is occupied on the server. For each session an EcoSpace
                              instance is created and released when the session ends.
Always                >0      EcoSpace-Data is saved in the session state of a session.
                              For the duration of the session the corresponding memory
                              is occupied on the server. A client request gets the
                              EcoSpace instance (if in stock) from the pool .After ending
                              the session the instance is returned to the pool.
IfDirty               =0      EcoSpace-Data is only saved in the session state during a
                              session, if EcoSpace still contains unsaved changes. for
                              the duration of the session the corresponding memory is
                              occupied on the server. A client request gets the
                              EcoSpace instance (if in stock) from the pool and returned
                              to the pool with a “clean” state
IfDirty               >0      EcoSpace-Data is only saved in the session state during a
                              session, if EcoSpace still contains unsaved changes. for
                              the duration of the session the corresponding memory is
                              occupied on the server. In need a client request gets the
                              EcoSpace instance (if in stock) from the pool, after ending
                              the session the instance is returned to the pool.

Depending on the requirements of an application, an appropriate combination of pooling and
SessionStateMode, as a compromise between memory use and performance has to be
found.




Page 300
                             6. ECO, ASP.NET and WebService


6.3 Databinding
The option of binding control to EcoSpace is playing a vital role when selecting different
controls (see chapter 6.2.1). We will use the example application [     ASP4] to demonstrate
databinding. Like the example [       ASP1], this application only consists of the class
CL_Customer, whose data is provided with use of the exphCustomer Handle of the
webform. In the WebForm itself only web controls are used. In the following text only web
controls are used when talking about controls.


6.3.1 Introduction
In chapter 5.1.3 we explained the databinding concept for ECO winform applications. In such
applications a so-called bindingcontext exists between a control and the connected
datasource (ECO Handle), This automatically administrates the „data indicator“, which is the
so-called currency manager, provided in ECO as CurrencyMangerHandle.

With this handle the object currently selected in a datagrid can be referenced at runtime. This
way Master/Detail Relations (customer – order list – order positions) can be displayed in an
elegant way with handle chains like this (see chapter 5.1.1):

ExpressionHandle1 -> CurrencyMangerHandle -> ExpressionHandle2...


CursorHandle vs. CurrencyManagerHandle
Unfortuntately there is no automatically provided BindingContext in ASP.NET and thus no
CurrencyManager(Handle). The determination of the currently selected object in a datagrid
and most of all the perpetuation of this information over the timespan exceeding a roundtrip
requires explicit coding.
This includes for example
      •    The explicit reaction of user actions that change the selection of the object (Event
           SelectedIndexChanged)
      •    The re-evaluation and/or saving of the position of the selected object
      •    The explicit reevaluation of associated objects with databinding expressions

If we want to stick close to the binding context for winforms applications, we can use the so-
called CursorHandle in ECO ASP.NET.
A CursorHandle handles the same tasks in ASP.NET as a CurrencyManagerHandle in
ECO WinForms applications.

A simple binding to a cursor handle is shown in the example application [      ASP4],
explained in chapter 6.3.4. The usage of a CursorHandle in an ECO handle chain can be
found in the same application, explanation in chapter 6.4.2.




                                                                                     Page 301
                                        6.3 Databinding




Binding expressions
In general the contents of bound controls in a page are determined by so called binding
expressions. So in our example application [       ASP4] for example a concrete ASP.NET
binding expression in the form datasource="<%# exphCustomer %>"stands behind the
            Da
link of the Datasource-Property of the Datagrid to the exphCustomer-Handle.

The binding expressions of a page are evaluated with the Databind-Method of the class
Page. This .NET-Method can be used on single controls or on the complete page with all its
controls.
In an ECO ASP.NET application the Page-Databind-Method is encapsulated by a
procedure, where first the EcoSpace function EnsureAllBindingLists and then the .NET
DataBind-call takes place .

   procedure TWebForm1.DataBind;
   begin
     ElementHandle.EnsureAllBindingLists;
     inherited DataBind;
   end;

The call of the EcoSpace function EnsureAllBindingsList ensures, that all relevant
EcoHandles are updated before re-evaluating the binding expressions.


6.3.2 Simple and complex databinding
Analogue to WinForms-applications we can also differentiate between two kinds of
databinding in ASP.NET; the simple (single-value binding) and the complex binding
(repeated-value binding).

Complex databinding is used in controls that can be connected „as a whole“ to a datasource
with the Datasource-Property.
All Repeater, DataList and DataGrid controls support complex databinding. The repeater
control provides a consistent layout scheme for a list of objects. The control data list contains
a one-column table display and basic ways of selecting and modifying objects and files in
addition.
A datagrid can display data in a table with explicit column assignment. Further properties are:
editing line by line, sorting by columns and paging. More on these controls in chapter 6.4.

The datasource of a complex databinding usually is an EcoHandle. Because of the structure
of corresponding handle chains (CursorHandle instead of CurrencyManagerHandle !) and
the use of appropriate expression entries, a vast range of uses is possible (see chapter
5.1.1).

In a simple binding, single properties of controls are linked to certain attributes of an
EcoHandle or to properties of other controls.




Page 302
                            6. ECO, ASP.NET and WebService


6.3.3 Databinding expressions and Databinder.Eval
In a simple databinding between the properties of a control and for example the attributes of
an ECO object, a so called databinding expression is placed in the aspx file, usually behind
the opening tag of the control.
The general form of a databinding expression is Property =“<%# Expression %>“.
A databinding expression can contain values and operators; it can reference all controls
defined in a page and their properties as well as methods of the page class defined in the
codebehind. The evaluation of a binding expression happens at runtime.

Notes
  Please note that a databinding expression itself can contain double quotes. In such cases
  we have to encapsulate the databinding expression with inverted commas.
  The identifiers in databinding expressions are case sensitive!


Binding to control properties
In simple cases the databinding expression can for example link only to contents of other
controls. The following code from the example application [   ASP4] displays the binding
expression of the label LBName, that is supposed to combine the contents of two text fields
(first and last name ).

   <ASP:Label id="LBName" runat="server"
   text=’<%# TBFirstName.Text + " " + TBLastName.Text%>’>
   </ASP:Label>

We can either enter the databinding expression manually to the aspx file or use the
Databiindiing--Diiallog , provided by the property DataBindings of the object inspector.
Datab nd ng D a og




                                                                                   Page 303
                                        6.3 Databinding


In this dialog we select the property to be bound in the left list, here the property Text of the
Label. On the right hand we enter the binding expression to the section user--deffiined
                                                                                  user de ned
biindiing expressiion .
b nd ng express on

Access to properties of other controls can also be more complex. The text area
TBOnProperty for example shows the first name (2nd column) of the currently selected
customer entry wit the following binding.

   …text="<%# dgCustomer.SelectedItem.Cells[1].Text %>"…

Note
  If the databinding source doesn’t contain any data, it is usually no problem, but with the
  expression above you better be cautious. For example in case the datagrid dgCustomer
  doesn’t contain data yet, indicated access to the Cells-Property of SelectedItem is
  prohibited and causes a runtime error. The section Binding to mthods shows a way to
  avoid such problems.


Binding to ECO Handle attributes
In cases where attributes of ECO handles are accessed, the .NET class DataBinder is used
instead of a direct databinding expression. The DataBinder-Method Eval makes data access
and the transformation of object data easier with the use of .NET Reflection. Eval requires as
parameter only the ECO handle, out of which data is received and the attribute name in
quotes. Optional an explicit formatting order can be given to this method as a 3rd parameter.

For example in order to access the attribute sLastName of a Customer-Instance, we can
use a DataBinder.Eval call with our ExpressionHandle exphCustomer.

    <ASP:TextBox id="TBLastName" runat="server"
   text='<%# DataBinder.Eval(exphCustomer, "[0].sLastName") %>'>
   </ASP:TextBox>

This assignment binds the textbox TBLastName to the sLastName-Attribute of the first
customer instance from the object list referenced by exphCustomer.

The Data biindiing--Diiallog provides the section siinplle Biindiing for an alternative way of
    Data b nd ng D a og                           s np e B nd ng
entering a databinding expression.




Page 304
                             6. ECO, ASP.NET and WebService




In the right-hand selection list all available ECO handles and their attributes are displayed.
The default set number [0] can be edited manually of course.
For the access with the set number the same rules apply as in the previous section. If the
ECO handle doesn’t yet reference any data the evaluation of such a databinding expression
causes a runtime error.


Binding to methods
A 3rd version of simple databinding is to have the binding executed by a method in the
codebehind.
Such a method for example could take into account the problem of „empty“ datasources. In a
previous example we determined the databinding with the following assignment.

  …text="<%# dgCustomer.SelectedItem.Cells[1].Text %>"…

If the Datagrid dgCustomer is still empty, the evaluation of this expression causes a runtime
error. To get rid of this problem we use a codebehind method that implements the binding
instead.

  function TWebForm1.MyBindingMethod : String;
  begin
    if (dgCustomer.SelectedIndex >= 0) then
        result := dgCustomer.SelectedItem.Cells[1].Text
    else
        result := ’N.N.’;
  end;

The databinding expression bound to this method in the aspx file is then

  …text="<%# MyBindingMethod() %>"…




                                                                                    Page 305
                                       6.3 Databinding


Binding to methods creates extra flexibility, for example for data evaluation and modification.
In our example application [    ASP4] we use this method for example to execute the
DataBinder.Eval Function directly from the code.


6.3.4 The [         ASP4] example
For the demonstration of the different kinds of databinding we placed a datagrid with the
                           CL
familiar connection to the CL_Customer-class in the example application [      ASP4].

Beneath 3 panels are placed that contain one or more controls (Textboxes and Labels). The
main goal of this example is, that these controls get bound to the attributes of the currently
selected datagrid entry by using the different kinds of simple databinding.




Binding to a CursorHandle
We start with the green section (Panel). For the access to the currently selected object of a
table we would use a CurrencyManagerHandle in an ECO winforms application. In
ASP.NET we can use a CursorHandle for such cases .
The example application contains such a CursorHandle (chCustomer), that is bound to the
                                                          c
exphCustomer Handle with the Root-Property.




Page 306
                             6. ECO, ASP.NET and WebService




Since the chCustomer Handle represents the current Customer-Instance due to this, we can
access for example the sLastName-Attribute of the instance with a databinding expression
like below.

   text='<%# DataBinder.Eval(chCustomer, "[0].sLastName") %>'>

In chapter 6.3.1 we described the limited capabilities of the CursorHandle. The value of the
property Position, which contains the set position of the current instance, gets lost with every
roundtrip. Which means the concrete binding context has to be reset with every page update
or has to be saved upfront .

To reevaluate the position value, we code the method UpdateCursorHandle. There we set
the position indicator of the cursor handle to the position of the currently selected datagrid
entry.

   function TWebForm1.UpdateCursorHandle : Boolean;
   var i : Integer;
   begin
     i := dgCustomer.SelectedIndex;
     IF (i >= 0) then // only if IsPostBack
         begin
           chCustomer.set_Position(i);
           result := TRUE;
         end
     else
         result := FALSE;
   end;

Next we decide about when to call this method. Here we have to differentiate between two
scenarios.
     •     The position in the grid is changed actively, thus chCustomer has to be updated
     •     The position in the grid remains unchanged, but an update has to follow because
           of the lost position value in the case of a postback.

For covering the first case we can use the SelectedIndexChanged-Event of the Datagrid and
place the UpdateCursorHandle-call there. An added Databind-call takes care, that the
display of the content of the text areas is also updated in the CursorHandle-update.

   procedure TWebForm1.dgCustomer_SelectedIndexChanged(…);
   begin
     UpdateCursorHandle;
     Databind;
   end;




                                                                                      Page 307
                                         6.3 Databinding


In order to deal with the second case, we add the processes MyRoundtripAction and
MyInitAction , that deals with the postback and the first page request, to the Page_Load
method.

   procedure TWebForm1.Page_Load(…);
   var
     Id: string;
   begin
     EcoSpace.Active := True;
     Id := Request.Params['RootId'];
     if Assigned(Id) and (Id <> '') then
        rhRoot.SetElement(ObjectForId(Id));
     if not IsPostBack then
        BEGIN
          MyInitAction;
          DataBind;
        end
     else
        MyRoundtripAction;
   end;

Here the question may arouse, why it’s not sufficient to simply update the position or the
CursorHandle with the MyRoundtripAction. The reason is that a postback-triggering action,
like for example the selection of a datagrid entry, also selects a roundtrip, but in this roundtrip
the Page_Load-Method is executed first, then the event connected with the triggering action
(see chapter 6.2.2). So UpdateCursorHandle is executed before the event that changes the
datagrid position, thus it’s not being updated itself.
Vice versa the adjustment only of the CursorHandle after an active position change is not
sufficient, since the CursorHandle position value gets lost in a roundtrip, that also is triggered
by actions that don’t change the datagrid position.

Note:
  An alternative solution is to save the position value of the CursorHandle, for example in
  the viewstate (see chapter 6.2.3)!

The function MyRoundtripAction only calls UpdateCursorHandle,                       the   function
MyInitAction initializes the CursorHandle position at the first page request.

   function TWebForm1.MyInitAction : BOOLEAN;
   begin
     if (exphCustomer.Element.GetAsCollection.Count > 0) then
         begin // Init CursorHandle and GridItemSelection
           chCustomer.set_Position(0);
           dgCustomer.SelectedIndex := 0;
         end
     else // mark CursorHandle as invalid
         chCustomer.set_Position(-1);
     result := TRUE;
   end;

So for the control in the green panel the following binding chains exist:




Page 308
                             6. ECO, ASP.NET and WebService

     •    exphCustomer -> chCustomer -> simple Binding ->TBOnHandleFirst
     •    exphCustomer -> chCustomer -> simple Binding ->TBOnHandleLast
     •    TBOnHandleFirst und TBOnHandleLast -> Binding expression -> LBFullName
          (Label)

Since in our example the text areas are not only used for the display of Firstname and
Lastname but also for editing these attributes, we now want to deal with this function.
The Textchanged-Event provides a possible reaction to changes in a textbox. However in
our example we use the OnClick-Event of the Ok-Button as trigger.

  procedure TWebForm1.BtnOk_Click(…);
  VAR o : CL_Customer;
  begin
    o := chCustomer.Element.AsObject AS CL_Customer;
    o.sFirstName := TBOnHandleFirst.Text;
    o.sLastName := TBOnHandleLast.Text;
    DataBind;
  end;

The process is simple. with the IElement-value of the CursorHandle we get access to the
current Customer-Instance (see chapter 4.1). The name-parts of the instance are replaced
with the textbox entries.
The Databind-call takes care of updating all controls.


Binding to a datagrid cell
The textbox control in the yellow panel executes the databinding with direct access to
individual columns values in the datagrid. In order to bind for example the textbox to the
sFirstName-Attribute of the current entry , we use the following binding expression.

  …text="<%# dgCustomer.SelectedItem.Cells[1].Text %>"…


Binding with a CodeBehind-Method
As mentioned in chapter 6.3.3, when codeing binding expression we have to see that they
are evaluate in any case, so that for example empty data sources don’t lead to runtime
errors. The controls in the yellow and green panel did not fulfil this requirement.

The two textbox controls in the blue panel however are a „save“ alternative.
Here binding is done with a CodeBehind-Method.

  function TWebForm1.MyBindingMethod (sAttribute : String): String;
  begin
    if (chCustomer.get_Position >= 0) then
        result := Databinder.Eval(chCustomer, sAttribute) As String
    else
        result := 'N.';
  end;

this method allows binding to any attribute of the chCustomer handle with a passing
parameter, the DataBinder.Eval call comes directly from the code. The binding expressions
for both textbox controls are:




                                                                                 Page 309
                                      6.3 Databinding


  …text='<%# MyBindingMethod(“[0].sFirstName“) %>'…
  …text='<%# MyBindingMethod(“[0].sLastName“) %>'…


Important note!!!
  The ASP4 example is coded, as mentioned above. But in order to prevent that individual
  controls cause a runtime error at a program start with still empty database, the embracing
  tag <%#..%> is removed from the affected control in the binding expressions. This way
  the binding expression is displayed as a simple string, and is not interpreted. So if you
  want to use this example, first you should create some instances with this modified
  version, save them and then re-enter the tags.




Page 310
                             6. ECO, ASP.NET and WebService


6.4 WebForm and Web controls
In chapter 6.2.1 we classified the controls provided by the Delphi IDE for ASP.NET into 4
groups. The most important one concerning ECO support is the group of web controls.
In this chapter we want to have a closer look at this group.
In general these controls can be divided into 4 subgroups.

Groupe               example
Standard Controls    Button, Panel, Label, Table, Hyperlink, Textbox, Checkbox
„Rich“ Controls      AdRotator, Calendar, XML, Validators
List-Controls        ListBox, DropDownList, RadioButtonList, CheckBoxList
Data-Controls        Datagrid, DataList, Repeater

List-Controls and Data-Controls offer the option of complex databinding with their
Datasource-Property (see chapter 6.3.2). Whereas only one attribute of a class can be
displayed with list controls, any number of attributes can be administrated in a table structure
with data controls.


6.4.1 Datagrid
In the two example applications [        ASP1 and ASP4] we already demonstrated the basic
use of the datagrid control. In the following we want to have a closer look at the details and
demonstrate these with the example application [ ASP5].
Unlike the previous examples ASP5 uses an OclPsHandle oclPsCustomer instead of an
ExpressionHandle (see chapter 3.2).

The datagrid control offers the most functions of all data controls. Here – like in a winform
datagrid – the so-called in-place-editing, editing in the corresponding line/column of a table,
is possible. Althoug the datagrid has the disadvantage that the data displayed in the grid are
transferred between server and client via Viewstate-Mechanismat each roundtrip (see
chapter 6.2.3).

The so-called Property Generator of a datagrid, that can be opened with the entry of the
              Property Generator
same name at the bottom of the object inspector window, provides a dialog in which the main
parameters of a datagrid can be set.


Property generator – general
In the section Generall of this dialog the databinding parameters can be set. Among these
               Genera
are the assignment of an ECO handle as Datasource and the selection of an attribute of the
datasource as Data key field.
As stated in chapter 6.1.4, the assignment of a unique key value is required for working with
an ASP.NET Datagrid. If none of the class attributes, the datasource is based on, is suitable,
the ECO handle itself can provide an corresponding key attribute, the ObjectID. To make
that happen only the EcoHandle-Property ExternalID has to be activated.




                                                                                      Page 311
                             6.4 WebForm and Web controls




The property DataMember is of no importance for ECO datasources. But when using
datasets and DBDatasource-components the selection of the data table is made with the
DataMember property.

The option Enablle Sortiing is another interesting property. The ASP.NET Datagrid can
             Enab e Sort ng
contain this function in contrast to an ECO-WinForms datagrid.
To enable sorting in our example application [   ASP5] we activate the sorting function in
the dialog above and assign the following SortCommand-Event to the datagrid:

  procedure TWebForm1.dgCustomer_SortCommand(…);
  var s : STRING;
  begin
    s := e.SortExpression; // get name of sorting column
    oclPSCustomer.Expression :=
                   'CL_Customer.allInstances->orderby(' + s + ')';
    DataBind; // show controls values again
  end;


Property generator – columns
In the section Collumns in the dialog above the attributes and additional columns the
                Co umns
datagrid is supposed to contain are defined.




Page 312
                               6. ECO, ASP.NET and WebService




Here we have the options of having the columns created automatically or creating them
explicitly one by one. The mode is determined by the Datagrid-Property
AutoGenerateColumns, that is active by default.

In most cases we will have to determine the columns manually. This is because
BoundColumn elements in the aspx file in the column section of the datagrid are not created
automatically when using AutoGenerateColumns.
                         Au
A consequence is for example, that the button column edit/update doesn’t work, because the
assignment of a BoundColumn object based on a datagrid column is not possible in the
corresponding codebehind method DataGrid_UpdateCommand.

In the list of available columns the following entries exist:

      •    data fields (BoundColumn)
      •    command columns (EditCommandColumn)
      •    hyperlink columns (HyperlinkColumn)
      •    template columns (TemplateColumn)

A range of attributes is assigned to each column type. All column types have layout attributes
like for example Header image, Header- and Footertext or the IsVisible-button.

Important for datafields are the attributes Sorting- and Formatting expression and the
Readonly-option. The sorting expression is usually the name of the attribute, this expression
is passed as SortExpression-Parameter to the SortCommand-Event (see section property
generator – general).




                                                                                    Page 313
                                6.4 WebForm and Web controls


The formatting expression is optional, with it a text can be integrated into surrounding text
and formatted (so called combined formatting).
In our example the formatting string the number {0:####} of the customer for the iCustNo-
datafield leads for the customer number 123 to the display ‘The number 123 of the
customer“.
You can find more on formatting in the Delphi online help under „combined formatting “ in the
.Net Framework-development manual .

Note
  Please note that in a textfield formatted in such a way data input always has to take place
  without the formatting string. In our example the customer number always has to be
  entered as a number only (without the additional text).

The button columns contain additional layout attributes, that determine the text and the form
of the button.

A hyperlink columns requires a display text (Attribute Text) and the URL of the link (Attribute
URL). Instead of linking directly to a URL there is also the option of linking to a datafield that
contains the URL (Attribute URL-Field).
The attribute target defines the target of the link (Frame or window).

With a template column the layout of a column can be defined with 4 templates. For example
in order to provide the sFirstName-Datafield with these templates, first activate this datafield
in the list of the selected column and then click the link converts column into template at the
lower end of the dialog.

Note:
  ASP.NET knows another column type called ButtonColumn that can call a server-side
  event. However in the Delphi property generator this type is not provided.


Property generator - paging
In the section Pagiing browsing in the datagrid can be activated and configured.
               Pag ng




Page 314
                             6. ECO, ASP.NET and WebService

The Parameter AllowPaging activates the function. Then additional settings like position and
layout of buttons can be executed in the dialog.
To activate paging, the PageIndexChanged-Event has to be assigned as well. This method
only requires two lines of code.

  procedure TWebForm1.dgCustomer_PageIndexChanged
        (src:System.Object;
         e: System.Web.UI.WebControls.DataGridPageChangedEventArgs);
  begin
    dgCustomer.CurrentPageIndex := e.NewPageIndex;
    DataBind;
  end;

The flipping of pages is realized internally by the control loading of all instances of the
datasource and realizing a display divided into individual pages within this data.

Unlike this the optional parameter AllowCustomPaging activates the so-called user defined
paging. In this mode the data area that is supposed to be displayed on one datagrid page
has to be requested explicitly.

This requires two additions in the codebehind.

First the complete number of objects to display at the start of the application has to be
determined and reevaluated whenever a customer instance is added or deleted. In our
example application we add the following to the Page_Load Method.

  …
      if not IsPostBack then
         begin
           …
           dgCustomer.VirtualItemCount :=
                OCLPsCustomer.Element.GetAsCollection.Count;
           DataBind;
         end;
  …

This way the VirtualItemCount-value of the datagrid is set at the first page request.
In theAddInstance- / DeleteInstance-Method this value gets updated.

    dgCustomer.VirtualItemCount := dgCustomer.VirtualItemCount + 1;
  bzw.
    dgCustomer.VirtualItemCount := dgCustomer.VirtualItemCount - 1;

Next the datasource has to reference the data area to display on one page exactly, that
means our OCLPsHandle has to be referenced accordingly and executed.

                                       L
For that we implement a common method (LoadData) with the corresponding passing
parameters.




                                                                                    Page 315
                              6.4 WebForm and Web controls


  procedure TWebForm1.LoadData (iStartAt, iEndAt : Integer;
                                 sExpression : String);
  begin
    OCLPsCustomer.Offset := iStartAt;
    OCLPsCustomer.MaxAnswers := iEndAt;
    if (sExpression <> '') then
        OCLPsCustomer.Expression := sExpression
    else
        OCLPsCustomer.Expression := 'CL_Customer.allInstances';
    OCLPsCustomer.Execute;
  end;

This LoadData-Method is called out of various situations. Most important is the call in the
PageIndexChanged-Event.

  procedure TWebForm1.DataGrid1_PageIndexChanged(…);
  begin
    dgCustomer.CurrentPageIndex := e.NewPageIndex;
    LoadData (dgCustomer.CurrentPageIndex * dgCustomer.PageSize,
              dgCustomer.PageSize, '');
    DataBind;
  end;

The optional second parameter of the LoadData-Method is used for example to pass the
sorting criteria.

  procedure TWebForm1.DataGrid1_SortCommand(…);
  var s : STRING;
  begin
    s := 'CL_Customer.allInstances->orderby('+e.SortExpression+')';
    LoadData (dgCustomer.CurrentPageIndex * dgCustomer.PageSize,
              dgCustomer.PageSize, s);
    DataBind;
  end;

The general advantage of user defined paging is, that .NET, when displaying a datagrid
page, only loads the required data, not all data from a datasource.


Property generator – format and frame
In the section format and frame the layout of the datagrid can be modified in many ways. The
link Automatic Formatting at the bottom end of the object inspector provides 13 additional
layout templates.




Page 316
                            6. ECO, ASP.NET and WebService


6.4.2 List controls
Among List controls are RadioButton- and Checkbox-List, as well as ListBox and
DropDownList. The base class ListControl contains the following Properties.

    Property             explanation
    DataSource           Datasource for connection to EcoSpace
    DataTextField        The attribute of the datasource displayed in the control
    DataValueField       The attribute of the datasource used as key field
    AutoPostBack         see chapter 6.2.2
    Items                Access to list entries of the control
    SelectedIndex        Index of the currently selected entry
    SelectedItem         The currently selected list entry

The administration of and access to entries of a list control can be managed with the Items
of the control in the codebehind area. But for us the option of databinding to an ECO source
is of more interest.
The example application [       ASP6] demonstrates the use of list controls. We use the
following class structure as model.




Each Customer-Instance can contain a CustomerType, besides any number of
Representatives can be assigned to it.

In the WebForm Customers are displayed in a            Datagrid, CustomerTypes as a
DropDownList (selection of one item) and the Representatives as a CheckBoxList (selection
of multiple items) and as a readonly-Listbox.




                                                                                    Page 317
                             6.4 WebForm and Web controls




For each of the 3 controls we use an ExpressionHandle (exphCustomer,     e
exphCustomerType and exphRepresentative) as datasource (DataSource-Property), that is
connected to EcoSpace via the central RootHandle. An additional CursorHandle
chCustomer, again bound to exphCustomer provides the currently selected customer entry.

The readonly-Listbox at the end of the page displays only the associated representatives of
the current customer entry via the ECO handle chain

rhRoot -> exphCustomer -> chCustomer -> exphSelectedReps.

The OnClick-Method of the AddCustomer-Button creates new Customer-entries in the
familiar way. In order to create CustomerType-Objects, the user first has to enter the type
name into the upper textbox and then add the entry to the DropDownList with the
AddCustomerType-Button.
Adding new Representatives happens the same way. We enter the name of the
representative into the upper textbox and create a new CheckBox-entry with a ButtonClick .




Page 318
                             6. ECO, ASP.NET and WebService

In this example two things are very important.

     •    The link of a CustomerType / multiple Representatives to a Customer-entry
     •    Synchronization of the display in the DropDownList and CheckBoxList when
          changing the selection in the Customer-Grid.

The corresponding list control takes over the following tasks simultaneously:

     •    Display of all available CustomerType- / Representative-Instances
     •    The instances assigned to the currently selected Customer-entry are displayed as
          a selection
     •    When a change in the selection happens, a new assignment to the current
          Customer-entry is executed automatically

Note
  As an alternative concept for this application one could for example place the
  administration of CustomerType and Representative-Instances in extra edit areas or
  webforms, separated from the assignment to a Customer-entry. Then one could use an
  ExpressionHandle whose data range already matches the assigned amount (Expression
  := chCustomer.Contacts.allInstances) instead of a CursorHandle for the display of the
  assigned instances .

To synchronize the display of list controls in our example with datagrid using the
CursorHandle chCustomer, we use -similar to the example Beispiel ASP4 – the method
UpdateCursorHandle for updating of the CursorHandle and the method
UpdateDetailsControls for the subsequent update of the entries in the list controls.

  procedure TWebForm1.UpdateCursorHandle;
  var iSelect : Integer;
  begin
    if (exphCustomer.Element.GetAsCollection.Count > 0) then
        begin // only when customer instances exists
          iSelect := dgCustomer.SelectedIndex;
          if (iSelect < 0) then
             begin // no selection, then choose 1. entry
               iSelect := 0;
               dgCustomer.SelectedIndex := 0;
             end;
          // update CursorHandle
          chCustomer.set_position (iSelect);
        end;
  end;




                                                                                 Page 319
                              6.4 WebForm and Web controls


  procedure TWebForm1.UpdateDetailsControls;
  var oCustomer         : CL_Customer;
      oRepresentative : CL_Representative;
      oItem             : ListItem;
      s                 : String;
  begin
    // deselect all CheckBox entries
    for oItem in CBRepresentative.Items do
         oItem.Selected := FALSE;
    if assigned (chCustomer.Element) then
        begin
          // get currently selected Customer instance
          oCustomer := chCustomer.Element.AsObject AS CL_Customer;
          if Assigned (oCustomer.HasType) then
              // select DropDownList-CustomerType
              DDCustomerType.SelectedValue :=
                IDForObject (oCustomer.HasType.AsIObject);

             for oRepresentative in oCustomer.Contacts do
                begin // new selection of the CheckBox entries
                  s := IdForObject (oRepresentative.AsIObject);
                  For oItem in CBRepresentative.Items DO
                     begin
                       if (oItem.Value = s) then
                           oItem.Selected := TRUE;
                     end;
                end;
           end;
  end;

The active assignment of a CustomerType-value to the selected customer entry is done by
the SelectedIndexChanged-Method of the DropDownList.

  procedure TWebForm1.DDCustomerType_SelectedIndexChanged(…);
  var oCustomerType : CL_CustomerType;
       oCustomer    : CL_Customer;
  begin
    oCustomerType := ObjectForId(DDCustomerType.SelectedValue).
                       AsObject AS CL_CustomerType;
    chCustomer.set_position (dgCustomer.SelectedIndex);
    oCustomer := chCustomer.Element.AsObject AS CL_Customer;
    oCustomer.HasType := oCustomerType;
    DataBind;
    UpdateDatabase;
  end;

The code for assigning the representatives is a little more complex, since multiple items can
be selected.




Page 320
                             6. ECO, ASP.NET and WebService

   procedure TWebForm1.CBRepresentative_SelectedIndexChanged(…);
   var oCustomer : CL_Customer;
       oItem      : ListItem;
   begin
     IF (dgCustomer.SelectedIndex >= 0) then
         begin
           // get current Customer instance
           chCustomer.set_position (dgCustomer.SelectedIndex);
           oCustomer := chCustomer.Element.AsObject AS CL_Customer;

            // clear all Representative links
            oCustomer.Contacts.Clear;

          // and now set the new links
          For oItem in CBRepresentative.Items DO
             if oItem.Selected then
                oCustomer.Contacts.Add(ObjectForId(oItem.Value).
                                       AsObject AS CL_Representative)
        end;
     UpdateCursorHandle;
     DataBind;
   end;



6.4.3 Repeater and DataList control
The Repeater control does have a Datasource-Property – like a datagrid- , but is equipped
poorly concerning display, selection and modification of data .However these limitations have
the advantage that the display doesn’t require buffering data in the viewstate even in a
roundtrip. So the Property EnableViewState can be deactivated for the Repeater control
without any problems, it’s sufficient if the data to display is requested from the datasource on
demand only.

The example application [                              R
                            ASP7] contains a Repeater (RPCustomer) and a DataList
         D
control (DLPCustomer).
As usual the CL_Customer-class is the base of this example, the connection of the
Repeater controls to EcoSpace via a Datasource-Property is again achieved with an
ExpressionHandle.

To be able to display data with the Repeater control, we have to define the data display
format first. The control supports 5 different kinds of templates

Group                     explanation
HeaderTemplate            Defines the header layout
ItemTemplate              Defines the line layout
AlternatingItemTemplate   Defines the layout of the 2nd line (in an alternating Layout)
SeparatorTemplate         Defines separator line
FooterTemplate            Defines the footer layout

Only the ItemTemplate is absolutely necessary, all other templates are optional.
In the aspx file we implemented 2 of the 5 possible template types, the header- and the item
template.




                                                                                      Page 321
                               6.4 WebForm and Web controls


   <ASP:Repeater id="RPCustomer" runat="server"
        datasource="<%# exphCustomer %>" enableviewstate="False">
     <ItemTemplate>
       <table cellspacing="1" cellpadding="1" width="300" border="1">
         <tr>
     <td><%# DataBinder.Eval(Container.DataItem,"sFirstName")%> </td>
     <td><%# DataBinder.Eval(Container.DataItem,"sLastName") %></td>
         </tr>
       </table>
     </ItemTemplate>

     <HeaderTemplate>
       <table cellspacing="1" cellpadding="1" width="300" border="1">
         <tr>
            <th>FirstName</th>
            <th>LastName</th>
         </tr>
     </HeaderTemplate>
   </ASP:Repeater>

While in a datagrid the assignment of instances / attributes of the datasource to the individual
lines / columns of a table happens automatically, a Repeater control requires an explicit
assignment in the ItemTemplate-Definition. The expression Container.DataItem provides
access to the current instance of the datasource, The DataBinder.Eval Function determines
the current attribute of the instance (see chapter 6.3.3).

The paging has to be coded manually as well. In our example we administrate a PageRecord
as Session-Variable, which saves among other things the current number of pages. With the
OnClick-Event of the NextPage- and PrevPage-Button the page values are reset. The central
method SetPageParams modifies the Expression-Property of the ECO Handle, then the
databinding is executed again.

   procedure TWebForm1.BtnPrevPage_Click(…);
   begin
     rPageParams := TPageParams (Session.Item['PageParams']);
     if (rPageParams.iPageNo > 0) then
         begin
           DEC (rPageParams.iPageNo);
           Session.Item['PageParams'] := rPageParams;
         end;
     SetPageParams;
     DataBind;
   end;




Page 322
                             6. ECO, ASP.NET and WebService

  procedure TWebForm1.SetPageParams;
  begin
    if (not IsPostBack) then
        with rPageParams do begin // at program start only
          iStartAt := 1;
          iPageSize := 5;
          iPageNo := 0;
          Session.Add('PageParams', rPageParams)
        end
    else
        begin // read PageParams
          with rPageParams do
             iStartAt := 1 + (iPageNo * iPageSize);
        end;

    with rPageParams do // rebuild expression
       exphCustomer.Expression :=
         'CL_Customer.allInstances->SubSequence (' +
             iStartAt.ToString + ',' +
             Integer(iStartAt+iPageSize-1).ToString + ')';
  end;

The DataList control has a kind of an intermediate position between Repeater and Datagrid
control. It has a display with templates like the Repeater. Besides that it supports also data
selection and editing of an entry.

Moreover it has two kinds of templates.

        Group                       explanation
        SelectedItemTemplate        Defines the layout of the selected line
        EditItemTemplate            Defines the layout of an edit-line




                                                                                    Page 323
                              6.4 WebForm and Web controls


6.4.4 Validators
In the group of web controls we can also find so-called validator controls, which are used to
check the content of common input fields according to various criteria. To make this happen
those controls are connected to the checked input field.


Overview
The following tables provide an overview of all available validator controls, their most
important properties and events.

Validator                      explanation
RequiredFieldValidator         Checks if the input field is empty
RangeValidator                 Checks if the field content is within a certain area, for
                               example numbers between 1 and 100
CompareValidator               Compares the content of a field to a constant or to the content
                               of another field.
RegularExpressionValidator     Checks the content of a field according to a pattern, for
                               example five figure zip codes.
CustomValidator                Freely customizable check method for event handling of the
                               control.
ValidationSummary              Result summary of all validator control of a page.


Property / Event             Validators                   explanation
ControlToValidate            ValidationSummary            Assingnment of the input field to
                                                          check.
EnableClientScript           ValidationSummary            Activates an additional client-side
                                                          check (see server-side and client-
                                                          side check ).
Display                      ValidationSummary            None, Static or Dynamic (see
                                                          reaction to a false input)
ErrorMessage                 ValidationSummary            The message to display at
                                                          incorrect input.
InitialValue                 RequiredFieldValidator       In selection lists this is the value
                                                          that can’t be selected.
Type                         RangeValidator,              Data type of the area (String,
                             CompareValidator             Integer, Date...)
MinimumValue/                RangeValidator               Min and max limit of the area
MaximumValue
ValueToCompare/              CompareValidator           Value to compare or field to
ControlToCompare                                        compare
Operator                     CompareValidator           =, <>, >, <, >= ,<=
ValidationExpression         RegularExpressionValidator Expression template
ClientValidationFunction     CustomValidator            client side check (JavaScript)
ServerValidate-Event         CustomValidator            Server side event handling
ShowMessageBox               ValidationSummary          additional Client-Messagebox
ShowSummary                  ValidationSummary          activate / deactivate display
DisplayMode                  ValidationSummary          List of error messages (List,
                                                        BulletList, SingleParagraph).




Page 324
                             6. ECO, ASP.NET and WebService


Connection to an input field
The connection between a validator control and an input field is established with the property
Property ControlToValidate. Depending on the kind of validator control additional properties
exist, which determine the details of the check.

If a RequiredFieldValidator is connected so a selection list, for example a certain value of the
list can be defined as initial value with the property InitialValue.

                                    T
For RangeValidatoren the Data-type (Type) of the area to reference and its limits
 M
(MinimumValue, MaximumValue) are determined.

                                                                      V
A CompareValidator compares the field content with a constant (ValueToCompare) or
               C
another field (ControlToCompare) with the Operator (=, <>, >...) and the data type (Type).
                                                                                    T

With the Property ValidationExpression of a RegularExpressionValidator the Format of a
character string can be predefined with a template expression. The control checks of the field
content complies with the template.
For the determination of this expression the IDE provides a so-called regular expression
editor that contains some predefined templates, for example for zip codes or telephone
numbers.
The underlying syntax of these templates at the client-side check is geared to the JScript-
Syntax for regular expressions, whereas the serverside validation uses a syntax defined by
the .NET rules for regular expressions (see Online-Help, „language elements for regular
expressions “ in the .NET-Framework).

A CustomValidator-Control offers the most flexible way of input check. For the check two
events can be implemented. A client side JavaScript-Method is connected via the Property
ClientValidationFunction. On the server side a ServerValidate event is provided.

The ValidationSummary-Control does not check itself, but enables an alternative and
summarizing display of all error messages of the Validator-Controls of a page.


Sever side and client side check
In general the check initiated by a Validator-Control always takes place server-side. A user
action that triggers the serverside validation for example with a TextChanged- or OnClick-
Event, is cancelled in case one validator determines a false input on the page, and the
corresponding error messages are displayed.

With the Validator-Property EnableClientScript an additional client side input check can be
activated. The required JavaScript-Section is added automatically to the HTML-Output .
The advantage of an additional client side check is obvious. In case of incorrect input a
roundtrip to the server isn’t even started.

Note
  A client side check is only possible with certain browsers / versions.


Displaying error messages
Usually the position of the validator control on the aspx page is also the location of the
display of an corresponding error message. As an alternative an additional
ValidationSummary-Control can be used to display error messages .




                                                                                      Page 325
                               6.4 WebForm and Web controls


If and how it should be reacted to a false input is determined with the validator properties
Display and ErrorMessage. The Property ErrorMessage determines the error message.
A Display-value None prevents the display of the error message at the control position,
however a display of the message remains in this case .
The Display-value Dynamic causes the display of the error message at the position of the
Validator-Control. The text is added dynamically to the html output.
The Display-value Static (default) generally leads to the same output as dynamic, but in
case of a client side check, a predefined position in the aspx file is used.

The display format can be selected for each control with layout properties like BackColor,
Font, CssClass etc..


Example [ASP7]
In the example application [    ASP7] 3 textbox fields are placed at the beginning of the
page for the attributes sFirstName, sLastName and iCustNo, as well as a AddCustomer-
Button, to add new CL_Customer-Instances. We assigned various validator controls to these
input fields in addition.

The customer number textbox is bound to a RequiredFieldValidator-Control, the first name
field additionally to a RegularExpressionValidator.
We assigned the expression [A-Z][a-z]* as ValidationExpression to this validator,
which means that each first name has to start with a capital letter and can only contain letters
without vowel mutation.

The 3rd Validator-Control used in our example is a CustomValidator, linked to the last name
field. The check is done server-side with an event in the codebehind. An OCL-Evaluation
checks if the selected last name already exists, thus prevents identical last names.

   procedure TWebForm1.ValCustLastName_ServerValidate
            (source: System.Object;
             args: System.Web.UI.WebControls.ServerValidateEventArgs);
   var rRet : IElementCollection;
   begin
     if (args.Value <> '') then
         rRet:= EcoSpace.OclService.Evaluate
           ('CL_Customer.allInstances->select
            (sLastName=''' + args.Value + ''')').GetAsCollection;
     args.IsValid := ((args.Value <> '') AND (rRet.Count = 0));
   end;




Page 326
                             6. ECO, ASP.NET and WebService


6.4.5 AutoForm
In chapter 5.4 we explained the AutoForm-Funtion for ECO-WinForms-applications. ECO
provides such a feature for ASP.NET as well.
This feature offersa way of visualizing and modifying instances of an application spanning all
classes, without any coding.

                   Integrating an autoform is very easy. We just add a special webform, the
                   so-called ECO ASP..NET AutoForm to our ASP.NET application.
                             ECO ASP NET AutoForm


                  The example application [        ASP8] also contains an autoform page.
When the page is requested first all classes in EcoSpace are displayed.




If you select an instance of a class now (for example CL_Customer), the associated
instances are displayed as well (for example CL_Orders).




With this way you can go through all instance connections and modify data at will.




                                                                                     Page 327
                              6.4 WebForm and Web controls


6.4.6 Navigation and data input between WebForms
In practice an ECO ASP.NET application consists of a large number of webform pages with
according explicit or implicit linking, between which a data exchange takes place in order to
be able to display detail instances in a master – detail –class relation for example.

For the navigation between two webforms ASP.NET provides the following functions.

Method                         explanation
Response.Redirect              The client calls the passed URLs.
Server.Transfer                Serverside transfer of the execution to the transferred (local)
                               page.
Server.Execute                 Server sid erequest of the transfered (local ) page and
                               automatic transfer to the base page.
WebRequest                     Serverside request of any URL.

We want to demonstrate navigation and data transfer with the example application
[   ASP8]. The application is based on a simple master/detail class construction.




Select an instance in the datagrid of the webform1 where Customer-Instances are listed and
then got to the web form 3 that displays the Orders-Instances of the selected customer with
a ButtonClick. From the webform3 you can access the individual lines of the selected order
analogically.

In an ECO WinForms-application we can use the selected object or its IElement-values as
„passing parameter“ between winforms pages (see chapter 5.1.4).
In ASP.NET this method is not recommended, except we take care that the EcoSpace
remains saved permanently during the session (see chapter 6.2.3).
In this case however we need additional server memory for each active session!

In ASP.NET we usually use the ObjectID of an ECO instance as passing parameter instead
of the object.
In our example application the request of the orders-page is done with the following OnClick-
Event.




Page 328
                           6. ECO, ASP.NET and WebService

  procedure TWebForm1.BtnCallOrderForm_Click(…);
  var s : String;
  begin
    if (dgCustomer.SelectedIndex >= 0) then
        begin
          s := dgCustomer.SelectedItem.Cells.Item[0].Text;
          Response.Redirect ('WebForm3.aspx?RootId='+s);
        end;
  end;

If a Customer-Instance was selected in the Datagrid, we fetch its ObjectID from the first
                                                          R
column of the grid and pass it as an URL parameter (RootId) at the request of the
WebForm3.

The parameter name RootId is recommended here, since each Page_Load Method in an
ECO-WebForm is already prepared to such a kind of transfer of an ObjectID.

  procedure TWebForm1.Page_Load(…);
  var
    Id: string;
  begin
    EcoSpace.Active := True;
    Id := Request.Params['RootId'];
    if Assigned(Id) and (Id <> '') then
      rhRoot.SetElement(ObjectForId(Id));
    if not IsPostBack then
  …


Note
  In chapter 6.2.3 we mentioned the page and application context of an ASP.NET
  Application and had a look at the various options of saving data. The method
  Request.Params used here enables access to many variables of the page- and
  application context , also to URL-Parameters.

The ECO Handle-chain in the WebForm3 is structured as follows.

ECO Handle                   Configuration
rhRoot                       Connection to EcoSpace and limitation to the CL_Customer-
                             Instances with StaticValueType.
exphOrder                    Connection to rhRoot and Selection of all order instances
                             with the Expression self.TheOrders.

So in the Page_Load Method the rhRoot Handle gets connected to the Customer-Instance
selected before. This way the exphOrder provides all Orders-Instances of this Customer-
Instance.

ExphOrder is assigned to the webform3 datagrid as Datasource.
Further navigation from a selected Order-entry to the Orderline-Instances in the WebForm4
is analogue.




                                                                                Page 329
                             6. ECO, ASP.NET and WebService


6.5 WebServices
Like an ASP.NET application a WebService application is executed on a webserver and
provides there functions for other programs. Unlike an ASP.NET Application a Webservice
doesn’t provide html pages displayed in a browser but structured data that is transferred
back and forth between client and server in xml format with the http protocol (SOAP).

Each program that can interpret the xml datastream created by a webserver can be used as
webservice client in general.
The Delphi-IDE supports the development of webservice and ECO-Webservice-applications
and the integration of WebService-requests in various project types (WinForms, ASP.NET,
WebService, Package).


6.5.1 Basics
The structure of an ECO-WebService application is similar to that of an ECO ASP.NET
application. The only difference is that the aspx files and their controls are missing.
This means that the implementation of modelling, persistence and EcoSpace in an ECO-
Webservice application differs only slightly or not at all from that of an ECO ASP.NET
application.
So we can concentrate here on the few new or different aspects of webservice
implementation and webservice use.

The process control of a webservice application differs from that of an ASP.Net only in the
fact that instead of page requests and the connected round-trip-expiration in a webservice
only individual method calls, in general independent from each other, happen .
When using ECO this means that a method, that requests an EcoSpace instance, returns
this instance at the end of the method to the pool or releases it.

The principle of the page- and application context is in general kept. WebService-
applications don’t have a ViewState-Mechanism but a Session- and Application-State.
The saving of session- / application wide data is done in the same way as in an ASP.NET
application. Creating a session however can only be done with a cookie.

An ECO-Webservice application contains the same configuration parameters as an ECO-
ASP.NET application. EcoSpace Strategy and Pooling are used analogue.

Concerning the program, behind a webservice is a class whose methods can be called from
the client program and whose function results are then returned to the client.

The result of a call of a webservice method is returned to the calling function as an xml file.
Each serializable object can be transferred to the client this way. ECO-Objects, that need an
EcoSpace to exist, can’t be transferred that way.




                                                                                     Page 331
                                         6.5 WebServices


6.5.2 Creating an ECO-Webservice
Now we want to explain the implementation of an ECO-Webservice with a simple example
application [         WebService1].

                         To create such an application we select the entry ECO ASP..NET
                                                                               ECO ASP NET
                        Web--Serviice--Applliicatiion in the main menu of the IDE under <Fiille>
                         Web Serv ce App cat on                                         < F e>
                        -- <New> -- <Other>… .
                           <New> <Other>…

Since a webservice is installed in the Internet/Intranet like an ASP.NET application, Delphi
offers a broad selection of various options in the following dialog, for example the choice
between the WebServers IIS or Cassini.


Project files of a WebService-application
After finishing this dialog the IDE generates an WebService-Project with the following files.

file                                       explanation
WebService1.bdsproj                        Delphi-Project file
Package_1Unit.pas                          Contains the class model (domain model)
WebService1EcoSpace.pas                    Implements the EcoSpace class
EcoPersisistenceMapperProvider.pas         Implements the central persistence
EcoSpaceProvider.pas                       Administrates the session state
WebService_1.asmx                          Counterpart to the aspx file(ASP.NET), contains
                                           only ECO handles
WebService_1.pas                           Application logic of the WebService
Global.asax                                Implements the global functions: Application_Start,
                                           Session_Start...
                                           Usually contains only the link to the Codebehind-file
                                           Global.pas, where these functions usually are coded
Global.pas                                 see Global.asax
Web.config                                 Configuration file: Debugging, error messages an
                                           authentification
bin/WebService1.dll                        The compiled application



Example [WebService1]
This   time     the    class   CL_ECOTeam is       the   model   of   our   example   application
[    WebService1], it administrates first and last names of all ECO team members (as far as
I know them ), as well as an absolute and relative hit value iTotalHits / iHitsPercentage for
each person. Again saving of data is done with a BDPConnection and a
PersistenceMapperBDP.

The example application is supposed to provide 3 methods.

       •   GetEcoTeamCount provides the number of team members
       •   GetECOTeamList provides a list of all team members
       •   VoteForECOTeam enables voting for a team member




Page 332
                            6. ECO, ASP.NET and WebService

The unit Webservice_1.pas generated automatically by IDE, already contains the complete
code – although commented out – for three class method examples, that we can use as a
template for our own methods.
We can describe details of our webservice with an attribute placed directly in front of the
class definition.

  [WebService(Name='EcoTeamRanking',
   Description= 'Ranking of the ECO Team',
   Namespace='http://www.myservice.de/webservices/')]

Notes:
  The function type of the support method ObjectForID contained in the unit has to be
  adjusted manually. ECO-III now uses an IObjectInstance instead of the previously used
  IObject.
  By default the asmx-file receives the same name as the project file, which leads to a
  circular reference. So we also have to rename the asmx file.

The design page of the asmx file only contains a rhRoot Handle, that we connect as usual to
EcoSpace. This way all necessary preparation are made to implement the web methods.

The method GetEcoTeamCount is of little importance for a client application, but we use this
                                                              C
method in the test mode to add team members to the database (CreateECOTeam).

  function TWebService1.GetEcoTeamCount: integer;
  var
    i : Integer;
  begin
    i := GetCount;
    if (i = 0) then
        begin
          CreateECOTeam;
          i := GetCount;
        end;
    Result := i;
  end;

For the GetCount-query we define an corresponding OCL expression that gets evaluated by
the OCLService.




                                                                                   Page 333
                                      6.5 WebServices


  function TWebService1.GetCount: integer;
  var
    OclService     : IOclService;
    ResultElement : IElement;
  begin
    OclService :=
       EcoSpace.GetEcoService(typeof(IOclService)) as IOclService;
    ResultElement :=
       OclService.Evaluate ('CL_ECOTeam.allInstances->size');
    Result := Integer(ResultElement.AsObject);
    DoneWithEcoSpace;
  end;


Data export
The method GetECOTeamList provides the client application with a list of all team
members. But since we can’t transfer ECO objects directly to the client as function value of a
                                          r
webservice method, we use a record array (rArray), to which we assign the attributes of the
instances, for the data export.

  function TWebService1.GetECOTeamList : TECOTeamList;
  var
    OclService : IOclService;
    ResultList : IElementCollection;
    rArray     : TECOTeamList;
    rPerson    : TECOTeamRec;
    i          : Integer;
  begin
    OclService := EcoSpace.GetEcoService(…) as IOclService;
    ResultList :=
    OclService.Evaluate ('CL_ECOTeam.allInstances').GetAsCollection;

    if (ResultList.Count > 0) then
       begin
         SetLength (rArray, ResultList.Count);
         for i := 0 to PRED(ResultList.Count) do
           begin
             rPerson.sFirstName :=
             (ResultList.Item[i].AsObject AS CL_ECOTeam).sFirstName;
             rPerson.sLastName := …
             …
             rArray[i] := rPerson;
           end;
       end
    else
       …
    result := rArray;
    DoneWithEcoSpace;
  end;

The 3rd method VoteForECOTeam expects first and last name of a person as selection
criteria.




Page 334
                             6. ECO, ASP.NET and WebService

The hit counter of the selected person is increased, an UpdateDatabase-call takes care of
saving this change .

  function TWebService1.VoteForECOTeam
               (sFirstName, sLastName : String) : BOOLEAN;
  var
    OclService : IOclService;
    ResultList : IElementCollection;
  begin
    OclService := EcoSpace.GetEcoService(…) as IOclService;
    ResultList := OclService.Evaluate
       ('CL_ECOTeam.allInstances->select
         ((sFirstName=''' + sFirstName + ''') and
          (sLastName=''' + sLastName + '''))').GetAsCollection;
    if (ResultList.Count = 1) then
        begin // found!
          (ResultList.Item[0].AsObject AS CL_ECOTeam).iTotalHits :=
            (ResultList.Item[0].AsObject AS CL_ECOTeam).iTotalHits+1;
          UpdateDatabase;
          result := TRUE;
        end
    else
        result := FALSE;
    DoneWithEcoSpace;
  end;

The retrun value of the method indicates if the voting was succesful.


6.5.3 Using a webservice
Bevor we start developing a client application for our webservice we want to have a look at
the webservice testing function provided by Delphi.


Integrated testing mode
The Delphi-IDE offers the option of testing a webservice with the start function, without a
client program. At the start of our example application [     WebService1] links to all methods
of the webservice and a service description, that describes the class and all methods of the
web service contained in it, is provided in detail in XML-format (WSDL).




                                                                                     Page 335
                                       6.5 WebServices


For example the link to the VoteForECOTeam-Method opens an additional page in the
browser that contains the XML structure for a call of this method and the format of the
answer.




But most important of all we can test the method here. To do this we enter the two requested
method parameters. The call button then displays the result in XML.




Note:
  In any case execute the GetECOTeamCount-Method first! This automatically fills the db
  with the data of the team members.


Requirements and process of a webservice query
In order to give a client application access to a webservice method, the client first has to
know the class and methods of the webservice. For that the client requests the so-called
class and interface definition (WSDL-Document) via the URL address of the webservice.
With this definition the client can locally create a so-called proxy class as kind of an image
(just the Interface without Implementation) of the webservice class.

Because of this the client “knows” the methods, their parameters and function type and can
call these methods as if the class was implemented locally in the application. The data
transfer (SOAP, XML) is realized by internal functions of the proxy class and thus remains
hidden for the client.

In order to be able to call a method, first the client has to make instances of the proxy class.
Each method call then results in the following process.




Page 336
                             6. ECO, ASP.NET and WebService

      •   Serialization of parameters (if necessary) and sending of the request to the server
          via SOAP.
      •   Deserialization of the request and execution of the selected webserver method on
          the server.
      •   Serialization of the function result and returning of the answer to the client
      •   Deserialization of the answer and transformation into a function result.

This scheme may suggest that the client has to wait for the answer and is blocked in the
meantime. This is not absolutely necessary, since some webservices can be executed in an
asynchronous manner.
Because of this the proxy class provides a Beginxyz and a Endxyz Method for each Method
xyz.
The realization of such a client application is demonstrated in the next section.


Example [WSClient]
As already mentioned, Delphi supports the integration of a webservice into various kinds of
applications. The example application [      WSClient], that we chose for the realization of a
webservice client application is a simple .NET application.
The Integration of the Webservice happens in the Projject management . There you open
                                                    Pro ect management
the context menu of the entry of the client application and select the entry Add Web
                                                                                   Add Web
Refference..
Re erence

In the following dialog enter the URL of the service (WebServcie1), which we created in
chapter 6.5.2.
Now Delphi imports the WSDL-Document of the Webservice and creates an interface file
Webservice_1.pas in the specified subfolder (default: localhost), which contains all definitions
required for calling the webservice methods.

By entering the interface file in the uses-list of the WSClient-WinForm-Unit, we can
implement there the calls of our choice.


                                                The WinForm only contains a Listbox for the
                                                visualization and selection of team members
                                                as well as two buttons for the asynchronous
                                                call of the team list and the voting for the
                                                selected member.


                                                The call of the team-list uses the webservice
                                                method GetECOTeamList and can be
                                                synchronous or asynchronous.




                                                                                      Page 337
                                        6.5 WebServices



  procedure TWinForm.GetRankingData (bAsynchron : BOOLEAN);
  var
    ws     : ECORanking.WebService_1.EcoTeamRanking;
    rData : ECORanking.WebService_1.TArrayOfTECOTeamRec;
  begin
    ws := ECORanking.WebService_1.EcoTeamRanking.Create;
    if bAsynchron then
        ws.BeginGetECOTeamList(MyCallBack, ws)
    else
        begin
          rData := ws.GetECOTeamList;
          UpdateListBox (rData);
        end;
  end;

The asynchronous call requires in addition the implementation of a callback process that
receives the data on completion.

  procedure TWinForm.MyCallBack (asyncresult : IAsyncResult);
  var
    ws    : ECORanking.WebService_1.EcoTeamRanking;
    rData : ECORanking.WebService_1.TArrayOfTECOTeamRec;
  begin
    ws := ECORanking.WebService_1.EcoTeamRanking.Create;
    rData := ws.EndGetECOTeamList(asyncresult);
    UpdateListBox (rData);
  end;

The voting is implemented as follows.

  procedure TWinForm.BtnHit_Click(…);
  var
    ws : ECORanking.WebService_1.EcoTeamRanking;
    s    : ARRAY OF STRING;
    bOk : BOOLEAN;
  begin
    if (LBRanking.SelectedIndex < 0) then
        begin
          MessageBox.Show ('Please select a person first!');
          Exit
        end;
    s := (LBRanking.SelectedItem As String).Split([' '],3);
    ws := ECORanking.WebService_1.EcoTeamRanking.Create;
    bOk := ws.VoteForECOTeam (s[0], s[1]);
    if bOK then
        begin
          MessageBox.Show ('You have successfully voted!');
          GetRankingData (FALSE);
        end
    else MessageBox.Show ('Your vote could not be registered!');
  end;




Page 338
                             6. ECO, ASP.NET and WebService




P.S: Don’t get lost in EcoSpace...




                                                              Page 339
Appendix
This appendix contains some URLs for ECO-Newsgroups, -Blogs and -Articles, as well as
some book recommendations for the topics UML, OCL, .NET and Delphi.




ECO-Newsgroups and -Forums
Borland ECO Newsgroup
- Import to a Newsreader (Outlook-Express etc.)
news://newsgroups.borland.com/borland.public.delphi.modeldrivenarchitecture.eco

- with Internet-Reader:
http://newsgroups.borland.com/cgi-
bin/dnewsweb?cmd=listall&group=borland.public.delphi.modeldrivenarchitecture.&utag=
or
http://delphi.newswhat.com/geoxml/forumlistthreads?groupname=borland.public.delphi.mode
ldrivenarchitecture.eco
or
http://homepages.borland.com/ecoteam/pmwiki/pmwiki.php


ECO-Wiki
http://homepages.borland.com/ecoteam/pmwiki/pmwiki.php


German ECO-Forum
http://www.ecospace.de




                                                                                  Page 341
                                           ECO-Blogs




ECO-Blogs
Borland
http://blogs.borland.com/JanNorden/
http://blogs.borland.com/jonashogstrom/
http://blogs.borland.com/jesperhogstrom/
http://blogs.borland.com/AndersIvner/
http://blogs.borland.com/timjarvis/
http://blogs.borland.com/malcolmgroves


Others
Peter Morris: http://blogs.slcdug.org/petermorris/
Dr. Bob:      http://www.drbob42.com/blog/
Holger Flick: http://delphi2006.blogspot.com/




ECO-Articles
Borland
http://bdn.borland.com/delphi/eco


Others
http://www.myecospace.net
http://www.howtodothings.com/computers-and-technology/c39-delphi.html
http://www.drbob42.com
http://www.bitwisemag.com/copy/delphi/swart/blog1.html
http://www.softwareschule.ch/download/eco2.pdf
http://www.cq.co.za/index.asp?newcore=ECOLESSONS

http://www.viewpointsa.com/bold_resources/getting_started_with_bold/Part3-OCL.html




Page 342
                                       Appendix



Recommended books
[Martin Fowler]
UML konzentriert, Addison-Wesley, ISBN 3-8273-2126-3

[Harald Störrle]
UML 2 erfolgreich einsetzen, Addison-Wesley, ISBN 3-8273-2268-5

[Bernd Oestereich]
Analyse und Design mit UML 2, Oldenbourg, ISBN 3-486-57654-2

[Craig Larman]
Applying UML and Patterns, Prentice Hall, ISBN 0-13-148906-2

[Jos Warmer, Anneke Kleppe]
Object Constraint Language 2.0, mitp, ISBN 3-8266-1445-3



[Holger Schwichtenberg, Frank Eller]
Programmierung mit der .NET Klassenbibliothek, Addison-Wesley, ISBN 3-8273-2128-X

[Stefan Falz, Karsten Samaschke]
Das ASP.NET Codebook, Addison-Weslay, ISBN 3-8273-2049-6

[Patrick A. Lorenz]
ASP.NET, Hanser, ISBN 3-446-22552-8

[Andreas Kosch]
Crashkurs .NET, S&S, ISBN 3-935042-39-6

[Marco Cantù]
Mastering Delphi 2005, Sybex, ISBN: 0-7821-4342-3

[Walter Doberenz, Thomas Gewinnus]
Borland Delphi 2005, Hanser, ISBN 3-446-40202-0




                                                                             Page 343

				
DOCUMENT INFO
Shared By:
Categories:
Tags:
Stats:
views:54
posted:1/17/2012
language:English
pages:343