Proposal based architecture system6158044Abstract A proposal based architecture system that converts a transaction submission process into a generic object in a computer environment. A preferred embodiment of the invention provides a tool set which allows the user to create a set of Proposal Specifications which define the structure of the possible components of a Proposal. The user defines the complete characteristics (meta-data) for any kind of Proposal which define the hierarchy of domain relationships, interaction modes, validation references, and assumptions. The actual Proposal instance is formed using the definitions in the Proposal Specifications. A Proposal allows a user to add, change, and annotate data, is self aware and navigates between pages and skips to appropriate fields automatically and supports n-level undo/redo. It also tracks all versions of data updates and the user that is responsible for each data update, recognizes and corrects stale data, and enables long-lived transactions, off-line transaction processing, and collaborative transactions. A Proposal is accessed via multiple User Interfaces (UI), breaking the close coupling between the front-end and the back-end and allowing the user to add a Web or Graphical User Interface (GUI) front-end without having to rewrite the back-end application. A UI coordinator maps user input fields to components of the Proposal and communicates with different user interfaces such as: Internet; Graphical User Interface (GUI); Object Oriented User Interface (OOUI); proprietary interface; and devices such as bar code readers or keypads. The invention also provides a default UI and components. A set of Transaction Processing/Data Processing (TP/DP) interfaces are provided to communicate with back-end transactional interfaces such as Database Management Systems (DBMS), Transactional Processing (TP) Monitors, and Object Oriented Databases. Claims What is claimed is: Description BACKGROUND OF THE INVENTION
__________________________________________________________________________
Class Name Description
__________________________________________________________________________
PropSpec 1201 Facade for all PropSpec operations
State iterator Current position in subsidiary FieldGroupSpec composite
propSpecName
Name of the PropSpec
Behavior
appendFgs
Append new FieldGroupSpec as child at iterator
getRootFgs
Get root FieldGroupSpec
insertFgs
Insert new FieldGroupSpec as peer at iterator
insertableFrom
Determine valid FieldGroupSpecs that can be inserted
here
remove Remove current FieldGroupSpec and its descendents
FieldGroup Container of metadata for each FieldGroup
Spec 1202
State fgsName Name of this FieldGroupSpec
min Minimum number of occurrences for this
FieldGroupSpec
max Maximum number of occurrences for this
FieldGroupSpec
domainName
Backend resource for this FieldGroupSpec
interactionMode
Control pattern for conversation between Proposal and
Server
Behavior
accessors
Access methods for FieldGroupSpec state
appendFieldDef
Append new FieldDef to FieldGroupSpec
getFieldDefs
Get the FieldDefs for this FieldGroupSpec
getNumberOfKeys
Compute the number of keys
getNumberOfFields
Compute the number of fields
insertFieldDef
Insert a FieldDef at a point in the FieldGroupSpec
isInputCandidate
Is the specified field updateable or is it owned by an
ancestor
removeFieldDef
Remove a FieldDef from the FieldGroupSpec
KeyDef 1203 Information about a field that is used as key
State fieldDef FieldDef that defines this particular key
parentKeyDef
Nonnull if this key is owned (defined) by a parent
FieldGroupSpec
Behavior
getKeyDef
Get fieldDef that defines this particular key
isParentMapped
Does parent FieldGroupSpec own this FieldSpec
FieldDef 1204 Information about a field definition entry
State isTemp Is this a temporary field (no backend interaction)?
isRequired
Is this field required to be defined
validators
List of Visitor classes that act as validation behaviors
typedObjectSpec
Detailed type information for this field
Behavior
accessors
Access methods for FieldDef state
__________________________________________________________________________
Comments 1. The PropSpec class implements a Facade pattern, a pattern used to create a single interface to a number of collaborating classes. 2. The principle class in the PropSpec is the FieldGroupSpec. This class defines the characteristics of each "FieldGroup." A FieldGroup is a group of fields related by a common key definition. It is roughly analogous to the fields that would be on each logical page of a multi-page proposal document. 3. Notice in the Class Diagram that FieldGroupSpec recurses (it can include itself any number of times). It is this line that defines the n-level hierarchy of the proposal. The proliferation of FieldGroupSpecs is bounded by the min and max values which indicate how many times the current FieldGroupSpec can (or must) occur within its particular parent. 4. The recursive FieldGroupSpec structure is best implemented as a Composite pattern with companion Iterator. 5. FieldGroupSpecs contain many FieldDefs, each of which contain detailed information about one field in the FieldGroupSpec. 6. Terminology note: it will become clear when comparing this section to the next that a parallel set of class structures are defined for the actual elements that the PropSpec defines. We've attempted to keep the names parallel: a FieldGroupSpec defines the specifications of a FieldGroup; a FieldDef specifies the definition of a Field; and so forth. 7. Supplementary information is kept for fields that are keys. In the invention, a key is a field or group of fields that defines the uniqueness of a FieldGroup. Note that the KeyDef keeps track of whether a key field is "owned" by a parent FieldGroup. Parent ownership means that the particular key field in question is defined in the current FieldGroup or by one of its ancestors. Consider this example: We are currently modifying a SalesOrder proposal and are positioned to the second line item for. Product Sweeper of SalesOrderNo 1234. This particular FieldGroup has two keys SalesOrderNo and Product. Both keys are required, since neither alone would uniquely specify this FieldGroup. Product is defined "locally" to this group--thus it could be changed in the current FieldGroup. But SalesOrderNo is owned by a parent FieldGroup (OrderHeader) and can only be changed in the parent. 8. The TypedObjectSpec is the top of an inheritance structure that defines different basic types to the system. Currently seven types are provided. Users can easily extend these types by adding new classes to the system. 9. The PropSpec needs to "persist." This is covered under "Proposal Persistence" in the section that follows. 2. Acting as a Container for Proposal Data Once metadata has been put into the Proposal to describe its application-dependent properties, it becomes possible to use the Proposal as a container for application data. Referring to FIG. 13, a class diagram shows the basic Proposal structure.
__________________________________________________________________________
Class Name Description
__________________________________________________________________________
Proposal 1301 Facade for all Proposal operations
State currentFieldGroup
Current FieldGroup
fieldState
Indicates whether key or nonKey fields are needed
iterator Current position in subsidiary FieldGroup composite
overrideMode
Are errors in data forced in without interaction?
tentativeInsertNode
If nonnull, node is still defining keys to execute an
insert
validateMode
Is data checked with special validation procedures?
Behavior
cancelInsert
Cancel the inflight tentative insert
changeFieldState
Sets whether key or nonKey fields are asked for
delete Delete FieldGroup and its subordinates
down Proceed to first child FieldGroup
find Find a specified FieldGroup
findFieldGroupSpec
Find a specified FieldGroupSpec
first Position to root FieldGroup
flush Flush all cached changed to FieldGroup
getCurrentFieldGroup
Get currently positioned FieldGroup
getField Get specified Field
getKeys Get key Fields
getOverrideMode
Get current override mode state
getValidateMode
Gets the current validation mode
insert Insert a new FieldGroup
insertableFrom
Determine all valid FieldGroupSpecs insertable from
here
insertComplete
Signal end of tentative insert mode
last Position to last FieldGroup in tree
next Position to next FieldGroup
getnextInsertPoint
Determine next valid FieldGroupSpec insertable from
here
notifyChange
Signal external objects to a significant change of
state
positionTo
Position to specified FieldGroup
previous Position to previous FieldGroup
redo Redo the last undone version
remapFields
Mutates FieldGroups if metadata has changed
setCurrentFieldGroup
Sets the current FieldGroup
setField Sets the data value of a specified field
setFields Sets the data values of a list of fields
setOverideMode
Sets the override mode
toString Renders the Proposal as a string
undo Undo a recent change
up Position FieldGroup to its parent
__________________________________________________________________________
Comments 1. Notice the congruence between the PropSpec and Proposal classes. This congruence has been reflected in the naming conventions used (e.g., FieldDef and Field). Both support Facade patterns to encapsulate the PropSpec objects (in the former case) and the Proposal itself (in the latter case). 2. The Proposal is implemented as a Composite pattern with Iterator. 3. Proposal objects (like the PropSpec object) are 100% non-visual. While other components may act as viewers, these objects are built for quiet use. This is a major feature: It allows these objects to be accessed and manipulated by non-human automata as well as human-driven user interfaces. 4. The Proposal object makes extensive use of the currentFieldGroup. This term designates the FieldGroup that is the current focus of attention. 5. An extensive amount of special behavior is associated with inserting data into the Proposal hierarchy. This will be covered under "Insert Processing" below. 6. Once the data is inserted into the hierarchy, navigation is simply a matter of invoking the various iterator functions (up, down, next, previous, top, bottom). 7. OverrideMode is a Proposal attribute that can be set so that errors are accepted without any notification to the user. It is useful when a batch program or other non-human consumer wants to push data into a Proposal and have it reviewed later. When OverrideMode is on, the Proposal still performs the error checks and marks the Fields in error; it simply doesn't complain to the consumer about the error. 8. ValidationMode allows new data to be entered with no error checks at all. It is used to speed up loading of data that has already been validated by some other process. 9. The validate methods are used to fire Visitor objects. These are dynamically loaded validations written in a scripting environment that the user can supply. 10. Special processing associated with building the actual tree is covered in the subsequent section "Insert Processing." 11. Proposal state needs to be saved. This is covered in the section "Proposal Persistence" below. Insert Processing Inserting into a Proposal poses a greater challenge than all the other navigation operations combined. The reason is simple: Insert mode has the responsibility for properly shaping the multi-level FieldGroup tree, where other operations simply travel on an already-constructed shape. Before describing the insert algorithms, it would be helpful to describe a sample application for use as a reference point. Consider a hypothetical sales order entry system. It consists of Order Header (customer info, shipping info) LineItems (product code, qty, amount--min=1, max=99) Shipment(shipQtyCommitment, shipDate--min 0, max 5) Special Instructions A given sales order in this sample: has one and only one header. must have at least one lineitem, and can have up to 99. can optionally have partial shipments, up to a max of 5, under each lineitem. can optionally have a single section of SpecialInstructions. As this sample indicates, there are numerous points in the order entry sequence in which an operator may either want to proceed to the next logical step, or skip to the next type of FieldGroup (example: I've entered two Shipments under LineItem 1 and have no more to enter, so I now want to proceed to LineItem 2). The invention accordingly provides two different user interface events that signal these two different kinds of Insert: InsertOK and InsertCancel. These two events can be assigned to specific keyboard keys (the default is InsertOK is a FunctionKey12 and InsertCancel is Escape), or to UI widgets such as buttons or menu items. InsertOK means to keep going "down" the tree (preorder traversal) until the max count is exhausted. Examples I've entered the Order Header; go to LineItem 1. I've entered LineItem 1; go to Shipment 1. I've entered Shipment 5; go to LineItem 2 (the max has been reached). InsertCancel means to escape from the current path and try the next logical type Examples I've canceled from LineItem 2; go to SpecialInstructions. I've canceled from Shipment 3; go to next LineItem. An insert technique (in pseudocode) for implementing entry of this sample (or any other arbitrarily deep tree structure) is as follows: Fgs=FieldGroupSpec Fg=FieldGroup if (Fg is empty) Insert(RootFieldGroupSpec) Return If (InsertKey is InsertCancel) goto Cancel If (current Fg's type has a descendent type) //e.g. LineItem has a Shipment Insert(Descendent Type) Return If (current Fg's own type is not exhausted (exceeded max)) Insert(Another Fg type) //e.g. Shipment follows Shipment Return; Cancel: If (any peer type of this type in the Fgs (that is not exhausted)) Insert(PeerType) //e.g. Item goes to SpecialInstructs Return While (this node has a parent in the Fgs) Make parent node the current If (there is any child node that is non-exhausted) Insert(it) Keep trying until root Stop trying . . . the Proposal is full. Tentative Inserts The algorithm specified above solves most of the problems relating to a Proposal insert. However, there is still one outstanding discrepancy. When a user decides on the node to insert there is still a gap between the time the new FieldGroup is created and the time that the keys that define this node's existence are specified. For example, a user might have executed an InsertCancel to finish work on LineItem 2 and now positions to LineItem 3. Until the full key is set (in this case OrderNo and Product) a canonic FieldGroup cannot be recognized by the Proposal object. This condition is called the Tentative Insert condition. The FieldGroup in this condition is called an "underspecified FieldGroup". The Proposal object has several methods for dealing with Tentative Insert. When an underspecified FieldGroup is created, it is automatically flagged as such. As key fields are subsequently entered, the Proposal notes when key field collection has been completed. At this moment the Proposal internally switches gears from Tentative Insert into Full Insert mode. It also fires an event that any interested party can "hear," signaling the change in status of the Proposal. An external consumer has the option to abandon a Tentative Insert by executing the cancelInsert method and moving on to the next available nodeType. For example, consider the case where the user is at LineItem 2, Shipment 3. Hitting the first InsertCancel makes the Proposal object start a tentative insert at LineItem 3. But if there are no further lineitems, a subsequent InsertCancel moves the user on (without penalty) to the SpecialInstructions. Yet another InsertCancel terminates entry into the Proposal altogether. In each of these cases a Tentative Insert was initiated, canceled, then passed onto the next candidate type. Proposal Persistence The Proposal and PropSpec will need to be saved to some "external form" so that they can persist between sessions or when passed around to users on different platforms. Unfortunately there is still no standard, portable mechanism for storing in-memory objects onto an external form. There are many such mechanisms that are specific to a language or platform, and a Proposal implementer can choose any of these mechanisms that are convenient or available. However, to satisfy those who need more options, the invention has defined its own formats for PropSpec and Proposal persistence. These storage models support all of the invention's features and functions described in this document. In both the PropSpec and Proposal cases, the internal objects are converted into a standard textual representation that can be read and written on any computer that supports text. It can be stored on any medium, sent over any communication (it can even be printed out on one computer and rekeyed into another, though this is not a recommended method of Proposal transfer). Proposal persistence to text files and to a relational database come as built-in features; almost any other kind can be added to the framework. The Proposal files can appear in two forms: PropSpec file, which contains only information related to a single PropSpec Proposal files, which contain all the information specific to a given Proposal, plus the PropSpec information that defines the Proposal. Proposal Syntax The following syntax definitions show how the Proposal and PropSpec state is formatted for persisting onto any external definition. These style of these definitions is rendered in a "relaxed" version of the standard Backus-Naur Form (BNF) that has been used for years to document the syntax of programming languages. A quick summary of this relaxed BNF is given below: The left-justified word that begins each "paragraph" is the. name of the term being defined. Italicized text represents the usage of a defined term or an informal comment that describes the usage of multiple terms (e.g., "One of the following"). Normal, non-italicized text represent the literal word used A term is defined before it is used. Words enclosed in angle-brackets (e.g., <fieldName>) are used merely to delimit terms in a context with intermixed terms or literals.
______________________________________
Proposal text:
One or more PropBlocks
PropBlock:
Fields {FieldBlock}
FieldGroup {FieldGroupBlock}
Proposal {ProposalBlock}
FieldBlock:
One or more FieldDefinitions
FieldDefinition:
<fieldName>,<typeDefinition>,<lengthSpecifier>,
<descriptionString>,
<default>,<validatorList>;
[Note: all zones after typeDefinition are optional]
fieldName:
A fieldName with leading letter,
Followed by letters, digits, or `.sub.-- `
TypeDefinition:
One of the following:
Int
Num
Dec
Char
Date
Time
Timestamp
<UserDefinedType>
UserDefinedType:
A string with a Visitor object defined to implement type behavior
Length Specifier:
Either:
Whole number that represents external length
Real number that represents <length>,<precision>
Default:
Default value of appropriate type
ValidatorList:
[validators .vertline. <validator1> . . . <validatorN>]
Validator:
[<validatorProcedure> .vertline. Zero or more args separated by
semicolons]
PropBlock:
<specifier1> = <specValue1>;
. . .
<specifierN> = <specValueN>;
[fields .vertline. <fieldUse>;fieldUseN>]
[subFieldGroups .vertline. <subFieldGroup>;<subFieldGroupSpec>]
[assumptions .vertline. <assumption>;<assumptionN>]
Specifier:
One of the following:
Domain [Note: Backend resource name]
InteractionMode [Note: Default interaction mode]
<userdefinedvalue>
SpecValue:
Appropriate value for specifier
FieldUse:
<FieldIdentifierInContext>,req [Note: `req` presence is optional]
FieldIdentifierInContext:
*fieldName
[Note: indicates a key field]
fieldName [Note: indicates a nonkey field]
SubFieldGroupSpec:
[<subFieldGroupName> .vertline.
<subFieldGroup Type> (<keyfields-comma-delimited>);
<min>;<max>;<interactionMode>]
InteractionMode:
One of the following:
Null Exists
Default Update
New Delete
Assumption:
<fieldGroupName>,<fieldName-or-list>,<commitAction>,
<notifyAction>,<fixupAction>
Action:
<same format as Validator>
[Note: Name of visitor that defines that action]
ProposalBlock:
<specifier1> = <specValue1>;
. . .
<specifierN> = <specValueN>;
<fieldGroupBlock>
<versions>
fieldGroupBlock:
[<fieldGroupName> .vertline. <fieldContent>; <fieldContentN>;
<fieldGroupBlock>]
[Note: internal <fieldGroupBlock> is optional]
fieldContent:
<fieldValue> [@fldNote.vertline. <name>;<time>;<noteString>]
[@fldErrs .vertline. #<id>; <errorcodeMessage>]
[Note: fldNote & fldErrs are optional depending on their existence]
versions:
[@commands .vertline. #<id>; <action>; <fieldGroup>; <fieldName>;
<keys>; <oldFields>; <newFields>;
<note>; <positionToPlace>]
keys:
List of comma-delimited fieldnames that are the keys
<oldFields> <newFields>
<fieldName> = <fieldValue>,
<fieldNameN> = <fieldValueN>
______________________________________
Sample Proposal This Sample Proposal is in external form. It is composed of fragments of the file. It is semantically incomplete. Its purpose is to demonstrate the syntax.
______________________________________
fields collected {
empId,num,6;
name,char,20;
addrType,char,8;
street1,char,30;
street2,char,30;
city,char,20;
state,char,2;
zip,num,5;
emailService,char,15;
fieldGroup Employee {
domain=PersonDomain;
interactionMode=New;
[fields.vertline.*empId,req;name]
[subFieldGroups.vertline.[HomeAddress.vertline.HomeAddress(empId,*);1;1;de
fault];
[OtherAddress.vertline.OtherAddress(empId,*);0;*;default];
[EmailAddress.vertline.EmailAddress(empId,*);0;3;default];
[EducationlEducation(empId,*);1;*;default];
[WorkHistory.vertline.WorkHistory(empId,*);0;*;default];
[Club.vertline.Club(empId,*);0;*;default];
]}
fieldGroup HomeAddress {
domain=Address;
interactionMode=New;
[fields.vertline.*empId,req;*addrType,req;street1;street2;city;state;zip]
}
fieldGroup OtherAddress {
domain=Address;
interactionMode=New;
[fields.vertline.*empId,req;*addrType,req;street1;street2,,
[validators.vertline.[Policy.RangeCheck.vertline.90000;99999]];city;state;
zip,,
[validators.vertline.[Policy.RangeCheck.vertline.90000;99999]]]
}
fieldGroup EmailAddress {
domain=Email;
interactionMode=Update;
[fields.vertline.*empId,req;*emailService,req;email]
}
Proposal this {
highCommandId=0;
highErrorId=2;
[Employee.vertline.1234;John Tibbetts;
[HomeAddress.vertline.1234;Home;289 Douglass St;;San Francisco;CA;94114;]
[OtherAddress.vertline.1234;Mom's;42240 Parm Ave:77777
[@fldErrs.vertline.[#1.vertline.street2 value of 77777 is below min value
90000]];
Mission San Jose;CA;66538
[@fldErrs.vertline.[#0.vertline.zip value of 66538 is below min value
90000]];]
[OtherAddress.vertline.1234;Vacation;999 Mountain
Road[@fldNote.vertline.Default;970324.123121;teststreet1];;Santa
Cruz[@fldNote.vertline.Default;970324.123113;tescity
];CA;95432[@fldNote.vertline.Default;970324.123102;test zip];]
[EmailAddress.vertline.1234;Internet;john@kinexis.com;]
[EmailAddress.vertline.1234;AOL;johntib@aol.com;]
[Education.vertline.1234;Bellarmine;9Q59;6Q63;
[Course.vertline.1234;Bellarmine;LibEd;Liberal Ed;]
[Course.vertline.1234;Bellarmine;Judo;Judo;]]
[Education.vertline.1234;LoyolaU;9Q70;6Q71;
[Course.vertline.1234;LoyolaU;Engr;Electrical Engineering;]]
[WorkHistory.vertline.1234;Tymshare;9Q71;8Q76;
[JobTitle.vertline.1234;Tymshare;Application Consultant;]
[JobTitle.vertline.1234;Tymshare;TASC Sales;]
[JobTitle.vertline.1234;Tymshare;Regional Tech Manager;]]
[WorkHistory.vertline.1234;Noesis;9Q76;3Q81;
[JobTitle.vertline.1234;Noesis;Vice President;]]
[WorkHistory.vertline.1234;Datalex;3Q81;8Q87;
[JobTitle.vertline.1234;Datalex;President;]
[JobTitle.vertline.1234;Datalex;Chief Technology Officer;]]
[WorkHistory.vertline.1234;Kinexis;9Q87;12Q99;
[JobTitle.vertline.1234;Kinexis;President;]]
[Club.vertline.1234;OS/2 User;Evangelist;]]
[@commands.vertline.
[#0.vertline.970324.123101;101;OtherAddress;zip;
[keys.vertline.1234;Vacation];;;[note.vertline.Default;970324.123102;test
zip];;]
[#1.vertline.970324.123113;101;OtherAddress;city;
[keys.vertline.1234;Vacation];;;[note.vertline.Default;970324.123113;tesci
ty
];;]
[#2.vertline.970324.123121;101;OtherAddress;street1;
[keys.vertline.1234;Vacation];;;[note.vertline.Default;970324.123121;tests
treet1];;]]
}
______________________________________
3. Keeps Versions of Itself There are two quite distinct advantages to having a Proposal keep versions of itself. Undo/Redo A Proposal can use the version list to undo actions that have been previously accepted. Further, a Redo operation can allow "undone" operations to be redone. These two operations let an end-user can scroll back and forth through previous versions of the Proposal to position on the exact candidate version from which he would like to continue. Auditing Since a Proposal can be passed among numerous parties during its life span, it is useful to be able to examine the Proposal later in its life to see exactly who was responsible for what changes in the Proposal. With respect to FIG. 14, a class diagram shows the Version classes for a Proposal 1401.
__________________________________________________________________________
Class Name Description
__________________________________________________________________________
CommandVector Collection of all versions
1402
State Commands
Collection of all versions
Behavior
Add Add a new command to the list
GetLast
Get the last command from the list
removeAbove
Prune all commands above a specified version number
removeLast
Remove the last command from the list
Command 1403 A command that creates a particular version
State timeStamp
Timestamp for when this version was created
signature
Identification of consumer that created this version
action Type of action that created version (eg. Insert, Delete,
Update)
keys Keys that identify the FieldGroup this action works on
oldValues
Old values in FieldGroup before version change
newValues
New values in FieldGroup after version change
Behavior
execute
Execute the action of this command
unExecute
Reverse the action of this command
__________________________________________________________________________
Comments The overall design of Versions is implemented with the Command pattern. This pattern records actions performed by some agent. Playing these actions backwards yields "undo;" replaying them forward yields "redo." Notice that the naming convention follows the Command pattern usage even though the elements end up representing Proposal versions. The granularity of Proposal version control is at the FieldGroup level. For example, a user who changes three fields in LineItem 2 generates a single version entry for Updating a LineItem. Logged changes record only fields that are relevant to a change. In the example above, only the three updated fields are logged, not the fields that remained the same. The version contains both the values before and after the change. This allows complete ability to undo or redo without reconstructing context. The signature field is a holder for any implementer-defined object or objects that identify the consumer making the change. This field can be as minimal as a character string that holds the person's name or as complete as a fully-constituted encrypted digital signature that could support high reliability and non-repudiation needs. Version information persists with the Proposal object. Even if the Proposal is routed to another user and reentered on another day, all of the previous versions are still available for either undo/redo or auditing purposes. 4. Retains and Tracks Errors A conventional transactional system rejects errors immediately. Incorrect or incomplete data will not even make it through the user interface, and usually terminates the transactional conversation. But with Proposals as part of the system, errors can be accepted, held, and monitored. The Proposal signals immediately that a field has been filled in with erroneous or incomplete information, then gives the user the option of fixing or retaining it. If the error is retained, the Proposal tracks it so that it can be found and resolved later. All errors must be eliminated before the Proposal turns into a transactional request at submission time. For example, an international Purchase Order Proposal object might signal an error if the end-user requests the shipment of a certain technology that cannot be legally exported. The user can continue to work on the Proposal, and route it later to a specialists in export policy who can perform a more informed fixup. Referring to FIG. 15, a class diagram shows the Error class.
______________________________________
Class Name Description
______________________________________
Error Error object
1501
State id Unique identifier for this error
code Application defined error code
message Application defined error message
______________________________________
Comments Error messages can be associated with any of three tiers in a Proposal: the Proposal object 1502 itself, each FieldGroup 1503, or each Field 1504 within each FieldGroup. This allows errors to be owned by their proper domain. For example, an error message signaling an invalid zip code would be associated with the faulty zip field, while a credit limit failure on the whole purchase order would be associated the Proposal object itself. Any number of error messages can be associated with any of the available slots. Error messages are saved with the Proposal object. Thus they can be retained across sessions and routed to other consumers of this object. 5. Hold Annotations Annotations are similar to error objects, except they contain informational notations rather than error messages. They can be used to record a user's notes to himself or to colleagues, giving instructions for the Proposal, making comments, suggestions, explanations or justifications. With respect to FIG. 16, a class diagram shows the Note class for a Proposal 1602 with FieldGroup 1603 and Field 1604.
______________________________________
Class Name Description
______________________________________
Note Note object
1601
State timestamp Date and time of annotation
username User who left the note
note Content of the message
______________________________________
Comments The annotation is signed and time-stamped. This positions it relative to the other Proposal activity. Annotations make version entries. They are audited just as data changes are. They can also be undone/redone. The preceding sections have reviewed the characteristics of the non-visual Proposal facade and the PropSpec, its metadata framework. The next sections discuss how these objects communicate with the outside world. 6. Interacts with a Variety of Consumers This section deals with the collaboration between the Proposal and the front end. The front end can be any type of consumer interface technology, but it is typically a graphical user interface or Web browser. The Proposal interface documented in section 2 above satisfies most consumer-interface needs. With these components a GUI widget, for example, can access a field value from the Proposal object and display it. Conversely, a button-press will cause a FieldGroup to be deleted. However, additional consumer interfaces may be needed. Proposal Event Structure This is the primary additional interface required. It allows the Proposal object to notify interested external parties about change in its internal state. Notification is accomplished via the Observer pattern (also called Publish-Subscribe). Consider this example: a user is using a ChangeOrder Proposal that will allow a change to be made to an existing order. He has entered the SalesOrderNo and the Proposal has accessed a database to populate its internal Field objects. Now the Proposal needs to notify various UI elements that the data has changed so that they will now display the populated values. It does this by firing the FIELDGROUP.sub.-- CHANGED event.
______________________________________
PROPOSAL.sub.-- INIT
A Proposal instance has been just created
PROPOSAL.sub.-- CHANGED
A data field has changed value
FIELDGROUP.sub.-- ADDED
A FieldGroup insert or append has been
done
FIELDGROUP.sub.-- REMOVE
A FieldGroup has been deleted
FIELDGROUP.sub.-- ENTRY
Proposal navigation has entered a
FieldGroup
FIELDGROUP.sub.-- EXIT
Proposal navigation has exited a
FieldGroup
FIELDS.sub.-- CHANGED
A group of Fields has changed
FIELD.sub.-- CHANGED
A specific Field has changed
FIELDSTATE.sub.-- CHANGED
Internal entry requirements (fieldState)
changed
FIELDGROUPCHGPEND
Get ready for FieldGroup switch
KEYS.sub.-- NEEDED
Keys needed in FieldGroup
KEYS.sub.-- RESOLVED
Keys have just been satisfied
NONKEYS.sub.-- NEEDED
Non keys needed
POPULATE.sub.-- FIELDGROUP
Populate fieldGroup
COMMIT.sub.-- FIELDGROUP
Commit fieldGroup
______________________________________
UICoordinator The Proposal event structure is sufficient to provide a two-way interface between a consumer component and the Proposal. However, since it is common in GUI front-ends to tie many components to a "model" object (the Proposal is a kind of model object), it is desirable to have a flexible mechanism for binding these components to the Proposal. The UICoordinator provides this additional level of functionality. Specifically, UICoordinator provides these features: The UI components have a single point to register their interest in a proposal. The component can specify which types of Proposal events it is interested in tuning in on (event filtering). The component can further specify which particular Proposal fields it is interested in observing. The coordinator will only notify of change to that particular field. The Coordinator can "autoregister" many components. "Autoregistration" needs additional explanation. Registration is the process by which a component makes itself known to the coordinator. In certain environments, it would be desirable for this registration to happen automatically. Consider a visual builder that constructs a GUI from "Proposal-aware" components. A coordinator might be dragged onto the visual palette to act as the intermediary for all activity between the Proposal and its components. These components--also dragged on to the GUI by developer--may number in the dozens: pushbuttons, fields, fieldPanels, labels, etc. All will need registration to the coordinator. In most GUI environments this represents separate gestures that "link" the coordinator to the component. Autoregistration is the aspect of this system that automatically provides the linkage, assuming there is no ambiguity. The coordinator initiates autoregistration after all the components have had a chance to register manually. It visits its parent "container" and takes a scan at all its descendents; in a GUI this means it asks its parent window for a list of all descendents. It then goes through each, spots the "Proposal-aware" ones (that is, the candidates for registration), then invites each to dynamically register. The table below shows the interactions between component, coordinator, and Proposal.
______________________________________
Proposal Coordinator A Component
______________________________________
Initialize:
An external component
initializes. It sends the
Coordinator register
method
Register:
Coordinator invokes
the Component
register method
Register:
Component answers with
a detailed list of which
Proposal event
it's interested in.
Autoregister:
Coordinator checks
around its GUI
"neighborhood"
(searches all
components that are
children of my parent
container) and reminds
still unregistered
components to register
Notify:
Proposal fire Proposal-
level Event (any event
above except
FIELD.sub.-- CHANGED)
Update:
Coordinator notifies all
component who've
registered interest in
specific
NotifyField:
Proposal fires Field-
level event
(FIELD.sub.-- CHANGED)
and cities particular
field
UpdateField:
Coordinator notifies all
components interested
in particular field
______________________________________
7. Knows How to Interact with Server The last section examined how the Proposal interacts with the front end. Now we examine how it will interact with the back end. The back end is where the managed resource (usually data but sometimes data and behavior) lives. This is a typically some sort of database, transaction processing environment, or more recently, object environment. In all of these cases the Proposal architecture "proposes" and the backend "disposes" of the Proposal. The invention provides a separate interface for each of three styles of back end "resource coordinator." All three of these ResourceCoordinators share a common superclass. In most operating environments a particular user would only use one of these three back end alternatives, depending on the needs and legacy of his system architecture. To allow for a Proposal conversation to reach all the way from Proposal to ultimate resource, the invention implements two translation stages: low-level, which links Backend Coordinator to ResourceCoordinator, and high-level, which links Proposal to Backend Coordinator. Low-level translation--BackendCoordinator to ResourceCoordinator The low-level translation provides the mapping between the BackendCoordinator 1702 and the diverse backend resource types. Internally the BackendCoordinator issues its request to the subclasses using a standard set of inputs: Type of low-level operation being performed 1. Select--read data by keys from the resource 2. Insert--insert data into the resource 3. Update--update resource data that matches the key 4. Delete--delete resource data that matches the key FieldGroup being worked on List of fields manipulated To make sense of how we can map these operations to the lower-level resources requires that we understand more about the precise interface style of each resource. Referring to FIG. 17, in very general terms, these three backend ResourceCoordinators represent the three ways that any client can interact with any server through the Proposal 1701 and the Backend Coordinator 1702 Data-oriented interface (DBCoordinator) 1703 Used with a database backend. Interaction is characterized by a standard data manipulation operation on specified data. Function-oriented interface (TPCoordinator) 1704 Used with any kind of function-oriented server (TP monitor, RPC, DCE, etc.). Interaction is characterized by a verb (function to be invoked) and arguments to the function. Object-oriented interface (OOCoordinator) 1705 Used with an interface to any OO environment. Interaction is characterized as a message with arguments sent to a particular object that interprets the message in its own particular way. The following table summarizes how the inputs listed at the top of the page match the particular characteristics of each ResourceCoordinators.
______________________________________
DBCoordinator
TPCoordinator
OOCoordinator
______________________________________
Operations
Operations Operation is
Operation dictates
directly equal
param to choice of object
SQL verbs FunctionMapper
resolution
FieldGroups
FieldGroup FieldGroup is
FieldGroup
equals relational
param to equals target
table FunctionMapper
class
Fields Fields equal
Fields are input to
Fields match
relational fields
DataMapper accessor methods
______________________________________
Comments on the DBCoordinator Column This is the simplest form of back end mapping. BackendCoordinator operations exactly match the SQL DML verbs, FieldGroups=Tables, Fields=fields Comments on the TPCoordinator Column This is the most complex form of back end mapping. There are no standards whatsoever for implementing business function in a function-oriented server (such as a TP monitor). The FunctionMapper is a Visitor object (user-supplied class) that takes two inputs: Action and FieldGroup. These two inputs are used to compute the server function to be executed; for example, Operation Select on FieldGroup Employee might compute a result that is ReadEmployeeData. The actual method of computation is left up to each installation of the invention. A simple form might be a two dimensional array that fills in all possible functionNames for each of the four operations and all the FieldGroups. Alternatively, a more architected solution would be to support invention-compatible naming conventions that would simply map to something like SelectEmployee. This last solution makes the FunctionMapper trivial but assumes that the server behavior has been explicitly modified for the invention. The DataMapper is a Visitor object that maps input arguments and return values (resultsets). The values that are passed (or returned) are simply lists of Field objects. For example, a TerminateEmployee might define the Field object EmployeeNumber and TerminationDate. The DataMapper allows these fields to be converted to the appropriate values that interface to the signature of the TerminateEmployee transaction. Like the FunctionMapper above, the DataMapper is user-supplied. It can be complex if it is interfacing to a server that has no previous knowledge of the invention. Conversely, if field arguments are architected to match between the resource and the invention, the DataMapper might do nothing at all. Comments on the OOCoordinator Column The OOCoordinator falls somewhere between the previous two in terms of complexity. Depending on the outcome of Business Object standards they could quite readily become as trivial as the DBCoordinator. Two of the three interface categories (FieldGroup becomes class; Field becomes accessor) provide a simple interface, assuming that the backend implementation has conformed to the standards outlines above. The Action operation depends on currently non-standardized object instantiation and access rules. Various ObjectDatabase technologies resolve these issues with propriety command sets. Failing that, an object implementer can use the Flyweight pattern to implement conformant activity. Action mapping involves using the keys for the object Logical Object ID (LOID). The actions correspond to: 1. select--access an object in domain space by keys (LOID) 2. insert--instantiate an object with keys=LOID 3. update--modify the object with keys=LOID 4. delete--stop referencing object with keys=LOID High-Level Translation--Proposal to BackendCoordinator The high-level translation converts the more coarse-grained Proposal operations into the finer-grained low-level operations seen above. The high-level resource operations that the Proposal uses are the following: Populate Populate is used when a FieldGroup needs its data fields filled. For example, a MeritIncrease proposal might take an EmployeeId and look up relevant employee info (e.g., Name and CurrentSalary) and fill it in to the FieldGroup. Commit Commit is used when a consumer has indicated that a Proposal is ready to be transacted. The FieldGroups data is then moved over to the BackendCoordinator. Validate Validate is used immediately before the commit (or earlier in a Proposal life if the consumer wishes) to validate that the data currently held in the Proposal is still current with the data that is kept on the server. The order of invocation of these operations is qualified by a parameter in the FieldGroupSpec class of the PropSpec called InteractionMode. The InteractionMode defines the context of the resource action sufficient to allow the BackendCoordinator to translate it into the appropriate low-level actions. The values of the InteractionMode are: InteractionMode: New This FieldGroup subtree is "New" to the resource. It requires that at populate time it does not preexist in the resource. It requires that at commit time it can be inserted in the resource. InteractionMode: Exists This FieldGroup subtree currently "Exists" in the resource. It requires that at populate time it preexists in the resource. InteractionMode: Update This FieldGroup subtree is going to be "Updated" in the resource. It requires that at populate time it preexists in the resource. It requires that at commit time it is updated in the resource. InteractionMode: Delete This FieldGroup subtree is going to be "Deleted" from the resource. It requires that at populate time it preexists in the resource. It requires that at commit time it will be committed. InteractionMode: <user-defined> A user-defined InteractionMode has been defined. It will be implemented by a Visitor pattern (user-exit). Notice from the PropSpec Class Diagram that each FieldGroup of the PropSpec tree has its own value for InteractionMode. While it is most common for all the FieldGroups in a PropSpec to have the same InteractionMode (e.g., all parts of an OrderEntry Proposal object are "New"), it is sometimes useful to have mixed subtrees of InteractionMode usage (e.g., an ExtendSubscription Proposal (IM: New) may include an optional AddressChange (IM: Update) subtree). The following tables show the full set of interactions for Proposal activity interacting with the back end. There is one table for each of the predefined InteractionModes. Note that a particular user can define his own table for highly-specialized InteractionModes. (Note: Where the diagrams below refer to "Event: Validate", this deals with the optimistic concurrency control that is discussed in the next section. See the next section for details.)
______________________________________
InteractionMode: New
Consumer Proposal BackendCoord
______________________________________
Starts work on
a new Proposal
Event: NEEDS.sub.-- KEY
Supplies keys
Event: Populate
Select from
FieldGroup
by keys
If EXISTS,
raise error
ELSE sets
FieldGroup to
DefaultValues
for Fields
Event:
NEEDS.sub.-- NONKEY
Supplies data
Commit
Event: Commit
Insert FieldGroup
Proceed to
children and
continue
______________________________________
8. Protects Against Stale Data The invention's design creates a potential data integrity problem that must be guarded against. In many cases, data will be removed from the datastore (via a Populate) and stored for some period of time in the Proposal itself. This time period can be a few seconds, or it can be several weeks or months. During this period, the data back on the server might change while, of course, the replicated data in the Proposal would not. This mismatch could cause data corruption when the Proposal is eventually submitted and the data rewritten. Even without such a possibility (as in InteractionMode: Exists), the data the user is working on is still "stale". The invention resolves this problem with a well-documented technique usually called either "optimistic concurrency control" or "optimistic locking ". However, the invention's approach is unusual in the following ways: The approach builds the supplementary information needed to perform reasonable optimistic techniques right into the PropSpec 1801 technique as seen in FIG. 18. A variety of recovery mechanisms are designed into the architecture. The advantages to this approach are the following: Optimistic concurrency control typically requires significant application design and implementation work. By building in the structure of the solution, the invention makes most if not all of this work unnecessary carriage return. In cases where supplementary behavior is required (e.g., a Fixup Visitor), the user needs only to supply the particular algorithm. The rest of the concurrency framework is already in place. This approach does a much better job of resolving the "data interference" that stale data causes. Typically, optimistic techniques are used in the databases and their replicas. The problem with this approach is that, by the time the data is put into the database, it is a mere artifact of the data interference event that caused it. In the invention, however, the optimistic recovery environment is encapsulated within the event itself that knows the reason for the change. This is called "proximate intentionality". The closer a fixup method can be to the source of the problem, the better the chance of fixing it correctly. For example, an address change that has grown stale might be resolved differently depending on whether: a) parking spaces are being reassigned, b) the employee has died, or c) insurance renewal notices are about to be sent out. To implement optimistic techniques, the invention defines a set of objects called "Assumptions." They establish what is assumed to be consistent between the datastore and the Proposal replica. They also contain information that defines the disposition when a failure in the assumption is detected. With respect to FIG. 18, a class diagram shows the Assumptions class, and a FieldGroupSpec 1803.
______________________________________
Class Name Description
______________________________________
Assumptions Specification of optimistic
1804 concurrency constraints
State fieldList List of fields to watch for stale data
abortCommit
Should data interference cause the commit
to abort
notifyParty
Name or address of party to notify on data
interference
Behavior
detector Custom behavior to detect stale data
notifier Custom behavior to notify the notifyParty
fixup Custom behavior to attempt repair of
stale data
Pouch 1805 Container of optimistic concurrency values
State fieldGroup FieldGroup instance this valueSet
applies to
keys Field values of key fields for the
fieldGroup
originalFields
Original fields values of fieldGroup at
Populate time
______________________________________
Comments Assumptions are associated with the FieldGroup. Notice that the Assumption processing is fired when the high-level Validate resource operation is fired (see previous section). Though not shown in the interaction diagrams, a consumer can choose to invoke Validate any time in the life of a Proposal. While it must be fired during Commit processing (in the relevant InteractionModes), it can optionally be fired earlier to ensure that the data being worked on has not gotten stale. The original values of a FieldGroup (those that specified in the fieldList of the Assumptions) are retained in a special container object called the Pouch. This is required because the user could be making modifications in the very Proposal fields that need to be used subsequently to check currency. The default interference check is to check all fields in the datastore against all the matching fields in the Proposal. The <fieldList>value in the Assumption metadata allows a subset of fields to be checked. For example, in a well-architected system only a timestamp need be checked against the data that the Proposal holds. The default detect algorithm is to check that the value of the datastore data equals the value of the Proposal data. A user can configure other detection methods using a Visitor (e.g., in a temporal database, ensure that a date is within a datastore date range). AbortCommit is a flag that indicates whether or not commit processing should proceed when stale data has been detected. The Notifier is a Visitor that provides a mechanism for notifying the NotifyParty parameter that interference has happened. This notification could be any specified technique (a system alert, an email, a console message to an operator, etc.). NotifyParty is an opaque object used to provide whatever information is necessary to execute the Notifier. Fixup is a Visitor that provides a user-defined fixup procedure. For example, a common fixup might be LastUpdaterWins (compare replica with datastore; update with the later timestamp begins canonic). Some Proposals may be processed very quickly and not required Optimistic Concurrency Control. A Proposal Policy Visitor can specify user-defined locking policies. (e.g., Use standard (pessimistic) database locks until the user decides to "disconnect" from the server. Then switch to optimistic). The combination of the above techniques provides an enormous amount of flexibility. Essentially the developer can choose what combination of commit processing, notification, and fixup will happen for each instance of stale data is noticed. Tools Proposal Builder The ProposalBuilder has four tabbed panels on which a developer enters the specifications (PropSpec) for the new Proposal he wishes to build. Panel 1: Defining the Field Dictionary The field dictionary is the container that holds field definitions that are common across all Proposals in any Proposal family. These field definitions are stored in a text file FIELDS.DCT that exists in a repository subdirectory. Many such subdirectories can exist, each containing any number of PropSpecs. Referring to FIG. 19, the top three fields in the ProposalBuilder are outside of the tabbed space and contain information common to the whole PropSpec. They are: Repository 1901 The name of the subdirectory that contains the field dictionary file and all the PropSpec files that are associated with any family of Proposals. This "family" is heuristically defined as all proposals that share some common set of field definitions. For example, one repository might contain HR Proposals and another the Football Pool Proposals. Proposal Name 1902 This is the file name of the PropSpec that we are currently working on. It contains all the elements associated with a single Proposal. A Proposal can be of virtually any size. For example, a tax form with its many required and optional supporting schedules could be a sin | ||||||
