Config::XrmDatabase

This is a pure Perl implementation of the X Window Resource Manager
Database (XrmDB). It allows creation and manipulation of Xrm compliant
databases.

Warning! The XrmDB refers to names and resources. These days they are
more typically called keys and values. The terminology used below (and
sometimes in the names of subroutines and methods) mixes these two
approaches, sometimes a bit too liberally.

The XrmDB differs from typical key-value stores in that a stored key may
be only partially specified, so that a single entry can provide the
value for many different queries.

  Keys

A key is a sequence of *components* (such as "editor", "toolbar", and
"foreground") separated by *bindings*. A binding says how the components
on either side of it are related:

"." The next component must follow immediately. "editor.foreground"
    matches only "editor.foreground".

"*" Any number of components, *including none*, may come between.
    "editor*foreground" matches "editor.foreground",
    "editor.toolbar.foreground", "editor.toolbar.save.foreground", and
    so on.

A key which begins with "*" may match starting at any level: *foreground
matches "foreground", "toolbar.foreground", and
"editor.toolbar.save.foreground". A key which doesn't begin with a
binding must match starting at the first level.

Separately from bindings, a component may be the placeholder "?", which
stands for exactly one component, whatever it is. "editor.?.foreground"
matches "editor.toolbar.foreground" and "editor.menu.foreground", but
not "editor.foreground" or "editor.toolbar.save.foreground".

"?" and "*" are easily confused. "?" *is* a component, and always takes
the place of exactly one level. "*" is a binding; it sits *between*
components and can span any number of levels, including none.

The last component of a key must be a name or class component; a key may
not end in "?" or in a binding. A key containing neither "?" nor "*" is
*fully qualified*.

(N.B., the X Window System documentation calls "." a *tight* binding and
"*" a *loose* binding.)

  Names and classes

Each key that is queried has a *class*, a parallel key with the same
number of components. Classes provide a second way of addressing a key:
a stored key may refer to a level by the name's component or by the
class's component. A class essentially creates a namespace, so that
values can be assigned based on which namespace a key belongs to rather
than on the content of the key.

Let's say that you have a number of keys that end in "Foreground":

  a.b.c.Foreground
  d.e.f.Foreground
  x.y.z.Foreground

and you want to set a value for any keys which end in "Foreground":

  *Foreground : 'yellow'

To give each one its own value:

  a.b.c.Foreground : 'red'
  d.e.f.Foreground : 'blue'
  x.y.z.Foreground : 'green'

Let's say that "a.b.c.Foreground" and "d.e.f.Foreground" are in the same
class, "U.V.W.Foreground", and all keys in that class should have the
same value:

  U.V.W.Foreground : 'red'
  x.y.z.Foreground : 'green'

At some point, a new hierarchy of keys that begin with "g" is added to
that class, but they should have a different value:

  g.V.W.Foreground : 'magenta'

You could try this:

  g.?.?.Foreground : 'magenta'

But that would affect *all* keys that begin with "g", not just those in
that class.

Classes help bring some order, but this system can become very confusing
if some discipline isn't maintained.

  Matching

"query" is given a fully qualified name and its fully qualified class,
which must have the same number of components. They are compared with
the stored keys one level at a time, from left to right. A stored key's
component matches a level if it is the name's component, the class's
component, or "?"; alternatively, a "*" in the stored key may span the
level.

More than one stored key may match a query. When that happens,
precedence rules choose the one whose value is returned.

   Precedence at a single level

Consider a query for the name "editor.toolbar.save.foreground" with the
class "Editor.Box.Button.Foreground". Each of the following keys matches
it. They differ only in how they match the third level (name "save",
class "Button"), and are listed from highest to lowest precedence:

1.  The name, immediately following the previous level

      editor.toolbar.save.foreground

2.  The name, following a "*" which spans no components

      editor.toolbar*save.foreground

3.  The class, immediately following the previous level

      editor.toolbar.Button.foreground

4.  The class, following a "*" which spans no components

      editor.toolbar*Button.foreground

5.  "?", immediately following the previous level

      editor.toolbar.?.foreground

6.  "?", following a "*" which spans no components

      editor.toolbar*?.foreground

7.  The level is spanned by a "*", so the key has no component there

      editor.toolbar*foreground

In other words:

*   Any component that matches the level (name, class, or "?") beats
    spanning the level with a "*".

*   A name beats a class, and a class beats "?", regardless of the
    binding which precedes them.

*   Between two otherwise equal matches, a component which immediately
    follows the previous level (".") beats one which follows a "*".

Note that a "*" which spans no components does not cause a level to be
skipped. In rules 2, 4, and 6, the key still has a component at the
third level, and it is that component which is compared.

   Precedence across levels

Levels are compared from left to right, and the first level at which two
keys differ decides between them; later levels matter only if all
earlier ones are the same. For example, using the same query of name
"editor.toolbar.save.foreground" with class
"Editor.Box.Button.Foreground":

  editor*save.foreground
  editor.toolbar.?.foreground

the second key wins. At the second level it matches "toolbar" by name
(rule 1), while the first key spans that level with a "*" (rule 7). That
the first key matches "save" by name at the third level, while the
second key only matches it with "?", doesn't matter.

Similarly, of

  Editor.toolbar.save.foreground
  editor*foreground

the second key wins, even though the first is much more specific. At the
first level, "editor" matches by name (rule 1), while "Editor" only
matches by class (rule 3).

INSTALLATION

This is a Perl module distribution. It should be installed with whichever
tool you use to manage your installation of Perl, e.g. any of

  cpanm .
  cpan  .
  cpanp -i .

Consult http://www.cpan.org/modules/INSTALL.html for further instruction.
Should you wish to install this module manually, the procedure is

  perl Build.PL
  ./Build
  ./Build test
  ./Build install

COPYRIGHT AND LICENSE

This software is Copyright (c) 2021 by Smithsonian Astrophysical
Observatory.

This is free software, licensed under:

  The GNU General Public License, Version 3, June 2007
