• No results found

Understanding the Personify API

N/A
N/A
Protected

Academic year: 2021

Share "Understanding the Personify API"

Copied!
67
0
0

Loading.... (view fulltext now)

Full text

(1)

Understanding the

Personify API

(2)

All material contained in this documentation is the confidential and proprietary property of TMA Resources, Inc. No part of this publication may be reproduced, stored in a retrieval system, or transmitted in any form by any means, electronic or otherwise, without the written permission of the publisher, TMA Resources, Inc. All trademarks, service marks, and trade names referenced in this material are the property of their respective owners.

• TIMSS and Personify are registered trademarks of TMA Resources, Inc.

• Microsoft, Windows, SQL Server, .NET, and Notepad are registered trademarks of Microsoft Corporation. • Group 1, CODE-1, and Universal Coder are registered trademarks of Group 1 Software, Inc.

• Crystal Reports is a registered trademark of Business Objects SA.

• EXPOCAD is a registered trademark of Applied Computer Technology, Inc. • NetAdvantage is a registered trademark of Infragistics, Inc.

• Firefox is a registered trademark of Mozilla Corporation. • Payflow Pro is a registered trademark of PayPal.

• CyberSource is a registered trademark of CyberSource Corporation. • Intel is a registered trademark of Intel Corporation.

• Wells Fargo is a registered trademark of Wells Fargo.

• Lyris ListManager is a registered trademark of Lyris Technologies, Inc.

• BusinessObjects and WebIntelligence are a registered trademark of Business Objects SA.

Warranties & Disclaimers

The information contained in this publication may be out-of-date or include omissions, inaccuracies or other errors. Except where expressly provided otherwise in an agreement between you and TMA Resources, all information in this publication is provided “as is” without warranty of any kind. TMA Resources hereby dis-claims all warranties with respect to this information, whether express or implied, including the implied war-ranties of merchantability and fitness for a particular purpose.

In no event shall TMA Resources be liable for any direct, indirect, incidental, special or consequential dam-ages, or damages for loss of profits, revenue, data or use, incurred by you or any third party, whether in an action in contract or tort, arising from your access to, or use of this publication.

TMA Resources reserves the right to make changes or updates to this documentation at any time without notice.

(3)

Table of Contents

Personify API Overview... 1

Goals for the API ... 1

Library Hierarchy ... 2

The Core Layer... 3

Application ... 3

BusinessObjectCollection ... 3

BusinessObject ... 3

Schema and PropertyInfo ... 4

Functionality Implemented in the Core Layer ... 4

Authentication ... 4

Authorization ... 5

Caching... 5

Communicating with the Data Access Layer ... 7

Instantiating a Collection... 8

Filling a Collection with Data... 8

Modifying Data in a Collection ... 10

Sorting Collections ... 14

Finding an Object in a Collection ... 14

Overriding Context Values ... 14

Specifying Collection Filters... 14

Complex Search Queries... 15

The Generated Layer ... 16

API Model Files... 17

The Code Generation Process ... 17

Code Generation Tools... 17

Working with the Code Generator Interface... 17

Elements of the API Model... 19

Personify... 19 ObjectModel... 19 DataTypes ... 19 DataType ... 19 Namespaces... 20 Namespace... 20 Collection ... 20 Item... 21 Properties ... 22 Property ... 22 CapitalizationFacet ... 27 StringPaddingFacet ... 28 RegexValidationFacet... 28 DateFacet ... 28 Methods ... 28 Method... 28 Parameters ... 29

(4)

Item Interface... 30

The Base Layer ... 32

Division of Database Tables ... 32

Common Functions/Properties of API Collections... 33

CreateNew and AddNew ... 33

Fill ... 33

Accessing Dataset and DataRow Properties ... 33

Programming Tasks... 34

Existing Code Base... 34

Verifying the Code Generation Metadata... 34

Value Properties ... 34

Code Properties ... 35

List Properties ... 35

Applying Default Values... 35

Ensuring Referential Integrity... 35

Implementing Calculated Members ... 35

Providing Shortcut Methods and Properties ... 36

Understanding Validation Issues ... 37

A Validation Issue is a Class... 37

Naming Standards for Validation Issues... 37

Validation Issue Classes Are Not Generated Code ... 37

Validation Issues Are Not Messages ... 38

Validation Issues Are Not Exceptions ... 38

Validation Issues During Runtime... 39

Setting Message ID Numbers ... 39

Use of AutoResponses ... 39

Clearing Validation Issues ... 39

Continue Processing or Exit... 39

Validation Issue Infrastructure ... 41

Classes ... 41 AutoResponsesCollection... 41 IssueBase ... 41 IssueEventArgs... 43 IssueResponse ... 43 IssueResponsesCollection... 44 IssuesCollection... 44 IIssue ... 46 IIssuesCollection... 47 IssueSeverityEnum ... 49 StandardIssueResponseEnum ... 49

Core Validation Issues ... 50

PropertyMissingIssue... 50

BusinessObjectPropertyMissingIssue... 50

(5)

YesNoIssue... 50

DuplicateObjectIssue ... 50

Validation Issue Examples... 51

OrderInfo Validation Issue Examples ... 53

MeetingRegistrationIssue ... 53

ProductOutofStockIssue ... 53

InvalidDateRangeIssue... 57

CustomerInfo Validation Issue Examples ... 58

AddressValidationIssue ... 58 SegmentWithMembersDisabledIssue... 59 SegmentChangeWithMembersIssue ... 59 UpdateSubCustomerStatusToReflectMasterCustomerStatusIssue ... 59 MarkAddressAsBillToORShipToIssue ... 60 CreateMultipleLinksToPrimaryAddressIssue ... 60 EmailExistAsPrimaryForAnotherCustomerIssue ... 61 PrimaryEmployerAlreadyExistsIssue ... 61 PrimaryContactAlreadyExistsIssue... 61 DuplicateCustomerMatchesFoundIssue ... 62

(6)

Personify API Overview

The Personify (TIMSS) API is a .NET framework class library that provides programmatic access to your Personify database. The library encapsulates all business logic related to managing the association data model. The API library is used for all access to Personify data from the Personify application, eBusiness, and customers who develop customized

Personify applications. The TIMSS API supports customization of the data model and business rules at the code level through inheritance.

The goal of this document is to give you an in-depth look at how Personify uses its APIs and API libraries.

Goals for the API

The primary design goals for the API are:

• Centralized Business Logic – All of the logic needed to work with Personify is coded into API objects. This assists in user-interface development and gives you flexibility to create new interface.

• Shortening the Development Cycle – Assists in shortening the time-to-market for development activities.

• Product Stability – Reduces the efforts needed to stabilize the product.

• Encapsulation – Reduces the complexity of the system by giving programmers a clear path to navigate through objects in the system. This minimizes the amount of

