Understanding the Personify API
Short Description
Download Understanding the Personify API...
Description
Understanding the Personify API January 2009
TMA Resources • 1919 Gallows Road • Suite 400 • Vienna, VA 22182 • www.tmaresources.com
Copyright Information ©2009 TMA Resources, Inc. All rights reserved. Produced in the United States of America. 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 disclaims all warranties with respect to this information, whether express or implied, including the implied warranties of merchantability and fitness for a particular purpose. In no event shall TMA Resources be liable for any direct, indirect, incidental, special or consequential damages, 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.
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
©2009 TMA Resources, Inc.
Proprietary & Confidential
i
The Interfaces Library ...................................................................................... 30 Collection Interface ................................................................................................... 30 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 InvalidPropertyValueIssue ................................................................................ 50
©2009 TMA Resources, Inc.
Proprietary & Confidential
ii
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
©2009 TMA Resources, Inc.
Proprietary & Confidential
iii
Goals for the API
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 internet.
©2009 TMA Resources, Inc.
Proprietary & Confidential
1
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. Customer Generated Layer Base Layer Generated Layer Core 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.
©2009 TMA Resources, Inc.
Proprietary & Confidential
2
Library Hierarchy
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
©2009 TMA Resources, Inc.
Proprietary & Confidential
3
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
©2009 TMA Resources, Inc.
Proprietary & Confidential
4
Functionality Implemented in the Core Layer
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 reauthenticate 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,
©2009 TMA Resources, Inc.
Proprietary & Confidential
5
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 TopLevel 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
©2009 TMA Resources, Inc.
Proprietary & Confidential
6
Functionality Implemented in the Core Layer
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: Class
Description
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
©2009 TMA Resources, Inc.
Proprietary & Confidential
7
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 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
©2009 TMA Resources, Inc.
Proprietary & Confidential
8
Functionality Implemented in the Core Layer
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 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
©2009 TMA Resources, Inc.
Proprietary & Confidential
9
Functionality Implemented in the Core Layer
the type specified by the collection’s ItemType property. this ensures that the mostderived 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 property set routine when a property change will result in a change in default values.
©2009 TMA Resources, Inc.
Proprietary & Confidential
10
Functionality Implemented in the Core Layer
• 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.
©2009 TMA Resources, Inc.
Proprietary & Confidential
11
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.
©2009 TMA Resources, Inc.
Proprietary & Confidential
12
Functionality Implemented in the Core Layer
The following flow chart demonstrates the Save() method.
©2009 TMA Resources, Inc.
Proprietary & Confidential
13
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()
©2009 TMA Resources, Inc.
Proprietary & Confidential
14
Functionality Implemented in the Core Layer
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.
©2009 TMA Resources, Inc.
Proprietary & Confidential
15
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.
©2009 TMA Resources, Inc.
Proprietary & Confidential
16
API Model Files
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.
©2009 TMA Resources, Inc.
Proprietary & Confidential
17
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.
©2009 TMA Resources, Inc.
Proprietary & Confidential
18
Personify
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.
SQL Name
Name of the type define in the SQL Server.
©2009 TMA Resources, Inc.
Proprietary & Confidential
19
Namespaces
Field
Description
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.
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: Field
Description
Name
Name of the namespace.
Abbreviation
Subsystem abbreviation for the namespace.
License Key
Holds information for enforcing licensing restrictions for API modules.
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
©2009 TMA Resources, Inc.
Proprietary & Confidential
20
Item
• User Interface: 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.
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
©2009 TMA Resources, Inc.
Proprietary & Confidential
21
Properties
• User Interface: 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.
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
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.
©2009 TMA Resources, Inc.
Proprietary & Confidential
22
Property
Field
Description
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.
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
©2009 TMA Resources, Inc.
Proprietary & Confidential
23
Property
columns that implement the ICode interface. A code property must have a CodeInfo child node that defines the parameters for the ICode object. 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.
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
Name
The name of the property.
Access
Object access to the property.
©2009 TMA Resources, Inc.
Proprietary & Confidential
24
Property
Field
Description
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.
©2009 TMA Resources, Inc.
Proprietary & Confidential
25
Property
Field Related Properties Table
Description 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.
©2009 TMA Resources, Inc.
Proprietary & Confidential
26
CapitalizationFacet
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. Field
Description
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
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).
©2009 TMA Resources, Inc.
Proprietary & Confidential
27
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
©2009 TMA Resources, Inc.
Proprietary & Confidential
28
Parameters
• 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.
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 parameter.
Type
The data type of the parameter.
Optional
Indicates an optional parameter.
Default Value
Defines the default value for optional parameters.
©2009 TMA Resources, Inc.
Proprietary & Confidential
29
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 Property Property Property Property Property Property Property Property Property Property Property ReadOnly ReadOnly ReadOnly ReadOnly ReadOnly
AbstractId() As Long MasterCustomerId() As String SubCustomerId() As Integer RoleCode() As Personify.API.Core.ICode RoleSinceDate() As Date ListingOrder() As Decimal Honorarium() As Decimal Comments() As String AllowToPublishFlag() As Boolean AllowToRecordFlag() As Boolean AllowToPhotographFlag() As Boolean AllowToInterviewFlag() As Boolean Property AddedBy() As String Property AddedOn() As Date Property ChangedBy() As String Property ChangedOn() As Date Property ConcurrencyId() As Long
©2009 TMA Resources, Inc.
Proprietary & Confidential
30
Item Interface
Property CorrespondingAuthorFlag() As Boolean End Interface
©2009 TMA Resources, Inc.
Proprietary & Confidential
31
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. Table Name
Subsystem
Namespace
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
©2009 TMA Resources, Inc.
Proprietary & Confidential
32
Common Functions/Properties of API Collections
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 “OrderMasters.Item(0).SourceRow”.
©2009 TMA Resources, Inc.
Proprietary & Confidential
33
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 reverseengineered 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.
©2009 TMA Resources, Inc.
Proprietary & Confidential
34
Programming Tasks
Code Properties Each code property on an object should be reviewed to determine that it has been configured correctly. For codes that are read from the APP_CODE table, this means checking that the Subsystem and Type parameters on the code set to their correct values and that the Option1/2/3 parameters are referenced if they are used for that code.
List Properties Each list property on an object should be reviewed to ensure that the cardinality is set correctly, that it is returning the correct API type, and that the join key is set up correctly. For zero-to-one or one-to-one relationships, the return type of the list property should be the interface name of the related properties item type. For zero-to-many or one-to-many relationships, the return type should be the interface name of the collection type for the related property. For example, the relationship of Customer to Demographics is one-tomany, therefore the property should return a type of Personify.API.CustomerInfo.CustomerDemographics. The relationship of Customer to Employer is one-to-one, therefore the property should return a type of Personify.API.CustomerInfo.ICustomer.
Applying Default Values Most of the defaults for value properties can be set in the metadata for the generated code. There are cases, however, where default values are dependent on other properties within the object or one of its related objects. In those cases, the SetDefaults() method should be overridden and the logic for defaulting the value should be implemented there. Since SetDefaults() is called as soon as the object is created, you may also call it at some later point when more knowledge about the object is available.
Ensuring Referential Integrity A large portion of the base code should be devoted to ensuring referential integrity among API objects. This means that your code should handle automatically verifying, and possibly creating or deleting, related objects in response to actions against an object. For example, a row in the PRODUCT table requires there to be one, and only one, related entry in one of the product subsystem tables (INV_PRODUCT, MBR_PRODUCT, SUB_PRODUCT, etc.) depending on the subsystem of the product. Consequentially, when the Subsystem property of the Product object is changed, logic in the Product object must verify that one of the product subsystem properties (InventoryProduct, MembershipProduct, SubscriptionProduct, etc.) contains a valid entry. The code must determine when it is appropriate to change the Subsystem property, take the appropriate action when the property is changed, or disallow the property change when that action would violate integrity rules.
Implementing Calculated Members It is the responsibility of the developer to implement business logic that calculates values for API objects. Calculated members are modified based on changes to one or more properties
©2009 TMA Resources, Inc.
Proprietary & Confidential
35
Programming Tasks
of the object. If multiple properties are involved, the code that calculates the member should be placed in a separate function. This function is then called from each of the properties’ set methods. Many methods should be callable independently of the standard interface methods. An indicator of this is whether or not the existing user interface has a button to perform the method’s action. Methods such as CalculateShipping(), CalculateTax(), RecalculateOrder(), etc. are such methods. These should be marked as Public and Overridable, so that they can be called independently of the standard interface and their behavior may be overridden by a subsequent API layer.
Providing Shortcut Methods and Properties Short-cut methods and properties encapsulate complex interactions into easier to use methods. However, they should never be used as a replacement for the standard interface methods. Examples of shortcut methods are: • OrderMaster.AddProduct() – Adds a new order detail line to an order using the specified product. • Customer.PrimaryAddress() – Retrieves the primary address for a customer. • Customer.MemberSince() – Provides a date value that represents when this customer became a member.
©2009 TMA Resources, Inc.
Proprietary & Confidential
36
Understanding Validation Issues This section describes the infrastructure for validation processing in Personify.
Definitions of Terms Used in this Section Term
Definition
API Developer
An internal TMA Resources programmer who implements business logic in the API. This logic may be implemented in the Base layer or any subsequent layers.
Consumer
Any program that makes use of the Personify API (e.g., the user interface, a batch process, or any customer program accessing the API).
Customer
For the purposes of this section, the programmer responsible for implementing the consumer. This could be an internal TMA Resources programmer, or an external developer working on some other application referencing the API.
Validation Issue
An object that represents additional information, a warning, a problem that must be addressed by the consumer, or a question that requires a response from the consumer.
A Validation Issue is a Class In the Personify API, Validation Issues are implemented as classes that inherit from TIMSS.API.Core.IssueBase. They can be implemented in any layer of the API, but will most likely be implemented in either the Core (in the case of a generic issue) or in the Base layer.
Naming Standards for Validation Issues Validation Issues can be identified easily. TMA Resources has created all of its Validation Issues to end in the word “Issue”. For example, “OrderInfo.ProductOutofStockIssue”, “CustomerInfo.InvalidAddressIssue”, etc.
Validation Issue Classes Are Not Generated Code Previously, Validation Issues were created as part of the code generation process in Personify, however, this is no longer practiced by TMA Resources programmers. Generic issues (i.e., issues that display simple informational messages or a simple yes/no response) are coded in the Core layer of the API. Validation Issues that are not simple must be manually coded by the API developer in the base or subsequent layers. However, manually created base layer validation issue classes should always inherit from the Core layer.
©2009 TMA Resources, Inc.
Proprietary & Confidential
37
Validation Issues Are Not Messages Personify Validation Issues are not simply message strings. They are a stand-alone class implemented in the API and can have their own properties and methods, implement complex behaviors, and provide multiple messages to the consumer. A single issue can be coded to report issues for a variety of situations. For example, for a subscription product there can be a number of problems regarding the start and end dates (start date greater than end date, start date missing, end date missing, etc.). All of these issues can be handled by a single Validation Issue class that accepts the StartDate and EndDate values. The issue class then determines the appropriate message to display. Therefore, there is no need to create issue classes for each specific message.
Validation Issues Are Not Exceptions Validation Issues are used to report/react business logic errors, while Exceptions are used to report/react system errors. When an Exception is thrown, it means that you have stepped out of the path of the code and an unexpected situation has occurred. In the case of a Validation Issue, a problem may have occurred but it is something that could normally happen during the course of running the program. The API will identify Validation Issues, create the appropriate issue class alerting the consumer of the issue, and take the default action.
©2009 TMA Resources, Inc.
Proprietary & Confidential
38
Validation Issues During Runtime Validation Issues are created at runtime by the API wherever the API developer saw fit to raise an issue. Each top-level BusinessObjectCollection in the API has a ValidationIssues collection property containing all of the outstanding issues for that collection, any child collections, and any respective BusinessObjects in those collections. Additionally, the API developer can also access Validation Issues belonging to a specific Business Object.
Setting Message ID Numbers The IssueBase class accepts a message ID on one of its overloaded constructors. Classes that inherit from IssueBase are coded with the specific message ID numbers they are using in the issue class. Message IDs used in issue classes are referenced by private constants in the issue class. If additional messages are needed within the issue, the API core Application.GetMessage() function provides cached access to messages based on MessageId and Subsystem.
Use of AutoResponses The core Application object has an AutoResponses property containing a collection of automatic issue responses. It is the responsibility of the consumer to populate the collection of autoresponses.
Clearing Validation Issues Issues that do not require a response are automatically cleared by the base Validate() method before it performs its validation. In addition, the Assert() function clears its issue when the condition passed to the assert method is false.
Continue Processing or Exit For some issues, further processing is stopped when the issue is encountered. For example, when trying to calculate a shipping amount, if no shipping address is specified, an issue is raised and processing is stopped. For other issues, the issue will be raised and processing continues. For example, if you are creating a LabelName for a customer and the LastName property is missing, you can still continue producing the LabelName while taking the missing information into account. It is the responsibility of the API developer to determine whether or not processing should continue when a particular issue is encountered and this is dependent upon the severity of the issue and the cost of continuing the operation. If the issue is an informational message or warning message that does not require a response, the program should continue with its processing.
©2009 TMA Resources, Inc.
Proprietary & Confidential
39
If the issue is an Error condition, the program will most likely not be able to continue. If the issue is a Question (i.e., a prompt to the consumer), the process may continue with a default response to the issue or exit the process and re-evaluate the issue when next called.
©2009 TMA Resources, Inc.
Proprietary & Confidential
40
Classes
Validation Issue Infrastructure The following identify the classes that support the Validation Issue handling in the Core layer of the API.
Classes AutoResponsesCollection The AutoResponsesCollection class contains a list of automatic responses to validation issues. The collection is loaded and referenced by the API Core Application object. The collection is implemented as a hash table that is keyed by API item type/issue type. For example, an auto-response fro the “product out of stock” issue that is coded in the base OrderInfo namespace is keyed in the hash table as “OrderInfo.OrderMaster/ OrderInfo.ProductOutOfStockIssue”. It is the responsibility of the consumer to load the autoresponses collection with the appropriate responses for that collection. The API developer may check for an auto response using the HasResponse and GetResponse methods.
Example From within the OrderInfo.OrderMasters collection, the following call determines if an auto response exists for the ProductOutOfStockIssue. Global.App.AutoResponses.HasResponse(Me.ItemType, GetType (ProductOutOfStockIssue)
Methods Name
Description
Add
Adds an auto response to the collection.
Remove
Removes the response from the collection.
HasResponse
Returns TRUE if the requested response exists in the collection.
GetResponse
Returns the StandardResponseType value of the response. If the response does not exist in the collection StandardResponseType, NONE is returned.
IssueBase The IssueBase class is the base class for all validation issues.
©2009 TMA Resources, Inc.
Proprietary & Confidential
41
Classes
Properties Name
Description
Caption
A short descriptive caption for the issue. This is used by UI programs as a dialog title when displaying the issue. If not overridden, the caption defaults to the Severity of the issue.
Key
A string that uniquely identifies the issue within an issues collection. The issue base class requires that the key be passed on the constructor. Inherited classes may automatically generate this key as appropriate. For example, the InformationMessageIssue in the Core generates a GUID for the key and combines the class name and additional key, if applicable, to arrive at the Unique key for the issue.
It is up to the API developer to determine if an issue needs an additional key. If the additional key is passes to the constructor, it is included as part of the Key. Message
This is the text message displayed for the issue. Overloaded constructors on IssueBase allow this to be specified as either a string message or as a MessageId number. Both constructors also take a number of issue parameters as well, allowing this message to be used as a format string. In addition, an inherited issue class may choose to override the message property so that more complex logic may be implemented to show a more appropriate message.
Reference
The reference property provides a place for the creator of the issue to store contextual information about the issue. For example, if the issue is a question about a particular product, the API developer may choose to store the product object in the reference property. This way, when the question is answered, the API developer can take action against the stored product value.
Response
The response property returns the Responses.SelectedResponses property. This supports legacy validation issue code.
ResponseRequired
This is a Boolean data type indicating whether a response is required for the issue.
Severity
The severity of the issue. See IssueSeverityEnum for a list of values.
©2009 TMA Resources, Inc.
Proprietary & Confidential
42
Classes
Name
Description
Responded
This property indicates whether a response has been received from the consumer of the API for the issue.
ParentGuid
This returns the GUID of the parent object of the object that raised the validation issue.
AdditionalKey
When identical issues exist in the same object, this property allows the user to obtain the AdditionalKey associated with the issue.
IssueEventArgs The IssueEventArgs class is used when the IssueAdded event is raised from the IssueCollection class. These events are intended to be used by the consumer to react to the raising of validation issues.
Properties Name Issue
Description The issue that was added to the collection
IssueResponse The Issue Response class represents a single response to the issue.
Properties Name
Description
Description
The text description of the response. This is the string that displays to the end user in an interactive application when the issue provides a choice of responses. The value for the description may be set using a string or message ID.
Empty
Shared property that returns an empty response.
Reference
The reference property provides a place where the creator of the issue can store contextual information about the response. For example, if an issue is asking the consumer to choose between a list of alternate products, the API developer may choose to store the ProductId of each choice in the Reference property.
StandardResponseValue
Converts the Value property, which is a string, to one of the value in StandardResponseEnum. If the Value property cannot be converted into a StandardResponseEnum, then StandardResponseEnum.None is returned.
©2009 TMA Resources, Inc.
Proprietary & Confidential
43
Classes
Name Value
Description The sting value of the response. This value is determined by the API developer when the issue is created. The developer may use the StandardRespons values (i.e., OK, Cancel, Yes, No, etc.) or any other sting value (i.e., a product code, customer ID, etc.).
IssueResponsesCollection The IssueResponsesCollection contains a list of IssueResponse objects. It is typically referenced via the Responses property of an Issue object.
Properties Name
Description
Item
Returns a single IssueResponse object from the collection using either the response’s string value, the StandardResponseEnum value, or the numeric index of the item within the collection.
SelectedResponse
Returns the response that was chosen by the consumer. If no choice has been made SelectedResponse returns Nothing.
DefaultResponse
Returns the response marked as the default response for the issue.
Responded
Returns TRUE if the consumer has responded to the issue.
Methods Name
Description
Add
Adds a new response to the collection.
Remove
Removes the response from the collection.
Contains
Returns TRUE if the collection contains the specified response.
IndexOf
Returns the integer index of the response within the collection. If the response is not found, it returns a negative number.
IssuesCollection The IssuesCollection is a collection of validation issues. The IssuesCollection class is referenced from the within a BusinessObject or BusinessObjectCollection by referencing the ValidationIssues property of the object. There is only one IssuesCollection for each top-
©2009 TMA Resources, Inc.
Proprietary & Confidential
44
Classes
level API collection. Each member of the top-level collection, all of its child collections, and all of their items point to the root-level ValidationIssues collection.
Properties Name
Description
Item
Returns an individual issue from the collection either via the issue’s key or the numeric index of the issue within the collection.
TriggerValidaitonIssueEvent
Set to TRUE by default. When this is set to FALSE, the ValidationIssueEvent will not be raised. This can be used to make the UI ignore the event when the issue is generated by the API.
Methods Name
Description
Assert
Accepts a conditional expression and an issue. If the condition is TRUE the issue is added to the collection. If the condition is FALSE the issue is removed from the collection.
ClearResponseNotRequiredIs sues
Shortcut method that removes all issues from the collection that do not require a response.
Add
This adds a new issue to the collection. By default, when an issue is added, the Add method checks the AutoResponses collection determine if there are any auto responses for the issue. If there is, the Add method sets the selected response on the issue to the appropriate value before adding it to the collection. If the auto response value is Ignore, the Add method ignores the issue and does not add it to the collection.
Remove
Removes the issue from the collection.
RemoveAll
Removes all of the issues from the collection.
Contains
Returns TRUE if the specified issue is in the collection.
ErrorCount
Returns the number of issues in the collection that have a severity of “ERROR”. The default save method checks this value before attempting to save a collection. If the ErrorCount > 0, the save method does not attempt to save the collection.
IndexOf
Returns the numeric index of the issue within the collection. If the issue is not found, IndexOf returns a negative number.
©2009 TMA Resources, Inc.
Proprietary & Confidential
45
Classes
Events Name
Description
IssueRaised
This event occurs whenever a new issue is added to the collection. It is used by the consumer to react to new validation issues.
IssuesReset
This event occurs when the issues collection is cleared. It is used by the consumer to display the list of current outstanding issues.
IIssue This is the interface implemented by all validation issues. This interface is implemented by IssueBase.
Properties Name
Description
Caption
A short descriptive caption for the issue. This is used by UI programs as a dialog title when displaying the issue. If not overridden, the caption defaults to the Severity of the issue.
Key
A string that uniquely identifies the issue within an issues collection. The issue base class requires that the key be passed on the constructor. Inherited classes may automatically generate this key as appropriate. For example, the InformationMessageIssue in the Core generates a GUID for the key and combines the class name and additional key, if applicable, to arrive at the Unique key for the issue.
It is up to the API developer to determine if an issue needs an additional key. If the additional key is passes to the constructor, it is included as part of the Key. Message
©2009 TMA Resources, Inc.
This is the text message displayed for the issue. Overloaded constructors on IssueBase allow this to be specified as either a string message or as a MessageId number. Both constructors also take a number of issue parameters as well, allowing this message to be used as a format string. In addition, an inherited issue class may choose to override the message property so that more complex logic may be implemented to show a more appropriate message.
Proprietary & Confidential
46
Classes
Name
Description
Reference
The reference property provides a place for the creator of the issue to store contextual information about the issue. For example, if the issue is a question about a particular product, the API developer may choose to store the product object in the reference property. This way, when the question is answered, the API developer can take action against the stored product value.
Response
The response property returns the Responses.SelectedResponses property. This supports legacy validation issue code.
ResponseRequired
This is a Boolean data type indicating whether a response is required for the issue.
Severity
The severity of the issue. See IssueSeverityEnum for a list of values.
Responded
This property indicates whether a response has been received from the consumer of the API for the issue.
ParentGuid
This returns the GUID of the parent object of the object that raised the validation issue.
AdditionalKey
When identical issues exist in the same object, this property allows the user to obtain the AdditionalKey associated with the issue.
IIssuesCollection The interface implementedd by the IssuesCollection class.
Properties
Name
Description
Item
Returns an individual issue from the collection either via the issue’s key or the numeric index of the issue within the collection.
TriggerValidaitonIssueEvent
Set to TRUE by default. When this is set to FALSE, the ValidationIssueEvent will not be raised. This can be used to make the UI ignore the event when the issue is generated by the API.
©2009 TMA Resources, Inc.
Proprietary & Confidential
47
Classes
Methods Name
Description
Assert
Accepts a conditional expression and an issue. If the condition is TRUE the issue is added to the collection. If the condition is FALSE the issue is removed from the collection.
ClearResponseNotRequiredIs sues
Shortcut method that removes all issues from the collection that do not require a response.
Add
This adds a new issue to the collection. By default, when an issue is added, the Add method checks the AutoResponses collection determine if there are any auto responses for the issue. If there is, the Add method sets the selected response on the issue to the appropriate value before adding it to the collection. If the auto response value is Ignore, the Add method ignores the issue and does not add it to the collection.
Remove
Removes the issue from the collection.
RemoveAll
Removes all of the issues from the collection.
Contains
Returns TRUE if the specified issue is in the collection.
ErrorCount
Returns the number of issues in the collection that have a severity of “ERROR”. The default save method checks this value before attempting to save a collection. If the ErrorCount > 0, the save method does not attempt to save the collection.
IndexOf
Returns the numeric index of the issue within the collection. If the issue is not found, IndexOf returns a negative number.
Events Name
Description
IssueRaised
This event occurs whenever a new issue is added to the collection. It is used by the consumer to react to new validation issues.
IssuesReset
This event occurs when the issues collection is cleared. It is used by the consumer to display the list of current outstanding issues.
©2009 TMA Resources, Inc.
Proprietary & Confidential
48
Classes
IssueSeverityEnum The IssueSeverityEnum identifies the severity of the issue. Name
Description
Information
The is extra information provided to the consumer and is only used if no response is necessary.
Warning
Warns the consumer about a particular action. Similar to Information, but allows the consumer to display the message differently.
Question
Used when a response from the consumer is needed.
Error
Identifies the issue as an error. Errors may or may not include responses. If a BusinessOject’s issues collection contains error issues, the save method does not attempt to save the object.
StandardIssueResponseEnum The StandardIssueResponseEnum represents a list of standard responses to issues. An issue may or may not use the standard responses, or may use a combination of standard and custom responses. It is the responsibility of the API developer to determine the correct set of responses for a particular issue. Valid values are: • Cancel • Continue • Ignore • No • None • OK • Retry • Yes
©2009 TMA Resources, Inc.
Proprietary & Confidential
49
Classes
Core Validation Issues The following issue classes are coded in the API core.
PropertyMissingIssue This issue is raised when an object requires a property value, but that value has not been set. The Reference property of the issue contains the object that is missing the property and the issue provides a property name property as well.
BusinessObjectPropertyMissingIssue This issue is similar to the PropertyMissingIssue, except that the Reference property is strongly typed to an IBusinessObject object. The name of the missing property is stored in the issue as well. This issue is raised by the core Validate() methods when checking that all required properties on a business object are set.
InvalidPropertyValueIssue This issue is raised when a consumer attempts to set a property to a value that is not valid for that property. This may be a violation of the minimum or maximum length of a string, the minimum or maximum value for a number, a setting outside of a specified date range, etc. The issue is raised by the various Property Setter methods in the core BusinessObject.
YesNoIssue This is a generic issue that automatically adds the YES and NO responses to its responses collection. This issue is not used by the core, but is available for the base layer developers to inherit from.
DuplicateObjectIssue This issue identifies that a duplicate object has been detected. It is raised by the DuplicateCheck() process in the Core.
©2009 TMA Resources, Inc.
Proprietary & Confidential
50
Classes
Validation Issue Examples This section displays a number of example of validation issues within a few different subsystems. It covers issues in which a user’s response is required in order to determine the proper course of the business flow. This section will answer the following questions for each validation issue example: • When is this issue thrown? • What is the message/response? • How do you resolve the issue? • What are the implications of this issue (may not apply to all examples)?
This section is only a sampling of validation issues and is not intended to cover every validation issue in Personify. The following examples describe the a sampling of validation issues handled by Personify. Each validation issue is a specific class designed and coded in the API.Base.. by the API developer to handle different business scenarios. For example, Order related validation issues are coded in OrderValidationIssues.vb within the OrderInfo namespace as shown below:
©2009 TMA Resources, Inc.
Proprietary & Confidential
51
Classes
If you have to extend the base functionality and a new Issue of response type is required to be added for the order entry process, you can add the new class in the following namespace of your Customer Layer.
All validation issues’ class names should end with “Issue”. It is not a mandatory requirement, but helps in identifying an Issue class among other objects when using context sensitive help.
The namespace definition is not required in the code if you set up the root namespace in the project properties.
©2009 TMA Resources, Inc.
Proprietary & Confidential
52
OrderInfo Validation Issue Examples
OrderInfo Validation Issue Examples MeetingRegistrationIssue When is this issue thrown? This issue is raised internally by the API when a meeting or session is added to the order if the business rules dictate it. Meetings and sessions normally have a limit on the amount of people that can be registered and waitlisted. When a meeting or a session is added to the order/shopping cart, the system validates whether or not seats are available. If the seats are not available, the system then checks to see if seats are available on the waitlist. If both the registrar and waitlist are full, the system does not allow the meeting or session to be added to the order. This validation can be thrown for these reasons: • There is no capacity and no waitlist capacity available. • There is no capacity, but the waitlist is available. • There is no capacity available, but the product allows you to Override Capacity (not available on the Web). • When you place an order for a meeting/session for which the registration date has passed. • When you exceed the maximum number of tickets allowed for a session.
ProductOutofStockIssue When is this issue thrown? The ProductOutOfStockIssue is raised when a product is selected on an order detail line. The OrderDetail object is responsible for raising the issue. The constructor for the issue class requires only a product ID and product name. The product ID is used for the Reference property and the product name is used as a parameter for constructing the message. The class determines the unique key for the issue and contains constants defined for all of the messages that it needs. The class also contains a CanBackOrder property and an AddAlternateProduct method. These are used by the OrderDetail object to control the behavior of the ProductOutOfStockIssue.
What is the message/response? When the CanBackOrder flag is set to TRUE, the issue class adds a response, with the appropriate message and a response value of “Continue” to its responses collection. It then sets this as the default response for the issue. When AddAlternateProduct is called, a new
©2009 TMA Resources, Inc.
Proprietary & Confidential
53
OrderInfo Validation Issue Examples
response is added to the responses collection specifying the appropriate message and using the ID of the alternate product as the value for the response.
©2009 TMA Resources, Inc.
Proprietary & Confidential
54
OrderInfo Validation Issue Examples
Invoking the ProductOutOfStockIssue The following code shows how the OrderDetail object would invoke the ProductOutOfStockIssue. This would be called when the order detail object determines that the product is out of stock. The code creates a new ProductOutOfStockIssue, passing the
©2009 TMA Resources, Inc.
Proprietary & Confidential
55
OrderInfo Validation Issue Examples
product ID and product name on the constructor. It then sets the CanBackOrder flag to true, and adds three alternate products.
©2009 TMA Resources, Inc.
Proprietary & Confidential
56
OrderInfo Validation Issue Examples
InvalidDateRangeIssue InvalidDateRangeIssue is an issue class that reports an invalid date range. The issue accepts an Owner object, a StartDate, and EndDate on the constructor. It uses the Owner object to create a unique key for the issue an stores the StartDate and EndDate in private variables. The class does not set a message string in the constructor, rather, it overrides the message property and returns one of three messages depending on the contents of the StartDate and EndDate properties.
©2009 TMA Resources, Inc.
Proprietary & Confidential
57
CustomerInfo Validation Issue Examples
CustomerInfo Validation Issue Examples AddressValidationIssue This validation issue alerts the user as to the results of the Address Validator. The Address Validator application is used to validate customer addresses.
When is this issue thrown? This issue is thrown when the Address Validator completes its function. For example, Group1 has completed its run and needs to inform the user of its results.
What is the message/response? There are two messages. If the address validation is successful, a message similar to, “Address has been validated. No errors. Continue?” displays. If issues arise with the Address Validator or an exception has been raised, a message similar to, “Address cannot be validated” followed by the error/exception displays.
How do you resolve this issue? If the address validation is successful, no action must be taken. If an error was raised by the Address Validator, the address must be corrected and re-validated. If an exception occurs, contact your System Administrator.
What are the implications of this issue? The address is either validated by the system or is rejected.
©2009 TMA Resources, Inc.
Proprietary & Confidential
58
CustomerInfo Validation Issue Examples
SegmentWithMembersDisabledIssue When is this issue thrown? This validation issue is raised when the user attempts to disable a segment definition for which there are existing members.
What is the message/response? “Members exist for this segment definition. Do you want to turn off Segmentation?” The message also displays the rule, description, and qualifiers for the segment definition. This requires a Yes/No response.
How do you resolve this issue? Since this is a Yes/No issue, the user must choose to either leave the segment definition as is or turn off segmentation.
What are the implications of this issue? The segment definition is turned on/off based upon the user’s response.
SegmentChangeWithMembersIssue When is this issue thrown? This issue is thrown when the user attempts to change a Segment Definition for which there are existing members.
What is the message/response? “Members exist for this segment definition. Do you want to continue with the change? The message also displays the rule, description, and qualifiers for the segment definition. This requires a Yes/No response.
How do you resolve this issue? Since this is a Yes/No issue, the user must choose to either leave the segment definition as is or allow for modifications to the segment definition.
What are the implications of this issue? The segment definition is turned on/off based upon the user’s response.
UpdateSubCustomerStatusToReflectMasterCustomerStatusIssue This validation issue updates the Customer Status Code of Sub Customer when the master record is being updated.
When is the issue thrown? This issue is thrown when the user updates the Customer Status Code and the customer has Sub Customer records linked to it.
What is the message/response? “Do you want to change the child record status to (modified status)?”
©2009 TMA Resources, Inc.
Proprietary & Confidential
59
CustomerInfo Validation Issue Examples
This requires a Yes/No response.
How do you resolve this issue? Since this is a Yes/No issue, the user must choose to either update the sub customer record(s) with the modified Customer Status Code or not.
What are the implications of this issue? The Customer Status Code of the sub customer record(s) are updated or not based on the user’s response.
MarkAddressAsBillToORShipToIssue This validation issue alerts the user of a potential duplicate primary customer address and updates of the customer’s Primary Address flag depending on the user’s response.
When is this issue thrown? This issue is thrown when the user adds a new address or edits an existing address and marks the address as the primary address when a primary address already exists for the customer.
What is the message/response? “Another address is marked as the primary #1# address. Should the new address become the primary #1# address?” This requires a Yes/No response.
How do you resolve this issue? Since this is a Yes/No issue, the user must choose whether or not to update the primary address flag.
What are the implications of this issue? The primary address flag of the customer may be modified based upon the user’s response. A customer can only have one primary address.
CreateMultipleLinksToPrimaryAddressIssue When is this issue thrown? This validation issue is thrown when a user creates a new address and attempts to link that address to another customer.
What is the message/response? “Cannot link to the company record entered because this company’s primary address is already linked to customer #1#. Link this record to #1# as well?” This requires a Yes/No response.
How do you resolve this issue? Since this is a Yes/No issue, the user must decide whether or not to proceed with linking the addresses.
©2009 TMA Resources, Inc.
Proprietary & Confidential
60
CustomerInfo Validation Issue Examples
EmailExistAsPrimaryForAnotherCustomerIssue When is this issue thrown? This issue is raised when a user creates a new primary email address for a customer, attempts to save the record, and the email address is already being used as the primary email address for another customer record.
What is the message/response? “Email address already exists in Personify as a primary email for customer #1#. Do you want to set this email as primary email for current customer?” This requires a Yes/No response.
How do you resolve this issue? Since this is a Yes/No isssue, the user must decide whether or not to use the email address as the primary email address for both customers.
PrimaryEmployerAlreadyExistsIssue This validation issue alerts the user to the fact that the customer already has a primary employer on record and updates the primary employer flag based upon the user’s response.
When is this issue thrown? This issue is raised when the user creates a new primary employment relationship for a customer and attempts to save the record.
What is the message/response? “Primary employment already exists, do you want to update existing primary employer information with new information? This requires a Yes/No response.
How do you resolve this issue? Since this is a Yes/No issue, the user must decide whether or not to update the primary employment flag of either of the customer’s employment relationship records.
What are the implications of this issue? The newly created relationship record is either set as the primary employment relationship or not based upon the user’s response. There can be only one primary employer for a single customer record. Customer records can have multiple, non-primary employer records.
PrimaryContactAlreadyExistsIssue This validation issue alerts the user to the existence of a primary contact relationship for the customer and updates the primary contact flag of the customer’s relationship depending on the user’s response.
©2009 TMA Resources, Inc.
Proprietary & Confidential
61
CustomerInfo Validation Issue Examples
When is this issue thrown? This issues is raised when a user creates a new primary contact relationship for a customer and attempts to save the record.
What is the message/response? “Primary contact already exists, do you want to update existing primary contact information with new information?” This requires a Yes/No response.
How do you resolve this issue? Since this is a Yes/No issue, the user must decide whether or not to update the primary contact flag of either of the customer’s contact relationship records.
What are the implications of this issue? The newly created relationship record is either set as the primary contact relationship or not based upon the user’s response. There can be only one primary contact relationship for a single customer record. Customer records can have multiple, non-primary employer records. < CHECK>
DuplicateCustomerMatchesFoundIssue This validation issue alerts the user of a potential duplicate customer match based on criteria set up for the application to match a duplicate customers and contains a list of the possible duplicate customer records. The user can choose to continue with the customer’s creation or select one of the identified duplicates.
When is this issue thrown? The issue is raised upon the user’s saving of a newly created customer record.
What is the message/response? “Duplicate Customer Match Found for . Do you want to continue?” This requires a Yes/No response.
How do you resolve this issue? If the Personify UI displays a screen with a data grid displaying the duplicate customers found, the user can either select one of the presented customer records or continue saving the record. If not using the Personify UI, the validation issue will contain “DuplicateCustomerIds” property, which displays a list of the potential duplicate customers.
What are the implications of this issue? The newly created customer record can either be saved as is or the user can select one of the duplicate matches to work with.
©2009 TMA Resources, Inc.
Proprietary & Confidential
62
View more...
Comments