Creating dictionaries of primitives

Forums for specific tips, techniques and example code
ConvertFromOldNGs
Posts: 5321
Joined: Wed Aug 05, 2009 5:19 pm

Creating dictionaries of primitives

Postby ConvertFromOldNGs » Fri Aug 07, 2009 2:36 pm

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
Attachments
2121_1.ddb
(2.27 KiB) Downloaded 175 times
2121_2.scm
(5.55 KiB) Downloaded 181 times
Last edited by ConvertFromOldNGs on Fri Aug 07, 2009 4:00 pm, edited 1 time in total.

ConvertFromOldNGs
Posts: 5321
Joined: Wed Aug 05, 2009 5:19 pm

Re: Creating dictionaries of primitives

Postby ConvertFromOldNGs » Fri Aug 07, 2009 2:36 pm

by pillick >> Mon, 11 Feb 2002 1:34:54 GMT

Ummmm, whats the point?

The reason for having data in a dictionary is so that you can access it simply with a key, isnt it? But in this case the key would be the object itself.

Once you have the key you have all the data about that object - you cant get any more information out of the dictionary, so why have it at all?

Am I missing something?

ConvertFromOldNGs
Posts: 5321
Joined: Wed Aug 05, 2009 5:19 pm

Re: Creating dictionaries of primitives

Postby ConvertFromOldNGs » Fri Aug 07, 2009 2:36 pm

by pillick >> Mon, 11 Feb 2002 1:59:51 GMT

Ummmm, whats the point?

The reason for having data in a dictionary is so that you can access it simply with a key, isnt it? But in this case the key would be the object itself.

Once you have the key you have all the data about that object - you cant get any more information out of the dictionary, so why have it at all?

Am I missing something?

ConvertFromOldNGs
Posts: 5321
Joined: Wed Aug 05, 2009 5:19 pm

Re: Creating dictionaries of primitives

Postby ConvertFromOldNGs » Fri Aug 07, 2009 2:36 pm

by cdshearer >> Mon, 11 Feb 2002 5:46:45 GMT

Ummm... well, yes, I guess the thing you're missing is examples of where you might use this.

A few things come to mind...

Basically, it's of use where you want to associate some primitive value with an object, without having to change the object's class to add a property to store that primitive value, and you can't immediately process the value - you need to have all the values available before doing some further processing on them.

It is similar to why you'd use an ExtKeyDictionary class. (Sometimes I have difficulty thinking of good examples where you'd use those too... but they do exist, and come in very handy sometimes!)

In my particular example, and why I invented this in the first place, was doing some particularly complex work calculating sizes of tabs on a form, and dynamically moving controls and resizing them. The algorithm called for finding the minimum and maximum height of each tab, and then doing some processing on those values.

I had already painted the tab sheets on the form, being JADE's Sheet controls. Since it's JADE's sheet control, I can't modify the Sheet class to add my minHeight and maxHeight properties to it. And, removing all the controls off my sheets and putting a subclassed Sheet control on would have been lots of work! Therefore, I needed a way to "lookup" these values for each of my tab sheets.

Even where you can modify the class, sometimes it's just a damn sight more convenient not to have to modify the class. What about if the object you want to have in the dictionary is persistent, but the value you want to store does't "belong" on the persistent object? I would be loathed to modify the class, and update a persistent object to achieve this result.

So, that's just a couple of example where you might use it. I admit it's not that common, but I was experimenting with automatically wrapping primitive values in an object.

Craig

ConvertFromOldNGs
Posts: 5321
Joined: Wed Aug 05, 2009 5:19 pm

Re: Creating dictionaries of primitives

Postby ConvertFromOldNGs » Fri Aug 07, 2009 2:36 pm

by CarlRanson >> Tue, 12 Feb 2002 0:14:04 GMT

Craig's method would also work for doing dictionaries of primitives keyed on other primitives.

For instance, looking up days of the week. The key would be the day number, and the object would be the text for the day string.

This is effectively similar to doing array[1..7] of String in languages like pascal. It has the added advantage that it's sparse, so doing array[integer] of String is no problem.

CR
Unify


Return to “Tips and Techniques”

Who is online

Users browsing this forum: No registered users and 25 guests