information needed to make changes and reduces the number of steps needed to perform a task.

• Ease of Customization – Allows our programmers to modify the base system to meet your business needs.

• Flexible Configuration – Can be installed in a variety of network architectures.

Personify can be load-balanced and/or can work against a clustered database. It can also be made accessible to clients on the same LAN, from remote offices, or over the

(7)

Library Hierarchy

Library Hierarchy

To support development and customization, the API library is built in layers, providing increasing levels of specialization. In practice, the library is delivered as two distinct compiled binaries:

• TimssAPIBase.dll – The core and generated code. • TimssAPI.dll – The base code.

Currently, code for all subsystems is included in the binaries. This scheme must be modified to support proper packaging and deployment of the final product.

Base Layer Layer Generated Layer Core Customer Generated Layer

The Core, Generated, and Base layers can only be modified by TMA Resources programmers (the Professional Services team can also not modify these layers). The Customer Generated Layer can be modified by TMA Resources’ customers by using the Database Designer in Personify. The Database Designer contains the definitions for the tables and columns added by the end user. For more information on the Database Designer see the Personify Studio Tools User Guide.

(8)

The Core Layer

The Core Layer provides the infrastructure needed for an application to work with the Personify data model, as well as a set of base classes from which subsequent API layers derive. The Core Layer contains common Methods and Properties to control Retrieval, Validation, Saving, etc.

The Core Layer contains a set of generic data access classes that are able to interact with the TimssDB database access library. The primary generic classes are:

• TimmsCollection – This represents a bindable list of objects, equivalent to a table in a database.

• TimssObject – This represents a single item from a Collection, equivalent ot a row from a table in the database.

• TimssRelationship – This represents a parent/child relationship between two TimssCollection objects, equivalent to a foreign key constraint in the database. • TimssDataObject – This is a generic bindable component that contains one or more

TimssCollection objects. The function of the TimssDataObject is to provide late-bound access to TimssObjects at runtime.

• TimssSystem – This is a class that contains the methods needed to authenticate to a TIMSS database, activate remote server objects, provide design-time support, and encapsulate the reflection functionality needed for late-bound objects.

The following sections provide a brief description of the primary classes in the Core API.

Application

The Application class is the primary class in the API. The Application class handles all communications with the data access layer, manages the individual API layers, and provides authentication, authorization, state management, and caching services. The class is

implemented as a single instance, meaning there can only be one instance of an Application object for a given application domain (i.e., an instance of a Personify client application).

BusinessObjectCollection

The BusinsessObjectCollection class is the base class for all API Collections. A BusinessObjectCollection is analogous to a Table in a relational database. The BusinessObjectCollection class has properties and methods to manage fetching the appropriate data from the database, caching retrieved data, caching related data, reading table schema information, and inserting and deleting items from the collection.

BusinessObject

The BusinessObject class is the base class for all Item types in the API. A BusinessObject is analogous to a Row in a relational database. The BusinessObject class provides property access to the individual columns in the underlying row and standard business logic for

(9)

Functionality Implemented in the Core Layer validating property values, generating appropriate SQL statements to update the row in the database, and navigating to related collections and items.

Schema and PropertyInfo

The Schema and PropertyInfo classes provide metadata about the BusinessObjectCollection and BusinessObject classes. Each BusinessObjectCollection/BusinessObject combination shares a Schema object. A schema object is a collection of PropertyInfo objects, which provide metadata for each of the BusinessObject’s properties.

There are three categories of properties:

• Value properties – Correspond to columns in the BusinessObject’s underlying data row. Value properties include types such as String, Boolean, DateTime, Integer, and Decimal. They are bound to a database column.

• Code properties – Correspond to columns in the underlying data row and specify a Codes class that enumerates the valid values for that column. They are bound to a database column type of CODE_CODE.

• List properties – Return other BusinessObjectCollections or singular BusinessObjects. List properties are the implementation of relationships between tables in the database. • Transient properties – Provides a means to reference calculated or derived information

at runtime through a property statement. Transient properties are not stored in the database. They are based on business logic. Transient properties can be of a Value, Code, or List property.

For example, the Customer object represents a row in the CUSTOMER table. It has a LastName property, which is a Value property that refers to the LAST_NAME column. This is also a JobFunctionCode property, which is a Code property that refers to the

JOB_FUNCTION_CODE column. This verifies that valid values for this column are read from the APP_CODE table, where subsystem=CUS and type=JOB_FUNCTION. The

Customer class also has a Demographics property, which returns a CustomerDemographics collection. This is a List property that defines the relationship between the CUSTOMER and CUS_DEMOGRAPHICS tables.

Functionality Implemented in the Core Layer

Authentication

Authentication is handled by the PersonifyPrincipal and PersonifyIdentity classes, which implement the System.Principal.IPrincipal and System.Security.Principal.IIdentity interfaces respectively.

Authentication is initiated by a call to the Application.Connect() method. The Connect() method instantiates a new PersonifyPrincipal object. It passes the database name, UserId, and password on the constructor. The Validate() method of the PersonifyPrincipal object

(10)

performs the actual authentication. It selects the appropriate data from the SEC_USER and SEC_GROUP_MEMBER tables and instantiates the PersonifyIdentity object.

If authentication is successful (i.e., a record is retrieved from the SEC_USER table), the IsAuthenticated flag in the PersonifyIdentity interface is set to TRUE.

The IPrincipal interface requires a read-only property, Roles(), which is a string array listing the roles in which the particular user can participate. For the PersonifyPrincipal object, the ORG_ID, ORG_UNIT_ID, and USER_GROUP columns combine from

SEC_GROUP_MEMBER to create the entries in the Roles() array. For example, a user who is a member of the Admin user group in the NSSWP organization’s NSSWP org unit and is a member of the CALLCENTER group in the NSSWP’s FNDTN org unit, has two entries in the Roles() array: “NSSWP/NSSWP/ADMIN” and “NSSWP/FNDTN/CALLCENTER”. The Connect method sets System.Threading.Thread.CurrentPrincipal to the newly created PersonifyPrincipal object.

Authorization

User Authorization

Every call to the data access layer is authorized by the application object. Authorization is implemented in the application object’s AuthCheck() method. AuthCheck looks at the current thread’s identity object to ensure the IsAuthenticated flag is “TRUE.” It then uses the OrgId and OrgUnitId properties from the current context to find an entry in the current thread’s Principal.Roles() collection. If an entry is found, the request is authorized. As long as the user is a member of any group for the Organization/OrgUnit they wish to access, the request will pass.

Data Access Authorization

Every call to the data access layer requires an AccessToken object. The AccessToken contains the database name, user ID, and some encrypted data. It is created by the API.Core.Application object. The data access layer verifies the access token before processing the request and throws an InvalidAccessToken Exception if invalid. This

