6 Hooks

    1. Vorgeschriebene Hooks
      1. sub CloseSTL
      2. sub OpenSTL
      3. ParseRegisterLine
      4. ParseSTLentry
    2. Optionale Hooks
      1. AvantiErrHook
      2. InitHook
      3. DefaultJTHook
      4. LinkEscape
      5. ResultHook
      6. JobHook
      7. TplHook
      8. STLmap
      9. sub stlsort
    3. Hook-Verteiler
      1. für die Aufbereitung
      2. für CollectQuery
Hooks sind definierte Schnittstellen, an denen in einer Datenbankkonfigurationsdatei definierte Unterprogamme ausgeführt werden.

Nachfolgend wird beschrieben, welche dieser Schnittstellen existieren, mit welchen Übergabeparametern sie von populo aufgerufen werden und welche Resultate es erwartet.

6.1 Vorgeschriebene Hooks

6.1.1 sub CloseSTL

Nur erforderlich, falls die Kurzliste mit OpenSTL ( (cf.)) geöffnet wird.

Ordnungsgemäßes Schließen der Kurztitelliste, der Zustand wird in $STLisopen verbucht.

sub CloseSTL {
  return unless $STLisopen > 0;
  close (STL);
  $STLisopen = 0;
}

6.1.2 sub OpenSTL

Nur erforderlich, falls $STL ungleich 0 und die Kurzeinträge nicht via qrix title + bzw. list recnum durch Avanti geliefert werden.

Ordnungsgemäßes Öffnen der Kurztitelliste, Fehler werden nach Möglichkeit abgefangen, der Zustand wird in $STLisopen verbucht.

  return '' unless (defined $DbPfad && $DbPfad);
  if ( open (STL, "<$DbPfad/$DbName.stl") ) {
      $STLisopen = 1}
  else {
      PopDebug->Mess("öffnen von $DbPfad/$DbName.stl"
                             . " hat nicht funktioniert!\n");
      $STLisopen = -1;
    };
  return '';
}

6.1.3 ParseRegisterLine

Die Routine wird beim Einlesen der LineTypen 1 und 11 aufgerufen, Übergeben wird eine nur geringfügig aufbereitete Rohform, wie sie vom qrix-Kommando von Avanti geliefert wird:

Die drei Aufrufparameter sind

  1. Trefferzahl
  2. Registerzeile
  3. Satznummern (durch ',' getrennt)

Zurückgegeben werden müssen ebenfalls drei Variable:

  1. Eine Zahl, die auf LineTyp addiert wird
  2. Ein Hash (mit den durch ParseRegisterline bestimmten Eigenschaften der Zeile, beispielsweise mit einem Key Toomuch)
  3. Ein Array, das die (zur Ausgabe) bestimmten identifizierten Teile der Registerzeile enthält.

Eine triviale Routine sähe so aus:

sub ParseRegisterline {
  my ($count, $line, $recs) = @_;
  my $toobig = ($count =  /^\>/); # Groesserzeichen bemerken
  $count =  s/^\>//;              # Groesserzeichen entfernen
  return (0, {count=>$count, toobig=>$toobig}, [$_]);
}

6.1.4 ParseSTLentry

Diese Routine zerlegt Kurztitelzeilen in ihre Elemente. Einfaches Beispiel:

@STLStruktur = ('TitelAut', 'Jahr', 'Signatur');

%STLPositionen = (
# Key           Start, Laenge
  TitelAut  => [1,    55],
  Jahr      => [58,   4],
  Signatur  => [64,   9],
);

sub ParseSTLentry {
  my ($localtyp, $line, $recno) = @_;
  my ($key, $value, $start, $len, @returnarray);
  foreach $key ( @STLStruktur ) {
      ($start, $len) = @{$STLPositionen{$key}};
      ($value = substr ($line, $start, $len)) =  s/\s+$//;
      push (@returnarray, $value);
    };
  return ($localtyp, {}, [@returnarray]);
}

6.2 Optionale Hooks

Wenn diese Routinen nicht definiert sind, wird von populo ein Standardverhalten generiert.

6.2.1 AvantiErrHook

Aus dem Resultat von Avanti identifizierte Fehlermeldungen werden an diese Routine übergeben, sofern sie definiert ist.

