Generic mapping index normalizer
authorBill Erickson <berick@esilibrary.com>
Tue, 6 Sep 2011 15:54:47 +0000 (11:54 -0400)
committerMike Rylander <mrylander@gmail.com>
Tue, 6 Sep 2011 20:25:11 +0000 (16:25 -0400)
Useful for mapping values extracted for SVF (metabib.record_attr.attrs)
attributes to alternate values.  For example, you can map collections of
MARC Audience codes into groups of codes for to create audience groups.

This normalizer takes a text parameter (in addition to the extracted value)
that defines a simple mapping between input and output.  Each mapping
consists of one or more comma separated strings on the left of a separator
(called the source group), a separator, and a alphanumeric string to the
right of the separator (called the mapping target). The format of a mapping
is:

  {string}[,{string}][..]=>{non-whitespace-string}

For example:

  a,b,c=>X

Multiple mappings can be supplied, separated by whitespace.  Each mapping
itself is not sensitive to most whitespace.  For instance, the following
are all equivalent:

 a,b,c=>X
 a, b, c => X
    a   ,   b   ,   c    =>     X

In each, "a", "b" and "c" are mapped to "X", and anything else is returned
without mapping.

Additionionally, whitespace within a string in the source group is tolerated.
Given a mapping of:

  a e i o u, y, w => V

The string "a e i o u", "y" or "w" will return "V".

In addition to explicit mapping, an empty source group will produce a default
mapping, where anything not matching another mapping will return the mapping
target.  For instance, given the following:

  =>X a,b,c=>Y

An input of "b" will return "Y" and an input of "k" will return "X".  The
Default mapping target may be the same as the mapping target with an explicit
source group.  For instance, the following can be interperated as "map a, b
and c to X, map 1, 2, 3 and anything we don't know about to Y":

 a,b,c=>X 1,2,3=>Y =>Y

As a practical example, simplifying the audience values in MARC fixed fields
to three groups and using those values in a new coded value map would allow
one to create a dynamically populated search interface that uses more patron-
friendly terms.  For instance:

  a,b,j=>K c,d=>T a=>A =>A g=>E

The above makes the assumption that Unknown, Specialized and Not Coded should
be lumped in with Audult, just to be safe, and General is for (E)veryone.

Signed-off-by: Mike Rylander <mrylander@gmail.com>
Signed-off-by: Bill Erickson <berick@esilibrary.com>
Open-ILS/src/sql/Pg/950.data.seed-values.sql
Open-ILS/src/sql/Pg/999.functions.global.sql
Open-ILS/src/sql/Pg/upgrade/XXXX.schema.generic-mapping-index-normalizer.sql [new file with mode: 0644]

index 8d224e8..d16f77f 100644 (file)
@@ -6045,6 +6045,13 @@ INSERT INTO config.index_normalizer (name, description, func, param_count) VALUE
        0
 );
 
+INSERT INTO config.index_normalizer (name, description, func, param_count) VALUES (
+    'Generic Mapping Normalizer', 
+    'Map values or sets of values to new values',
+    'generic_map_normalizer', 
+    1
+);
+
 -- make use of the index normalizers
 
 INSERT INTO config.metabib_field_index_norm_map (field,norm)
index 034b9e9..25dfb6a 100644 (file)
@@ -1897,3 +1897,29 @@ CREATE TRIGGER ingest_item_trigger
     AFTER INSERT OR UPDATE ON vandelay.queued_bib_record
     FOR EACH ROW EXECUTE PROCEDURE vandelay.ingest_bib_items();
 
+
+-- evergreen.generic_map_normalizer 
+
+CREATE OR REPLACE FUNCTION evergreen.generic_map_normalizer ( TEXT, TEXT ) RETURNS TEXT AS $f$
+my $string = shift;
+my %map;
+
+my $default = $string;
+
+$_ = shift;
+while (/^\s*?(.*?)\s*?=>\s*?(\S+)\s*/) {
+    if ($1 eq '') {
+        $default = $2;
+    } else {
+        $map{$2} = [split(/\s*,\s*/, $1)];
+    }
+    $_ = $';
+}
+
+for my $key ( keys %map ) {
+    return $key if (grep { $_ eq $string } @{ $map{$key} });
+}
+
+return $default;
+
+$f$ LANGUAGE PLPERLU;
diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.generic-mapping-index-normalizer.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.generic-mapping-index-normalizer.sql
new file mode 100644 (file)
index 0000000..d7239fd
--- /dev/null
@@ -0,0 +1,43 @@
+-- Evergreen DB patch XXXX.schema.generic-mapping-index-normalizer.sql
+--
+BEGIN;
+
+-- check whether patch can be applied
+SELECT evergreen.upgrade_deps_block_check('XXXX', :eg_version);
+
+-- evergreen.generic_map_normalizer 
+
+CREATE OR REPLACE FUNCTION evergreen.generic_map_normalizer ( TEXT, TEXT ) RETURNS TEXT AS $f$
+my $string = shift;
+my %map;
+
+my $default = $string;
+
+$_ = shift;
+while (/^\s*?(.*?)\s*?=>\s*?(\S+)\s*/) {
+    if ($1 eq '') {
+        $default = $2;
+    } else {
+        $map{$2} = [split(/\s*,\s*/, $1)];
+    }
+    $_ = $';
+}
+
+for my $key ( keys %map ) {
+    return $key if (grep { $_ eq $string } @{ $map{$key} });
+}
+
+return $default;
+
+$f$ LANGUAGE PLPERLU;
+
+-- evergreen.generic_map_normalizer 
+
+INSERT INTO config.index_normalizer (name, description, func, param_count) VALUES (
+    'Generic Mapping Normalizer', 
+    'Map values or sets of values to new values',
+    'generic_map_normalizer', 
+    1
+);
+
+COMMIT;