mechanism is meant to ensure the data access layer only accepts calls from the Application object. It allows you to have a stateless data access layer that does not have to

re-authenticate every request. The data access layer trusts the application object to handle authentication and authorization.

Caching

The API Core implements a variety of caching mechanisms to improve performance.

Type Cache

The Type Cache maintains a list of resolved API types (BusinessObjectCollections and BusinessObjects). It is implemented as a HashTable, keyed by the shortened API type name (the API Namespace and Class name, without the library prefix). As API types are resolved,

(11)

Functionality Implemented in the Core Layer they are added to the Type Cache, improving the performance of the API by reducing the need to search through the various API layers to find the most derived object type. The cache exists for the life of the application and items are never automatically cleared from it, however, the cache does have a Clear() method to allow it to be reset programmatically.

Schema Cache

The Schema Cache maintains the SQL table schemas for each API collection. It is

implemented as a Dataset that contains a DataTable for each referenced table. When a new collection is instantiated, it first looks for its table schema in the Schema Cache and if not found, the collection executes a “SELECT * FROM table name WHERE 1=2” statement in order to receive an empty table definition from the database. It then stores these results in the Schema Cache. The cache exists for the life of the application and items are never automatically cleared from it, however, the cache does have a Clear() method to allow it to be reset programmatically.

The table schema is fetched from the database at runtime, rather than simply relying on the schema information from generated code. This allows accessing customer columns on any table in the database without having to re-generate or re-compile the code.

Codes Cache

The Codes Cache stores data for classes that implement the ICode interface. These are lists containing name/value (or code/description) pairs and support enumeration and validation of code type properties. The cache is implemented as a HashTable, keyed by the individual code’s GetHashKey() function. Each ICode class is responsible for implementing the

appropriate GetHashkey() function that uniquely distinguishes its list from any other code list. The cache exists for the life of the application and items are never automatically cleared from it, however, the cache does have a Clear() method to allow it to be reset

programmatically.

Application-Level Data Cache

The Application-Level Data Cache is a data set intended to hold table data that does not change for the life of a particular application. The intent is to tag individual API collection types as able to be cached at the application level, which informs collections to first look at the Application-Level Data Cache when filling.

Collection-Level Data Cache

Every API collection has a private member variable called _Dataset, of type Dataset. When the collection is a Top-Level collection (i.e., it has no ParentObject), the _Dataset member is instantiated as a new Dataset and a table is added to hold the collection’s data. Any

descendent collections from the top-level collections set their _Dataset member to the Top-Level collection’s _Dataset and add their own data table to it if needed. For any API

collection, all of the collection’s data, as well as the data for any child collection, is stored in a single dataset. The tables in the dataset are named using the SQL table name and

properties derived from the same table share that table in the underlying dataset.

For example, if you are given an order that has the same BillTo and ShipTo customer, a new OrderMasters collection is instantiated, which creates a new dataset and adds an

(12)

ORDER_MASTER table to hold the order master data. When the BillToCustomer is referenced, since no customer data has yet been retrieved, a select statement is executed to retrieve customer data from the database. This data is stored in the CUSTOMER table of the OrderMasters collection’s dataset. When the ShipToCustomer property is referenced, since the customer ID points to the same customer, no data is retrieved from the database. The ShipToCustomer object is pointed to the same underlying row as the BillToCustomer.

Communicating with the Data Access Layer

All communications with the data access layer are done via two methods in the Application object, GetData() and SaveData(). Both methods pass an AccessToken and RequestSet to the corresponding method in the Data Access layer.

The AccessToken is described in the Data Access Authorization section of this document. The RequestSet object is a collection of RequestItem objects. A RequestItem object is an object that implements the IRequestItem interface. It embodies a SQL statement. The following classes implement IRequestItem:

BaseRequest Base class for request items.

DeleteRequest Executes a DELETE statement.

InsertRequest Executes an INSERT statement.

NextIdRequest Executes the AppNextNumber stored

procedure to receive an auto numbered column value.

RowCountRequest Issues a SELECT COUNT(*) statement.

SelectRequest Issues a SELECT statement.

SimpleRequest Executes a generic SQL statement. TableSchemaRequest Executes a SELECT*FROM table name

WHERE 1=2 to get an empty table schema. VersionCheckRequest Used to check CONCURRENCY_ID column

value.

Since the data access methods accept a RequestSet object, multiple independent requests can be bundled together and sent to the data access layer as a batch.

The data access layer executes each RequestItem in the RequestSet and records the results in a results dataset. For GetData() calls, the data access layer creates a table in the results dataset for each RequestItem. For SaveData() calls, the data access layer creates a table in the

(13)

Functionality Implemented in the Core Layer results dataset called “Results” in which it stores the status, number or rows effected, and response message for each request. The results dataset is returned to the API core as a ResultSet object.

The ResultSet object is an object that implements the IResultSet interface. The ResultSet is a wrapper from the .NET dataset and has two methods: Pack(oDataset As Dataset) and Unpack() As Dataset. The data access layer calls Pack() to store the results dataset in the ResultSet and the API Core calls Unpack() to retrieve the results dataset from the ResultSet. This wrapper provides a way to change the serialization mechanism used to pass data back to the API and to dynamically change serialization strategies depending on the details of a particular network architecture.

Instantiating a Collection

Instantiation of new collections is handled by one of the overloaded GetCollection() methods of the Application object. The GetCollection methods handle finding the most derived collection type and calling the collection’s constructor.

Our programmers never directly call New() on an API collection type, they use Application.GetCollection(). Calling New() means you instantiate a collection from a particular layer of the API, whereas GetCollection() ensures that an instance of the most derived type is returned.

GetCollection first looks at the Type Cache to see if an object of the request type is already instantiated. If so, a new object of that type is instantiated and returned. If not, the code searches for the appropriate type to return.

The code to search for an API type uses the entries in the <APILibraries> section of the app.config file. Each entry in this section specifies an assembly that contains API objects. The assemblies are searched in order until an object matching the specified criteria is found. Once found, the type is added to the type cache and returned.

This mechanism allows you to have any number of layers in the API, implement partial layers in multiple assemblies, and add/remove layers by modifying the app.config file.

Filling a Collection with Data

A collection is filled by calling one of its overloaded Fill() methods. The basic process for filling a collection is as follows:

1. Construct the SELECT statement.

The fill method first uses the state of the collection and any parameters passed to the method to construct a SELECT statement.

• The SELECT clause: Normally this is “SELECT*”. This is done so that any custom columns added to the collection’s table are picked-up. The exception is when the

(14)

FillMode flag on the collection is set to OnDemand. In this case the select clause only includes the columns that participate in the primary key of the table. Refer to <<FillMode>> for more information about the OnDemand fill mode.

