by cdshearer >> Wed, 6 Feb 2002 9:53:16 GMT
Hello All
I thought I'd pass on a technique that I came up with...
In the past I've been frustrated by the fact that there is no easy way of having a dictionary of primitive values. Occassionally, I want to be able to look up a primitive value (eg. an Integer) from an Object. As JADE's dictionaries can only contain Objects, I'd have to create a new class to hold the Integer to accomplish this. This was usually a right pain!
So, I thought of a pre-built, generic solution, which I call a PrimitiveMap. Basically, having one of these allows you to associate an object with a primitive, say a particular control on a form with a number. In my particular case, I was calculating the minimum and maximum heights of some tab sheets, and wanted to look them up using the sheet once I had calculated them all.
Here's the solution:
I have an abstract PrimitiveWrapper class which holds primitive values. This is subclassed, with one concrete subclass for each primitive type I want to store. In my case I only needed an IntegerWrapper class...
PrimitiveWrapper
IntegerWrapper
Primitive Wrapper has two abstract methods: setValue(value: Any), and getValue(): Any. These must be implemented by the concrete subclasses. The IntegerWrapper class has an integer attribute that actually stores the value when setValue is called, and returns it when getValue is called.
The PrimitiveMap class is a subclass of ExtKeyDictionary, with membership of PrimitiveWrapper, and a key of object: Object.
The PrimitiveMap class has the following methods:
setPrimitiveType(type: Type) lockReceiver, updating;
associate(object: Object; withPrimitive: Any) lockReceiver, updating; lookup(object: Object): Any lockReceiver;
- The setPrimitiveType method is used to intialise the PrimitiveMap with the actual primitive type that it will be storing. This method must be called before using the associate or lookup methods.
- The associate method is used to add a primitive value to the collection, with object as the key.
- The lookup method is used to retrieve a primitive from the collection, using the key.
The PrimitiveMap class also defines two references:
myWrapperClass : Class
allCreatedWrappers: ObjectSet
- The myWrapperClass reference is initialised by the setPrimitiveType method call - using the passed in type to identify what concrete subclass of PrimitiveWrapper to use when creating wrapper objects.
- The allCreatedWrappers collection is used simply to keep track of all PrimitiveWrapper objects that were created, so that they can be deleted when the primitive map is deleted. This ensures that the PrimitiveMap cleans up all the objects it created, even if the user calls removeKey or removeKeys method.
Here's the full method bodies, including a couple of helper methods:
setPrimitiveType(type: Type) lockReceiver, updating;
begin
if type = Integer then
myWrapperClass := IntegerWrapper;
endif;
end;
associate(object: Object; withPrimitive: Any) lockReceiver, updating;
vars
wrapper : PrimitiveWrapper;begin
wrapper := createWrapper(withPrimitive);
self[object] := wrapper;
end;
lookup(object: Object): Any lockReceiver;
vars
wrapper : PrimitiveWrapper;begin
wrapper := self[object].PrimitiveWrapper;
if wrapper <> null then
return wrapper.getValue;
else
return null;
endif;
end;
createWrapper(value: Any): PrimitiveWrapper protected;
vars
wrapper : PrimitiveWrapper;begin
create wrapper as myWrapperClass;
wrapper.setValue(value);
allCreatedWrappers.add(wrapper);
return wrapper;
end;
delete() updating, protected, lockReceiver;
vars
begin
allCreatedWrappers.purge;
end;
Finally, here's some contrived example code showing how it might be used...
vars
tabHeights: PrimitiveMap;
tab : Sheet;
tabHeight : Integer;begin
create tabHeights transient;
foreach tab in allSheets do
tabHeight := ... // calculate the height of the tab
// now, associate this tab with its height
tabHeights.associate(tab, tabHeight);
endforeach;
// now, lookup the tab heights again
foreach tab in allSheets do
tabHeight := tabHeights.lookup(tab).Integer;
// use the tab height...
endforeach;
epilog
delete tabHeights;
end;
I hope you can use this in your own systems. Note that you'd have to implement your own subclasses of PrimitiveWrapper, and update the setPrimitiveType method to handle these.
I've also attached a schema containing the classes...
Craig Shearer
Chief Architect
Helix Software Limited
http://www.helix.co.nz
craig.shearer@helix.co.nz