Edit Rename Changes History Upload Download Back to Top

Glorp MMS Descriptors

Rather than explaining each class and then showing the descriptors, I'll just show some of the descriptors and comment as seems necessary.

Member class model

This is the classModelForCccc: method for the MMSMember class:

classModelForMMSMember: aClassModel 
	aClassModel newAttributeNamed: #id type: Integer.
	aClassModel newAttributeNamed: #actions collectionOf: MMSAction.



	aClassModel newAttributeNamed: #applicationDate type: Integer.
	aClassModel newAttributeNamed: #membershipDate type: Integer.
	aClassModel newAttributeNamed: #membershipNumber type: Integer.
	aClassModel newAttributeNamed: #passwords collectionOf: MMSPassword.
	aClassModel newAttributeNamed: #currentPassword type: MMSPassword.
	aClassModel newAttributeNamed: #keys collectionOf: MMSOpenPGPKey.
	aClassModel newAttributeNamed: #registeredKey type: MMSOpenPGPKey.
	aClassModel newAttributeNamed: #emailAddresses
		collectionOf: MMSEmailAddress.
	aClassModel newAttributeNamed: #contactEmailAddress type: MMSEmailAddress.
	^self

For each instance variable in the class that we wish Glorp to handle an attribute (a GlorpAttributeModel) is added to the class model. The class model is created by the Glorp code and passed into this method.

Three methods may be used to add the attributes:

  • newAttributeNamed:type:
  • newAttributeNamed:collectionOf:
  • newAttributeNamed:collection:of:
The first method is used where an instance variable holds a sigle instance of a particular class of object. Taking an example from the above code, the id instance variable of MMSMember will hold an instance of class Integer.

The second method is used where an instance variable holds a collection (an OrderedCollection) of objects. For example, the actions instance variable is defined as holding a collection of MMSAction objects.

The third example (which I have not seen used - not even in the Glorp tests) allows the specification of the class of collection to be used. For example, Set, Bag or OrderedCollection.

Member table

This is the tableForTttt: method for the MMS_MEMBER table:

tableForMMS_MEMBER: aTable 
	| currentPasswordId currentKeyId currentEmailAddressId |
	(aTable createFieldNamed: 'ID' type: self platform serial) bePrimaryKey.
	aTable createFieldNamed: 'APPLICATION_DATE' type: self platform int4.
	aTable createFieldNamed: 'MEMBERSHIP_DATE' type: self platform int4.
	aTable createFieldNamed: 'MEMBERSHIP_NUMBER' type: self platform int4.
	currentPasswordId := aTable createFieldNamed: 'CURRENT_PASSWORD_ID'
				type: self platform int4.
	aTable addForeignKeyFrom: currentPasswordId
		to: ((self tableNamed: 'MMS_PASSWORD') fieldNamed: 'ID').
	currentKeyId := aTable createFieldNamed: 'CURRENT_KEY_ID'
				type: self platform int4.
	aTable addForeignKeyFrom: currentKeyId
		to: ((self tableNamed: 'MMS_KEY') fieldNamed: 'ID').
	currentEmailAddressId := aTable createFieldNamed: 'CURRENT_EMAIL_ID'
				type: self platform int4.
	aTable addForeignKeyFrom: currentEmailAddressId
		to: ((self tableNamed: 'MMS_EMAIL') fieldNamed: 'ID').
	^self

For each column in the table a field (a DatabaseField) is added to the table. The table object is created by Glorp and passed in as an argument.

Fields are created using createFieldNamed:type:. The field name is a the column name as a String. The type is one of the types defined for the platform (a GlorpPlatform. One of these for each supported DBMS).

Once created, a field can be defined as a primary key as in the definition of the field called "ID" above.

Also, a field can be defined as a foreign key as in the definietion of 'CURRENT_PASSWORD_ID' above.

Member descriptor

This is the descriptorForCccc: method for the MMSMember class:

descriptorForMMSContact: aDescriptor 
	| table |
	table := self tableNamed: 'MMS_CONTACT'.
	aDescriptor table: table.
	(aDescriptor newMapping: DirectMapping) from: #id
		to: (table fieldNamed: 'ID').
	(aDescriptor newMapping: DirectMapping) from: #applicationDate
		to: (table fieldNamed: 'APPLICATION_DATE').
	(aDescriptor newMapping: DirectMapping) from: #membershipDate
		to: (table fieldNamed: 'MEMBERSHIP_DATE').
	(aDescriptor newMapping: DirectMapping) from: #membershipNumber
		to: (table fieldNamed: 'MEMBERSHIP_NUMBER').
	(aDescriptor newMapping: OneToManyMapping) attributeName: #passwords.
	(aDescriptor newMapping: OneToOneMapping) attributeName: #currentPassword.
	(aDescriptor newMapping: OneToManyMapping) attributeName: #keys.
	(aDescriptor newMapping: OneToOneMapping) attributeName: #registeredKey.
	(aDescriptor newMapping: OneToManyMapping) attributeName: #emailAddresses.
	(aDescriptor newMapping: OneToOneMapping) 
		attributeName: #contactEmailAddress.

Glorp passes a descriptor as an argument to this method. Mappings are added to the descriptor which describe how data in the database maps to the instance variables in objects. Using the Glorp terminology, this means mapping fields to attributes. Also, a mapping can describe a relationship between entities.

Use >>newMapping to add a descriptor. So not use the older >>addMapping descriptor.

In the simplest case a field is mapped to an attribute using a DirectMapping, as with the #ID attribute above. The DirectMapping needs the identity of one field and the identity of one attribute.

In the case of #passwords, we need to say that for one member there can be many passwords. A OneToManyMapping is created. This only needs to know the identity of the attribute (instance variable) in order to work. The rest of the information to do the joining etc. is obtained from the MMSMember class model and the tableForTttt of the 'other' table - the table that contains the foriegn key pointing back to the member.

For the #currentPassword, we have a OneToOneMapping. This is the opposite of the OneToMany in that the member holds the foriegn key to the password. Again, all the information can be obtained from the class and table informaion in the descriptor system.

Joins

In most straightforward cases, the mappings defined above would be sufficient. In cases where there is more than one mapping from one class/table to another, or where there are references in both directions, we need to explicitly tell Glorp what columns are to be used to when constructing joins.

The basic form of a join is:

Join
 from: <a field here>
 to: <a field there>.

Here is a field in the context of the class/table of the descriptor, and there is in the context of the other class/table.

Here is a concrete example which adds a joins to the mappings for email address in the member above:

(aDescriptor newMapping: OneToManyMapping)
  attributeName: #emailAddresses;
  join: (Join
    from: (table fieldNamed: 'ID')
    to: ((self tableNamed: 'MMS_EMAIL') fieldNamed: 'MEMBER_ID')).
(aDescriptor newMapping: OneToOneMapping)
  attributeName: #currentEmailAddress;
  join: (Join
    from: (table fieldNamed: 'CURRENT_EMAIL_ID')
    to: ((self tableNamed: 'MMS_EMAIL') fieldNamed: 'ID')).

Note that the from:to: "direction" has nothing to do with which field is a primary or foriegn key. It's just "from this descriptor to another descriptor".


Edit Rename Changes History Upload Download Back to Top