• The FROM clause: This is always “From (table name)” using the collection’s Schema.TableName property. All joins are handled in the WHERE clause. • The WHERE clause: This is built by combining a variety of sources:

• Any filter criteria set by adding items to the collection’s FILTER property.

• Any filter criteria passed as a parameter to the fill method.

• If this collection is not a top-level collection (i.e., it has a ParentObject), the relationship that joins the parent to the child is added to the WHERE clause.

• Any values in the Application.Context dictionary that have the UseInQuery flag = TRUE and have a matching column name in the collection are added to the WHERE clause.

• The ORDER BY clause: if the SortProperty has been set on the collection, its column value is added as an ORDER BY clause to the select statement.

2. Check the local cache.

Once the select statement has been constructed, the fill method determines if there is already data in the local dataset that matches the criteria (See “Collection-Level Data Cache” on page 6). If the local dataset contains rows that match the selection criteria, that data is used to fill the collection and no call is made to the data access layer.

The check for local data uses the Select() method of the DataTable class, which does not support all possible SQL predicates. Any query that contains a BETWEEN, LIKE, or IN clause is not supported by the DataTable.Select() method and cannot be cached in the current implementation. Queries containing these predicates always issue a select statement against the database, regardless of whether or not data has already been retrieved.

3. Fetch the data from the database.

If there is no data in the local cache, or the selection criteria cannot be cached, a call is made to the Application.GetData() method, which constructs the AccessToken and RequestSet objects, passes the request to the DataAccess GetData() method, and unpacks the returned ResultSet into a Dataset. This data is then merged into the collection’s dataset.

4. Convert data rows to BusinessObjects.

Once the rows have been retrieved, either from cache or from a call to the database, the Fill() method calls FillList(), which creates an appropriately typed BusinessObject for each row in the results and adds that BusinessObject to the collection’s underlying list. The BusinessObjects are created by calling the Application.GetAPIItem() method for

(15)

Functionality Implemented in the Core Layer the type specified by the collection’s ItemType property. this ensures that the most-derived item type for that collection is the one that is created. This also means that the type of collection you are working with and the type of item it contains may by implemented in different layers of the API. For example, the Customer object may be overridden in a user layer, while the Customers collection has not been. In this case, you would have a collection of type Personify.API.Generated.CustomerInfo.Customer, but each item in the collection would be of type

Personify.API.User.CustomerInfo.Customer.

The BusinessObject is a wrapper that provides strongly-typed properties and business logic for an individual data row. The actual data for the business object is maintained in the data row and is pointed to via the BusinessObject’s SourceRow() property.

Modifying Data in a Collection

Creating New Objects

A new BusinessObject for a collection is created by calling the collection’s CreateNew() method. CreateNew() finds the appropriate item type for the collection, instantiates the new object, and returns it. The BusinessObject returned from the CreateNew() method is a stand-alone object and is not part of a collection. To add the object to the collection, use the Add() method. This adds the object to the collection and adds a new data row to the

collection’s data table to be inserted into the database. The CreateNew() and Add() methods have been combined into a single method AddNew(), which calls Add(CreateNew()). The following actions take place when a new BusinessObject is created:

• BuildRow() – This method creates the underlying data row in the collection’s data table. It set the AddedBy property (ADD_OPER column) to the current user, the AddedOn property (ADD_DATE column) to the current date/time, and the ConcurrencyId property (CONCURRENCY_ID column) to 0. BuildRow then calls SetDefaults() and NewKey() and propagates column values.

• SetDefaults – This method sets all default values for a BusinessObject. For Value type columns, the default value is taken from the default value defined for the property in the generated code. For Code (lookup) type columns, the particular code class’s

DefaultValue property is used. This value is typically read from the database at runtime.

To implement complex default value logic, our programmers override the SetDefaults() method, call MyBase.SetDefaults(), then implement the logic. This method is automatically called when a new object is created, but may also be called programmatically from a

(16)

• NewKey – This method ensures that the BusinessObject has a unique primary key. It takes an optional Boolean parameter (TemporaryKey), which tells the routine whether to create a temporary key or the final primary key for the object.

Temporary keys are used to minimize the number of round-trips to the database when creating objects. For integer and decimal columns, the code starts with the maximum value for an integer, then continually subtracts “1” from that value until it finds a value that is not already in use in the collection. For string columns, the logic is the same, but the numeric value is padded with “9s” and converted to a string. This is done to

minimize the possibility of key clashes with data that is already in the database and may be added to the collection by subsequent Fill() calls. When a TemporaryKey is created the HasTemporaryKey property of the BusinessObject is set to TRUE.

Final keys are set by calling the AppNextNumber() stored procedure in the database for any properties of the primary key marked as AutoNumbered. This happens

automatically when saving any object where the HasTemporaryKey is set.

Propagating Column Values

When BuildRow() is called for an object that has a ParentObject, the property values that participate in the foreign-key relationship with that parent object are automatically copied to the child object. In addition, any properties that have been marked with a

ValuePropagationRule in the code generation schema are also copied from the parent.

Modifying Existing Objects in a Collection

Modifications to an existing object is accomplished by setting the object’s properties. There are a number of automatic formatting and validation routines that can occur when a

property value is set. The rules are specified for the property in the code generation schema.

Formatting Rules

• Capitalization – Specifies that the property value should be converted to upper, lower, or proper case and whether to always perform the conversion or only when the existing value is null.

• String Padding – Specifies a character, padding direction, and length. Used primarily from “numeric” columns that are really strings (i.e., OrderNumber).

Validation Rules

• Minimum and Maximum Value – Applied to numeric values. An exception is thrown if the specified value falls outside the specified range.

• Minimum and Maximum Length – For string properties, if the value’s length is less than the minimum an exception is thrown. If it is longer than the maximum, the value is truncated.

• Regular Expression Matching – For string properties, if the string does not match the regular expression, an exception is thrown.

• Date Range – For date properties, specifies that a date may be in the Past, Present, and/ or Future. An exception is thrown if the specified date fails the rule.

(17)

Functionality Implemented in the Core Layer • Code List Validation – used for ICode type properties when the Validate() flag is TRUE.

If the value specified does not match a code from the ICode’s list, the value is ignored.

Deleting an Object from a Collection

An object is deleted by calling the collection’s Remove method. This removes the object from the collection and marks the underlying row for deletion when the collection is saved.

Validating the Data in a Collection

The Validate() method is used to determine if the data in a collection is valid. The Validate() method in the core BusinessObjectCollection calls the Validate() method on each item in its list. The Validate() method on the core BusinessObject class ensures that all required fields are set. When any of the Validate() methods encounter invalid data, a new entry is created in the ValidationIssues() collection on the top-level collection.

Saving Changes to a Collection

To commit collection changes back to the database the Save() method is called. Save() calls the Validate() method and if no validation issues are reported, Save() creates a new

