package TM::View; # $Id: View.pm,v 1.5 2008-08-29 02:39:34 az Exp $ use strict; use vars qw($VERSION @ISA @EXPORT @EXPORT_OK); $VERSION = qw(('$Revision: 1.5 $'))[1]; require Exporter; require AutoLoader; use TM 1.43; use TM::Literal; use base qw(TM); use Data::Dumper; use XML::Writer; use IO::String; use UNIVERSAL qw(isa); =pod =head1 NAME TM::View - Topic Maps, Views and Listlets =head1 SYNOPSIS use TM; use TM::View; my $map; # map is created/synced somehow # do not change the map afterwards or pass the constructor # a deep copy (e.g. using dclone from Storable). my $view=TM::View->new($map); $view->sequence_add("tm://sometopic"); # added with default style info $view->sequence_add("tm://othertopic",0); # add at the beginning my $length=$view->sequence_length; my $whogoesthere=$view->who(0); # which topic is shown first? # retrieve the style describing the topic's midlet by location my ($who,%style)=$view->style(1,0); ($who,%style)=$view->style("tm://sometopic",0); # or by topic $style{bullet}=1; # modify it $style{emphasize}=0; $style{custom_attrib}="what you want!"; $view->style("tm://sometopic",0,%style); # and write it back my $xml=$view->make_listlet; =head1 DESCRIPTION This package provides sequencing and styling mechanisms for Topic Map slide shows or other serialized presentations. =head1 CONCEPTS A view consists of an extract of a map together with rendering information which presents a linear sequence of topics and their interesting aspects. The main use of views is for using topicmaps as source for slides or similar linear presentation mechanisms. A view contains information about which topics are shown in what sequence, and what of the available information related to a topic is presented and how. TM::View manages this information in data structures called I. Every topic in a map can have sundry attributes associated with it, e.g. basenames, occurrences and class/instance information. None of these have any implicit ordering. From a view perspective, these attributes belong to the topic and their display is controlled by the topic's style. A topic can also be involved in associations as member, role being played or type of the association. Associations are thus not directly associated with a single topic but instead are deemed to be interesting for every involved topic. A view thus includes information about a particular association multiple times in each involved topic's style. In TM::View a style element consists of two components: an identifier of the topicmap object being controlled, and a reference to a hash of attribute/value pairs. The attributes describe the formatting of the object but do not include the object content. Besides certain attributes with predefined meanings (see topic_as_listlet below), there are no restrictions on the attributes. TM::View uses the data structures and identification concepts described in L, which separate the world into Midlets (without assertions) and Assertions (with midlets). (Everything in a map is a midlet. "Real" topics are only present as midlets, whereas implicit topics have a midlet and an assertion with the same identifier.) Midlets contain only topic id and reification information, whereas assertions carry everything else: topic attributes and associations. A single style element controls the display of a single assertion. In practice that means that a basename has its style element, separate from an occurrence even if they both belong to the same topic. The style elements for all displayable aspects of a single topic are collected in a list: this is called the I. Position in this list controls display position, and this style list contains all information to create a slide or page about this topic. Note that the style of a topic is always I and contains I the topic's aspects: Aspects that should not be displayed are flagged thus by a specific attribute (see topic_as_listlet). Any midlet in a map can have such a style list (but of course not all midlets are worth displaying: for example, a topic that was implicitely defined by specifying a scope for some other attribute hardly contains interesting information). Multiple topic styles describe a linear journey through the map, and this is represented in TM::View as the I. A view contains exactly one sequence, which lists the topics that are to be displayed (and their order). The sequence usually is only a subset of all available topics (or more precisely midlets). =head1 RELATIONSHIP BETWEEN MAP AND VIEW A TM::View object embeds a topicmap upon its creation, after which this map object must not be modified anymore. (To be precise, adding elements to the map might be mostly safe, but modification or removal of existing map content is definitely unsafe.) It is suggested that the programmer use dclone (see L) or something similar to create a deep copy of the map object for the constructor, if modification of the map object is expected at a later stage. As maps change over time, one-shot discardable views would be of little use for serious knowledge management: specifying a display sequence and extracting the appropriate information from a map is time-consuming. One would have to recreate the display sequence with a new view that applies to the new map, and manually copy over all transferrable attributes. Obviously this is tedious and inefficient, and TM::View provides automation for as much of this process as possible. A TM::View object can be "applied" to a modified version of the respective map using the method I. I resolves the differences between the old (embedded) and updated map and migrates the view information into the context of the updated map. This is done minimizing the loss of style information: the styles for unmodified elements are copied over, styles applying to removed elements are removed and new elements are added where appropriate (e.g. a new occurrence is added to the styles of the topic it applies to, with default display attributes). Modified (and renamed) topics and associations are identified and their styles are transported over, but style information for modified assertions is lost (the assertion will show up as new). Topics and assertions affected by these changes are flagged and upon completion, the map embedded in the old view is discarded and the new map is snapshotted in. =head1 INTERFACE The methods provided by TM::View fall into three categories: managing the overall sequence of topics, managing the styles (of assertions) of a particular topic and creating output. The methods commonly use two different identifiers: a I and an I, both of which are I as described in L. The I applies to the sequence, whereas the I applies to the aspects related to a particular topic. The sequence-related methods obviously do not require aid parameters. Most methods allow to specify topics by either I or position in the sequence. Similar mechanisms apply to selecting assertions by their I or by position in the sequence of styles. =head2 Constructor $view=TM::View->new($tmobj); The constructor requires a TM map object as sole argument, which is the map the view applies to. The map object is attached to the view and must not be modified afterwards. It is highly suggested to use dclone (see L) or similar to create a deep copy of the map for the view: $safeview=TM::View->new(dclone($tmobj)); =cut # makes a new blank view # arguments: a TM map sub new { my ($class,$map,%opts)=@_; die "map MUST be provided\n" if (!$map); my $self= { tm=>$map, sequence=>[], }; return bless $self, $class; # reblessing } =pod =head2 Methods =over =item B $tmobj=$view->map; This method returns the map object associated with the view. The map object can be used for retrieval purposes but must not be modified. =cut sub map { my ($self)=@_; die "argument is not a TM::View object\n" if (!$self || ref($self) ne __PACKAGE__); return $self->{tm}; } # want basenames first, occurrences next, then assocs but assoc kind is zero. # occurrences and assocs sorted by their types sub _sort_elems { my $ak=($a->[TM->KIND]||3).$a->[TM->TYPE]; my $bk=($b->[TM->KIND]||3).$b->[TM->TYPE]; return $ak cmp $bk; } =pod =item B $length=$view->sequence_add(I [,I]); This method adds the topic I to the view. If no position argument is given (or if it is invalid), the topic is added at the end of the sequence. The position argument is a number, with zero being the start of the sequence. The sequence can not have holes. The style information for the topic is a built-in default, which can be modified using the B