Die Übergabeparameter sind:

$num
Numerischer Fehlercode von Avanti
$origtext
Text der Originalzeile von der Fehlernummer bis zum ersten ':'
$num
Rest der Originalzeile ab und einschließlich dem ersten ':'

Als Resultat muß die Routine einen (evtl. leeren) Ausgabetext zurückgeben.

Beispiel (Leitet alle Fehlermeldungen ans Ende des Dokuments um)

sub AvantiErrHook {
my ($num, $origtext, $extra) = @_;
  PopDebug->Mess(“\E$num\$origtext$extra\n“);
  return '';
}

6.2.2 InitHook

Wird aufgerufen, nachdem populo gestartet wurde, seine Zustandsavariablen initialisiert hat und die Aufrufparameter eingelesen wurden. Hier kann man also in Kenntnis des konkreten Aufrufs Nachinitialisierungen vornehmen, etwa um das Einlesen stets genutzter globaler Variablen nicht in jedem einzelnen Job veranlassen zu nüssen:

sub InitHook {      # !LI:<Register>:<Suchbegriff>!<Anzeige>!
  $Debug = $in{'debug'} ? 1 : 0;
}

Ein anderes Beispiel wäre eine Sprachumschaltung innerhalb des Scripts:

sub InitHook {      # !LI:<Register>:<Suchbegriff>!<Anzeige>!
  $Lang = $in{'lang'} || "";
  if ( $Lang =  /^(de|en|fr|it)$/ ) {  # alle erlaubten aufzaehlen
      substr($pathpraefix, 0, 0) = "cat_$Lang/;";  # also cat_de ...
    }
}

6.2.3 DefaultJTHook

Gibt $JobTyp und optional $JobSubtyp zurück, wenn kein Paramter t_... übergeben wurde. Fallback ist $Defaults{'JobTyp'}.

6.2.4 LinkEscape

Ist dieser Hook definiert, so wird Ausgabe vom Typ 4 (Vollanzeige) auf schematische Flips / Hyperlinks der folgenden Form durchsucht (kein Zeilenumbruch!):

…!LI:[Qualifier]Register:!Begriff! …
bzw.
…!LI:[Qualifier]Register:Suchbegriff!Text!…

Der optionale Qualifier sollte dabei analog zur Notation von Flips entweder leer oder '?' oder ' ' sein.

Register wird mittels der Struktur ReverseRegister aus der Konfigurationsdatei in ein Avanti-Register übersetzt, ReverseRegister muß daher für jedes als Ziel von Links vorkommende symbolische Register REG eine Zuordnung

 'REG:' => 'REG',
enthalten.

In der ersten Form wird Begriff von HTML nach ANSI zurückgerechnet und URL-enkapsuliert, in der zweiten Form wird Suchbegriff von ASCII nach ANSI verwandelt und dann URL-enkapsuliert. In der Praxis wird man also bei expliziter Angabe eines Suchbegriffs diesen durch die Allegro-Parameter mittels y0 formatieren lassen.

Der Hook LinkEscape wird stets mit vier Parametern

Qualifier
Register
Suchbegriff
Anzeigebegriff
aufgerufen und muß einen fertig formatierten Link
<a href=“…“>…</a>
zurückliefern.

Beispiel (aus avdemo):

sub LinkEscape {      # !LI:<Register>:<Suchbegriff>!<Anzeige>!
  my ($qualify, $register, $suchbegriff, $anzeige) = @_;
  local ($_);

  # Typ 'acindex' fuer ?-Begriffe, 'allegro' sonst
  my ( $ty ) = $qualify ? 'acindex' : 'allegro';
  if ( $ty eq 'acindex' ) { 
          # JobTyp 'acindex' mit Parametern index u. s1
      $_ = "&index=$ix&s1=$suchbegriff"}
  else {  # JobTyp 'allegro' mit Parameter f_Reg
      $_ = "&f_$ix=$suchbegriff"};

  return "<a href=$Pop?db=$Db&t_$ty=x" . $_ . ">$anzeige</a>";
}

6.2.5 ResultHook