RequestSet to hold the SQL commands to update the database. The collection then calls the GetCommands() method on each of its items. The GetCommands() method on the

BusinessObject creates an INSERT, UPDATE, or DELETE statement for the object and calls Save() for each of its child collections. Calling the Save() and GetCommands() methods in this way produces a hierarchically ordered set of SQL statements to update the root collection and all of its descendents. The collection then passes the RequestSet on to the Application.SaveData method, which appends the AccessToken and calls the SaveData method in the data access layer. The data access layer creates a new transaction and executes each statement in the request set. If any statement fails, the transaction is rolled back.

(18)
(19)

Functionality Implemented in the Core Layer

Sorting Collections

Collection sorting is accomplished by using one of the collection’s overloaded Sor()

methods. Sort() can be called with a property name and optional sort direction, an array of property names, or an array of PropertyInfo objects.

If the collection is already filled with data, the sort method re-sorts the items in the collection using the specified criteria. the sort criteria is also included as an ORDER BY clause when the collection is filled from the database. Specifying the sort criteria before filling the collection off loads the work of sorting the collection to the database server.

Finding an Object in a Collection

The BusinessObjectCollection.FindObject() and FindAll() methods find objects in an already filled collection. Both methods take PropertyName and Value as parameters. FindObject loops through the collection and returns the first item it finds that matches the criteria. FindAll returns all items that match the criteria. Both methods work only against data already in the collection, they do not fetch additional data from the database.

Overriding Context Values

The ApplicationContext object is a dictionary that contains values that are global to the currently running application. The collection’s Fill() method automatically applies any values in the context dictionary to the WHERE clause before fetching data from the

database. This is how collections are automatically filtered for the particular Org/OrgUnitId that the user is logged in to.

To prevent an item in the context from being used as a query filter, set the context item’s UseInQuery property to FALSE. For example, while the Customer table contains the columns ORG_ID and ORG_UNIT_ID, these columns are set to null for individuals and not used as filtering criteria. To fill a Customers collection with individuals, you must set Application.Context.OrgId.UseInQuery and Application.Context.OrgUnitId.UseInQuery to FALSE.

Specifying Collection Filters

A filter is a set of selection criteria that is applied to a collection prior to filling it with data. All collections are automatically filtered by the property values that specify the collection’s relation ship to its parent object and value in the application context.

Additional criteria may be specified by adding FilterItem objects to the collection’s Filter property. A filter item is an object that specifies a property name, a relational operator, and a value. For example, to fill a Customers collection with individuals who have a last name of “Smith”:

oCustomers=_App.GetCollection(“CustomerInfo.Customers”) oCustomers.Filter.Add(“LastName”,“Smith”)

oCustomers.Filter.Add(“RecordType”,”I”) oCustomers.Fill()

(20)

Filters are used to determine what data to select from the database.

Complex Search Queries

When a simple property filter on a collection is insufficient, a SearchObject is used. The SearchObject class is able to produce complex, joined queries that target a specific API collection type. To use the SearchObject, create a new instance of SearchObject, set the Target property to the type of API collection you are searching, and add values to the SearchObject’ s Parameter() property.

The following code searches for Customers with the last name of “Smith” who have a “good” address in the state of Maryland:

oSearch=New Personify.API.Core.SearchObject oSearch.Target=oApp.GetCollection(Personify.Enumerations.NamespaceEnum.Custo merInfo,”Customers”) oSearch.Parameters.Add(“LastName”,”Smith”) oSearch.Parameters.Add(“Addresses.State”,”MD”) oSearch.Parameters.Add(“Addresses.Detail.StatusCode”,”GOOD”) oSearch.search()

This creates a select statement with the appropriate WHERE clauses to join CUSTOMER to CUS_ADDRESS and CUS_ADDRESS to CUS_ADDRESS_DETAIL, as well as the specified search criteria. Executing the SearchObject’s Search() method fills the SearchObject’s Results() dataset with the selected rows. The SearchObject’s GetObjectKey() method can then be used to choose a particular row from the results and can be used to fill a collection.

(21)

The Generated Layer

The Generated Layer of the API builds directly upon the Core Layer and is the starting point for the definition of the Personify business model. Code generation works from a set of XML files, referred to as the API Model, which contain information about the tables and columns in the Personify database, as well has how those database entities are used to create the classes and properties of the API.

Advantages to generating the code in this manner are:

• Completeness – Every entity in the Personify database has a set of API objects that provide access to it.

• Consistency – Since every API class is coded in the same way, there is consistency across the library.

• Stability – Bugs in the generated code are apparent across all objects in the system and are easily identified and fixed. Bug fixes made in one location apply to all objects in the system.

• Accelerated Development – Repetitive coding tasks are handled by the generated code allowing you to focus on specialized business logic for individual classes.

The Generated library consists entirely of classes created with the API Generator tool. The generated library provides typing for underlying business objects, friendly names for database objects, creates default navigation paths between objects, and enforces referential integrity and data value constraints. The entire generated library can be frequently re-built at any time using the generator and this library should never include any manually written code.

For each table in the database, the generated library will contain:

• A class derived from the TimssCollection that represents the table using the pluralized friendly name for the object.

• The derived TimssCollection class will have data access methods to allow fetching appropriate data into this collection with the option to fill by primary key values or a set of filtering conditions.

• A class derived from TimssObject that represents a row from the table using the singular friendly name for the object.

• The derived TimssObject class will contain a friendly-named, strongly-typed property for each column in the table.

• For each child relationship defined in the schema, the derived TimssObject class will contain a shortened, friendly-named property that provides access to the foreign table object using the TimssObject instance as a parent.

(22)

API Model Files

The API Model is the input to the code generation process.

The Code Generation Process

Code generation is accomplished by applying an XSL transformation to the API model. In this way you can apply a different transformation to the same API model input to produce various work products.

The following transformations are used:

• Classes.xslt – Produces the VB source code that makes up the generated layer. • Interfaces.xslt – Produces the VB source code that makes up the interfaces library. • Documentation.xslt – Produces HTML class library documentation.

Code Generation Tools

There are three software components that make up the Personify code generation utilities. • CodeGen.dll – The main code generation library. This contains the methods responsible

for checking model files in and out of VSS, running the XSL transformations to generate the classes, interfaces and documentation, compiling the generated code, and

synchronizing the API model with the Personify database.

• CodeGenCMD.exe – A command line interface to CodeGen.dll. This utility is used to create the generated code at build time.

• CodeGenGUI.exe – A windows interface to CodeGen.dll. It is used to modify the API model and re-generate code for the development environment.

Working with the Code Generator Interface

Default Behavior

When the code generator starts, it connects to the VSS database using the current Windows user ID and loads the top-level model XML file.

Command Line Parameters

Our programmers can pass the following parameters to the utility: • SSDB – The path to the VSS database containing the model files. • SSUSER – The VSS user ID to use when connecting.

