Perl TM Tutorial: The Trick is to Keep Breathing (Part X)

(Followup to IX)

While there will always be scenarios where you will appreciate the genericity and flexibility in terms of synchronisation which comes with using traits, in many cases the problem you need to solve is much simpler.

Maybe you just have a map in a CTM file and every time the program starts, map content should be read from that file. Or maybe your program probes a database at regular intervals and creates topic map content from it. Which should be finally copied into an XTM file. Or maybe you want both, i.e. content should be sync'ed in at construction time as CTM and sync'ed out as XTM at object destruction.


The processing follows the breath in, hold breath, breath out pattern, something we humans do quite frequently, and unconsciously.

In any case your application is still dealing with a topic map:

use TM::Tau;
{                          # constructor time
  my $tm = new TM::Tau ('mymap.atm > mymap.xtm');
  ....                     # hard work here
  }                        # destructor time

TM::Tau is a subclass of TM, so it exposes map behavior. The only difference is that this object is told with an expression what to do at object construction time:

It will find a file called mymap.atm, it will then guess that it contains AsTMa= map content and will try to consume that. If successful, that content will end up in the map object. No need to explicitly trigger sync_in to make that happen.

From then on you have the opportunity to inspect or modify the object. Once you are tired of it, you can let it go out of scope. At object destruction the rest of the expression becomes active:

The map content will be copied into the file mymap.xtm, with the machine making an educated guess that this should be in XTM format.

Guessing Works, Mostly

Map resources are obviously addressed via URLs: The mymap.atm is only the short form of file:mymap.atm. As you would expect other forms of URLs work as well, at least safely when on the left-hand side of >.

Which format the map content is in has to be guessed from the URL. If you are using the usual suspects as file extensions (such as .ctm, .xtm and so forth), then there should not be much drama. But should a URL have no extension registered with TM::Tau, then the parser will complain. Loudly.

To fix that you can fiddle around with two hashes, one responsible for resolving sources (the other for resolving filters). If you want to hook in your own implementations, you could write

$TM::Tau::sources{'tm:server\.com'} = 'My::Driver';

and everytime you use as URL your driver will be happily used when the map is sourced. Consult the docs how your constructor will be invoked in that case.

Basic Algebra

Another thing I have added is that you can combine several maps, at least on the incoming (left) side:

file:tm1.atm + file:tm2.atm > file:tm.xtm

It does the obvious, namely to read tm1.atm and tm2.atm, consume both files as AsTMa= content, and then merge these maps together. That merged result is then copied into the file tm.xtm at destruction time.

Naturally this works with any number of maps. Later the whole thing will support more than maps, overloading the meaning of +.

There is also a binary * operator, but that does not work between two maps, but a map and a transformer:

tm.ctm *

A transformer is nothing else than a program which converts a topic map into another topic map. In the above case it is one which analyses the map and produces some statistics. These are also in topic map form.

It is implemented in TM::Tau::Filter::Analyze and it is written in such a way that it auto-registers itself with the URI used above into the other hash TM::Tau::filters when it is loaded.

Another obvious choice for transformers are those written in TMQL. I will let some infrastructure follow once I got TMQL to understand CTM.

Final Note

The documentation of TM::Tau will be fixed with the next upload.

Work supported by the Austrian Research Centers.

Posted In