NAME | SYNOPSIS | DESCRIPTION | IMPLEMENTATION | NOTES | WARNINGS | SEE ALSO | AUTHORS |
Entity - Abstract base class ythat handles persistance.
Entity | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Namespace Procedure Constructors
Static Public Interface
Specific Private Interface
|
This section will walk through the process of specifying the Building Service entity as the example. Each Entity file contains a namespace definition, an initialization function, the standard procedure instantiations, and the specialized procedure defintions. Definition of an entity requires the following steps:
A namespace definition contains a definition of directives, attributes and their properties, and entity initializations. While an entity can map to several database tables, each namespace should map to a single table. A namespace definition can then pull in other namespaces for a multiple table mapping. Definition of a namespace requires the following steps:
The convention is to begin the Entity name with a capital letter. It does not have to be the same name as the underlying Table that the namespace represents. The convention in the example is to use the same name.
Initialize any immediate base classes or contained classes. Entity Initialization for BuildingService are as follows:
namespace eval BuildingService { variable this variable attr cariable oid variable dt variable buildingLocation # Insure the base class is initialized ServiceInit #Insure the refers to class is initialized #The refers to class is initialized in Service according to the model #Insure the contained class is Initialized #There are no contained classes . . . }
Each namespace contains certain required directives in a this array. These directives define the relationships of the entity to other entities and to the underlying database table or tables. Each directive will be described.
The directives provide a mapping from the entity to one or more database tables. An Entity can map to a single database table or to several database tables with the case of inheritance or other relationships. The following relationships can be encapsulated with an entity
An example of the directives for BuildingService is as follows:
namespace eval BuildingService { . . . #The directives #This is a derived class so a join is needed with the base class and any refers to classes #The from clause specifies the tables and aliases to be read in order from base to derived #Table specifies the derived table name and alias #Class specifies the namespace #Where specifies the join constraint #Hierarchy specifies the order of the tables to be written from base to derived set this(from) "ManagedObj m, Service s, ServiceDescription sd, BuildingService bs" set this(table) "BuildingService bs" set this(class) BuildingService set this(containedClass) {} set this(container) {ManagedObj} set this(where) "m.oid = s.managedObjOid and s.serviceDescriptionOid = sd.oid and bs.serviceOid = s.managedObjOid" set this(hierarchy) [list ManagedObj Service $this(class)] . . . }
Base class attributes must be imported before defining the derived class attributes. They are imported using the standard interface procedure, GetAttribute. The base class for BuildingService is Service as follows:
namespace eval BuildingService { . . . #Import the Base class attributes array set attr [Service::GetAttribute] . . . }
There are required attributes for different situations which are sumarized as follows
All attributes must map one-to-one to the columns of the table. The column names do not have to match the attribute names.
set attribute(enum) {tag value tag value ...}
set attribute(defWidth) [Entity::EnumMax $attribute(enum)]
An example of the attributes and properties for BuildingService is defined as follows:
namespace eval buildingService { . . . #Specify the derive class attributes #oid lappend this(attrs) oid set oid(type) Integer set oid(key) Foreign set oid(column) {bs.serviceOid) set oid(table) $this(class) set oid(defWidth) 9 set oid(label) {} set oid(default) {} set attr(oid) [array get oid] #dt lappend this(attrs) dt set dt(type) Text set dt(column) {bs.dt} set dt(table) $this(class) set dt(label) {(a,A - z,Z); 24 characters max} set dt(defWidth) 24 set dt(default) {} set attr(dt) [array get dt] #buildingLocation lappend this(attrs) buildingLocation set buildingLocation(type) Text set buildingLocation(table) $this(class) set buildingLocation(label) {(a,A - z,Z); 50 characters max} set buildingLocation(defWidth) 50 set buildingLocation(column) {bs.buildingLocation} set buildingLocation(default) {} set attr(buildingLocation) [array get buildingLocation] #Import base class attr list set this(attrs) [union $this(attrs) $Service::this(attrs)] }
This is the Entity namespace specification. Notice the easy mapping from the information in the object model. This is a candidate for automatic code generation.
The standard set of constructors are specified in the form
<standard procedure constructor> <newEntity::this(class)>
These are intialized outside the namepace definition.
//Always Specify EntityCreate $MyEntity::this(class) EntityQuery $MyEntity::this(class) EntityNext $MyEntity::this(class) EntityRefresh $MyEntity::this(class) EntityGetAttribute $MyEntity::this(class) EntityGetListOf $MyEntity::this(class) EntityRetrieve $MyEntity::this(class) EntityMdtRetrieve $MyEntity::this(class) EntityRetrieveOidBy $MyEntity::this(class) EntityRetrieveObjBy $MyEntity::this(class) EntityArrayCopy $MyEntity::this(class) EntityCount $MyEntity::this(class) //Optional EntityInsert $MyEntity::this(class) EntityInsertUpdate $MyEntity::this(class) EntityUpdate $MyEntity::this(class) EntityUpdateWhere $MyEntity::this(class) EntityDelete $MyEntity::this(class) EntityDeleteWhere $MyEntity::this(class) EntityContainedList $MyEntity::this(class) EntityContainer $MyEntity::this(class) EntityValue $MyEntity::this(class)
The behavior of an entity can be controlled by selective specification. Overriding the standard behavior is done by not specifying the constructor and redefining the standard procedure within this file. The following rules apply for different entities.
The namespace is loaded by the following initialization function. Invocation of this function causes the Tcl interpreter to load the namespace. It also allows the entity to be initialized with a different DbObject and connection instance.
proc BuildingServiceInit { {db DbObject} {connection 1} } { set BuildingService::this(dbObject) $db set BuildingService::this(inst) $connection }
Occasionally it is neccesary to override the standard interface procedure with one that enforces specific business rules. I provide an example of theServiceInsert override to implement the automatic linkage with the ServiceDescription instance. This example also serves to show how the standard interface is used within a program
proc BuildingService::Insert {objref} { upvar $objref obj variable this #Test if ServiceDescriptionOid or serviceName are provided and valid if {[ string match $obj(serviceDescriptionOid) {} ]} { #See if serviceName was provided if {[ string match $obj(serviceName) {} ]} { error "BuildingService::Insert failed. Object reference doesn't contain a ServiceDescriptionOid or serviceName." } else { #validate serviceName and obtain ServiceDescriptionOid set serviceOid [ServiceDecription::RetrieveOidBy serviceName $obj(serviceName)] if {[ string match $serviceOid {} ]} { error "BuildingService::Insert failed. The provided serviceName, $obj(serviceName), is not valid" } else { set obj(serviceDescriptionOid) $serviceOid } } else { #validate the serviceDescriptionOid if { ![ServiceDescription::Count * oid $obj(serviceDescriptionOid)] } { error "BuildingService::Insert failed. The provided serviceDescriptionOid is not valid." } } #Insert into Database return [Entity::Insert $this(class) obj] }
A template constructor that makes a Create procedure in the given entity namespace in the form,
This procedure is to be created on-the-fly right after the namespace is first created.
A template constructor that makes a ArrayCopy procedure in the given entity namespace in the form,
This procedure is to be created on-the-fly right after the namespace is first created.
A template constructor that makes a Query procedure in the given entity namespace in the form,
This procedure is to be created on-the-fly right after the namespace is first created.
A template constructor that makes a Next procedure in the given entity namespace in the form,
This procedure is to be created on-the-fly right after the namespace is first created.
A template constructor that makes a Insert procedure in the given entity namespace in the form,
This procedure is to be created on-the-fly right after the namespace is first created.
A template constructor that makes a InsertUpdate procedure in the given entity namespace in the form,
This procedure is to be created on-the-fly right after the namespace is first created.
A template constructor that makes a Update procedure in the given entity namespace in the form,
This procedure is to be created on-the-fly right after the namespace is first created.
A template constructor that makes an UpdateWhere procedure in the given entity namespace in the form,
proc <entity>::UpdateWhere { objref attr value {attr value} ...} : oidList
This procedure is to be created on-the-fly right after the namespace is first created.
A template constructor that makes a Delete procedure in the given entity namespace in the form,
This procedure is to be created on-the-fly right after the namespace is first created.
A different Delete procedure is created depending on whether the given entity contains the attribute, mdt.
A template constructor that makes a DeleteWhere procedure in the given entity namespace in the form,
proc <entity>::DeleteWhere { objref attr value {attr value} ...}
This procedure is to be created on-the-fly right after the namespace is first created.
A different DeleteWhere procedure is created depending on whether the given entity contains the attribute, mdt.
A template constructor that makes a Refresh procedure in the given entity namespace in the form,
This procedure is to be created on-the-fly right after the namespace is first created.
A template constructor that makes a GetAttribute procedure in the given entity namespace in the form,
proc <entity>::GetAttribute { {attribute {}} {property {}} {enumTagList {}} }
This procedure is to be created on-the-fly right after the namespace is first created.
A template constructor that makes a Value procedure in the given entity namespace in the form,
This procedure is to be created on-the-fly right after the namespace is first created.
A template constructor that makes a RetrieveOidBy procedure in the given entity namespace in the form,
This procedure is to be created on-the-fly right after the namespace is first created.
A template constructor that makes a RetrieveObjBy procedure in the given entity namespace in the form,
This procedure is to be created on-the-fly right after the namespace is first created.
A template constructor that makes a GetListOf procedure in the given entity namespace in the form,
This procedure is to be created on-the-fly right after the namespace is first created.
A template constructor that makes a Count procedure in the given entity namespace in the form,
This procedure is to be created on-the-fly right after the namespace is first created.
A template constructor that makes a ContainedList procedure in the given entity namespace in the form,
proc <entity>::ContainedList { containerOid {selectList {}} }
This procedure is to be created on-the-fly right after the namespace is first created.
A template constructor that makes a Container procedure in the given entity namespace in the form,
proc <entity>::Container { oid objref } :1(Success), 0(failure)
This procedure is to be created on-the-fly right after the namespace is first created.
A template constructor that makes a Retrieve procedure in the given entity namespace in the form,
This procedure is to be created on-the-fly right after the namespace is first created.
A template constructor that makes a MdtRetrieve procedure in the given entity namespace in the form,
This procedure is to be created on-the-fly right after the namespace is first created.
A template constructor that makes a Transition procedure in the given entity namespace in the form,
This procedure is to be created on-the-fly right after the namespace is first created.
This procedure initializes the given objref name into an array with the attributes given in selectList. the attributes, oid, mdt, and dt are always included if they exist in the entity. If no attributes are given, the array is initialized with all attributes in the entity object of the given class. The array attributes are initialized to the default values. No interaction with the database occurs.
- Example Usage
Building::Create b "createDate"- Creates an array with default values
b(oid) {} b(mdt) {} b(dt) {} b(createDate) function getdate()
This Procedure is a wrapper which passes the entity class into the static procedure, Entity::Create, which fully implements the behavior.
Created by a template constructor, EntityCreate
This procedure returns a copy array list of the given objref array. If a selectList is provided, the returned array list contains only copies of the specified items plus internals such as oid, dt, and mdt. If no selectList is provided, it copies the entire entity-defined array. This can act as a filter to remove any composite attributes. It
- Example Usage
array set newManagedObj [ManagedObj::ArrayCopy t "action adminState"]- Copies the array t, into newManagedObj but only the following values
newManagedObj(oid) 25002432 newManagedObj(mdt) Building newManagedObj(dt) {} newManagedObj(action) I: Inserted newManagedObj(adminState) U: Unlocked
This Procedure is a wrapper which passes the entity class into the static procedure, Entity::ArrayCopy, which fully implements the behavior.
Created by a template constructor, EntityArrayCopy
This procedure sets up a query that may involve a join across multiple tables, depending on how the entity is defined. The given objref array specifies the attributes that are to be retrieved. The where clause and order by clause specify the filtering and ordering of the retrieved results. Since the where and order clauses are raw SQL strings, the application programmer is encouraged to define new member procedures so these SQL specifications remain private to this object. It is implemented by calling DbObject::Query
- Example Usage
ManagedObj::Query m "coid = $parentOid" "oid asc"- This send off a query for the attributes contained in array m where the coid=parentOid. Results are retrieved by ManagedObj::Next is ascending order by oid.
This Procedure is a wrapper which passes the entity class into the Database interface class procedure, DbObject::Query, which fully implements the behavior.
Created by a template constructor, EntityQuery
This procedure retrieves the query results. It is important that the given objref array is the same as the array used in Entity::Query. Each attribute is given the value returned by the query and an oid is also assigned if the return code is 1. It is implemented by calling DbObject::Next
- Example Usage
while {[ManagedObj::Next m ]} { parray m }- This procedure loads the array m with the contents of a query and returns a 1. When no more information is available, the procedure returns 0
This Procedure is a wrapper which passes the entity class into the Database interface class procedure, DbObject::Next, which fully implements the behavior.
Created by a template constructor, EntityNext
This procedure inserts the object into the database. If the object is implemented as an inheritance hierarchy, it will divide the data acording to table and inserts it into the all of the proper tables in the proper order, thus hiding the inheritance implementation. It also automatically does the derived and most derived type bookkeeping. The oid is returned. It
- Example Usage
set newOid [ManagedObj::Insert m]- This procedure inserts the entity into the database using the information inside array m and returns the oid. It also sets m(oid).
This Procedure is a wrapper which passes the entity class into the static entity procedure, Entity::Insert, which fully implements the behavior.
Created by a template constructor, EntityInsert
This procedure will search for an object specified by the attr and value pairs. One or more attribute and value pairs may be specified in the args list. A "!" preceding the value in the parameter list translates to attr !=value in the constructed where clause. If the object is not found, this procedure inserts the object and returns the oid. If the object is found, this procedure updates the object and returns the oid.
- Example Usage
Service::InsertUpdate s owner $owner serviceName !ARAMARK- This procedure searches the database using the where clause, where owner=$owner and serviceName !=ARAMARK. If the object is not found, this procedure inserts the object into the database using the data in s. If the object is found, this procedure updates the object in the database using the data in s.
This Procedure is a wrapper which passes the entity class into the static entity procedure, Entity::InsertUpdate, which fully implements the behavior.
Created by a template constructor, EntityInsertUpdate
This procedure updates the object represented by the given objref array. This array must contain a valid oid. Only the values of the attributes represented in the array are updated in the database so parts of the object can be updated. If the object is implemented as an inheritance hierarchy, it will divide the data acording to table and update it into the all of the proper tables in the proper order, thus hiding the inheritance implementation. It
- Example Usage
set m(action) [ManagedObj::GetAttribute action enum inserted] ManagedObj::Update m- This procedure update the entity in the database using the information inside array m
This Procedure is a wrapper which passes the entity class into the static entity procedure, Entity::Update, which fully implements the behavior.
Created by a template constructor, EntityUpdate
This procedure is used to make updates to multiple instances in a single transaction. This procedure updates any instance whose value(s) match the given attribute(s). It returns an oidList of the instances that were updated. It
This procedure deletes the entity represented by the given objref array. It requires attributes, oid, mdt (for inheritance), and coid (for containment), since this tells the procedure which entity(s) to delete. If the object crosses multiple tables, this procedure will delete all data relating to the object. If <entity>::Delete is called on a base class, the entire entity is deleted since delete is implemented by calling DbObject::Delete on the most derived type, mdt. If the entity contains other entities, a delete operation is executed on each of these contained entities. It
- Example Usage
ManagedObj::Delete m- This procedure deletes the entity in the database using the information inside array m
This Procedure is a wrapper which passes the entity class into the static entity procedure, Entity::Delete, which fully implements the behavior. If mdt exists and is set, the mdt class is passed to the procedure so the most derived entity and its inheritance chain is properly deleted.
Created by a template constructor, EntityDelete
This procedure is used to delete multiple instances in a single transaction. This procedure deletes any instance whose value(s) match the given attribute(s). It
This procedure refreshes the data in the object represented by the given objref array. The only required attribute value is the oid since this tells the procedure which object to refresh. The attributes in the array indicate what data is to be refreshed. If the object crosses multiple tables, this procedure will refresh all data in the objref array.
- Example Usage
ManagedObj::Refresh m- This procedure refreshes the data in array m from the database. It returns a 1 if successful.
This Procedure is a wrapper which passes the entity class into the static entity procedure, Entity::Refresh, which fully implements the behavior.
Created by a template constructor, EntityRefresh See Entity::Refresh
This procedure retrieves an object given by oid and populates the given objref array. It is a shortcut for the programmer if the oid is known. If selectList is given, only those attributes are populated in the array. It
- Example Usage
ManagedObj::Retrieve $oid m- This procedure loads the data in the given array name m from the database object indicated by $oid. It returns a 1 if successful.
ManagedObj::Retrieve $oid m "action adminState coid"- This procedure loads the array name t with the data, (oid, mdt, dt are loaded by default), action, coid, and adminState from the database object indicated by $oid. It returns 1 if successful
This Procedure is a wrapper which passes the entity class into the static entity procedure, Entity::Retrieve, which fully implements the behavior.
Created by a template constructor, EntityRetrieve
This procedure retrieves a most derived object given by oid and populates the given objref array. This procedure is called from a base class and retrieves its most derived class. It is a shortcut for the programmer if the oid is known. It
- Example Usage
ManagedObj::MdtRetrieve $oid m- This procedure loads the data in the given array name m from the database object indicated by $oid.
- If the $oid belongs to a derived class of ManagedObj (Building for example), this procedure loads the data in the given array name m from the derived database object. It returns 1 if successful.
This Procedure is a wrapper which passes the entity class into the static entity procedure, Entity::MdtRetrieve, which fully implements the behavior.
Created by a template constructor, EntityMdtRetrieve
This procedure retrieves the static attribute property information for the given class.
- Example Usage
array set attr [ManagedObj::GetAttribute]The attr array is an array of all attributes and their properties for the entire entity. This is used to populate a derived entity with the base class entity attributes.
array set mdt [ManagedObj::GetAttribute mdt]mdt is an array of the properties of the mdt attribute in the entity. This is used whenever the programer wants to pick and choose certain attributes for an entity such as a view management entity.
mdt(type) Text mdt(column) m.mdt mdt(table) ManagedObj mdt(label) {(a,A - z,Z); 10 characters max} mdt(defWidth) 10 mdt(default) {} set column [ManagedObj::GetAttribute mdt column]This retrieves the column name (for example m.mdt) for the mdt attribute.
array set domain [ManagedObj::GetAttribute action enum]This creates an array, domain, as follows
action(inserted) I: Inserted action(updated) U: Updated action(deleted) D: Deleted set domain [ManagedObj::GetAttribute action enum updated]This returns the value of the production enumeration, U: Updated
set values [ManagedObj::GetAttribute action enum "inserted deleted"]This returns the values of the specified tags, {I: Inserted} {D: Deleted}
set tags [ManagedObj::GetAttribute action enum tags]This returns a tcl list of the domain tags, inserted, updated, deleted.
set values [ManagedObj::GetAttribute action enum valuesThis returns the list of values to the enumerations, {I: Inserted} {U: Updated} {D: Deleted}
This Procedure is a wrapper which passes the entity class into the static entity procedure, Entity::GetAttribute, which fully implements the behavior.
Created by a template constructor, EntityGetAttribute
Inputs | Returns |
---|---|
no parameters | The list of all of the attributes and their properties. Use "array set to form an array of attributes. |
<attribute> | The list of all of the properties for that attribute. Use "array set to form an array of properties for that attribute |
<attribute> <property> | A single value for the property of that attribute. |
<attribute> enum <tag> | A single corresponding enumerated value of the form, {T: Verbose} |
<attribute> enum <tagList> | A list of corresponding enumerated values of the form, {T: Verbose} |
<attribute> enum tags | A list of allowable enumeration tags that are used in the code. |
<attribute> enum values | A list of allowable enumeration values of the form, {T: Verbose} |
This procedure will find the objects contained within the object of given containerOid. It returns a list of entities. If the selectList is given, it only returns the values specified. It
- Example Usage
foreach objList [BuildingService::ContainedList $containerOid] { array set bs $objList parray bs }- This procedure returns a list of BuildingService arrays that are contained within the entity of oid $containerOid.
This Procedure is a wrapper which passes the entity class into the static entity procedure, Entity::ContainedList, which fully implements the behavior.
Created by a template constructor, EntityContainedList
This procedure, given the containee oid, polymorphically retrieves its container object and populates the container objref array. It is a shortcut for the programmer if the oid is known. It
- Example Usage
BuildingService::Container $oid b- This procedure loads the Building data in the given array name, b from the database object indicated by oid by using the retieved object's coid. It returns a 1 if successful.
This Procedure is a wrapper which passes the entity class into the static entity procedure, Entity::Container, which fully implements the behavior.
Created by a template constructor, EntityContainer
This procedure can be used to produce a list for optionMenus etc. It returns a list of all values in the database corresponding to the given attribute. This procedure is only applicable to tables such as static tables where the given attr is unique. It
- Example Usage
set valueList [ServiceDescription::GetListOf serviceName]- This procedure returns a list of service names to populate, for example, and option menu.
This Procedure is a wrapper which passes the entity class into the static entity procedure, Entity::GetListOf, which fully implements the behavior.
Created by a template constructor, EntityGetListOf
This procedure can be used to count instances. If no attr is given or '*' is specified, it returns a count of all instances. If attr is provided, it returns a count of all distinct values for that attribute. The parameter, args (otherwise shown as {attr value} ...), if given, will define a where clause using attr-value pairs that further constrains the count. A "!" preceding the value in the arg list translates to attr !=value in the constructed where clause. This procedure is only applicable to tables such as static tables where the given attr's values are unique. It
- Example Usage
set count [BuildingService::Count]- or
set count [BuildingService::Count *]- This procedure (either form) counts the number of BuildingService instances.
set count [BuildingService::Count serviceName]- This procedure counts the number of distinct serviceNames in the BuildingService instances.
set count [BuildingService::Count serviceName serviceType food]- This procedure counts the number of distinct serviceNames of the serviceType food.
set count [BuildingService::Count * serviceType food]- This procedure counts the total BuildingService instances of the serviceType food.
This Procedure is a wrapper which passes the entity class into the static entity procedure, Entity::Count, which fully implements the behavior.
Created by a template constructor, EntityCount
This procedure can be used to populate oids in entities. It will search for the given attributes and their corresponding unique values specified in attr, value and the args list. One or more attribute and value pairs may be specified in the args list. A "!" preceding the value in the parameter list translates to attr !=value in the constructed where clause. A list of Oids is returned. The procedure RetrieveOidBy
- Example Usage
set oid [lindex [Building::RetrieveOidBy buildingName $buildingName buildingNumber !101] 0]- This procedure returns a list of oids for the Building entity of the given buildingName and buildingNumber attributes. The where clause constructed would be as follows: where buildingName=$buildingName and buildingNumber !=101
This Procedure is a wrapper which passes the entity class into the static entity procedure, Entity::RetrieveOidBy, which fully implements the behavior.
Created by a template constructor, EntityRetrieveOidBy
This procedure will find the objects in the entity that match the given attributes and their corresponding unique values specified in attr, value and the args list. One or more attribute and value pairs may be specified in the args list. A "!" preceding the value in the parameter list translates to attr !=value in the constructed where clause. It returns a list of entity objects. The procedure RetrieveObjBy
- Example Usage
foreach objList [Building::RetrieveObjBy buildingName $buildingName buildingNumber !101] { array set building $objList parray building }- This procedure returns a list of Building objects that are found matching the specified values of the attributes buildingName and buildingNumber defined in attr, value and the args list. The where clause constructed would be as follows: where buildingName=$buildingName and buildingNumber !=101
This Procedure is a wrapper which passes the entity class into the static entity procedure, Entity::RetrieveObjBy, which fully implements the behavior.
Created by a template constructor, EntityRetrieveObjBy
This procedure is a generic accessor function for setting or getting a single value. If value is not given, a single value for the entity is returned from the database. If value is given, the single value is saved to the database. It
- Example Usage
set buildingName [Building::Value $oid buildingName]- This procedure returns the buildingName for the Building entity of the given $oid.
Building::Value $oid buildingName $buildingNameThis allows the buildingName attribute to be set to the value $buildingName in the Building entity, $oid.
This Procedure is a wrapper which passes the entity class into the static entity procedure, Entity::Value, which fully implements the behavior.
Created by a template constructor, EntityValue
This procedure searches the given list for the given terse or verbose value and returns the enum value of form {Terse: Verbose} if found. It returns the given value if not found.
This procedure returns the verbose portion of the enumValue; the portion to the right of the colon.
This procedure returns the terse portion of the enumValue; the portion to the left of the colon.
This procedure returns the tag portion of the enumValue.
This procedure returns a list of the maximum terse and verbose lengths on the given enumList. This is used for user input for view management settings for column width.
This procedure returns a list of database tables represented by the attributes in the given objref. It is used by an entity class to determine which tables need to be touched when modifying the database.
This procedure returns the list of attribute-value pairs that belong to the given database table. If an entity object spans two or more database tables, that object, objref, will contain attributes and values that belong to more than one. This procedure returns an instance that corresponds to the given table. this procedure is used by an entity class when modifying the database since it must update one table at a time. It
This procedure converts a list of attribute-value pairs, {attr1 value1 attr2 %value2 attr3 !value3 attr4 !value4% attr5 <value5 attr6 >value6 attr7 !>value7} into a where string of the form:
attr1=value1 and attr2 like %value2 and attr3 !=value3 and attr4 not like value4% and attr5<=value5 and attr6 >=value6 and attr7<value7
If a value is proceeded by a "!" sign, as in our example, this translates into a "!=" or a "not like" in the where clause. The wildcard, "%" is accepted anywhere in the value string. Its presence in the string results in a "like" or "not like" match. If the value is preceeded by a "<" or ">", this translates into "<=" or ">=" respectively. If the value is preceeded by "!<" or "!>", this translates into the negation of "<" or ">", namely ">" or "<", respectively. Note that ">" really means ">=", and its negation is "<". This is especially useful for comparing dates. For example,
set oidList [Building::RetrieveOidBy createDate "<function getdate()"]
This will retrieve an oids that have a createDate < the current time. It
This procedure builds the body of an "order by" clause (excluding the SQL keywords "order by" from an entity of the given class. It has two forms, in one, the attributes and sorting orders (ascending or descending) are passed as a single list, or alternately, each attribute and sorting order is passed as an individual argument.
More specifically, this procedure:
This procedure is used to bring a finite state machine to its next state given an event. The object that uses this must have the state machine defined in an fsm array in its namespace constructor. e.g. "set MyClass::fsm(initialState, anEvent) {ready MyClass::MakeReady}" would be the state information needed to move from initialState to ready for an event of anEvent. MyClass::MakeReady would be the procedure executed on the state change. If no proc is to be executed, use the word, null, as the procedure name. The attribute, fsmState must be the attribute of the object and obj(fsmState) must be intialized to the beginning state.
namespace eval Entity { }
proc EntityCreate {entity} { namespace eval $entity { lappend this(procedures) Create proc Create {objref {selectList {}}} { upvar $objref obj variable this if [catch {Entity::Create $this(class) obj $selectList} result] { error "[lindex [info level 0] 0] $result" } } } }
proc EntityArrayCopy {entity} { namespace eval $entity { lappend this(procedures) ArrayCopy proc ArrayCopy { objref {selectList {}} } { upvar $objref obj variable this if [catch {set rtn [Entity::ArrayCopy $this(class) obj $selectList]} result] { error "[lindex [info level 0] 0] $result" } return $rtn } } }
proc EntityQuery {entity} { namespace eval $entity { lappend this(procedures) Query proc Query { objref {where {}} {order {}} } { upvar $objref obj variable this set DbObject [set $this(class)\::this(DbObject)] if [catch {$DbObject\::Query $this(class) obj $where $order} result] { error "[lindex [info level 0] 0] $result" } } } }
proc EntityNext {entity} { namespace eval $entity { lappend this(procedures) Next proc Next {objref} { upvar $objref obj variable this set DbObject $this(DbObject) if [catch {set rtn [$DbObject\::Next $this(class) obj]} result] { error "[lindex [info level 0] 0] $result" } return $rtn } } }
proc EntityInsert {entity} { namespace eval $entity { lappend this(procedures) Insert proc Insert {objref} { upvar $objref obj variable this if [catch {set rtn [Entity::Insert $this(class) obj]} result] { error "[lindex [info level 0] 0] $result" } return $rtn } } }
proc EntityInsertUpdate {entity} { namespace eval $entity { lappend this(procedures) InsertUpdate proc InsertUpdate {objref attr value args} { upvar $objref obj variable this set argList [list $this(class) obj $attr $value] foreach item $args {lappend argList $item} if [catch { set rtn [eval Entity::InsertUpdate $argList] } result] { error "[lindex [info level 0] 0] $result" } return $rtn } } }
proc EntityUpdate {entity} { namespace eval $entity { lappend this(procedures) Update proc Update {objref} { upvar $objref obj variable this if [catch {set rtn [Entity::Update $this(class) obj]} result] { error "[lindex [info level 0] 0] $result" } } } }
proc EntityUpdateWhere {entity} { namespace eval $entity { lappend this(procedures) UpdateWhere proc UpdateWhere {objref attr value args} { upvar $objref obj variable this set argList [list $this(class) obj $attr $value] foreach item $args {lappend argList $item} if [catch { set objList [eval Entity::UpdateWhere $argList] } result] { error "[lindex [info level 0] 0] $result" } return $objList } } }
proc EntityDelete {entity} { upvar #0 $entity\::attr attr if [info exists attr(mdt)] { namespace eval $entity { lappend this(procedures) Delete proc Delete {objref} { upvar $objref obj variable this if {[info exists obj(mdt)] == 0 || [string compare $obj(mdt) {}] == 0} { error "[lindex [info level 0] 0] Mdt not set, Cannot Delete" return } #Now delete the object in question if [catch {set rtn [Entity::Delete $obj(mdt) obj]} result] { error "[lindex [info level 0] 0] $result" } } } } else { namespace eval $entity { lappend this(procedures) Delete proc Delete {objref} { upvar $objref obj variable this if [catch {Entity::Delete $this(class) obj} result] { error "[lindex [info level 0] 0] $result" } } } } }
proc EntityDeleteWhere {entity} { namespace eval $entity { lappend this(procedures) DeleteWhere proc DeleteWhere {attr value args} { variable this set argList [list $this(class) $attr $value] foreach item $args {lappend argList $item} if [catch {eval Entity::DeleteWhere $argList} result] { error "[lindex [info level 0] 0] $result" } } } }
proc EntityRefresh {entity} { namespace eval $entity { lappend this(procedures) Refresh proc Refresh {objref} { upvar $objref obj variable this if [catch {set rtn [Entity::Refresh $this(class) obj]} result] { error "[lindex [info level 0] 0] $result" } return $rtn } } }
proc EntityGetAttribute {entity} { namespace eval $entity { lappend this(procedures) GetAttribute proc GetAttribute {{attribute {}} {property {}} {enumTagList {}} } { variable this if [catch {set rtn [Entity::GetAttribute $this(class) $attribute $property $enumTagList]} result] { error "[lindex [info level 0] 0] $result" } return $rtn } } }
proc EntityValue {entity} { namespace eval $entity { lappend this(procedures) Value proc Value { oid attr {value {}} } { variable this if [catch {set value [Entity::Value $this(class) $oid $attr $value]} result] { error "[lindex [info level 0] 0] $result" } return $value } } }
proc EntityRetrieveOidBy {entity} { namespace eval $entity { lappend this(procedures) RetrieveOidBy proc RetrieveOidBy { attr value args } { variable this set argList [list $this(class) $attr $value] foreach item $args {lappend argList $item} if [catch { set oidList [eval Entity::RetrieveOidBy $argList] } result] { error "[lindex [info level 0] 0] $result" } return $oidList } } }
proc EntityRetrieveObjBy {entity} { namespace eval $entity { lappend this(procedures) RetrieveObjBy proc RetrieveObjBy { attr value args } { variable this set argList [list $this(class) $attr $value] foreach item $args {lappend argList $item} if [catch { set objList [eval Entity::RetrieveObjBy $argList] } result] { error "[lindex [info level 0] 0] $result" } return $objList } } }
proc EntityGetListOf {entity} { namespace eval $entity { lappend this(procedures) GetListOf proc GetListOf { attr args } { variable this set argList [list $this(class) $attr] foreach item $args {lappend argList $item} if [catch { set attrList [eval Entity::GetListOf $argList] } result] { error "[lindex [info level 0] 0] $result" } return $attrList } } }
proc EntityCount {entity} { namespace eval $entity { lappend this(procedures) Count proc Count { {attr *} args } { variable this set argList [list $this(class) $attr] if {[llength $argList] == 1} { set argList [lindex $argList 0] } foreach item $args {lappend argList $item} if [catch { set count [eval Entity::Count $argList] } result] { error "[lindex [info level 0] 0] $result" } return $count } } }
proc EntityContainedList {entity} { namespace eval $entity { lappend this(procedures) ContainedList proc ContainedList { containerOid {selectList {}} } { variable this if [catch {set containedList [Entity::ContainedList $this(class) \ $containerOid $selectList] } result] { error "[lindex [info level 0] 0] $result" } return $containedList } } }
proc EntityContainer {entity} { namespace eval $entity { lappend this(procedures) Container proc Container { oid objref } { upvar $objref obj variable this if [catch { set rtn [Entity::Container $this(class) $oid obj] } result] { error "[lindex [info level 0] 0] $result" } return $rtn } } }
proc EntityRetrieve {entity} { namespace eval $entity { lappend this(procedures) Retrieve proc Retrieve { oid objref {selectList {}} } { upvar $objref obj variable this if [catch { set rtn [Entity::Retrieve $this(class) $oid obj $selectList] } result] { error "[lindex [info level 0] 0] $result" } return $rtn } } }
proc EntityMdtRetrieve {entity} { namespace eval $entity { lappend this(procedures) MdtRetrieve proc MdtRetrieve { oid objref } { upvar $objref obj variable this if [catch { set rtn [Entity::MdtRetrieve $this(class) $oid obj] } result] { error "[lindex [info level 0] 0] $result" } return $rtn } } }
proc EntityTransition {entity} { namespace eval $entity { lappend this(procedures) Transition proc Transition { event objref } { upvar $objref obj variable this if [catch { Entity::Transition $this(class) $event obj } result] { error "[lindex [info level 0] 0] $result" } return } } }
proc Entity::GetAttribute { class {attribute {}} {property {}} {enumTagList {}} } { upvar #0 $class\::attr attr set valueList {} #if no attribute is given return the entire set if {[string compare $attribute {}] == 0} { return [array get attr] } else { #Does it exist? if {[info exists attr($attribute)] == 0} {return {}} #If no property is given return the entire attribute instance if {[string compare $property {}] == 0} { return $attr($attribute) } else { #Return the property of the attribute array set attrArray $attr($attribute) #Does it exist? If so, return the property value if {[info exists attrArray($property)] == 0} {return {}} switch -- $property { enum { if {[string compare $enumTagList {}] == 0} { return $attrArray($property) } else { array set enum $attrArray(enum) switch $enumTagList { tags {return [array names enum]} values { foreach tag [array names enum] {lappend valueList $enum($tag)} return $valueList } default { #enumTagList may be a list foreach tag $enumTagList { if [info exists enum($tag)] {lappend valueList $enum($tag)} } if {[llength $enumTagList] > 1} { return $valueList } else { return [join $valueList] } } } } } default {return $attrArray($property)} } } } return {} }
proc Entity::Create {class objref {selectList {}}} { upvar $objref obj upvar #0 $class\::attr classAttr logEntryLS DbgEntryExit "Entering Entity::Create" if {[string compare $selectList {}] == 0} { set selectList [array names classAttr] } else { #If given a selectList, always include oid, dt, mdt lappend selectList oid if [info exists classAttr(dt)] { lappend selectList dt } if [info exists classAttr(mdt)] { lappend selectList mdt } } foreach attr $selectList { set obj($attr) [GetAttribute $class $attr default] } logEntryLS DbgEntryExit "Exiting Entity::Create" }
proc Entity::ArrayCopy { class objref {selectList {}} } { upvar $objref obj upvar #0 $class\::attr classAttr logEntryLS DbgEntryExit "Entering Entity::ArrayCopy" #return the entire list if {[string compare $selectList {}] == 0} { set selectList [array names classAttr] } else { #return the list given plus the necessary internals, oid, dt, mdt lappend selectList oid if [info exists classAttr(dt)] { lappend selectList dt } if [info exists classAttr(mdt)] { lappend selectList mdt } if [info exists classAttr(coid)] { lappend selectList coid } } foreach attr $selectList { if [info exists obj($attr)] {set tmp($attr) $obj($attr)} } logEntryLS DbgEntryExit "Exiting Entity::ArrayCopy" return [array get tmp] }
proc Entity::Insert {class objref} { upvar $objref obj upvar #0 $class\::this this logEntryLS DbgEntryExit "Entering Entity::Insert" #Only begin a transaction if there is more than one table involved set updateTableList [GetTableList $this(class) obj] set DbObject $this(DbObject) if {[llength $updateTableList] > 1} { $DbObject\::Begin } #Loop through all of the tables set i 1 foreach table $this(hierarchy) { upvar #0 $table\::attr attr #Get all attributes belonging to that table #array set subobj [SplitTables $this(class) obj $table] # Account for tables that whose name differs from the class. if {[llength $this(hierarchy)] == 1} { if {![cequal [lindex $this(hierarchy) 0] $this(table)]} { set holdTable $this(table) set this(table) [lindex [split $this(table) \ ] 0] array set subobj [SplitTables $this(class) obj $this(table)] } else { array set subobj [SplitTables $this(class) obj $table] } } else { array set subobj [SplitTables $this(class) obj $table] } #If mdt exists for this table, ensure it is in the list and set to this object's value #This also ignores any value set by the user if [info exists attr(mdt)] { if {[string compare [GetAttribute $table mdt table] $table] == 0} { set subobj(mdt) $this(class) set obj(mdt) $this(class) } } #If dt exists for this table, ensure it is in the list and set to the next objects value if [info exists attr(dt)] { set subobj(dt) [lindex $this(hierarchy) $i] set obj(dt) $subobj(dt) incr i } #If attributes are returned (more than just oid) do the insert if {[array size subobj] > 1} { if [catch {set obj(oid) [$DbObject\::Insert $table subobj]} result] { if {[llength $updateTableList] > 1} { $DbObject\::Rollback } error "Entity::Insert $result" } } unset subobj } if {[llength $updateTableList] > 1} { $DbObject\::Commit } logEntryLS DbgEntryExit "Exiting Entity::Insert with oid, $obj(oid)" if {[llength $this(hierarchy)] == 1} { if {![cequal [lindex $this(hierarchy) 0] $this(table)]} { set this(table) $holdTable } } return $obj(oid) }
proc Entity::Update {class objref} { upvar $objref obj upvar #0 $class\::this this logEntryLS DbgEntryExit "Entering Entity::Update" set updateTableList [GetTableList $this(class) obj] set DbObject $this(DbObject) if {[llength $updateTableList] > 1} { $DbObject\::Begin } #Loop through all of the tables foreach table $this(hierarchy) { #Get all attributes belonging to that table if {[llength $this(hierarchy)] == 1} { if {![cequal [lindex $this(hierarchy) 0] $this(table)]} { set holdTable $this(table) set this(table) [lindex [split $this(table) \ ] 0] array set subobj [SplitTables $this(class) obj $this(table)] } else { array set subobj [SplitTables $this(class) obj $table] } } else { array set subobj [SplitTables $this(class) obj $table] } #If attributes are returned (more than just oid) do the insert if {[llength $this(hierarchy)] == 1} { if {![cequal [lindex $this(hierarchy) 0] $this(table)]} { set this(table) $holdTable } } if [catch {$DbObject\::Update $table subobj} result] { if {[llength $updateTableList] > 1} { $DbObject\::Rollback } error "Entity::Update $result" } unset subobj } if {[llength $updateTableList] > 1} { $DbObject\::Commit } logEntryLS DbgEntryExit "Exiting Entity::Update" }
proc Entity::UpdateWhere {class objref attr value args} { upvar $objref obj upvar #0 $class\::this this set oidList {} set argList [list $attr $value] set DbObject $this(DbObject) foreach item $args {lappend argList $item} if [ catch { set oidList [eval $class\::RetrieveOidBy $argList] if {[llength $oidList] > 1} { $DbObject\::Begin } foreach oid $oidList { set obj(oid) $oid $class\::Update obj } } result ] { if {[llength $oidList] > 1} {$DbObject\::Rollback } error "Entity::UpdateWhere: $result" } if {[llength $oidList] > 1} { $DbObject\::Commit } return $oidList }
proc Entity::Delete {class objref} { upvar $objref obj upvar #0 $class\::this this logEntryLS DbgEntryExit "Entering Entity::Delete" set DbObject $this(DbObject) $DbObject\::Begin foreach table $this(hierarchy) { upvar #0 $table\::this parentclass #First, check for and delete any containees foreach containedclass $parentclass(containedClass) { if [info exists $containedclass\::attr(coid)] { if [catch { foreach containeeList [$containedclass\::ContainedList $obj(oid)] { array set containee $containeeList #Call the derived function so redefinition is possible if [info exists containee(mdt)] { $containee(mdt)\::Delete containee } else { [set $containedclass\::this(class)]\::Delete containee } unset containee } } result] { $DbObject\::Rollback error "[lindex [info level 0] 0] $result" } } } #Now handle the inheritance if [catch {$DbObject\::Delete $table obj} result] { $DbObject\::Rollback error "Entity::Delete $result" } } $DbObject\::Commit logEntryLS DbgEntryExit "Exiting Entity::Delete" }
proc Entity::DeleteWhere {class attr value args} { upvar #0 $class\::this this set objList {} set argList [list $attr $value] set DbObject $this(DbObject) foreach item $args {lappend argList $item} if [ catch { set objList [eval $class\::RetrieveObjBy $argList] if {[llength $objList] > 1 } { $DbObject\::Begin } foreach instanceList $objList { array set obj $instanceList $class\::Delete obj } } result ] { if {[llength $objList] > 1} {$DbObject\::Rollback } error "Entity::DeleteWhere: $result" } if {[llength $objList] > 1} {$DbObject\::Commit } }
proc Entity::EnumValue {enumValueList value} { # Match for tersevalue | verbosevalue # For terse, match anything beginning(^) with the given value # followed by ':' # For verbose, match any character that is not ":" # followed by ": " and ending with value. set enumIndex [lsearch -regexp $enumValueList \ "^$value: .*\$|^.: $value\$"] if { $enumIndex == -1 } { return $value } return [lindex $enumValueList $enumIndex] }
proc Entity::Verbose {enumValue} { regsub {[^:]*: } $enumValue {} verbose return $verbose }
proc Entity::Tag {enumValueList enumValue} { set enumIndex [lsearch $enumValueList $enumValue] incr enumIndex -1 #Return the tag return [lindex $enumValueList $enumIndex] }
proc Entity::Terse {enumValue} { regsub -- {[:] .*} $enumValue {} terse return $terse }
proc Entity::EnumMax {enumList} { set maxFriendlyLength 0 set maxTerseLength 0 array set enum $enumList foreach tag [array names enum] { set friendlyLength [string length [Verbose $enum($tag)]] if {$maxFriendlyLength < $friendlyLength} { set maxFriendlyLength $friendlyLength } set terseLength [string length [Terse $enum($tag)]] if {$maxTerseLength < $terseLength} { set maxTerseLength $terseLength } } return [list $maxTerseLength $maxFriendlyLength] }
proc Entity::Refresh {class objref} { upvar $objref obj upvar #0 $class\::this this logEntryLS DbgEntryExit "Entering Entity::Refresh" set DbObject $this(DbObject) set oidColumn [GetAttribute $class oid column] if [ catch { $DbObject\::Query $class obj "$oidColumn = $obj(oid)" set rtn [$DbObject\::Next $class obj] } result] { error "Entity::Refresh: $result" } logEntryLS DbgEntryExit "Exiting Entity::Refresh" return $rtn }
proc Entity::GetListOf {class attr args} { upvar #0 $class\::this this set DbObject $this(DbObject) if [catch { set where [Entity::BuildWhere $class $args] set column [lindex [split [Entity::GetAttribute $class $attr column] .] 1] set valueList [$DbObject\::GetListOf $class $attr $where "$column asc "] } result] {error "Entity::GetListof: $result"} return $valueList }
proc Entity::Count {class attr args} { upvar #0 $class\::this this set DbObject $this(DbObject) if [catch { set count [$DbObject\::Count $class [Entity::BuildWhere $class $args] $attr] } result] {error "Entity::Count: $result"} return $count }
proc Entity::RetrieveOidBy {class attr value args} { upvar #0 $class\::this this set DbObject $this(DbObject) set oidList {} set where {} if [catch { set argList [list $attr $value] foreach item $args {lappend argList $item} } result] { error "$result" } Create $class s oid if [catch { $DbObject\::Query $class s [Entity::BuildWhere $class $argList] while {[$DbObject\::Next $class s]} {lappend oidList $s(oid)} } result] {error "$result"} return $oidList }
proc Entity::BuildWhere {class attrList} { upvar #0 $class\::this this set DbObject $this(DbObject) set where {} if {([llength $attrList] % 2)} { error {list must have an even number of elements} } #Process each attr-qual pair foreach {attribute qualifier} $attrList { logEntryLS DebugAll "Processing '$attribute' '$qualifier'." #Convert the attributes to raw where components using the SI #properties. set whereColumn [Entity::GetAttribute $class $attribute column] set attrType [Entity::GetAttribute $class $attribute type] if {[string equal {} $whereColumn]} { logEntryLS Warning "Entity::BuildWhere $class could not find\ column for attribute '$attribute', qualifier '$qualifier'." } #Build the where clause from the list of attributes and their #values #Strip off operator indicator, <, >, !, or % and #translate to where operator switch -glob $qualifier { {!<*} { #Strip the !< and convert operator to > set whereValue [$DbObject\::BuildType $attrType \ [string trimleft $qualifier {!<}]] set whereString "$whereColumn > $whereValue" } {!>*} { #String the !> and convert operator to < set whereValue [$DbObject\::BuildType $attrType \ [string trimleft $qualifier {!>}]] set whereString "$whereColumn < whereValue" } {!*} { #Negating operator ! found - Strip it out set whereValue [$DbObject\::BuildType $attrType \ [string trimleft $qualifier !]] #Check for a % anywhere in the string, but leave token #as part of the where. if {[string first % $qualifier] != -1} { #Convert to the proper operator set whereString "$whereColumn Not like $whereValue" } else { set whereString "$whereColumn != $whereValue" } } {<*} { #Strip the < and convert operator to <= set whereValue [$DbObject\::BuildType $attrType \ [string trimleft $qualifier <]] set whereString "$whereColumn <= whereValue" } {>*} { #Strip the > and convert operator to >= set whereValue [$DbObject\::BuildType $attrType \ [string trimleft $qualifier >]] set whereString "$whereColumn >= whereValue" } default { set whereValue [$DbObject\::BuildType $attrType $qualifier] #Check for a % anywhere in the string, but leave token #as part of the where. if {[string first % $qualifier] != -1} { #convert to the proper operator. set whereString "$whereColumn like $whereValue" } else { set whereString "$whereColumn = $whereValue" } } } logEntryLS DebugAll "Entity::BuildWhere whereString\ '$whereString'. " #Append each tag-value where element to the clause. if {[string match $where {}]} { set where $whereString } else { set where "$where and $whereString" } } return $where }
proc Entity::BuildOrder {class args} { set argc [llength $args] set eMsg {attribute, order list must have an even number of args} if {!$argc} { return {} } elseif {$argc == 1} { if {[llength [lindex $args 0]] > 1} { return [eval [list Entity::BuildOrder $class] [lindex $args 0]] } else { error $eMsg } } elseif {$argc % 2} { error $eMsg } else { set oc {} foreach {attr order} $args { set col [Entity::GetAttribute $class $attr column] lappend oc [list $col $order] } return " [join $oc {, }] " } }
proc Entity::RetrieveObjBy {class attr value args} { upvar #0 $class\::this this set objList {} set DbObject $this(DbObject) if [catch { set argList [list $attr $value] foreach item $args {lappend argList $item} } result] { error "$result" } Create $class s if [catch { $DbObject\::Query $class s [Entity::BuildWhere $class $argList] while {[$DbObject\::Next $class s]} { lappend objList [array get s] } } result] {error "$result"} return $objList }
proc Entity::Value {class oid attr {value {}}} { upvar #0 $class\::this this set DbObject $this(DbObject) Create $class s $attr set s(oid) $oid if {[string compare $value {}] == 0} { if [catch {Refresh $class s} result] { error "Entity::Value: $result"} return $s($attr) } else { if [catch { Refresh $class s set s($attr) $value Update $class s } result] { error "Entity::Value: $result"} return $value } }
proc Entity::InsertUpdate {class objref attr value args} { upvar $objref obj upvar #0 $class\::this this set DbObject $this(DbObject) #Set up the attribute array using the parameter arguments if [catch { set argList [list $attr $value] foreach item $args {lappend argList $item} array set attrArray $argList } result] { error "Entity::InsertUpdate: Parsing the argument list: $result" } if [catch { set oidList [eval $class\::RetrieveOidBy $argList] } result] {error "Entity::InsertUpdate: Retrieving using argument list: $result"} if [catch { #Found an object if {[llength $oidList] == 1} { $class\::Update obj set tmpoid [lindex $oidList 0] set obj(oid) $tmpoid $class\::Update obj #No object found } elseif {[llength $oidList] == 0} { set tmpoid [$class\::Insert obj] #More than 1 object found, generate error } else { error "Entity::InsertUpdate: The given search is not\ unique; multiple objects found" } } result] { error "Entity::InsertUpdate: $result" } return $tmpoid }
proc Entity::GetTableList { class objref } { upvar $objref obj logEntryLS DbgEntryExit "Entering Entity::GetTableList" set tableList {} foreach attr [array names obj] { #Skip the oid if {[string compare oid $attr] == 0} {continue} set table [Entity::GetAttribute $class $attr table] if {[lsearch -exact $tableList $table] == -1} { lappend tableList $table } } logEntryLS DbgEntryExit "Exiting Entity::GetTableList with tableList. $tableList" return $tableList }
proc Entity::SplitTables { class objref table } { upvar $objref obj logEntryLS DbgEntryExit "Entering Entity::SplitTables" set tmp(oid) $obj(oid) foreach attr [array names obj] { #Skip the oid if {[string compare oid $attr] == 0} {continue} if {[string compare [Entity::GetAttribute $class $attr table] $table] == 0} { set tmp($attr) $obj($attr) } } logEntryLS DbgEntryExit "Exiting Entity::SplitTables" return [array get tmp] }
proc Entity::ContainedList { class containerOid {selectList {}} } { upvar #0 $class\::attr attr upvar #0 $class\::this this set DbObject $this(DbObject) set containedList {} Entity::Create $class tmp $selectList set coidColumn [$class\::GetAttribute coid column] $DbObject\::Query $class tmp "$coidColumn = $containerOid" while {[$DbObject\::Next $class tmp]} { lappend containedList [array get tmp] } return $containedList }
proc Entity::Container {class oid objref} { upvar $objref obj upvar #0 $class\::this this set rtn 0 if [catch { set coid [Entity::Value $class $oid coid] if {![string match $coid {}]} { set rtn [Entity::MdtRetrieve $this(container) $coid obj] } else { error "Entity::Container: Object $oid not found"} } result] {error "entity::Container:$result"} return $rtn }
proc Entity::Retrieve { class oid objref {selectList {}} } { upvar $objref obj upvar #0 $class\::this this set DbObject this(DbObject) if [catch { Create $class obj $selectList set obj(oid) $oid set rtn [Refresh $class obj] } result] { error "Entity::Retrieve:$result" } return $rtn }
proc Entity::MdtRetrieve { class oid objref } { upvar $objref obj if [catch { set rtn [Entity::Retrieve $class $oid obj] # Check for successful retrieve if {$rtn == 1 } { if {[info exists obj(mdt)]} { if {[string compare $obj(mdt) $class] != 0} { # A most derived class exists for this base class eval [$obj(mdt)Init] set rtn [$obj(mdt)\::Retrieve $oid obj] } } } } result] { error "$result" } return $rtn }
proc Entity::Transition { class event objref } { upvar $objref obj LC::logArray DebugAll obj if {[catch { set priorfsmState $obj(fsmState) set tag [Entity::Tag [$class\::GetAttribute fsmState enum] " $obj(fsmState)"] LC::logEntry DebugAll "tag" set fsmEntry [set $class\::fsm($tag,$event)] } result]} { LC:logEntry Error "No event $event for state [Entity::Verbose $obj(fsmState)] found. " error "No event $event for state [Entity::Verbose $obj(fsmState)] found." else { LC::logEntry DebugAll "Old State: $obj(fsmState)" if {[catch { # Execute the action if a proc is specified if {![string equal [lindex $fsmEntry 1] NULL]} { LC::logEntry Debug "Executing [lindex $fsmEntry 1]" [lindex $fsmEntry 1] obj $class\::Refresh obj } } result]} { error $result } else { # Bring obj to next state set obj(fsmState) [$class\::GetAttribute fsmState enum [lindex $fsmEntry 0]] if {![string equal $priorFsmState $obj(fsmState]} { $class\::Value $obj(oid) priorFsmState $priorFsmState } LC::logEntry Debug "New State: $obj(fsmState)" $class\::Value $obj(oid) fsmState $obj(fsmState) } } } }