• SSPASSWORD – The VSS password to use when connecting.

• COREDEV – Allows you to modify model information without checking out files. This option is used for testing the generator utility and should not be used for actual

development.

• NOCONNECT – The UI does not automatically connect to the VSS. You must manually connect to VSS using the menu option.

(23)

API Model Files • NOLOAD – The UI does not automatically load the API model files. You must specify

the model files to load using the menu option.

• WSROOT – Identifies the root directory of the developer’s workspace. This should be the working directory that is mapped to the VSS root ($/) project.

(24)

Elements of the API Model

The following sections describe each element of the API Model.

Personify

The Personify element is the root of the API Model. • Parent Nodes – None

• Child Nodes – ObjectModel

• User Interface – Navigation only. There is no UI to directly edit this element.

ObjectModel

The ObjectModel element is the root element for all information related to generating code. • Parent Nodes – Personify

• Child Nodes – DataTypes, Namespaces

• User Interface – Navigation only. There is no UI to directly edit this element.

DataTypes

The DataTypes element contains a collection of DataType elements. • Parent Nodes – ObjectModel

• Child Nodes – DataType

• User Interface – Navigation only. There is no UI to directly edit this element.

DataType

Defines a common data type for use by properties in the API. The initial list of data types is derived from the date types defined in the SQL server. Data types do not directly produce any generated code. They are specify a reusable set of attributes and facets for value properties in the API.

• Parent Nodes – DataTypes

• Child Nodes – CapitalizationFacet, StringPaddingFacet, RegexValidationFacet, DateFacet

• User Interface:

Field Description

Name Name of the data type.

(25)

Namespaces

Namespaces

The Namespaces element contains a collection of Namespace elements. • Parent Nodes – ObjectModel

• Child Nodes – Namespace

• User Interface – Navigation only, there is no UI to directly edit this element.

Namespace

The Namespace element defines a Namespace in the API and corresponds directly to the Subsystems defined for Personify.

• Parent Nodes – Namespaces

• Child Nodes – Collection, Item, Exception, ValidationIssue • User Interface:

Collection

Defines an API Collection class. A Collection class corresponds to a table in the SQL server and inherits from Core.BusinessObjectCollection. For every Collection element, there is a matching Item element that defines the individual column properties for the table.

• Parent Nodes – Namespace

• Child Nodes – Properties, Methods, Events

Base Type API data type that is the basis for this type. Default Value Default value for the data type.

Min Length For String based types, the minimum length of the string. Max Length For String base types, the maximum length of the string. Min Value For Numeric types, the minimum value of the number. Max Value For Numeric types, the maximum value of the number.

Field Description

Name Name of the namespace.

Abbreviation Subsystem abbreviation for the namespace.

License Key Holds information for enforcing licensing restrictions for API modules.

(26)

• User Interface:

Item

Defines an Item class for the API. An item class corresponds to a Row in a SQL Server table and inherits from Core.BusinessObject.

• Parent Nodes – Namespace

• Child Nodes – Properties, Methods, Events

Field Description

Name The name of the API Collection class.

Item Type The name of the API Item class that corresponds with this collection.

Interface Name The name of the API Interface for this class is always the same as the Collection class name (with the letter “I” prefixed).

Item Interface The name of the API Interface for this class is always the same as the Item Type name (with the letter “I” prefixed).

Table Name The name of the SQL server table that this collection represents. Access The access modifier for the generated collection class: Public,

Friend, Protected, or Private. Defaults to Public. Caption English caption for the class.

Description Description of the class.

Read Only Specified whether items in the collection may be modified. This flag controls the _DisableAdd, _DisableEdit, and

_DisableRemove flags on the base BusinessObjectCollection. Top-Level Collection Intended to indicate whether this collection may be instantiated

as a standalone object, or only as the child of another object. At this time, all collection types may be standalone and this flag is not referenced.

Primary Collection for Namespace

Intended to indicate that this collection is the primary collection (first-order object) of its namespace. Useful for dynamically generating user interface code, but not currently referenced anywhere.

Publish Specifies that this collection is to be included in the generated code.

(27)

Properties • User Interface:

Properties

A collection of Property elements. • Parent Nodes – Collection, Item • Child Nodes – Property

• User Interface – Navigation only, there is no UI to directly edit this element.

Property

This represents a property on a class in the API.

There are four kinds of properties that can be represented in the model:

1. Value Properties – Value properties correspond directly to Columns in the SQL Server database. They represent simple data elements. Value property definitions may include one or more facets that supply additional formatting or validation rules for the

property. Currently the available facets are CapitalizationFacet, StringPaddingFacet, RegexValidationFacet, and DateFacet..

Field Description

Name Name of the API Item class.

Collection Type Name of the corresponding collection class for the item. Interface Name Name of the API Interface for the item.

Collection Name Name of the API Interface for this item’s collection type. Table Name Name of the SQL Server table for which this item represents a

single row.

Field Description

Name The name of the property.

API Type API (VB) data type of the value. Access Object access to the property.

Column Name The SQL Server column name corresponding to the property. Caption The generic caption name for the property.

SQL Type SQL Server data type for the column.

Description A brief description, for documentation purposes, of the property. Default Value The default value for the property.

(28)

2. Code Properties – Code properties correspond to Columns in a table, but they include information about the enumerated (lookup) values for that column. This is used for

Read-Only This specifies that the property should be generated as a

“ReadOnly” property. The API does not expose a means of setting the property.

Read-Only on Insert This specifies that the value may not be changed when the object is in the “Inserted” state.

Inserted means that the item has been created and added to the collection, but the collection has not yet been committed to the database. This flag does not generate a “ReadOnly” property; a property set statement is still created when this value is True, but the logic in the core prevents changes to this property when in Inserted mode.

Read-Only on Update This specifies that the value may not be changed after the original object has been committed to the database. This provides the ability to create “Write-Once” properties.

Required This specifies that this property is required. All non-nullable columns in SQL Server are marked as Required.

Enforce Uniqueness This specifies a unique constraint for this property within its collection. When this flag is checked, the core checks to ensure any value entered into this property does not already exist in the underlying table.

Key Position This indicates that this property is part of the table’s primary key and, if so, its position in the key. The first column in the table’s primary key should have a value of “1.” A value of “0” means that this property is not part of the key.

Auto Numbered For key properties, this specifies that the column is to be

automatically numbered (using the APP_NEXT_NUMBER table). Length: Min and Max For string properties, this specifies the minimum and maximum

length of the string.

Value: Min and Max For numeric properties, this specifies the minimum and maximum value of the number.

Development Status Displays whether the work on this API property is Completed, In Progress, or Pending.

(29)

Property columns that implement the ICode interface. A code property must have a CodeInfo child node that defines the parameters for the ICode object.