Die aktuelle Zeile (vom LineTyp '4') ist in $_ und kann vor der Ausgabe noch individuell modifiziert werden.

Keine Rückgabeparameter, $_ wird modifiziert.

Beispiel (URLs aus Datensätzen ausarbeiten):

sub ResultHook {
s!URL: http:(//[/-?.:\w]+)!URL: <a href=“$1“>http:$1</a>!g;
}

6.2.6 JobHook

Hier kann man die eingelesenen Zeilen von Job-Dateien vor der Bearbeitung durch Populo selbst modifizieren.

Beispiel (URLs aus Datensätzen ausarbeiten):

sub JobHook {
s!URL: http:(//[/-?.:\w]+)!URL: <a href=“$1“>http:$1</a>!g;
}

6.2.7 TplHook

Hier kann man die eingelesenen Zeilen von Template-Dateien vor der Bearbeitung durch Populo selbst modifizieren.

Keine Rückgabeparameter, $_ wird modifiziert.

Beispiel (Syntax von ${...} in Populo-Syntax umbauen):

sub TplHook {
s=\$\{([A-Z]\w*)\}=PO!$1!=g;
}

6.2.8 STLmap

Diese Routine sortiert Kurztitelzeilen, wenn sie direkt (etwa im Zusammenhang mit einem erweiterten Register) geholt wurden. Die ersten Zeilen sollten analog gestaltet werden, dabei entsprechen $$aaref[i] und $$bbref[i] den Elementen der Kurztitelzeile, so wie sie in @returnarray von ParseSTLentry ( (cf.)) zurückgeliefert wurden.

Die Einträge können mittels Aufruf von iso2sor ggfls. sortierfähig gemacht werden.

Diese Routine übernimmt die Funktionalität von stlsort.

Übergeben wird eine Referenz auf ein Array, dessen 2. Element das Array mit den Feldern des aktuellen Kurzlisteneintrags ist.

Zurückgegeben werden muß ein String.

Beispiel:

# $_[0] ist Referenz auf Array...
   my $ref = ($_[0])->[2];
# sortiere nach Verfasser / Titel / Jahr absteigend
   return join("\x01", iso2sor($$ref[1]), 
                       iso2sor($$ref[0]), 
                    (  $$ref[2])
              );
}   

6.2.9 sub stlsort

Diese Routine sortiert Kurztitelzeilen, wenn sie direkt (etwa im Zusammenhang mit einem erweiterten Register) geholt wurden. Die ersten Zeilen sollten analog gestaltet werden, dabei entsprechen $$aaref[i] und $$bbref[i] den Elementen der Kurztitelzeile, so wie sie in @returnarray von ParseSTLentry zurückgeliefert wurden.

Ist die Routine STLmap definiert, so wird stlsort nicht benötigt (STLmap ist effizienter).

sub stlsort {
   $aaref = $$a[2];        # $aa ist Referenz auf Array...
   $bbref = $$b[2];        # $aa ist Referenz auf Array...
# sortiere nach Jahr / TitelAut
   $aa = iso2sor(join("\x01", $$aaref[1], $$aaref[0]));
   $bb = iso2sor(join("\x01", $$bbref[1], $$bbref[0]));
   return $aa cmp $bb;
}   

6.3 Hook-Verteiler

6.3.1 für die Aufbereitung

Die Struktur LineFlow in der Konfigurationsdatei ermöglicht das Einhängen von Spezialbehandlungen beim Einlesen von durch Avanti gelieferten Ergebnissen.

Vordefiniert sind:

1
DifferentiateRegister
3
DifferentiateSTL
4
ChannelResult
5
StoreRecnums
11
DifferentiateRegister
13
StoreSTLnums
14
StoreSTL

Im einzelnen tun diese Routinen folgendes:

DifferentiateRegister

Die aktuelle Zeile wird untersucht, ob es sich um eine „reguläre“ Registeranzeige ('qrix') oder um einen Kurlisteneintrag (bei 'qrix title+') handelt.

Dementprechend werden Trefferzählung, Satznummer(n) und Text identifiziert, der Text wird dann durch ParseSTLentry ( (cf.)) bzw. ParseRegisterLine( (cf.))

Der Cache der verfügbaren Kurzlistenzeilen wird aktualisiert, ebenso die Liste Thisnums der aktuellen Satznummern.

DifferentiateSTL

Die Liste Thisnums der aktuell geführten Satznummern wird aktualisiert, der Text wird durch ParseSTLentry ( (cf.)) aufbereitet.

ChannelResult

Mit '\' abschließende Zeilen werden mit der/den Folgezeile(n) zu überlangen Zeilen zusammengefaßt. Damit kann man etwa auch ohne den Allegro-Parameter zl auf '0' zu setzen in kritischen Situationen (Links!) beliebig lange Zeilen emulieren.

StoreRecnums

Die Zeile wird als Liste von Satznummern interpretiert und in der Variablen Recnums hinterlegt, Recnumsnum wird aktualisiert.

StoreSTLnums

Die aktuelle Satznummer wird als „benötigt“ im Kurztitelcache vermerkt.

StoreSTL

Die aktuelle Kurztitelzeile wird im Kurztitelcache vermerkt, an dieser Stelle aber nicht in die Ausgabe eingefügt!

6.3.2 für CollectQuery

Die Struktur MaskenSpecial in der Konfigurationsdatei ermöglicht das Einhängen von Spezialbehandlungen bei der Formulierung von Suchbegriffen.

Jede dieser Routinen darf dann folgende Variablen manipulieren:

$register
symbolisches Register
$logik
Logik
$trunk
Trunkierung
$_
Suchbegriff

Wird ein komplizierter, gar geklammerter Suchbegriff konstruiert, empfiehlt es sich, in der Behandlung die Variable $register zu löschen, dann erfolgt keine weitere Aufbereitung durch CollectQuery mehr, insbesondere kein Umschließen des Suchbegriffs durch Anführungszeichen.

Beispiel:

%MaskenSpecial = (  # definiert Unterprogramme zur Vorbehandlung
                    # der suchbegriffe
    'PER' => 'Persify,Trunkify,SR',
    'KOR' => 'Korify',
    'TIT' => 'Orify',
    'ISB' => 'Isbify',
);

Dabei sind dann etwa

sub Isbify {
  s/\s/-/g;    # amerikanische Form der Eingabe...
  substr($_, 11) = '' if length ($_) > 11;
               # kappen, da Prüfziffer nicht indexiert
  $trunk = "?";   # immer trunkiert suchen!
  return;
}

oder (damit auch Nach Personen als „Vorname Nachname“ gesucht werden kann:

sub Persify {  # Person etwa als VN NN eingegeben?
mehr als ein Wort muß sein, damit wir arbeiten:
  return unless /\s/;
Komma oder Ordnungshilfe: Profi am Werk, nichts tun!
  return if /[\,\<\>]/;
In Worte zerlegen, Letztes Wort von Komma gefolgt voranstellen:
  my @parts = split(/\s/, $_);
  my $bla = pop(@parts) . ", " . join(" ", @parts);
Originalbegriff sicherheitshalber auch noch suchen, alles natürlich trunkiert.
  $_ = "(PER \"$_\?\") OR ( PER \"$bla\?\")";
Zusammengebauter Begriff ist zu komplex, als daß wir CollectQuery daran auch noch herumfummeln lassen wollten, so wird dies ausgeschlossen:
  $register = $trunk = '';
}

oder (ziemlich wüst):

sub Korify {
  if ( ! (/^\"/ | /\?/) ) {
aus KOR=x y mache (KOR=x y z) OR (TIT=x§) OR (TIT=y§)
      tr/"//d;     # alle Anfuehrungen loeschen
Es ist '\xA7' das Paragraphenzeichen ANSI-codiert. Es werden nur Worte mit mindestens vier Buchstaben gesucht, um nicht evtl. mit 'AND' nach Stopworten zu suchen!
      my $hilf = join("\xA7\" AND TIT \"", 
                      grep (/.{4,}/, split(/\s+/, "$_")));
      $hilf =  tr/<>//d;
      $_ = "(KOR \"$_\?\") OR ( TIT \"" . $hilf . "\xA7\")";
      $register = $trunk = '';
      return;
    };
  tr/"//d;     # erst einmal alle Anfuehrungen loeschen
  $_ = "\"$_\"";
}