Perl TM Tutorial: For TMDM Acolytes (Part VII)

(Followup to part VI)

If you belong to the "Church of TAO" and the TMDM standard is your bible, then the Perl package TM::DM might be something for you.

The package provides a (thin) layer on top of the existing TM implementation. The layer should work with any map, also those which are virtual, or others which persist in some backend.

Ramping Up

The synopsis should already give you a good idea how to use this. First we need some map:

use TM::Materialized::AsTMa;
my $tm = new TM::Materialized::AsTMa (inline => '
sacklpicka (cat)
bn: Der Sacklpicka
bn (nickname): Sleeping Devil

rho (person)
oc (blog):

owner: rho
owned: sacklpicka

Then we sugar-coat this map with the TMDM layer:

use TM::DM;
my $tmdm = new TM::DM (map => $tm);

To bootstrap the access into the map we first get hold of the whole map:

my $topicmap = $tmdm->topicmap;

To learn about all topics, except those the infrastructure provided you can use the same search spec minilanguage as for TM:

my @ts = $topicmap->topics (\ '+all -infrastructure');
warn join ", " , (map { $_->id } @ts);


To get one particular topic you can lazily use the internal identifier

my $sp = $topicmap->topic ('sacklpicka');

but using the full expanded works too:

my $sp = $topicmap->topic ('tm://nirvana/sacklpicka');

And so would have the subject identifier:

my $sp = $topicmap->topic (\ 'http://kill...ll.jpg');

Names and Occurrences

To learn about all of Sacklpicker's names, you could iterate over the list:

foreach my $n ($sp->names) {
   next if $n->type->id eq 'tm://nirvana/nickname';
   warn $n->value;

Here we print all except those where the type of the name is nickname.

Of course, you can also retrieve the scope of a name. Surprisingly, this will never be empty. If the scope was not explicitely provided, then the unconstrained scope will be used. This is a TM feature.

What works for names, also does for occurrences:

my $rho = $topicmap->topic ('rho');
foreach my $o ($rho->occurrences) {
   warn $o->value;

The only difference is now that values are TM::Literals, i.e. a structure which carries the data type and the value. So to reach into the value itself, you have to take the first component:

warn $o->value->[0];

Yes, I agree. This is sooo much cleaner than in TMDM.


From a particular topic we can navigate to all the roles it is playing in associations:

foreach my $r ( $rho->roles ) {
   warn "player: ".$r->player->id;
   warn " for role: ".$r->type->id;

You will note in the output that not only the above ownership of sacklpicker is listed, but also the fact that rho is an instance of a person. TM stores this as association too.

Another extension shining through is that you can use the simple axes language of TM to look for particular assertions.

The following would also find all of rho's involvements in associations:

my @as = $topicmap->associations (iplayer => 'rho');

Occurrences and names are not included here.

Associations themselves you can dissect with their TMDM properties:

foreach my $a (@as) {
   warn $a->type->id;
   warn $a->scope->id;
   warn map { $_->type->id } $a->roles;

Wrap Up

You have to be careful when you compare items with each other. Bear in mind, that the original information is still in the underlying map and that - when information is brought to you via TM::DM - you alway receive a copy.

Overall, when you use the TM::DM layer there are some drawbacks:

  • it is cumbersome to use
  • it is not overly fast
  • it is read-only

Against the latter only massive amounts of chocolate in my direction would help. About the speed issue: more about that in some later installment.

Nothing that I can do about the cumbersome part. That's TMDM.

Work supported by the Austrian Research Centers.

Posted In