Name The name of the property.

API Type API (VB) data type of the value. Access Object access to the property.

Column Name The SQL Server column name corresponding to the property. Caption The generic caption name for the property.

SQL Type SQL Server data type for the column.

Description A brief description, for documentation purposes, of the property. Default Value The default value for the property.

Code Type This identifies the Code Class (i.e., the class that implements the ICode interface) that handles the code. The code type is the return type for this property.

Read-Only This specifies that the property should be generated as a

“ReadOnly” property. The API does not expose a means of setting the property.

Required This specifies that this property is required. All non-nullable columns in SQL Server are marked as Required.

Key Position This indicates that this property is part of the table’s primary key and, if so, its position in the key. The first column in the table’s primary key should have a value of “1.” A value of “0” means that this property is not part of the key.

Auto Numbered For key properties, this specifies that the column is to be

automatically numbered (using the APP_NEXT_NUMBER table). Development Status Displays whether the work on this API property is Completed, In

Progress, or Pending.

3. List Properties – List properties correspond to relationships between tables in the database. For example, the CUSTOMER CUS_DEMOGRAPHIC relationship in the database is represented by the Demographics property of the Customer object in the API. A list property definition must have a Relationship child node that defines the relationship.

Field Description

Field Description

Name The name of the property.

(30)

Caption The generic caption name for the property.

Description A brief description, for documentation purposes, of the property. Target Namespace Namespace of the API object that this property references. Target Collection Class name of the collection type that this property references. Min Cardinality The minimum number of items that this property refers to. If this

is not required, enter “0”.

Max Cardinality The maximum number of items that this property refers to. If there is no limit, enter “0”.

Cascade Insert Indicates that a new item should be created when the parent is created.

Cascade Delete Indicates that the items referenced by the property should be deleted when the parent is deleted.

(31)

Property

Related Properties Table Defines the relationship (i.e., the foreign-key) from this object to the target. This table has four columns:

• SourceProperty – The name of the parent object. • TargetProperty – The name of the property of the child

object.

• IsJoinKey – Specifies that the Source/Target pair is part of the foreign-key relationship. Values that have IsJoinKey set are used by the Core to create the inner join clauses needed to fill collections.

• ValuePropagationRule – Specifies the rule to use for copying property values from parent to child when inserting or updating the parent.

Options are:

• Always – Overwrites the value in the child object with the value in the parent object.

• IfNull – Copies the value from the parent to the child only if the value is null on the child object.

• IfSame – Copies the value from the parent to the child only when the value on the child is the same as the original value on the parent.

• IfNullOrSame – Copies the value from the parent to the child if the value is null on the child object or if the value on the child is the same as the original value on the parent.

• Never – Does not copy values from the parent to the child.

For properties that are part of the join key, the value propagation rule must be Always (i.e., being part of the join key means that the values must match between parent and child and any changes to the parent are reflected in the child). Other properties that are not part of the join key may be specified on the relationship. For example, the OrgId column. The OrgId column is not part of the table’s key, but when set on a parent object, you want the value to be reflected on all child objects.

(32)

4. Transient Properties – A transient property provides a means to reference calculated or derived information at runtime through a property statement. Transient properties are not stored in the database.

Name The name of the property.

Member Name The name for the private member variable that is generated to hold this property’s value.

Return Type The data type of the property. Default Value The default value for the property. Access Object access to the property.

Caption The generic caption name for the property.

Description A brief description, for documentation purposes, of the property. ReadOnly This specifies that the property should be generated as a

“ReadOnly” property. The API does not expose a means of setting the property.

Overridable Determines whether the property’s calculated information can be overridden.

CapitalizationFacet

A CapitalizationFacet specifies capitalization rules for string-based, value properties. • Parent Node – Property

• Child Nodes – None • User Interface:

Field Description

Field Description

Capitalize Specifies how to capitalize the string: • Preserve – Take no action on the string. • Upper – Convert to upper case.

• Proper – Convert to property (i.e., Name) case. • Lower – Convert to lower case.

Apply Rule Specifies how the capitalization rule is applied. • Always – The rule is always applied.

• One Time – The rule is only applied when the property value is changed to a different string (not just a different case of the string).

(33)

StringPaddingFacet

StringPaddingFacet

Applies a padding character, with an optional prefix, to the string value using the max length specified on the string property. For example, if the OrderNumber property has a padding character of “0”, a prefix of “1”, and a direction of left, when the value “1234” is entered for an order number, the value will be converted to “1000000001234”.

• Parent Nodes – Property • Child Nodes – None

RegexValidationFacet

Specifies a regular expression that must be matched when setting the property’s value. If the new value does not match the expression, an exception is thrown.

• Parent Nodes – Property • Child Nodes – None

DateFacet

Applies to value properties that are based on the Date data type. This facet provides runtime checking of a date value relative to the current date. For example, this could be used to require that a BirthDate property not be able to be set to a future date.

• Parent Nodes – Property • Child Nodes – None

Methods

A collection of Method elements. • Parent Nodes – Collection, Item • Child Nodes – Method

• User Interface – Navigation only, there is no UI to edit in this element.

Method

This element allows you to specify a method to generate on the class. The code generator uses the information to create an empty Sub or Function in the generated class. Actual implementation of the method must be done by overriding the method in the base layer.

• Parent Nodes – Methods • Child Nodes – Parameters

(34)

• User Interface:

Parameters

This element represents a set of parameters that are passed to a method or event. It is used to generate the method signature for methods and events.

• Parent Nodes – Method, Event • Child Nodes – Parameter • User Interface:

Field Description

Name The name of the method.

Return Type The data type returned by the method. If none is specified the method is generated as a Sub rather than a Function.

Access Code access to the method.

Overloaded Specifies whether or not there is overloaded parameter sets for this method.

Field Description

Name The name of the parameter.

Type The data type of the parameter.

Optional Indicates an optional parameter.

(35)

Collection Interface

The Interfaces Library

The code generator creates the Interfaces library at the same time as the generated layer. The library contains an interface definition for each collection type and for each item type. These interfaces are a part of making the multi-layered API work. When working with objects in any layer of the API, you always reference the interface rather than the class definition. This allows the actual implementation of that object to reside in any layer of the API.

Collection Interface

This is a typical interface created for the AbstractAuthors BusinessObjectCollection:

Public Interface IAbstractAuthors

Inherits Personify.API.Core.IBusinessObjectCollection

Default Shadows ReadOnly Property Item(ByVal nIndex As Integer) As IAbstractAuthor

Function CreateNew() As IAbstractAuthor Shadows Function AddNew() As IAbstractAuthor

Shadows Function Add(ByVal Item As IAbstractAuthor) As Integer Shadows Sub Remove(ByVal Item As IAbstractAuthor)

Overloads Sub Fill(By Val AbstractId As Long,_By Val MasterCustomerId As String, ByVal SubCustomerId As Integer)

End Interface

Item Interface

This interface is created for the AbstractAuthor BusinessObject:

Public Interface IAbstractAuthor

Inherits Personify.API.Core.IBusinessObject Property AbstractId() As Long

Property MasterCustomerId() As String Property SubCustomerId() As Integer

Property RoleCode() As Personify.API.Core.ICode Property RoleSinceDate() As Date

Property ListingOrder() As Decimal Property Honorarium() As Decimal Property Comments() As String

Property AllowToPublishFlag() As Boolean Property AllowToRecordFlag() As Boolean Property AllowToPhotographFlag() As Boolean Property AllowToInterviewFlag() As Boolean ReadOnly Property AddedBy() As String ReadOnly Property AddedOn() As Date ReadOnly Property ChangedBy() As String ReadOnly Property ChangedOn() As Date ReadOnly Property ConcurrencyId() As Long

(36)

Property CorrespondingAuthorFlag() As Boolean End Interface

(37)

Division of Database Tables

The Base Layer

The Base Layer of the API is where business logic is implemented. All code in the base layer is hand-written; it contains no generated code. To implement specific logic for a particular business object or collection, a developer must create a new class that inherits from the business object and overrides existing properties or methods.

The base layer can be used to enforce complex business rules, override default behavior in the generated library, create custom classes, properties, relationships, etc. For example, the base layer could contain a class called Individuals that derives from the Customers class and enforces the rule that the RecordType property is set to “I”.

The base library is also where complex logic such as calculating order discounts, tax, shipping, etc. are coded.

Division of Database Tables

Each table is mapped to a collection in the API. The table is placed in its appropriate namespace based upon the subsystem to which it belongs.

The following table shows some example of the tables and where they are placed in the API structure.

Product Product Timss.TimssAPI.ProductInfo.Product

Order_Master Order Timss.TimssAPI.OrderInfo.OrderMaster Lck_Holding_Detail LockBox Timss.TimssAPI.LockBoxInfo.LockBoxHolding

Detail

Customer Customer Timss.TimssAPI.CustomerInfo.Customer Member_Group Membership Timss.TimssAPI.MembershipInfo.Membergrou

p

(38)

Common Functions/Properties of API

Collections

CreateNew and AddNew

This creates a new instance of the object contained in the collection class. For example, OrderMasters.CreateNew creates a new instance of the OrderMaster object. Use this in conjunction with AddNew to save new records in the database. In another example, to save a new customer record, the following code needs to be written:

Dim mcolCustomers as New Timss.TimssApi.Customers.Customer(AppContext) Dim moCustomer as Timss.TimssApi.Customers.Customer

moCustomer=mColCustomers.CreateNew() moCustomer.MasterCustomerId = ‘0001’ moCustomer.SubCustomerId = 0 mcolCustomers.AddNew(moCustomer) mcolCustomers.Save

Fill

This method fills a collection (for example, fetching data from the database table). This function is overloaded to facilitate data fetching with almost any condition (for example, fetching all orders created on July 1, 2008):

Dim mColOrderMasters as New Timss.TimssAPI.Order.OrderMasters(AppCOntext) Dim oFilter as new Timss.ApiBase.TimssFilter

oFilter.Add(“order_date”, 07-01-2008) mColOrdermasters.fill(nothing, oFilter)

To fetch a specific customer record:

Dim moColCustomers as new Timss.Api.Customers.Customer(AppContext) moColCustomers.Fill(“1234”, 0)

Accessing Dataset and DataRow Properties

The structure of the API is based on the dataset. The collections are directly mapped to the data tables and the data rows are directly mapped to the objects. Essentially, the underlying engine that supports the API structure is a Dataset. For example, accessing a dataset would resemble “OrderMasters.Dataset” and accessing a data row would resemble

(39)

Programming Tasks

Programming Tasks

The following highlights the tasks that are performed by the developer for each API collection/object.

Existing Code Base

The existing Personify windows application remains the primary source of information for coding the base API objects. However, since the individual screens are responsible for data access, user interface management, and business logic, it is often difficult to determine the parts of the logic in the screens that need to go to the API.

The following are some guidelines to help make that determination:

• Code that deals with data access (i.e., selecting data from a table, initiating a database transaction, committing changes to the database, etc.) is handled by the API core and should not be coded into the base. However, if there is code to select dependent data from the database given the state of the object in focus, you should make sure that a List Property exists on the API object to retrieve the dependent collection.

• Code that deals with selecting data to populate combo boxes, list boxes, or other enumeration type controls should not be coded into the base. You must ensure that an ICode property exists and is configured correctly for that enumerated data.

• Code that deals with formatting and validating data should be included in the code generator schema, if possible, and coded into the base layer if not possible.

• Code that deals with retrieving a new key for a data row should not be ported (this is covered by the API core).

• Code that manipulates the visible or enabled properties of controls on a form should be given careful consideration. Often these are indicators that a particular property may not be modified for a given state. If so, this code should be ported to mark the property as ReadOnly in the same way the control was disabled.

• Code that creates new data rows given the state of a particular parent row should be ported to the base code. This code should be implemented on the property “get” statement for the child object.

• Code that deletes rows from the database should not be ported. • Code that deals with QBE should not be ported.

Verifying the Code Generation Metadata

Since the majority of the metadata used to create the generated layer has been reverse-engineered from the database, it is important to review and verify its correctness.

Value Properties

Each value property on an object should be reviewed to determine that it has the correct data type, has the correct default, min and max values, and that it’s “required” and “autonumber” flags are correctly set.

References

Related documents

Minors who do not have a valid driver’s license which allows them to operate a motorized vehicle in the state in which they reside will not be permitted to operate a motorized

4 (c) shows optical micrographs of friction stir weld AA6061 at heat affected zone from the micrograph it can be observed that grains are slightly elongated. 4

Em informática, fazem parte da memória de um computador todos os um computador todos os dispositivos que são usados para armazenar dados e instruções, seja de forma dispositivos que

Building on the family-centered, evidence-based initiatives present in many communities, such as Even Start Family Literacy Partnerships, Head Start, Family Resource

Such agreements are often defined by service level agreements (SLAs), which indicate the quality of service that the provider will guarantee, or peering contracts, which define

Jako náhradu využili autoři [26] MS-SSIM (Multiscale Structural Similarity) v upravené verzi, autory nazývané PU2MS-SSIM, kde PU značí perceptually uniform

In liver cancer, accumulating evidence has demonstrated the existence of a small subset of cancer cells with stem cell properties (self-renewal and differentiation) and several

When COPUs compared with COPUs-C30B nanocomposites (Fig. 3 ), presence of small bands at 1,560–1,680 cm -1 was observed, which is related to the stretching vibrations of hydrogen