[open-ils-commits] [GIT] Evergreen ILS branch master updated. df5de4a008eef0518bda7a23543096dd65947985

Evergreen Git git at git.evergreen-ils.org
Mon Jul 11 14:28:52 EDT 2011


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Evergreen ILS".

The branch, master has been updated
       via  df5de4a008eef0518bda7a23543096dd65947985 (commit)
       via  49081017012efb43fbc3114058cee53f629aab9c (commit)
       via  6343d40803699e3d287ba8adec979dd99c4687ef (commit)
       via  8569fc04d0fe959a90bdf1dbe967011bfe915edd (commit)
       via  60755ab30c9ef33a1e0f8d2e526d2838dc03dc48 (commit)
       via  04eeb545bbbf07af05dc75e365632f4ef2cb3acb (commit)
       via  3fd2e7e750745f49e10083c98f23eba749dd8a1e (commit)
       via  985728674e25f66939255e2631c7e90c9e802320 (commit)
       via  e82a1234718120f7673922862d70e24123bf2cc8 (commit)
       via  3ffe952996807d42ef50a56a16981e6fbc12fa51 (commit)
       via  d8367973056752365a69ada9593b77fea9b92600 (commit)
       via  bbefc2e9ef49dfe0cecbff3f5afb5d99d057291c (commit)
       via  adab035d5ffe86417a24a49c89681419489909a6 (commit)
       via  0bba2a081dcfc3c4b9c492d3aa50f92e7acb8bd5 (commit)
       via  693520254eb55728d54826f910876ebc79d44299 (commit)
       via  6b419fe6abe7c779bf97c262776e446f829f9e8e (commit)
       via  e675b8540174233d534473251151721d435cf636 (commit)
       via  796f3b49b99d5237f6367f81a30983f5b74ca4cc (commit)
       via  2be66e212c390f9e1bf46235c57f06467b4e9afc (commit)
       via  e881cbb4731884f5eb7572a43a8ff7cda5de6f0f (commit)
       via  b95e14356c1ff9d150d2cc75aebf1f1fbb650845 (commit)
       via  c6c3223f585b9f3c36a2d46d1a828dbcd376709a (commit)
       via  a80f625b27a794866f7121ec4ea52f1268993c56 (commit)
       via  f634d30849f91bd51ef9fbfcbba639ad658a1c1c (commit)
       via  e3fa59368c8e8a3b1d26c442e58b1fe57526611c (commit)
       via  ade9dc1af909b8a31e98b1c6df2a63af3b4aeba8 (commit)
       via  580fed6d32cd8113c6d45a6c36fa97e28cce9f78 (commit)
       via  382e517182fcbd4c37778bd21dd567f1f0e6df4a (commit)
       via  41eb0560ca9810d9d1b6c5342c384aa56aef43c5 (commit)
       via  fe16ee4245a7df991ce645967a6ffdd798c13f46 (commit)
       via  3f4e0e6834a35d8bfca9b1e14fb51306f049e7f5 (commit)
       via  71948964b5361b5084f762a518c7cd23a37c3f92 (commit)
       via  3f8c866509587b066109a1051f82df0aef9d2b79 (commit)
       via  cf5a35ed963692a7e265224f65adadba9ee2ce58 (commit)
       via  3f47c3f331d2cf45153cf0590eb462c2c36b718a (commit)
       via  509eb848ebf06e4dc45b3b03f7cea8929b6faab1 (commit)
       via  1cdc294001f2d05f3701a04eed7c98957957c763 (commit)
       via  4e1432dc5f5c1f0353b7a02564b555367366e3e7 (commit)
       via  6b02e30519a690dc0b27cca9679a078c919c463e (commit)
       via  45916bdead2f8821acec6601dd186d6ac0839912 (commit)
       via  aefd51031be384e5db8e9da63682f70be95fdc2c (commit)
       via  106520e58aa7ab388f575242a89bfe299ec0a5d1 (commit)
       via  0cd95625806247edb1350af52ac35cfda3710c14 (commit)
       via  3a63f4579eed4582fd6dc0d910dcdc301737108c (commit)
       via  de741e118148e9593f218bae37c09eebdbd965e0 (commit)
       via  750fcec8604c3054a68d99c2a1e4be6b5b05add7 (commit)
       via  5ed4a1ffebf9c7191123f642d2865bf2de3b63d7 (commit)
       via  655fcbd6e50d1f76c555c2af686a5fb9ce7065c0 (commit)
       via  1e7663696b09c43379510faff416e94a9b1827ae (commit)
       via  d2e334b617523cd6a559238b38d0a0808a36a377 (commit)
       via  df89ecb9bfe15027d0c15c157c29b2f1649b4384 (commit)
       via  731f2e7c2fc1af4060b97656f2637fab05b0ebe2 (commit)
       via  fb6f9fd5c7059b21650eb472ed3650994556bb73 (commit)
       via  635e304d9b111851d4b57f2b9d8a2844ce918f1b (commit)
       via  36c64ccf37bb8e245c84cfb79ffc549bde59346b (commit)
       via  c923eac2cd5c6d758ae84f5774775a6c2ad06ae9 (commit)
       via  3e6438abe4008b89b11497c32ae466e565d8bb3f (commit)
       via  2151d7ea85b4c70c89ee6c928c9291441525c29f (commit)
       via  52f13d946eaa663b6f7a94d69150347b2aa3408e (commit)
       via  bfd2f1fbc65368a799731adaeb5d863e61f1c4cf (commit)
       via  1376352fb9f18b5784a20ac81889df6b0e251fe4 (commit)
       via  3457b554dc84bdca171ad8458f428ca9587bcf24 (commit)
       via  cedebcd8835579bdcd047e9a5601455036144d43 (commit)
       via  c7f4ec8091d071ffd07e9e6ccb815c85a88b49c6 (commit)
       via  0fec22966751d1c56070a6d21dc1a737b8f029f6 (commit)
       via  cd319a49c59f3cdc82dcaec571dc3dd957c2468c (commit)
       via  40283f335c75a75ab2829af3e202a1d33115f44d (commit)
       via  89732bcec8e8aa84b5fc1b319db2ebc781144667 (commit)
       via  470fa05860f0f911e40bb19b04e707f0d5e5bc7e (commit)
       via  331649ac7c0e046bd3e73958ba7bec6afd5dc863 (commit)
       via  4740d69d92072017bc31fef38169b92540916546 (commit)
       via  0196b3b5e2b5c1bab752ec763185e089efed973c (commit)
       via  bfed0299bd167da616b8960d96c1fc8bda1754a1 (commit)
       via  09e928786c75e67e24bd563c44ef91d85d3dbb79 (commit)
       via  da36fd8365210436597c7499c44bf85e5a6c6379 (commit)
       via  bdbcc734d179f8c12a27ec65f49650667ed658cc (commit)
       via  3ab55df32f5eefae941097a34f24cfb776c8508f (commit)
       via  063e907ad504270efd34e063f4784aee8621e493 (commit)
      from  df467c8cd0feeee08ce401544e60453899aa4ed7 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit df5de4a008eef0518bda7a23543096dd65947985
Merge: df467c8 4908101
Author: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>
Date:   Mon Jul 11 14:26:16 2011 -0400

    Merge branch 'authority-control-sets-squashed_for_master'
    
    Authority control sets! Largely by Mike Rylander, somewhat by me and
    others.
    
    This is the merge commit.  See individual commit messages for more
    detail.
    
    Signed-off-by: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>


commit 49081017012efb43fbc3114058cee53f629aab9c
Author: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>
Date:   Mon Jul 11 14:23:30 2011 -0400

    Stamping Mike's upgrade script for authority control sets
    
    Signed-off-by: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>

diff --git a/Open-ILS/src/sql/Pg/002.schema.config.sql b/Open-ILS/src/sql/Pg/002.schema.config.sql
index 294eb0e..96277db 100644
--- a/Open-ILS/src/sql/Pg/002.schema.config.sql
+++ b/Open-ILS/src/sql/Pg/002.schema.config.sql
@@ -86,7 +86,7 @@ CREATE TRIGGER no_overlapping_deps
     BEFORE INSERT OR UPDATE ON config.db_patch_dependencies
     FOR EACH ROW EXECUTE PROCEDURE evergreen.array_overlap_check ('deprecates');
 
-INSERT INTO config.upgrade_log (version, applied_to) VALUES ('0574', :eg_version); -- berick
+INSERT INTO config.upgrade_log (version, applied_to) VALUES ('0575', :eg_version); -- miker/senator
 
 CREATE TABLE config.bib_source (
 	id		SERIAL	PRIMARY KEY,
diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.authority-control-sets.sql b/Open-ILS/src/sql/Pg/upgrade/0575.schema.authority-control-sets.sql
similarity index 99%
rename from Open-ILS/src/sql/Pg/upgrade/XXXX.schema.authority-control-sets.sql
rename to Open-ILS/src/sql/Pg/upgrade/0575.schema.authority-control-sets.sql
index 9703301..c8b74dc 100644
--- a/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.authority-control-sets.sql
+++ b/Open-ILS/src/sql/Pg/upgrade/0575.schema.authority-control-sets.sql
@@ -6,7 +6,7 @@ BEGIN;
 
 
 -- check whether patch can be applied
-SELECT evergreen.upgrade_deps_block_check('XXXX', :eg_version);
+SELECT evergreen.upgrade_deps_block_check('0575', :eg_version);
 
 CREATE TABLE authority.control_set (
     id          SERIAL  PRIMARY KEY,

commit 6343d40803699e3d287ba8adec979dd99c4687ef
Author: Mike Rylander <mrylander at gmail.com>
Date:   Mon Jul 11 11:41:35 2011 -0400

    Unstamped upgrade script for Authority Control Sets
    
    ... with additional fixes from Lebbeous Fogle-Weekley
    
    Signed-off-by: Mike Rylander <mrylander at gmail.com>
    Signed-off-by: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>

diff --git a/Open-ILS/src/sql/Pg/011.schema.authority.sql b/Open-ILS/src/sql/Pg/011.schema.authority.sql
index 7c44d7e..630fece 100644
--- a/Open-ILS/src/sql/Pg/011.schema.authority.sql
+++ b/Open-ILS/src/sql/Pg/011.schema.authority.sql
@@ -218,14 +218,14 @@ CREATE OR REPLACE VIEW authority.tracing_links AS
             main.id AS main_id,
             main.tag AS main_tag,
             oils_xpath_string('//*[@tag="'||main.tag||'"]/*[local-name()="subfield"]', are.marc) AS main_value,
-            authority.normalize_heading(are.marc) AS normalized_main_value,
             substr(link.value,1,1) AS relationship,
             substr(link.value,2,1) AS use_restriction,
             substr(link.value,3,1) AS deprecation,
             substr(link.value,4,1) AS display_restriction,
             link.id AS link_id,
             link.tag AS link_tag,
-            oils_xpath_string('//*[@tag="'||link.tag||'"]/*[local-name()="subfield"]', are.marc) AS link_value
+            oils_xpath_string('//*[@tag="'||link.tag||'"]/*[local-name()="subfield"]', are.marc) AS link_value,
+            authority.normalize_heading(are.marc) AS normalized_main_value,
       FROM  authority.full_rec main
             JOIN authority.record_entry are ON (main.record = are.id)
             JOIN authority.control_set_authority_field main_entry
diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.authority-control-sets.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.authority-control-sets.sql
new file mode 100644
index 0000000..9703301
--- /dev/null
+++ b/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.authority-control-sets.sql
@@ -0,0 +1,501 @@
+-- Evergreen DB patch XXXX.schema.authority-control-sets.sql
+--
+-- Schema upgrade to add Authority Control Set functionality
+--
+BEGIN;
+
+
+-- check whether patch can be applied
+SELECT evergreen.upgrade_deps_block_check('XXXX', :eg_version);
+
+CREATE TABLE authority.control_set (
+    id          SERIAL  PRIMARY KEY,
+    name        TEXT    NOT NULL UNIQUE, -- i18n
+    description TEXT                     -- i18n
+);
+
+CREATE TABLE authority.control_set_authority_field (
+    id          SERIAL  PRIMARY KEY,
+    main_entry  INT     REFERENCES authority.control_set_authority_field (id) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
+    control_set INT     NOT NULL REFERENCES authority.control_set (id) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
+    tag         CHAR(3) NOT NULL,
+    sf_list     TEXT    NOT NULL,
+    name        TEXT    NOT NULL, -- i18n
+    description TEXT              -- i18n
+);
+
+CREATE TABLE authority.control_set_bib_field (
+    id              SERIAL  PRIMARY KEY,
+    authority_field INT     NOT NULL REFERENCES authority.control_set_authority_field (id) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
+    tag             CHAR(3) NOT NULL
+);
+
+CREATE TABLE authority.thesaurus (
+    code        TEXT    PRIMARY KEY,     -- MARC21 thesaurus code
+    control_set INT     NOT NULL REFERENCES authority.control_set (id) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
+    name        TEXT    NOT NULL UNIQUE, -- i18n
+    description TEXT                     -- i18n
+);
+
+CREATE TABLE authority.browse_axis (
+    code        TEXT    PRIMARY KEY,
+    name        TEXT    UNIQUE NOT NULL, -- i18n
+    sorter      TEXT    REFERENCES config.record_attr_definition (name) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
+    description TEXT
+);
+
+CREATE TABLE authority.browse_axis_authority_field_map (
+    id          SERIAL  PRIMARY KEY,
+    axis        TEXT    NOT NULL REFERENCES authority.browse_axis (code) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
+    field       INT     NOT NULL REFERENCES authority.control_set_authority_field (id) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED
+);
+
+ALTER TABLE authority.record_entry ADD COLUMN control_set INT REFERENCES authority.control_set (id) ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE authority.rec_descriptor DROP COLUMN char_encoding, ADD COLUMN encoding_level TEXT, ADD COLUMN thesaurus TEXT;
+
+CREATE INDEX authority_full_rec_value_index ON authority.full_rec (value);
+CREATE OR REPLACE RULE protect_authority_rec_delete AS ON DELETE TO authority.record_entry DO INSTEAD (UPDATE authority.record_entry SET deleted = TRUE WHERE OLD.id = authority.record_entry.id; DELETE FROM authority.full_rec WHERE record = OLD.id);
+ 
+CREATE OR REPLACE FUNCTION authority.normalize_heading( marcxml TEXT, no_thesaurus BOOL ) RETURNS TEXT AS $func$
+DECLARE
+    acsaf           authority.control_set_authority_field%ROWTYPE;
+    tag_used        TEXT;
+    sf              TEXT;
+    thes_code       TEXT;
+    cset            INT;
+    heading_text    TEXT;
+    tmp_text        TEXT;
+BEGIN
+    thes_code := vandelay.marc21_extract_fixed_field(marcxml,'Subj');
+    IF thes_code IS NULL THEN
+        thes_code := '|';
+    END IF;
+
+    SELECT control_set INTO cset FROM authority.thesaurus WHERE code = thes_code;
+    IF NOT FOUND THEN
+        cset = 1;
+    END IF;
+
+    heading_text := '';
+    FOR acsaf IN SELECT * FROM authority.control_set_authority_field WHERE control_set = cset AND main_entry IS NULL LOOP
+        tag_used := acsaf.tag;
+        FOR sf IN SELECT * FROM regexp_split_to_table(acsaf.sf_list,'') LOOP
+            tmp_text := oils_xpath_string('//*[@tag="'||tag_used||'"]/*[@code="'||sf||'"]', marcxml);
+            IF tmp_text IS NOT NULL AND tmp_text <> '' THEN
+                heading_text := heading_text || E'\u2021' || sf || ' ' || tmp_text;
+            END IF;
+        END LOOP;
+        EXIT WHEN heading_text <> '';
+    END LOOP;
+ 
+    IF thes_code = 'z' THEN
+        thes_code := oils_xpath_string('//*[@tag="040"]/*[@code="f"][1]', marcxml);
+    END IF;
+
+    IF heading_text <> '' THEN
+        IF no_thesaurus IS TRUE THEN
+            heading_text := tag_used || ' ' || public.naco_normalize(heading_text);
+        ELSE
+            heading_text := tag_used || '_' || thes_code || ' ' || public.naco_normalize(heading_text);
+        END IF;
+    ELSE
+        heading_text := 'NOHEADING_' || thes_code || ' ' || MD5(marcxml);
+    END IF;
+
+    RETURN heading_text;
+END;
+$func$ LANGUAGE PLPGSQL IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION authority.simple_normalize_heading( marcxml TEXT ) RETURNS TEXT AS $func$
+    SELECT authority.normalize_heading($1, TRUE);
+$func$ LANGUAGE SQL IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION authority.normalize_heading( marcxml TEXT ) RETURNS TEXT AS $func$
+    SELECT authority.normalize_heading($1, FALSE);
+$func$ LANGUAGE SQL IMMUTABLE;
+
+CREATE OR REPLACE VIEW authority.tracing_links AS
+    SELECT  main.record AS record,
+            main.id AS main_id,
+            main.tag AS main_tag,
+            oils_xpath_string('//*[@tag="'||main.tag||'"]/*[local-name()="subfield"]', are.marc) AS main_value,
+            substr(link.value,1,1) AS relationship,
+            substr(link.value,2,1) AS use_restriction,
+            substr(link.value,3,1) AS deprecation,
+            substr(link.value,4,1) AS display_restriction,
+            link.id AS link_id,
+            link.tag AS link_tag,
+            oils_xpath_string('//*[@tag="'||link.tag||'"]/*[local-name()="subfield"]', are.marc) AS link_value,
+            authority.normalize_heading(are.marc) AS normalized_main_value
+      FROM  authority.full_rec main
+            JOIN authority.record_entry are ON (main.record = are.id)
+            JOIN authority.control_set_authority_field main_entry
+                ON (main_entry.tag = main.tag
+                    AND main_entry.main_entry IS NULL
+                    AND main.subfield = 'a' )
+            JOIN authority.control_set_authority_field sub_entry
+                ON (main_entry.id = sub_entry.main_entry)
+            JOIN authority.full_rec link
+                ON (link.record = main.record
+                    AND link.tag = sub_entry.tag
+                    AND link.subfield = 'w' );
+ 
+CREATE OR REPLACE FUNCTION authority.generate_overlay_template (source_xml TEXT) RETURNS TEXT AS $f$
+DECLARE
+    cset                INT;
+    main_entry          authority.control_set_authority_field%ROWTYPE;
+    bib_field           authority.control_set_bib_field%ROWTYPE;
+    auth_id             INT DEFAULT oils_xpath_string('//*[@tag="901"]/*[local-name()="subfield" and @code="c"]', source_xml)::INT;
+    replace_data        XML[] DEFAULT '{}'::XML[];
+    replace_rules       TEXT[] DEFAULT '{}'::TEXT[];
+    auth_field          XML[];
+BEGIN
+    IF auth_id IS NULL THEN
+        RETURN NULL;
+    END IF;
+
+    -- Default to the LoC controll set
+    SELECT COALESCE(control_set,1) INTO cset FROM authority.record_entry WHERE id = auth_id;
+
+    FOR main_entry IN SELECT * FROM authority.control_set_authority_field WHERE control_set = cset LOOP
+        auth_field := XPATH('//*[@tag="'||main_entry.tag||'"][1]',source_xml::XML);
+        IF ARRAY_LENGTH(auth_field,1) > 0 THEN
+            FOR bib_field IN SELECT * FROM authority.control_set_bib_field WHERE authority_field = main_entry.id LOOP
+                replace_data := replace_data || XMLELEMENT( name datafield, XMLATTRIBUTES(bib_field.tag AS tag), XPATH('//*[local-name()="subfield"]',auth_field[1])::XML[]);
+                replace_rules := replace_rules || ( bib_field.tag || main_entry.sf_list || E'[0~\\)' || auth_id || '$]' );
+            END LOOP;
+            EXIT;
+        END IF;
+    END LOOP;
+ 
+    RETURN XMLELEMENT(
+        name record,
+        XMLATTRIBUTES('http://www.loc.gov/MARC21/slim' AS xmlns),
+        XMLELEMENT( name leader, '00881nam a2200193   4500'),
+        replace_data,
+        XMLELEMENT(
+            name datafield,
+            XMLATTRIBUTES( '905' AS tag, ' ' AS ind1, ' ' AS ind2),
+            XMLELEMENT(
+                name subfield,
+                XMLATTRIBUTES('r' AS code),
+                ARRAY_TO_STRING(replace_rules,',')
+            )
+        )
+    )::TEXT;
+END;
+$f$ STABLE LANGUAGE PLPGSQL;
+ 
+CREATE OR REPLACE FUNCTION authority.generate_overlay_template ( BIGINT ) RETURNS TEXT AS $func$
+    SELECT authority.generate_overlay_template( marc ) FROM authority.record_entry WHERE id = $1;
+$func$ LANGUAGE SQL;
+ 
+CREATE OR REPLACE FUNCTION vandelay.add_field ( target_xml TEXT, source_xml TEXT, field TEXT, force_add INT ) RETURNS TEXT AS $_$
+
+    use MARC::Record;
+    use MARC::File::XML (BinaryEncoding => 'UTF-8');
+    use MARC::Charset;
+    use strict;
+
+    MARC::Charset->assume_unicode(1);
+
+    my $target_xml = shift;
+    my $source_xml = shift;
+    my $field_spec = shift;
+    my $force_add = shift || 0;
+
+    my $target_r = MARC::Record->new_from_xml( $target_xml );
+    my $source_r = MARC::Record->new_from_xml( $source_xml );
+
+    return $target_xml unless ($target_r && $source_r);
+
+    my @field_list = split(',', $field_spec);
+
+    my %fields;
+    for my $f (@field_list) {
+        $f =~ s/^\s*//; $f =~ s/\s*$//;
+        if ($f =~ /^(.{3})(\w*)(?:\[([^]]*)\])?$/) {
+            my $field = $1;
+            $field =~ s/\s+//;
+            my $sf = $2;
+            $sf =~ s/\s+//;
+            my $match = $3;
+            $match =~ s/^\s*//; $match =~ s/\s*$//;
+            $fields{$field} = { sf => [ split('', $sf) ] };
+            if ($match) {
+                my ($msf,$mre) = split('~', $match);
+                if (length($msf) > 0 and length($mre) > 0) {
+                    $msf =~ s/^\s*//; $msf =~ s/\s*$//;
+                    $mre =~ s/^\s*//; $mre =~ s/\s*$//;
+                    $fields{$field}{match} = { sf => $msf, re => qr/$mre/ };
+                }
+            }
+        }
+    }
+
+    for my $f ( keys %fields) {
+        if ( @{$fields{$f}{sf}} ) {
+            for my $from_field ($source_r->field( $f )) {
+                my @tos = $target_r->field( $f );
+                if (!@tos) {
+                    next if (exists($fields{$f}{match}) and !$force_add);
+                    my @new_fields = map { $_->clone } $source_r->field( $f );
+                    $target_r->insert_fields_ordered( @new_fields );
+                } else {
+                    for my $to_field (@tos) {
+                        if (exists($fields{$f}{match})) {
+                            next unless (grep { $_ =~ $fields{$f}{match}{re} } $to_field->subfield($fields{$f}{match}{sf}));
+                        }
+                        my @new_sf = map { ($_ => $from_field->subfield($_)) } grep { defined($from_field->subfield($_)) } @{$fields{$f}{sf}};
+                        $to_field->add_subfields( @new_sf );
+                    }
+                }
+            }
+        } else {
+            my @new_fields = map { $_->clone } $source_r->field( $f );
+            $target_r->insert_fields_ordered( @new_fields );
+        }
+    }
+
+    $target_xml = $target_r->as_xml_record;
+    $target_xml =~ s/^<\?.+?\?>$//mo;
+    $target_xml =~ s/\n//sgo;
+    $target_xml =~ s/>\s+</></sgo;
+
+    return $target_xml;
+
+$_$ LANGUAGE PLPERLU;
+
+
+CREATE INDEX by_heading ON authority.record_entry (authority.simple_normalize_heading(marc)) WHERE deleted IS FALSE or deleted = FALSE;
+
+INSERT INTO config.metabib_field ( id, field_class, name, label, format, xpath, search_field, facet_field) VALUES
+    (28, 'identifier', 'authority_id', oils_i18n_gettext(28, 'Authority Record ID', 'cmf', 'label'), 'marcxml', '//marc:datafield/marc:subfield[@code="0"]', FALSE, TRUE);
+ 
+INSERT INTO config.marc21_rec_type_map (code, type_val, blvl_val) VALUES ('AUT','z',' ');
+INSERT INTO config.marc21_rec_type_map (code, type_val, blvl_val) VALUES ('MFHD','uvxy',' ');
+ 
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('ELvl', 'ldr', 'AUT', 17, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Subj', '008', 'AUT', 11, 1, '|');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('RecStat', 'ldr', 'AUT', 5, 1, 'n');
+ 
+INSERT INTO config.metabib_field_index_norm_map (field,norm,pos)
+    SELECT  m.id,
+            i.id,
+            -1
+      FROM  config.metabib_field m,
+            config.index_normalizer i
+      WHERE i.func = 'remove_paren_substring'
+            AND m.id IN (28);
+
+SELECT SETVAL('authority.control_set_id_seq'::TEXT, 100);
+SELECT SETVAL('authority.control_set_authority_field_id_seq'::TEXT, 1000);
+SELECT SETVAL('authority.control_set_bib_field_id_seq'::TEXT, 1000);
+
+INSERT INTO authority.control_set (id, name, description) VALUES (
+    1,
+    oils_i18n_gettext('1','LoC','acs','name'),
+    oils_i18n_gettext('1','Library of Congress standard authority record control semantics','acs','description')
+);
+
+INSERT INTO authority.control_set_authority_field (id, control_set, main_entry, tag, sf_list, name) VALUES
+
+-- Main entries
+    (1, 1, NULL, '100', 'abcdefklmnopqrstvxyz', oils_i18n_gettext('1','Heading -- Personal Name','acsaf','name')),
+    (2, 1, NULL, '110', 'abcdefgklmnoprstvxyz', oils_i18n_gettext('2','Heading -- Corporate Name','acsaf','name')),
+    (3, 1, NULL, '111', 'acdefgklnpqstvxyz', oils_i18n_gettext('3','Heading -- Meeting Name','acsaf','name')),
+    (4, 1, NULL, '130', 'adfgklmnoprstvxyz', oils_i18n_gettext('4','Heading -- Uniform Title','acsaf','name')),
+    (5, 1, NULL, '150', 'abvxyz', oils_i18n_gettext('5','Heading -- Topical Term','acsaf','name')),
+    (6, 1, NULL, '151', 'avxyz', oils_i18n_gettext('6','Heading -- Geographic Name','acsaf','name')),
+    (7, 1, NULL, '155', 'avxyz', oils_i18n_gettext('7','Heading -- Genre/Form Term','acsaf','name')),
+    (8, 1, NULL, '180', 'vxyz', oils_i18n_gettext('8','Heading -- General Subdivision','acsaf','name')),
+    (9, 1, NULL, '181', 'vxyz', oils_i18n_gettext('9','Heading -- Geographic Subdivision','acsaf','name')),
+    (10, 1, NULL, '182', 'vxyz', oils_i18n_gettext('10','Heading -- Chronological Subdivision','acsaf','name')),
+    (11, 1, NULL, '185', 'vxyz', oils_i18n_gettext('11','Heading -- Form Subdivision','acsaf','name')),
+    (12, 1, NULL, '148', 'avxyz', oils_i18n_gettext('12','Heading -- Chronological Term','acsaf','name')),
+
+-- See Also From tracings
+    (21, 1, 1, '500', 'abcdefiklmnopqrstvwxyz4', oils_i18n_gettext('21','See Also From Tracing -- Personal Name','acsaf','name')),
+    (22, 1, 2, '510', 'abcdefgiklmnoprstvwxyz4', oils_i18n_gettext('22','See Also From Tracing -- Corporate Name','acsaf','name')),
+    (23, 1, 3, '511', 'acdefgiklnpqstvwxyz4', oils_i18n_gettext('23','See Also From Tracing -- Meeting Name','acsaf','name')),
+    (24, 1, 4, '530', 'adfgiklmnoprstvwxyz4', oils_i18n_gettext('24','See Also From Tracing -- Uniform Title','acsaf','name')),
+    (25, 1, 5, '550', 'abivwxyz4', oils_i18n_gettext('25','See Also From Tracing -- Topical Term','acsaf','name')),
+    (26, 1, 6, '551', 'aivwxyz4', oils_i18n_gettext('26','See Also From Tracing -- Geographic Name','acsaf','name')),
+    (27, 1, 7, '555', 'aivwxyz4', oils_i18n_gettext('27','See Also From Tracing -- Genre/Form Term','acsaf','name')),
+    (28, 1, 8, '580', 'ivwxyz4', oils_i18n_gettext('28','See Also From Tracing -- General Subdivision','acsaf','name')),
+    (29, 1, 9, '581', 'ivwxyz4', oils_i18n_gettext('29','See Also From Tracing -- Geographic Subdivision','acsaf','name')),
+    (30, 1, 10, '582', 'ivwxyz4', oils_i18n_gettext('30','See Also From Tracing -- Chronological Subdivision','acsaf','name')),
+    (31, 1, 11, '585', 'ivwxyz4', oils_i18n_gettext('31','See Also From Tracing -- Form Subdivision','acsaf','name')),
+    (32, 1, 12, '548', 'aivwxyz4', oils_i18n_gettext('32','See Also From Tracing -- Chronological Term','acsaf','name')),
+
+-- Linking entries
+    (41, 1, 1, '700', 'abcdefghjklmnopqrstvwxyz25', oils_i18n_gettext('41','Established Heading Linking Entry -- Personal Name','acsaf','name')),
+    (42, 1, 2, '710', 'abcdefghklmnoprstvwxyz25', oils_i18n_gettext('42','Established Heading Linking Entry -- Corporate Name','acsaf','name')),
+    (43, 1, 3, '711', 'acdefghklnpqstvwxyz25', oils_i18n_gettext('43','Established Heading Linking Entry -- Meeting Name','acsaf','name')),
+    (44, 1, 4, '730', 'adfghklmnoprstvwxyz25', oils_i18n_gettext('44','Established Heading Linking Entry -- Uniform Title','acsaf','name')),
+    (45, 1, 5, '750', 'abvwxyz25', oils_i18n_gettext('45','Established Heading Linking Entry -- Topical Term','acsaf','name')),
+    (46, 1, 6, '751', 'avwxyz25', oils_i18n_gettext('46','Established Heading Linking Entry -- Geographic Name','acsaf','name')),
+    (47, 1, 7, '755', 'avwxyz25', oils_i18n_gettext('47','Established Heading Linking Entry -- Genre/Form Term','acsaf','name')),
+    (48, 1, 8, '780', 'vwxyz25', oils_i18n_gettext('48','Subdivision Linking Entry -- General Subdivision','acsaf','name')),
+    (49, 1, 9, '781', 'vwxyz25', oils_i18n_gettext('49','Subdivision Linking Entry -- Geographic Subdivision','acsaf','name')),
+    (50, 1, 10, '782', 'vwxyz25', oils_i18n_gettext('50','Subdivision Linking Entry -- Chronological Subdivision','acsaf','name')),
+    (51, 1, 11, '785', 'vwxyz25', oils_i18n_gettext('51','Subdivision Linking Entry -- Form Subdivision','acsaf','name')),
+    (52, 1, 12, '748', 'avwxyz25', oils_i18n_gettext('52','Established Heading Linking Entry -- Chronological Term','acsaf','name')),
+
+-- See From tracings
+    (61, 1, 1, '400', 'abcdefiklmnopqrstvwxyz4', oils_i18n_gettext('61','See Also Tracing -- Personal Name','acsaf','name')),
+    (62, 1, 2, '410', 'abcdefgiklmnoprstvwxyz4', oils_i18n_gettext('62','See Also Tracing -- Corporate Name','acsaf','name')),
+    (63, 1, 3, '411', 'acdefgiklnpqstvwxyz4', oils_i18n_gettext('63','See Also Tracing -- Meeting Name','acsaf','name')),
+    (64, 1, 4, '430', 'adfgiklmnoprstvwxyz4', oils_i18n_gettext('64','See Also Tracing -- Uniform Title','acsaf','name')),
+    (65, 1, 5, '450', 'abivwxyz4', oils_i18n_gettext('65','See Also Tracing -- Topical Term','acsaf','name')),
+    (66, 1, 6, '451', 'aivwxyz4', oils_i18n_gettext('66','See Also Tracing -- Geographic Name','acsaf','name')),
+    (67, 1, 7, '455', 'aivwxyz4', oils_i18n_gettext('67','See Also Tracing -- Genre/Form Term','acsaf','name')),
+    (68, 1, 8, '480', 'ivwxyz4', oils_i18n_gettext('68','See Also Tracing -- General Subdivision','acsaf','name')),
+    (69, 1, 9, '481', 'ivwxyz4', oils_i18n_gettext('69','See Also Tracing -- Geographic Subdivision','acsaf','name')),
+    (70, 1, 10, '482', 'ivwxyz4', oils_i18n_gettext('70','See Also Tracing -- Chronological Subdivision','acsaf','name')),
+    (71, 1, 11, '485', 'ivwxyz4', oils_i18n_gettext('71','See Also Tracing -- Form Subdivision','acsaf','name')),
+    (72, 1, 12, '448', 'aivwxyz4', oils_i18n_gettext('72','See Also Tracing -- Chronological Term','acsaf','name'));
+
+INSERT INTO authority.browse_axis (code,name,description,sorter) VALUES
+    ('title','Title','Title axis','titlesort'),
+    ('author','Author','Author axis','titlesort'),
+    ('subject','Subject','Subject axis','titlesort'),
+    ('topic','Topic','Topic Subject axis','titlesort');
+
+INSERT INTO authority.browse_axis_authority_field_map (axis,field) VALUES
+    ('author',  1 ),
+    ('author',  2 ),
+    ('author',  3 ),
+    ('title',   4 ),
+    ('topic',   5 ),
+    ('subject', 5 ),
+    ('subject', 6 ),
+    ('subject', 7 ),
+    ('subject', 12);
+
+INSERT INTO authority.control_set_bib_field (tag, authority_field) 
+    SELECT '100', id FROM authority.control_set_authority_field WHERE tag IN ('100')
+        UNION
+    SELECT '600', id FROM authority.control_set_authority_field WHERE tag IN ('100','180','181','182','185')
+        UNION
+    SELECT '700', id FROM authority.control_set_authority_field WHERE tag IN ('100')
+        UNION
+    SELECT '800', id FROM authority.control_set_authority_field WHERE tag IN ('100')
+        UNION
+
+    SELECT '110', id FROM authority.control_set_authority_field WHERE tag IN ('110')
+        UNION
+    SELECT '610', id FROM authority.control_set_authority_field WHERE tag IN ('110')
+        UNION
+    SELECT '710', id FROM authority.control_set_authority_field WHERE tag IN ('110')
+        UNION
+    SELECT '810', id FROM authority.control_set_authority_field WHERE tag IN ('110')
+        UNION
+
+    SELECT '111', id FROM authority.control_set_authority_field WHERE tag IN ('111')
+        UNION
+    SELECT '611', id FROM authority.control_set_authority_field WHERE tag IN ('111')
+        UNION
+    SELECT '711', id FROM authority.control_set_authority_field WHERE tag IN ('111')
+        UNION
+    SELECT '811', id FROM authority.control_set_authority_field WHERE tag IN ('111')
+        UNION
+
+    SELECT '130', id FROM authority.control_set_authority_field WHERE tag IN ('130')
+        UNION
+    SELECT '240', id FROM authority.control_set_authority_field WHERE tag IN ('130')
+        UNION
+    SELECT '630', id FROM authority.control_set_authority_field WHERE tag IN ('130')
+        UNION
+    SELECT '730', id FROM authority.control_set_authority_field WHERE tag IN ('130')
+        UNION
+    SELECT '830', id FROM authority.control_set_authority_field WHERE tag IN ('130')
+        UNION
+
+    SELECT '648', id FROM authority.control_set_authority_field WHERE tag IN ('148')
+        UNION
+
+    SELECT '650', id FROM authority.control_set_authority_field WHERE tag IN ('150','180','181','182','185')
+        UNION
+    SELECT '651', id FROM authority.control_set_authority_field WHERE tag IN ('151','180','181','182','185')
+        UNION
+    SELECT '655', id FROM authority.control_set_authority_field WHERE tag IN ('155','180','181','182','185')
+;
+
+INSERT INTO authority.thesaurus (code, name, control_set) VALUES
+    ('a', oils_i18n_gettext('a','Library of Congress Subject Headings','at','name'), 1),
+    ('b', oils_i18n_gettext('b',$$LC subject headings for children's literature$$,'at','name'), 1), -- silly vim '
+    ('c', oils_i18n_gettext('c','Medical Subject Headings','at','name'), 1),
+    ('d', oils_i18n_gettext('d','National Agricultural Library subject authority file','at','name'), 1),
+    ('k', oils_i18n_gettext('k','Canadian Subject Headings','at','name'), 1),
+    ('n', oils_i18n_gettext('n','Not applicable','at','name'), 1),
+    ('r', oils_i18n_gettext('r','Art and Architecture Thesaurus','at','name'), 1),
+    ('s', oils_i18n_gettext('s','Sears List of Subject Headings','at','name'), 1),
+    ('v', oils_i18n_gettext('v','Repertoire de vedettes-matiere','at','name'), 1),
+    ('z', oils_i18n_gettext('z','Other','at','name'), 1),
+    ('|', oils_i18n_gettext('|','No attempt to code','at','name'), 1);
+ 
+CREATE OR REPLACE FUNCTION authority.map_thesaurus_to_control_set () RETURNS TRIGGER AS $func$
+BEGIN
+    IF NEW.control_set IS NULL THEN
+        SELECT  control_set INTO NEW.control_set
+          FROM  authority.thesaurus
+          WHERE vandelay.marc21_extract_fixed_field(NEW.marc,'Subj') = code;
+    END IF;
+
+    RETURN NEW;
+END;
+$func$ LANGUAGE PLPGSQL;
+
+CREATE TRIGGER map_thesaurus_to_control_set BEFORE INSERT OR UPDATE ON authority.record_entry FOR EACH ROW EXECUTE PROCEDURE authority.map_thesaurus_to_control_set ();
+
+CREATE OR REPLACE FUNCTION authority.reingest_authority_rec_descriptor( auth_id BIGINT ) RETURNS VOID AS $func$
+BEGIN
+    DELETE FROM authority.rec_descriptor WHERE record = auth_id;
+    INSERT INTO authority.rec_descriptor (record, record_status, encoding_level, thesaurus)
+        SELECT  auth_id,
+                vandelay.marc21_extract_fixed_field(marc,'RecStat'),
+                vandelay.marc21_extract_fixed_field(marc,'ELvl'),
+                vandelay.marc21_extract_fixed_field(marc,'Subj')
+          FROM  authority.record_entry
+          WHERE id = auth_id;
+     RETURN;
+ END;
+ $func$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION authority.indexing_ingest_or_delete () RETURNS TRIGGER AS $func$
+BEGIN
+
+    IF NEW.deleted IS TRUE THEN -- If this authority is deleted
+        DELETE FROM authority.bib_linking WHERE authority = NEW.id; -- Avoid updating fields in bibs that are no longer visible
+        DELETE FROM authority.full_rec WHERE record = NEW.id; -- Avoid validating fields against deleted authority records
+          -- Should remove matching $0 from controlled fields at the same time?
+        RETURN NEW; -- and we're done
+    END IF;
+
+    IF TG_OP = 'UPDATE' THEN -- re-ingest?
+        PERFORM * FROM config.internal_flag WHERE name = 'ingest.reingest.force_on_same_marc' AND enabled;
+
+        IF NOT FOUND AND OLD.marc = NEW.marc THEN -- don't do anything if the MARC didn't change
+            RETURN NEW;
+        END IF;
+        -- Propagate these updates to any linked bib records
+        PERFORM authority.propagate_changes(NEW.id) FROM authority.record_entry WHERE id = NEW.id;
+    END IF;
+
+    -- Flatten and insert the afr data
+    PERFORM * FROM config.internal_flag WHERE name = 'ingest.disable_authority_full_rec' AND enabled;
+    IF NOT FOUND THEN
+        PERFORM authority.reingest_authority_full_rec(NEW.id);
+        PERFORM * FROM config.internal_flag WHERE name = 'ingest.disable_authority_rec_descriptor' AND enabled;
+        IF NOT FOUND THEN
+            PERFORM authority.reingest_authority_rec_descriptor(NEW.id);
+        END IF;
+    END IF;
+
+    RETURN NEW;
+END;
+$func$ LANGUAGE PLPGSQL;
+
+COMMIT;
+

commit 8569fc04d0fe959a90bdf1dbe967011bfe915edd
Author: Mike Rylander <mrylander at gmail.com>
Date:   Mon Jul 11 09:52:26 2011 -0400

    Merge/rebase cleanup -- remove useless/incorrect versions of the MARC flattener for different record types
    
    Signed-off-by: Mike Rylander <mrylander at gmail.com>

diff --git a/Open-ILS/src/sql/Pg/030.schema.metabib.sql b/Open-ILS/src/sql/Pg/030.schema.metabib.sql
index b70fae4..f8c3d16 100644
--- a/Open-ILS/src/sql/Pg/030.schema.metabib.sql
+++ b/Open-ILS/src/sql/Pg/030.schema.metabib.sql
@@ -451,77 +451,6 @@ BEGIN
 END;
 $func$ LANGUAGE PLPGSQL;
 
-/* Old form of biblio.flatten_marc() relied on contrib/xml2 functions that got all crashy in PostgreSQL 8.4 */
--- CREATE OR REPLACE FUNCTION biblio.flatten_marc ( TEXT, BIGINT ) RETURNS SETOF metabib.full_rec AS $func$
---     SELECT  NULL::bigint AS id, NULL::bigint, 'LDR'::char(3), NULL::TEXT, NULL::TEXT, NULL::TEXT, oils_xpath_string( '//*[local-name()="leader"]', $1 ), NULL::tsvector AS index_vector
---         UNION
---     SELECT  NULL::bigint AS id, NULL::bigint, x.tag::char(3), NULL::TEXT, NULL::TEXT, NULL::TEXT, x.value, NULL::tsvector AS index_vector
---       FROM  oils_xpath_table(
---                 'id',
---                 'marc',
---                 'biblio.record_entry',
---                 '//*[local-name()="controlfield"]/@tag|//*[local-name()="controlfield"]',
---                 'id=' || $2::TEXT
---             )x(record int, tag text, value text)
---         UNION
---     SELECT  NULL::bigint AS id, NULL::bigint, x.tag::char(3), x.ind1, x.ind2, x.subfield, x.value, NULL::tsvector AS index_vector
---       FROM  oils_xpath_table(
---                 'id',
---                 'marc',
---                 'biblio.record_entry',
---                 '//*[local-name()="datafield"]/@tag|' ||
---                 '//*[local-name()="datafield"]/@ind1|' ||
---                 '//*[local-name()="datafield"]/@ind2|' ||
---                 '//*[local-name()="datafield"]/*/@code|' ||
---                 '//*[local-name()="datafield"]/*[@code]',
---                 'id=' || $2::TEXT
---             )x(record int, tag text, ind1 text, ind2 text, subfield text, value text);
--- $func$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION biblio.flatten_marc ( TEXT ) RETURNS SETOF metabib.full_rec AS $func$
-
-use MARC::Record;
-use MARC::File::XML (BinaryEncoding => 'UTF-8');
-use MARC::Charset;
-
-MARC::Charset->assume_unicode(1);
-
-my $xml = shift;
-my $r = MARC::Record->new_from_xml( $xml );
-
-return_next( { tag => 'LDR', value => $r->leader } );
-
-for my $f ( $r->fields ) {
-	if ($f->is_control_field) {
-		return_next({ tag => $f->tag, value => $f->data });
-	} else {
-		for my $s ($f->subfields) {
-			return_next({
-				tag      => $f->tag,
-				ind1     => $f->indicator(1),
-				ind2     => $f->indicator(2),
-				subfield => $s->[0],
-				value    => $s->[1]
-			});
-
-			if ( $f->tag eq '245' and $s->[0] eq 'a' ) {
-				my $trim = $f->indicator(2) || 0;
-				return_next({
-					tag      => 'tnf',
-					ind1     => $f->indicator(1),
-					ind2     => $f->indicator(2),
-					subfield => 'a',
-					value    => substr( $s->[1], $trim )
-				});
-			}
-		}
-	}
-}
-
-return undef;
-
-$func$ LANGUAGE PLPERLU;
-
 CREATE OR REPLACE FUNCTION vandelay.marc21_record_type( marc TEXT ) RETURNS config.marc21_rec_type_map AS $func$
 DECLARE
 	ldr         TEXT;
diff --git a/Open-ILS/src/sql/Pg/999.functions.global.sql b/Open-ILS/src/sql/Pg/999.functions.global.sql
index 0561596..f0d95e5 100644
--- a/Open-ILS/src/sql/Pg/999.functions.global.sql
+++ b/Open-ILS/src/sql/Pg/999.functions.global.sql
@@ -1378,64 +1378,6 @@ CREATE OR REPLACE FUNCTION authority.propagate_changes (aid BIGINT) RETURNS SETO
     SELECT authority.propagate_changes( authority, bib ) FROM authority.bib_linking WHERE authority = $1;
 $func$ LANGUAGE SQL;
 
-CREATE OR REPLACE FUNCTION authority.flatten_marc ( TEXT ) RETURNS SETOF authority.full_rec AS $func$
-
-use MARC::Record;
-use MARC::File::XML (BinaryEncoding => 'UTF-8');
-
-my $xml = shift;
-my $r = MARC::Record->new_from_xml( $xml );
-
-return_next( { tag => 'LDR', value => $r->leader } );
-
-for my $f ( $r->fields ) {
-    if ($f->is_control_field) {
-        return_next({ tag => $f->tag, value => $f->data });
-    } else {
-        for my $s ($f->subfields) {
-            return_next({
-                tag      => $f->tag,
-                ind1     => $f->indicator(1),
-                ind2     => $f->indicator(2),
-                subfield => $s->[0],
-                value    => $s->[1]
-            });
-
-        }
-    }
-}
-
-return undef;
-
-$func$ LANGUAGE PLPERLU;
-
-CREATE OR REPLACE FUNCTION authority.flatten_marc ( rid BIGINT ) RETURNS SETOF authority.full_rec AS $func$
-DECLARE
-    auth    authority.record_entry%ROWTYPE;
-    output    authority.full_rec%ROWTYPE;
-    field    RECORD;
-BEGIN
-    SELECT INTO auth * FROM authority.record_entry WHERE id = rid;
-
-    FOR field IN SELECT * FROM authority.flatten_marc( auth.marc ) LOOP
-        output.record := rid;
-        output.ind1 := field.ind1;
-        output.ind2 := field.ind2;
-        output.tag := field.tag;
-        output.subfield := field.subfield;
-        IF field.subfield IS NOT NULL THEN
-            output.value := naco_normalize(field.value, field.subfield);
-        ELSE
-            output.value := field.value;
-        END IF;
-
-        CONTINUE WHEN output.value IS NULL;
-
-        RETURN NEXT output;
-    END LOOP;
-END;
-$func$ LANGUAGE PLPGSQL;
-
 CREATE OR REPLACE FUNCTION authority.map_thesaurus_to_control_set () RETURNS TRIGGER AS $func$
 BEGIN
     IF NEW.control_set IS NULL THEN

commit 60755ab30c9ef33a1e0f8d2e526d2838dc03dc48
Author: Mike Rylander <mrylander at gmail.com>
Date:   Mon Jul 11 09:51:33 2011 -0400

    Merge/rebase cleanup -- authority template by id is needed
    
    Signed-off-by: Mike Rylander <mrylander at gmail.com>

diff --git a/Open-ILS/src/sql/Pg/011.schema.authority.sql b/Open-ILS/src/sql/Pg/011.schema.authority.sql
index 8b2a528..7c44d7e 100644
--- a/Open-ILS/src/sql/Pg/011.schema.authority.sql
+++ b/Open-ILS/src/sql/Pg/011.schema.authority.sql
@@ -286,6 +286,10 @@ BEGIN
 END;
 $f$ STABLE LANGUAGE PLPGSQL;
 
+CREATE OR REPLACE FUNCTION authority.generate_overlay_template ( BIGINT ) RETURNS TEXT AS $func$
+    SELECT authority.generate_overlay_template( marc ) FROM authority.record_entry WHERE id = $1;
+$func$ LANGUAGE SQL;
+
 CREATE OR REPLACE FUNCTION authority.merge_records ( target_record BIGINT, source_record BIGINT ) RETURNS INT AS $func$
 DECLARE
     moved_objects INT := 0;

commit 04eeb545bbbf07af05dc75e365632f4ef2cb3acb
Author: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>
Date:   Tue Jul 5 15:50:20 2011 -0400

    Make search by authority ID actually work on the first try
    
    and also show an odd number of authority record results so that
    there can actually be a "middle."
    
    Signed-off-by: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>

diff --git a/Open-ILS/web/opac/skin/default/js/authbrowse.js b/Open-ILS/web/opac/skin/default/js/authbrowse.js
index 5e0f710..1e58dd5 100644
--- a/Open-ILS/web/opac/skin/default/js/authbrowse.js
+++ b/Open-ILS/web/opac/skin/default/js/authbrowse.js
@@ -15,7 +15,7 @@ function doAuthorityBrowse(axis, term, page, per_page) {
         axis = cgi.param(PARAM_AUTHORITY_BROWSE_AXIS);
         term = cgi.param(PARAM_AUTHORITY_BROWSE_TERM);
         page = cgi.param(PARAM_AUTHORITY_BROWSE_PAGE) || 0;
-        per_page = cgi.param(PARAM_AUTHORITY_BROWSE_PER_PAGE) || 20;
+        per_page = cgi.param(PARAM_AUTHORITY_BROWSE_PER_PAGE) || 21;
     }
 
     var url = '/opac/extras/browse/marcxml/authority.'
@@ -236,6 +236,8 @@ function displayRecordCount(axis, id, count) {
     args[PARAM_DEPTH] = depthSelGetDepth();
     args[PARAM_FORM] = "all";
     args[PARAM_LOCATION] = depthSelGetNewLoc();
+    args[PARAM_STYPE] = "keyword";
+    args[PARAM_RTYPE] = "keyword";
     args[PARAM_TERM] = "identifier|authority_id[" + id + "]";
 
     var axis_obj = acs_helper.browseAxisByCode(axis);

commit 3fd2e7e750745f49e10083c98f23eba749dd8a1e
Author: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>
Date:   Tue Jul 5 14:22:38 2011 -0400

    Provide sorters for browse axes
    
    Make the default bib result sorter 'titlesort' for every
    browse axis, which is what makes sense if you think about it.
    
    Signed-off-by: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>

diff --git a/Open-ILS/examples/fm_IDL.xml b/Open-ILS/examples/fm_IDL.xml
index 5816331..7b621a9 100644
--- a/Open-ILS/examples/fm_IDL.xml
+++ b/Open-ILS/examples/fm_IDL.xml
@@ -1855,11 +1855,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 		<fields oils_persist:primary="code">
 			<field reporter:label="Code" name="code" reporter:datatype="id" reporter:selector="name" oils_obj:validate="^\S+$"/>
 			<field reporter:label="Name" name="name" reporter:datatype="text" oils_persist:i18n="true" oils_obj:required="true"/>
+			<field reporter:label="Sorter Attribute" name="sorter" reporter:datatype="link"/>
 			<field reporter:label="Description" name="description" reporter:datatype="text"/>
 			<field reporter:label="Authority Fields" name="fields" reporter:datatype="link" oils_persist:virtual="true"/>
 			<field reporter:label="Authority Field Maps" name="maps" reporter:datatype="link" oils_persist:virtual="true"/>
 		</fields>
 		<links>
+			<link field="sorter" reltype="has_a" key="name" map="" class="crad"/>
 			<link field="fields" reltype="has_many" key="axis" map="field" class="abaafm"/>
 			<link field="maps" reltype="has_many" key="axis" map="" class="abaafm"/>
 		</links>
diff --git a/Open-ILS/src/sql/Pg/011.schema.authority.sql b/Open-ILS/src/sql/Pg/011.schema.authority.sql
index 3e6fda0..8b2a528 100644
--- a/Open-ILS/src/sql/Pg/011.schema.authority.sql
+++ b/Open-ILS/src/sql/Pg/011.schema.authority.sql
@@ -54,6 +54,7 @@ CREATE TABLE authority.thesaurus (
 CREATE TABLE authority.browse_axis (
     code        TEXT    PRIMARY KEY,
     name        TEXT    UNIQUE NOT NULL, -- i18n
+    sorter      TEXT    REFERENCES config.record_attr_definition (name) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
     description TEXT
 );
 
diff --git a/Open-ILS/src/sql/Pg/950.data.seed-values.sql b/Open-ILS/src/sql/Pg/950.data.seed-values.sql
index b245199..0082b83 100644
--- a/Open-ILS/src/sql/Pg/950.data.seed-values.sql
+++ b/Open-ILS/src/sql/Pg/950.data.seed-values.sql
@@ -9476,11 +9476,11 @@ INSERT INTO authority.control_set_authority_field (id, control_set, main_entry,
     (71, 1, 11, '485', 'ivwxyz4', oils_i18n_gettext('71','See Also Tracing -- Form Subdivision','acsaf','name')),
     (72, 1, 12, '448', 'aivwxyz4', oils_i18n_gettext('72','See Also Tracing -- Chronological Term','acsaf','name'));
 
-INSERT INTO authority.browse_axis (code,name,description) VALUES
-    ('title','Title','Title axis'),
-    ('author','Author','Author axis'),
-    ('subject','Subject','Subject axis'),
-    ('topic','Topic','Topic Subject axis');
+INSERT INTO authority.browse_axis (code,name,description,sorter) VALUES
+    ('title','Title','Title axis','titlesort'),
+    ('author','Author','Author axis','titlesort'),
+    ('subject','Subject','Subject axis','titlesort'),
+    ('topic','Topic','Topic Subject axis','titlesort');
 
 INSERT INTO authority.browse_axis_authority_field_map (axis,field) VALUES
     ('author',  1 ),
diff --git a/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js b/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
index 3583d66..990583f 100644
--- a/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
+++ b/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
@@ -42,7 +42,7 @@ if(!dojo._hasResource["openils.AuthorityControlSet"]) {
                     "abaafm": "_browse_field_map_list"
                 });
 
-                openils.AuthorityControlSet._browse_axis_by_name = {};
+                openils.AuthorityControlSet._browse_axis_by_code = {};
                 dojo.forEach( openils.AuthorityControlSet._browse_axis_list, function (ba) {
                     ba.maps(
                         dojo.filter(
@@ -50,7 +50,7 @@ if(!dojo._hasResource["openils.AuthorityControlSet"]) {
                             function (m) { return m.axis() == ba.code() }
                         )
                     );
-                    openils.AuthorityControlSet._browse_axis_by_name[ba.code()] = ba;
+                    openils.AuthorityControlSet._browse_axis_by_code[ba.code()] = ba;
                 });
 
                 // loop over each acs
@@ -199,6 +199,10 @@ if(!dojo._hasResource["openils.AuthorityControlSet"]) {
             return this.controlSet(thes.control_set());
         },
 
+        browseAxisByCode: function(code) {
+            return openils.AuthorityControlSet._browse_axis_by_code[code];
+        },
+
         bibFieldByTag: function (x) {
             var me = this;
             return dojo.filter(
@@ -213,15 +217,15 @@ if(!dojo._hasResource["openils.AuthorityControlSet"]) {
 
         bibFieldBrowseAxes : function (t) {
             var blist = [];
-            for (var bname in openils.AuthorityControlSet._browse_axis_by_name) {
+            for (var bcode in openils.AuthorityControlSet._browse_axis_by_code) {
                 dojo.forEach(
-                    openils.AuthorityControlSet._browse_axis_by_name[bname].maps(),
+                    openils.AuthorityControlSet._browse_axis_by_code[bcode].maps(),
                     function (m) {
                         if (dojo.filter(
                                 m.field().bib_fields(),
                                 function (b) { return b.tag() == t }
                             ).length > 0
-                        ) blist.push(bname);
+                        ) blist.push(bcode);
                     }
                 );
             }
diff --git a/Open-ILS/web/opac/skin/default/js/authbrowse.js b/Open-ILS/web/opac/skin/default/js/authbrowse.js
index e1b1442..5e0f710 100644
--- a/Open-ILS/web/opac/skin/default/js/authbrowse.js
+++ b/Open-ILS/web/opac/skin/default/js/authbrowse.js
@@ -31,7 +31,7 @@ function doAuthorityBrowse(axis, term, page, per_page) {
         "content": {"format": "marcxml"},
         "preventCache": true,
         "load": function(doc) {
-            displayAuthorityRecords(doc);
+            displayAuthorityRecords(axis, doc);
             setPagingLinks(axis, term, page, per_page);
         }
     });
@@ -167,7 +167,7 @@ function renderAuthorityRecord(m, control_set, auth_id) {
  * records, display each one in a table using the apporiate control set to
  * determine which fields to show.
  */
-function displayAuthorityRecords(doc) {
+function displayAuthorityRecords(axis, doc) {
     if (!acs_helper)
         acs_helper = new openils.AuthorityControlSet();
 
@@ -181,7 +181,6 @@ function displayAuthorityRecords(doc) {
 
     var records = dojo.query("record", doc);
     last_fetched_length = records.length;
-    console.log("length here is " + last_fetched_length);
 
     dojo.forEach(
         records,
@@ -202,11 +201,11 @@ function displayAuthorityRecords(doc) {
             );
         }
     );
-    displayRecordCounts(auth_ids);
+    displayRecordCounts(axis, auth_ids);
     swapCanvas(dojo.byId("canvas_main"));
 }
 
-function displayRecordCounts(auth_ids) {
+function displayRecordCounts(axis, auth_ids) {
     fieldmapper.standardRequest(
         ["open-ils.cat", "open-ils.cat.authority.records.count_linked_bibs"], {
             "params": [auth_ids],
@@ -215,7 +214,7 @@ function displayRecordCounts(auth_ids) {
                 if ((r = openils.Util.readResponse(r))) {
                     dojo.forEach(r, function(blob) {
                         if (blob.bibs > 0) {
-                            displayRecordCount(blob.authority, blob.bibs);
+                            displayRecordCount(axis, blob.authority, blob.bibs);
                         }
                     });
                 }
@@ -224,7 +223,7 @@ function displayRecordCounts(auth_ids) {
     );
 }
 
-function displayRecordCount(id, count) {
+function displayRecordCount(axis, id, count) {
     /* 1) put record count where we can see it */
     dojo.query("#authority_" + id + " .authority-count-holder")[0].innerHTML =
         "(" + count + ")"; /* XXX i18n ? */
@@ -239,6 +238,10 @@ function displayRecordCount(id, count) {
     args[PARAM_LOCATION] = depthSelGetNewLoc();
     args[PARAM_TERM] = "identifier|authority_id[" + id + "]";
 
+    var axis_obj = acs_helper.browseAxisByCode(axis);
+    if (axis_obj.sorter())
+        args[PARAM_TERM] += " sort(" + axis_obj.sorter() + ")";
+
     dojo.create(
         "a", {
             "innerHTML": span.innerHTML,
diff --git a/Open-ILS/web/templates/default/conify/global/cat/authority/browse_axis.tt2 b/Open-ILS/web/templates/default/conify/global/cat/authority/browse_axis.tt2
index fc31b6e..8834b02 100644
--- a/Open-ILS/web/templates/default/conify/global/cat/authority/browse_axis.tt2
+++ b/Open-ILS/web/templates/default/conify/global/cat/authority/browse_axis.tt2
@@ -13,7 +13,7 @@
                 dojoType="openils.widget.AutoGrid"
                 autoHeight="true"
                 defaultCellWidth="'auto'"
-                fieldOrder="['code','name','description']"
+                fieldOrder="['code','name','description','sorter']"
                 suppressEditFields="['id']"
                 query="{id: '*'}"
                 fmClass="aba"
@@ -25,6 +25,9 @@
     dojo.require("openils.widget.AutoGrid");
 
     function my_init() {
+        aba_grid.overrideWidgetArgs.sorter = {
+            "dijitArgs": {"query": {"sorter": "t"}}
+        };
         aba_grid.loadAll({"order_by": {"aba": "code"}});
     }
 

commit 985728674e25f66939255e2631c7e90c9e802320
Author: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>
Date:   Thu Jun 30 17:25:06 2011 -0400

    Create facet for going right to records linked to a given authority record
    
    Still need an upgrade script, of course, but so does this whole branch
    
    Signed-off-by: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>

diff --git a/Open-ILS/src/sql/Pg/950.data.seed-values.sql b/Open-ILS/src/sql/Pg/950.data.seed-values.sql
index d59cd8c..b245199 100644
--- a/Open-ILS/src/sql/Pg/950.data.seed-values.sql
+++ b/Open-ILS/src/sql/Pg/950.data.seed-values.sql
@@ -95,6 +95,8 @@ INSERT INTO config.metabib_field ( id, field_class, name, label, format, xpath )
     (26, 'identifier', 'tcn', oils_i18n_gettext(26, 'Title Control Number', 'cmf', 'label'), 'marcxml', $$//marc:datafield[@tag='901']/marc:subfield[@code='a']$$ );
 INSERT INTO config.metabib_field ( id, field_class, name, label, format, xpath ) VALUES
     (27, 'identifier', 'bibid', oils_i18n_gettext(27, 'Internal ID', 'cmf', 'label'), 'marcxml', $$//marc:datafield[@tag='901']/marc:subfield[@code='c']$$ );
+INSERT INTO config.metabib_field ( id, field_class, name, label, format, xpath, search_field, facet_field) VALUES
+    (28, 'identifier', 'authority_id', oils_i18n_gettext(28, 'Authority Record ID', 'cmf', 'label'), 'marcxml', '//marc:datafield/marc:subfield[@code="0"]', FALSE, TRUE);
 
 SELECT SETVAL('config.metabib_field_id_seq'::TEXT, (SELECT MAX(id) FROM config.metabib_field), TRUE);
 
@@ -5894,6 +5896,15 @@ INSERT INTO config.metabib_field_index_norm_map (field,norm,params)
       WHERE i.func IN ('replace')
             AND m.id IN (19);
 
+INSERT INTO config.metabib_field_index_norm_map (field,norm,pos)
+    SELECT  m.id,
+            i.id,
+            -1
+      FROM  config.metabib_field m,
+            config.index_normalizer i
+      WHERE i.func = 'remove_paren_substring'
+            AND m.id IN (28);
+
 INSERT INTO config.record_attr_index_norm_map (attr,norm,pos)
     SELECT  m.name, i.id, 0
       FROM  config.record_attr_definition m,

commit e82a1234718120f7673922862d70e24123bf2cc8
Author: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>
Date:   Thu Jun 30 16:54:35 2011 -0400

    attempted to add sanity to paging, but not really there yet
    
    Signed-off-by: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>

diff --git a/Open-ILS/web/opac/skin/default/js/authbrowse.js b/Open-ILS/web/opac/skin/default/js/authbrowse.js
index f073b0c..e1b1442 100644
--- a/Open-ILS/web/opac/skin/default/js/authbrowse.js
+++ b/Open-ILS/web/opac/skin/default/js/authbrowse.js
@@ -2,7 +2,7 @@ dojo.require("openils.CGI");
 dojo.require("openils.Util");
 dojo.require("MARC.FixedFields");
 dojo.require("openils.AuthorityControlSet");
-var cgi, acs_helper;
+var cgi, acs_helper, last_fetched_length = 0;
 
 attachEvt("common", "init", doAuthorityBrowse);
 
@@ -18,8 +18,6 @@ function doAuthorityBrowse(axis, term, page, per_page) {
         per_page = cgi.param(PARAM_AUTHORITY_BROWSE_PER_PAGE) || 20;
     }
 
-    setPagingLinks(axis, term, page, per_page);
-
     var url = '/opac/extras/browse/marcxml/authority.'
         + axis
         + '/1' /* this will be OU if OU ever means anything for authorities */
@@ -32,28 +30,38 @@ function doAuthorityBrowse(axis, term, page, per_page) {
         "handleAs": "xml",
         "content": {"format": "marcxml"},
         "preventCache": true,
-        "load": displayAuthorityRecords
+        "load": function(doc) {
+            displayAuthorityRecords(doc);
+            setPagingLinks(axis, term, page, per_page);
+        }
     });
 }
 
 function setPagingLinks(axis, term, page, per_page) {
-    /* XXX since authority browse drops us into the middle of the record set,
-     * we need additional complexity to find out if we're have more records
-     * above and below, so just assume we always do for now.
-     */
     var up_page = Number(page) - 1;
     var down_page = Number(page) + 1;
 
+    unHideMe(dojo.byId("authority-page-up"));
     dojo.attr(
         "authority-page-up", "onclick", function() {
             doAuthorityBrowse(axis, term, up_page, per_page);
         }
     );
-    dojo.attr(
-        "authority-page-down", "onclick", function() {
-            doAuthorityBrowse(axis, term, down_page, per_page);
-        }
-    );
+
+    /* XXX In theory this would generally stop the "next page" link from
+     * showing up when it's unwanted, but in practice the supercat/unapi
+     * call we make doesn't return the number of records it's supposed to.
+     */
+//    if (last_fetched_length == per_page) {
+        unHideMe(dojo.byId("authority-page-down"));
+        dojo.attr(
+            "authority-page-down", "onclick", function() {
+                doAuthorityBrowse(axis, term, down_page, per_page);
+            }
+        );
+//    } else {
+//        hideMe(dojo.byId("authority-page-down"));
+//    }
 }
 
 function renderAuthorityTagContent(m, af) {
@@ -168,8 +176,15 @@ function displayAuthorityRecords(doc) {
      * from record to record when different control sets were in use.
      */
     var auth_ids = [];
+
     dojo.empty("authority-record-holder");
-    dojo.query("record", doc).forEach(
+
+    var records = dojo.query("record", doc);
+    last_fetched_length = records.length;
+    console.log("length here is " + last_fetched_length);
+
+    dojo.forEach(
+        records,
         function(record) {
             var m = new MARC.Record({"xml": record});
 
diff --git a/Open-ILS/web/opac/skin/default/xml/page_authbrowse.xml b/Open-ILS/web/opac/skin/default/xml/page_authbrowse.xml
index f137c5d..f8c8897 100644
--- a/Open-ILS/web/opac/skin/default/xml/page_authbrowse.xml
+++ b/Open-ILS/web/opac/skin/default/xml/page_authbrowse.xml
@@ -2,12 +2,12 @@
 	<script language='javascript' type='text/javascript' src='<!--#echo var="OILS_OPAC_JS_HOST"-->/skin/default/js/authbrowse.js'></script>
 
     <div class="authority-pager">
-        <a id="authority-page-up" href="#" class="classic_link">&common.cn.previous;</a>
+        <a id="authority-page-up" href="#" class="hide_me classic_link">&common.cn.previous;</a>
     </div>
 
     <div id="authority-record-holder"></div>
 
     <div class="authority-pager">
-        <a id="authority-page-down" href="#" class="classic_link">&common.cn.next;</a>
+        <a id="authority-page-down" href="#" class="hide_me classic_link">&common.cn.next;</a>
     </div>
 </div>

commit 3ffe952996807d42ef50a56a16981e6fbc12fa51
Author: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>
Date:   Thu Jun 30 15:59:07 2011 -0400

    Make linking to bib records work better by saying any format will do.
    
    Signed-off-by: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>

diff --git a/Open-ILS/web/opac/skin/default/js/authbrowse.js b/Open-ILS/web/opac/skin/default/js/authbrowse.js
index b266490..f073b0c 100644
--- a/Open-ILS/web/opac/skin/default/js/authbrowse.js
+++ b/Open-ILS/web/opac/skin/default/js/authbrowse.js
@@ -220,6 +220,7 @@ function displayRecordCount(id, count) {
     var args = {};
     args.page = RRESULT;
     args[PARAM_DEPTH] = depthSelGetDepth();
+    args[PARAM_FORM] = "all";
     args[PARAM_LOCATION] = depthSelGetNewLoc();
     args[PARAM_TERM] = "identifier|authority_id[" + id + "]";
 

commit d8367973056752365a69ada9593b77fea9b92600
Author: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>
Date:   Wed Jun 29 19:34:56 2011 -0400

    working! with paging and linking to bibs, except:
    
    ... my new facet thingy doesn't seem to work.  here's what I did
    sql-wise:
    
        INSERT INTO config.metabib_field (
            id, field_class, name, label, xpath,
            format, search_field, facet_field
        ) VALUES (
            28, 'identifier',
            'authority_id', 'Authority Record ID',
            '//marc:datafield/marc:subfield[@code=''0'']', 'marcxml', false, true
        );
    
        INSERT INTO config.metabib_field_index_norm_map (field, norm)
        VALUES (28, 5);
    
    Yet after re-ingesting my bibs I have nothing new in
    metabib.facet_entry.  So the "show related bibliographic holdings" links
    don't quite work (I believe they /would/, though, if I had the facet
    thingy right).
    
    Signed-off-by: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>

diff --git a/Open-ILS/web/opac/common/js/config.js b/Open-ILS/web/opac/common/js/config.js
index 21b20fa..1cdc09d 100644
--- a/Open-ILS/web/opac/common/js/config.js
+++ b/Open-ILS/web/opac/common/js/config.js
@@ -47,8 +47,10 @@ var PARAM_PUBD_AFTER = 'pda';
 var PARAM_PUBD_BETWEEN = 'pdt';
 var PARAM_PUBD_DURING = 'pdd';
 var PARAM_NOPERSIST_SEARCH = 'nps';
-var PARAM_AUTHORITY_BROWSE_AXIS = "ax";
+var PARAM_AUTHORITY_BROWSE_AXIS = "bx";
 var PARAM_AUTHORITY_BROWSE_TERM = "bt";
+var PARAM_AUTHORITY_BROWSE_PAGE = "bp";
+var PARAM_AUTHORITY_BROWSE_PER_PAGE = "be";
 
 /* URL param values (see comments above) */
 var TERM;  
diff --git a/Open-ILS/web/opac/skin/default/css/layout.css b/Open-ILS/web/opac/skin/default/css/layout.css
index 7aaed35..8a4ca89 100644
--- a/Open-ILS/web/opac/skin/default/css/layout.css
+++ b/Open-ILS/web/opac/skin/default/css/layout.css
@@ -76,8 +76,10 @@ table { border-collapse: collapse; }
 
 table.authority-record { width: 48em; background-color: #ddd; margin: 1em; }
 td.authority-record-right { width: 24em; }
-td.authority-record-main { font-weight: bold; }
 td.authority-tag-label { font-style: italic; }
+.authority-pager { margin: 1ex 0; }
+.authority-count-holder { padding-left: 1em; font-weight: bold; }
+a.authority-content { font-weight: bold; }
 
 #searchbar { margin-top: 22px; width: 100%; }
 #searchbar table tr td {font-weight: bold; font-size: 8pt; }
diff --git a/Open-ILS/web/opac/skin/default/js/authbrowse.js b/Open-ILS/web/opac/skin/default/js/authbrowse.js
index 643d6c5..b266490 100644
--- a/Open-ILS/web/opac/skin/default/js/authbrowse.js
+++ b/Open-ILS/web/opac/skin/default/js/authbrowse.js
@@ -2,20 +2,24 @@ dojo.require("openils.CGI");
 dojo.require("openils.Util");
 dojo.require("MARC.FixedFields");
 dojo.require("openils.AuthorityControlSet");
-var cgi;
+var cgi, acs_helper;
 
 attachEvt("common", "init", doAuthorityBrowse);
 
 /* repeatable, supports all args or no args */
 function doAuthorityBrowse(axis, term, page, per_page) {
+    swapCanvas(dojo.byId("loading_alt"));
+
     if (!axis) {
         if (!cgi) cgi = new openils.CGI();
         axis = cgi.param(PARAM_AUTHORITY_BROWSE_AXIS);
         term = cgi.param(PARAM_AUTHORITY_BROWSE_TERM);
-        page = 0;
-        per_page = 20;
+        page = cgi.param(PARAM_AUTHORITY_BROWSE_PAGE) || 0;
+        per_page = cgi.param(PARAM_AUTHORITY_BROWSE_PER_PAGE) || 20;
     }
 
+    setPagingLinks(axis, term, page, per_page);
+
     var url = '/opac/extras/browse/marcxml/authority.'
         + axis
         + '/1' /* this will be OU if OU ever means anything for authorities */
@@ -32,7 +36,30 @@ function doAuthorityBrowse(axis, term, page, per_page) {
     });
 }
 
+function setPagingLinks(axis, term, page, per_page) {
+    /* XXX since authority browse drops us into the middle of the record set,
+     * we need additional complexity to find out if we're have more records
+     * above and below, so just assume we always do for now.
+     */
+    var up_page = Number(page) - 1;
+    var down_page = Number(page) + 1;
+
+    dojo.attr(
+        "authority-page-up", "onclick", function() {
+            doAuthorityBrowse(axis, term, up_page, per_page);
+        }
+    );
+    dojo.attr(
+        "authority-page-down", "onclick", function() {
+            doAuthorityBrowse(axis, term, down_page, per_page);
+        }
+    );
+}
+
 function renderAuthorityTagContent(m, af) {
+    /* XXX This doesn't take into account possible tag repeatability -- a
+     * bona fide library scientist could probably improve this. :-)
+     */
     if (af.tag() && af.sf_list()) {
         return dojo.filter(
             dojo.map(
@@ -82,14 +109,19 @@ function renderAuthorityMainEntry(m, field, tbody) {
     if (!content.length) return;    /* don't display empty tags */
 
     var tr = dojo.create("tr", null, tbody);
-    dojo.create(
+    var content_holder = dojo.create(
         "td", {
             "className": "authority-tag-content authority-record-main",
-            "innerHTML": content,
             "colspan": 2
         }, tr
     );
     dojo.create(
+        "span",
+        {"className":"authority-content", "innerHTML": content},
+        content_holder
+    );
+    dojo.create("span", {"className":"authority-count-holder"}, content_holder);
+    dojo.create(
         "td", {
             "className": "authority-tag-label authority-record-right",
             "innerHTML": field.name(),
@@ -105,7 +137,7 @@ function renderAuthorityMainEntry(m, field, tbody) {
     }
 }
 
-function renderAuthorityRecord(m, control_set) {
+function renderAuthorityRecord(m, control_set, auth_id) {
     var main_entries = openils.Util.objectSort(
         dojo.filter(
             control_set.authority_fields(),
@@ -114,7 +146,7 @@ function renderAuthorityRecord(m, control_set) {
     );
 
     var table = dojo.create("table", {"className": "authority-record"});
-    var tbody = dojo.create("tbody", null, table);
+    var tbody = dojo.create("tbody", {"id": "authority_" + auth_id}, table);
 
     dojo.forEach(
         main_entries, function(af) { renderAuthorityMainEntry(m, af, tbody); }
@@ -123,19 +155,82 @@ function renderAuthorityRecord(m, control_set) {
     return table;
 }
 
+/* displayAuthorityRecords: given a DOM document object that contains marcxml
+ * records, display each one in a table using the apporiate control set to
+ * determine which fields to show.
+ */
 function displayAuthorityRecords(doc) {
-    var acs_helper = new openils.AuthorityControlSet();
+    if (!acs_helper)
+        acs_helper = new openils.AuthorityControlSet();
 
     /* XXX I wanted to use bibtemplate here, but now I'm not sure it makes
      * sense: the template itself would have to be dynamic, as it would vary
      * from record to record when different control sets were in use.
      */
+    var auth_ids = [];
+    dojo.empty("authority-record-holder");
     dojo.query("record", doc).forEach(
         function(record) {
             var m = new MARC.Record({"xml": record});
-            var s = m.extractFixedField("Subj");
-            var cs = acs_helper.controlSetByThesaurusCode(s);
-            dojo.place(renderAuthorityRecord(m, cs.raw), "test-holder");
+
+            /* is 001 reliable for this? I'm guessing not */
+            var auth_id = m.field("001").data;
+            auth_ids.push(auth_id);
+
+            var cs = acs_helper.controlSetByThesaurusCode(
+                m.extractFixedField("Subj")
+            );
+
+            dojo.place(
+                renderAuthorityRecord(m, cs.raw, auth_id),
+                "authority-record-holder"
+            );
+        }
+    );
+    displayRecordCounts(auth_ids);
+    swapCanvas(dojo.byId("canvas_main"));
+}
+
+function displayRecordCounts(auth_ids) {
+    fieldmapper.standardRequest(
+        ["open-ils.cat", "open-ils.cat.authority.records.count_linked_bibs"], {
+            "params": [auth_ids],
+            "async": true,
+            "oncomplete": function(r) {
+                if ((r = openils.Util.readResponse(r))) {
+                    dojo.forEach(r, function(blob) {
+                        if (blob.bibs > 0) {
+                            displayRecordCount(blob.authority, blob.bibs);
+                        }
+                    });
+                }
+            }
         }
     );
 }
+
+function displayRecordCount(id, count) {
+    /* 1) put record count where we can see it */
+    dojo.query("#authority_" + id + " .authority-count-holder")[0].innerHTML =
+        "(" + count + ")"; /* XXX i18n ? */
+
+    /* 2) also, provide a link to show those records */
+    var span = dojo.query("#authority_" + id + " .authority-content")[0];
+
+    var args = {};
+    args.page = RRESULT;
+    args[PARAM_DEPTH] = depthSelGetDepth();
+    args[PARAM_LOCATION] = depthSelGetNewLoc();
+    args[PARAM_TERM] = "identifier|authority_id[" + id + "]";
+
+    dojo.create(
+        "a", {
+            "innerHTML": span.innerHTML,
+            "href": buildOPACLink(args),
+            "className": "authority-content",
+            "title": "Show related bibliographic holdings" /* XXX i18n! */
+        },
+        span, "replace"
+    );
+}
+
diff --git a/Open-ILS/web/opac/skin/default/xml/page_authbrowse.xml b/Open-ILS/web/opac/skin/default/xml/page_authbrowse.xml
index 69675eb..f137c5d 100644
--- a/Open-ILS/web/opac/skin/default/xml/page_authbrowse.xml
+++ b/Open-ILS/web/opac/skin/default/xml/page_authbrowse.xml
@@ -1,5 +1,13 @@
 <div id='canvas_main' class='canvas' style='margin-top: 20px;'>
 	<script language='javascript' type='text/javascript' src='<!--#echo var="OILS_OPAC_JS_HOST"-->/skin/default/js/authbrowse.js'></script>
-    Records: <div id="test-holder">
+
+    <div class="authority-pager">
+        <a id="authority-page-up" href="#" class="classic_link">&common.cn.previous;</a>
+    </div>
+
+    <div id="authority-record-holder"></div>
+
+    <div class="authority-pager">
+        <a id="authority-page-down" href="#" class="classic_link">&common.cn.next;</a>
     </div>
 </div>

commit bbefc2e9ef49dfe0cecbff3f5afb5d99d057291c
Author: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>
Date:   Wed Jun 29 15:45:40 2011 -0400

    Finally starting to get somewhere: record display
    
    Record display kind of works.  Need paging and links to bibs.
    
    Signed-off-by: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>

diff --git a/Open-ILS/web/js/dojo/MARC/Record.js b/Open-ILS/web/js/dojo/MARC/Record.js
index 8bb6a1b..861f200 100644
--- a/Open-ILS/web/js/dojo/MARC/Record.js
+++ b/Open-ILS/web/js/dojo/MARC/Record.js
@@ -65,7 +65,10 @@ if(!dojo._hasResource["MARC.Record"]) {
 
         subfield : function (spec, code) {
             var f = this.field(spec);
-            if (dojo.isArray(f)) f = f[0];
+            if (dojo.isArray(f)) {
+                if (!f.length) return f;
+                f = f[0];
+            }
             return f.subfield(code)
         },
 
diff --git a/Open-ILS/web/opac/skin/default/css/layout.css b/Open-ILS/web/opac/skin/default/css/layout.css
index 1197a74..7aaed35 100644
--- a/Open-ILS/web/opac/skin/default/css/layout.css
+++ b/Open-ILS/web/opac/skin/default/css/layout.css
@@ -74,6 +74,11 @@ table { border-collapse: collapse; }
 
 /* ---------------------------------------------------------------------- */
 
+table.authority-record { width: 48em; background-color: #ddd; margin: 1em; }
+td.authority-record-right { width: 24em; }
+td.authority-record-main { font-weight: bold; }
+td.authority-tag-label { font-style: italic; }
+
 #searchbar { margin-top: 22px; width: 100%; }
 #searchbar table tr td {font-weight: bold; font-size: 8pt; }
 #searchbar select, input { border-collapse: collapse; font-size: 9pt; }
diff --git a/Open-ILS/web/opac/skin/default/js/authbrowse.js b/Open-ILS/web/opac/skin/default/js/authbrowse.js
index 5fcb5ec..643d6c5 100644
--- a/Open-ILS/web/opac/skin/default/js/authbrowse.js
+++ b/Open-ILS/web/opac/skin/default/js/authbrowse.js
@@ -1,4 +1,5 @@
 dojo.require("openils.CGI");
+dojo.require("openils.Util");
 dojo.require("MARC.FixedFields");
 dojo.require("openils.AuthorityControlSet");
 var cgi;
@@ -7,7 +8,6 @@ attachEvt("common", "init", doAuthorityBrowse);
 
 /* repeatable, supports all args or no args */
 function doAuthorityBrowse(axis, term, page, per_page) {
-    console.log("doAuthorityBrowse 1");
     if (!axis) {
         if (!cgi) cgi = new openils.CGI();
         axis = cgi.param(PARAM_AUTHORITY_BROWSE_AXIS);
@@ -15,7 +15,6 @@ function doAuthorityBrowse(axis, term, page, per_page) {
         page = 0;
         per_page = 20;
     }
-    console.log("doAuthorityBrowse 2");
 
     var url = '/opac/extras/browse/marcxml/authority.'
         + axis
@@ -24,7 +23,6 @@ function doAuthorityBrowse(axis, term, page, per_page) {
         + '/' + page
         + '/' + per_page
     ;
-    console.log("doAuthorityBrowse 3: " + url);
     dojo.xhrGet({
         "url": url,
         "handleAs": "xml",
@@ -34,22 +32,110 @@ function doAuthorityBrowse(axis, term, page, per_page) {
     });
 }
 
+function renderAuthorityTagContent(m, af) {
+    if (af.tag() && af.sf_list()) {
+        return dojo.filter(
+            dojo.map(
+                af.sf_list().split(""),
+                function(code) {
+                    var result = m.subfield(af.tag(), code);
+                    return (typeof(result[1]) == "undefined") ? "" : result[1];
+                }
+            ), function(datum) { return datum.length > 0; }
+        ).join(" ");
+    } else {
+        return "";
+    }
+}
+
+function renderAuthoritySubEntry(m, field, tbody) {
+    var content =
+        openils.Util.trimString(renderAuthorityTagContent(m, field));
+    if (!content.length) return;    /* don't display empty tags */
+
+    var tr = dojo.create("tr", null, tbody);
+    dojo.create("td", {"style": {"width": "2em"}, "innerHTML": ""}, tr);
+    dojo.create(
+        "td", {
+            "className": "authority-tag-label",
+            "innerHTML": field.name() + ":",
+            "title": field.description() || ""
+        }, tr
+    );
+    dojo.create(
+        "td", {
+            "className": "authority-tag-content authority-record-right",
+            "innerHTML": content
+        }, tr
+    );
+
+    if (field.sub_entries() && field.sub_entries().length) {
+        /* I *think* this shouldn't happen with good data? */
+        console.log("I, too, have " + field.sub_entries().length +
+            "sub_entries");
+    }
+}
+
+function renderAuthorityMainEntry(m, field, tbody) {
+    var content =
+        openils.Util.trimString(renderAuthorityTagContent(m, field));
+    if (!content.length) return;    /* don't display empty tags */
+
+    var tr = dojo.create("tr", null, tbody);
+    dojo.create(
+        "td", {
+            "className": "authority-tag-content authority-record-main",
+            "innerHTML": content,
+            "colspan": 2
+        }, tr
+    );
+    dojo.create(
+        "td", {
+            "className": "authority-tag-label authority-record-right",
+            "innerHTML": field.name(),
+            "title": field.description() || ""
+        }, tr
+    );
+
+    if (field.sub_entries()) {
+        dojo.forEach(
+            field.sub_entries(),
+            function(f) { renderAuthoritySubEntry(m, f, tbody); }
+        );
+    }
+}
+
+function renderAuthorityRecord(m, control_set) {
+    var main_entries = openils.Util.objectSort(
+        dojo.filter(
+            control_set.authority_fields(),
+            function(o) { return o.main_entry() == null; }
+        ), "tag"
+    );
+
+    var table = dojo.create("table", {"className": "authority-record"});
+    var tbody = dojo.create("tbody", null, table);
+
+    dojo.forEach(
+        main_entries, function(af) { renderAuthorityMainEntry(m, af, tbody); }
+    );
+
+    return table;
+}
+
 function displayAuthorityRecords(doc) {
-    console.log("displayAuthorityRecords");
     var acs_helper = new openils.AuthorityControlSet();
-    console.log("got acs_helper");
+
+    /* XXX I wanted to use bibtemplate here, but now I'm not sure it makes
+     * sense: the template itself would have to be dynamic, as it would vary
+     * from record to record when different control sets were in use.
+     */
     dojo.query("record", doc).forEach(
         function(record) {
-            console.log("record");
             var m = new MARC.Record({"xml": record});
             var s = m.extractFixedField("Subj");
             var cs = acs_helper.controlSetByThesaurusCode(s);
-            console.log("got cs");
-            dojo.create(
-                "div", {
-                    "innerHTML": "record here, control set is " + cs
-                }, "test-holder"
-            );
+            dojo.place(renderAuthorityRecord(m, cs.raw), "test-holder");
         }
     );
 }

commit adab035d5ffe86417a24a49c89681419489909a6
Author: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>
Date:   Tue Jun 28 15:28:40 2011 -0400

    Closer to being able to get authority control set from thesaurus code
    
    Signed-off-by: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>

diff --git a/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js b/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
index 9284094..3583d66 100644
--- a/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
+++ b/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
@@ -162,8 +162,23 @@ if(!dojo._hasResource["openils.AuthorityControlSet"]) {
             }
         },
 
-        _preFetchWithFielder: function(map) {
-            // TODO get pkeys from fieldmapper but use fielder to get everything
+        _preFetchWithFielder: function(cmap) {
+            for (var hint in cmap) {
+                var cache_key = cmap[hint];
+                var method = "open-ils.fielder." + hint + ".atomic";
+                var pkey = fieldmapper.IDL.fmclasses[hint].pkey;
+
+                var query = {};
+                query[pkey] = {"!=": null};
+
+                openils.AuthorityControlSet[cache_key] = dojo.map(
+                    fieldmapper.standardRequest(
+                        ["open-ils.fielder", method],
+                        [{"cache": 1, "query" : query}]
+                    ),
+                    function(h) { return new fieldmapper[hint]().fromHash(h); }
+                );
+            }
         },
 
         controlSetId: function (x) {
@@ -176,14 +191,12 @@ if(!dojo._hasResource["openils.AuthorityControlSet"]) {
         },
 
         controlSetByThesaurusCode: function (x) {
-            console.log("1");
             var thes = dojo.filter(
                 openils.AuthorityControlSet._thesaurus_list,
                 function (at) { return at.code() == x }
             )[0];
-            console.log("2");
 
-            return this.controlSet(thes.controlSet());
+            return this.controlSet(thes.control_set());
         },
 
         bibFieldByTag: function (x) {
diff --git a/Open-ILS/web/opac/skin/default/js/authbrowse.js b/Open-ILS/web/opac/skin/default/js/authbrowse.js
index 3aa8f2f..5fcb5ec 100644
--- a/Open-ILS/web/opac/skin/default/js/authbrowse.js
+++ b/Open-ILS/web/opac/skin/default/js/authbrowse.js
@@ -42,9 +42,7 @@ function displayAuthorityRecords(doc) {
         function(record) {
             console.log("record");
             var m = new MARC.Record({"xml": record});
-            console.log("got m");
             var s = m.extractFixedField("Subj");
-            console.log("got s");
             var cs = acs_helper.controlSetByThesaurusCode(s);
             console.log("got cs");
             dojo.create(
diff --git a/Open-ILS/web/opac/skin/default/xml/common/js_common.xml b/Open-ILS/web/opac/skin/default/xml/common/js_common.xml
index 498e5df..4fc4605 100644
--- a/Open-ILS/web/opac/skin/default/xml/common/js_common.xml
+++ b/Open-ILS/web/opac/skin/default/xml/common/js_common.xml
@@ -5,7 +5,7 @@
     type='text/javascript'></script>
 <!--#else-->
 <script language='javascript'  
-    src='/IDL2js?mvr,bre,aou,aout,pgt,lasso,cmf,cmc,cmsa,cam,cifm,clfm,citm,cblvl,ccs,aba'
+    src='/IDL2js?mvr,bre,aou,aout,pgt,lasso,cmf,cmc,cmsa,cam,cifm,clfm,citm,cblvl,ccs,aba,acs,at,abaafm,acsaf,acsbf'
     type='text/javascript'></script>
 <!--#endif-->
 

commit 0bba2a081dcfc3c4b9c492d3aa50f92e7acb8bd5
Author: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>
Date:   Tue Jun 28 11:49:17 2011 -0400

    towards using fielder in openils.AuthorityControlSet
    
    Signed-off-by: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>

diff --git a/Open-ILS/examples/fm_IDL.xml b/Open-ILS/examples/fm_IDL.xml
index e89d46e..5816331 100644
--- a/Open-ILS/examples/fm_IDL.xml
+++ b/Open-ILS/examples/fm_IDL.xml
@@ -1758,7 +1758,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 		</links>
 	</class>
 
-	<class id="acs" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="authority::control_set" oils_persist:tablename="authority.control_set" reporter:label="Authority Control Set">
+	<class id="acs" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="authority::control_set" oils_persist:tablename="authority.control_set" reporter:label="Authority Control Set" oils_persist:field_safe="true">
 		<fields oils_persist:primary="id" oils_persist:sequence="authority.control_set_id_seq">
 			<field reporter:label="Control Set ID" name="id" reporter:datatype="id" reporter:selector="name"/>
 			<field reporter:label="Name" name="name" reporter:datatype="text" oils_persist:i18n="true" oils_obj:required="true" />
@@ -1780,7 +1780,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 		</permacrud>
 	</class>
 
-	<class id="acsaf" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="authority::control_set_authority_field" oils_persist:tablename="authority.control_set_authority_field" reporter:label="Authority Control Set Authority Field">
+	<class id="acsaf" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="authority::control_set_authority_field" oils_persist:tablename="authority.control_set_authority_field" reporter:label="Authority Control Set Authority Field" oils_persist:field_safe="true">
 		<fields oils_persist:primary="id" oils_persist:sequence="authority.control_set_authority_field_id_seq">
 			<field reporter:label="Control Set Authority Field ID" name="id" reporter:datatype="id" reporter:selector="name"/>
 			<field reporter:label="Main Entry" name="main_entry" reporter:datatype="link"/>
@@ -1812,7 +1812,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 		</permacrud>
 	</class>
 
-	<class id="acsbf" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="authority::control_set_bib_field" oils_persist:tablename="authority.control_set_bib_field" reporter:label="Authority Control Set Bib Field">
+	<class id="acsbf" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="authority::control_set_bib_field" oils_persist:tablename="authority.control_set_bib_field" reporter:label="Authority Control Set Bib Field" oils_persist:field_safe="true">
 		<fields oils_persist:primary="id" oils_persist:sequence="authority.control_set_bib_field_id_seq">
 			<field reporter:label="Controlled Bib Field ID" name="id" reporter:datatype="id" reporter:selector="name"/>
 			<field reporter:label="Controlling Authority Field" name="authority_field" reporter:datatype="link"/>
@@ -1831,7 +1831,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 		</permacrud>
 	</class>
 
-	<class id="at" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="authority::thesaurus" oils_persist:tablename="authority.thesaurus" reporter:label="Authority Thesaurus">
+	<class id="at" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="authority::thesaurus" oils_persist:tablename="authority.thesaurus" reporter:label="Authority Thesaurus" oils_persist:field_safe="true">
 		<fields oils_persist:primary="code">
 			<field reporter:label="Thesaurus Code" name="code" reporter:datatype="id" reporter:selector="name"/>
 			<field reporter:label="Control Set" name="control_set" reporter:datatype="link"/>
@@ -1851,7 +1851,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 		</permacrud>
 	</class>
 
-	<class id="aba" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="authority::browse_axis" oils_persist:tablename="authority.browse_axis" reporter:label="Authority Browse Axis">
+	<class id="aba" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="authority::browse_axis" oils_persist:tablename="authority.browse_axis" reporter:label="Authority Browse Axis" oils_persist:field_safe="true">
 		<fields oils_persist:primary="code">
 			<field reporter:label="Code" name="code" reporter:datatype="id" reporter:selector="name" oils_obj:validate="^\S+$"/>
 			<field reporter:label="Name" name="name" reporter:datatype="text" oils_persist:i18n="true" oils_obj:required="true"/>
@@ -1873,7 +1873,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 		</permacrud>
 	</class>
 
-    <class id="abaafm" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="authority::browse_axis_authority_field_map" oils_persist:tablename="authority.browse_axis_authority_field_map" reporter:label="Authority Browse Axis Field Map">
+    <class id="abaafm" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="authority::browse_axis_authority_field_map" oils_persist:tablename="authority.browse_axis_authority_field_map" reporter:label="Authority Browse Axis Field Map" oils_persist:field_safe="true">
         <fields oils_persist:primary="id" oils_persist:sequence="authority.browse_axis_authority_field_map_id_seq">
             <field reporter:label="Axis Authority Field Map ID" name="id" reporter:datatype="id"/>
             <field reporter:label="Authority Field" name="field" oils_obj:required="true" reporter:datatype="link"/>
diff --git a/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js b/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
index ae650af..9284094 100644
--- a/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
+++ b/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
@@ -16,8 +16,6 @@
  */
 
 if(!dojo._hasResource["openils.AuthorityControlSet"]) {
-
-    dojo.require('openils.PermaCrud');
     dojo.require('MARC.FixedFields');
 
     dojo._hasResource["openils.AuthorityControlSet"] = true;
@@ -34,15 +32,15 @@ if(!dojo._hasResource["openils.AuthorityControlSet"]) {
 
                 // TODO -- push the raw tree into the oils cache for later reuse
 
-                var pcrud = new openils.PermaCrud({authtoken : ses()});
-
                 // fetch everything up front...
-                openils.AuthorityControlSet._control_set_list = pcrud.retrieveAll('acs');
-                openils.AuthorityControlSet._thesaurus_list = pcrud.retrieveAll('at');
-                openils.AuthorityControlSet._authority_field_list = pcrud.retrieveAll('acsaf');
-                openils.AuthorityControlSet._bib_field_list = pcrud.retrieveAll('acsbf');
-                openils.AuthorityControlSet._browse_axis_list = pcrud.retrieveAll('aba');
-                openils.AuthorityControlSet._browse_field_map_list = pcrud.retrieveAll('abaafm');
+                this._preFetchWithFielder({
+                    "acs": "_control_set_list",
+                    "at": "_thesaurus_list",
+                    "acsaf": "_authority_field_list",
+                    "acsbf": "_bib_field_list",
+                    "aba": "_browse_axis_list",
+                    "abaafm": "_browse_field_map_list"
+                });
 
                 openils.AuthorityControlSet._browse_axis_by_name = {};
                 dojo.forEach( openils.AuthorityControlSet._browse_axis_list, function (ba) {
@@ -164,6 +162,10 @@ if(!dojo._hasResource["openils.AuthorityControlSet"]) {
             }
         },
 
+        _preFetchWithFielder: function(map) {
+            // TODO get pkeys from fieldmapper but use fielder to get everything
+        },
+
         controlSetId: function (x) {
             if (x) this._controlset = ''+x;
             return this._controlset;
@@ -174,10 +176,12 @@ if(!dojo._hasResource["openils.AuthorityControlSet"]) {
         },
 
         controlSetByThesaurusCode: function (x) {
+            console.log("1");
             var thes = dojo.filter(
                 openils.AuthorityControlSet._thesaurus_list,
                 function (at) { return at.code() == x }
             )[0];
+            console.log("2");
 
             return this.controlSet(thes.controlSet());
         },
diff --git a/Open-ILS/web/opac/skin/default/js/authbrowse.js b/Open-ILS/web/opac/skin/default/js/authbrowse.js
index 69dc516..3aa8f2f 100644
--- a/Open-ILS/web/opac/skin/default/js/authbrowse.js
+++ b/Open-ILS/web/opac/skin/default/js/authbrowse.js
@@ -24,6 +24,7 @@ function doAuthorityBrowse(axis, term, page, per_page) {
         + '/' + page
         + '/' + per_page
     ;
+    console.log("doAuthorityBrowse 3: " + url);
     dojo.xhrGet({
         "url": url,
         "handleAs": "xml",
@@ -35,14 +36,20 @@ function doAuthorityBrowse(axis, term, page, per_page) {
 
 function displayAuthorityRecords(doc) {
     console.log("displayAuthorityRecords");
+    var acs_helper = new openils.AuthorityControlSet();
+    console.log("got acs_helper");
     dojo.query("record", doc).forEach(
         function(record) {
             console.log("record");
             var m = new MARC.Record({"xml": record});
+            console.log("got m");
+            var s = m.extractFixedField("Subj");
+            console.log("got s");
+            var cs = acs_helper.controlSetByThesaurusCode(s);
+            console.log("got cs");
             dojo.create(
                 "div", {
-                    "innerHTML": "record here, Subj is " +
-                        m.extractFixedField("Subj")
+                    "innerHTML": "record here, control set is " + cs
                 }, "test-holder"
             );
         }

commit 693520254eb55728d54826f910876ebc79d44299
Author: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>
Date:   Tue Jun 28 10:43:54 2011 -0400

    working on an auth browser
    
    Signed-off-by: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>

diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/SuperCat.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/SuperCat.pm
index 1f0a46a..a43abc5 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/SuperCat.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/SuperCat.pm
@@ -888,6 +888,7 @@ Returns a list of the requested org-scoped record IDs held
 );
 
 sub grab_authority_browse_axes {
+    my ($self, $client, $full) = @_;
 
     unless(scalar(keys(%authority_browse_axis_cache))) {
         my $axes = new_editor->search_authority_browse_axis([
@@ -897,14 +898,26 @@ sub grab_authority_browse_axes {
         $authority_browse_axis_cache{$_->code} = $_ for (@$axes);
     }
 
-    return [keys %authority_browse_axis_cache];
+    if ($full) {
+        return [
+            map { $authority_browse_axis_cache{$_} } sort keys %authority_browse_axis_cache
+        ];
+    } else {
+        return [keys %authority_browse_axis_cache];
+    }
 }
 __PACKAGE__->register_method(
 	method    => 'grab_authority_browse_axes',
 	api_name  => 'open-ils.supercat.authority.browse_axis_list',
 	api_level => 1,
-	argc      => 0,
-	note      => "Returns a list of valid authority browse/startswith axes"
+	argc      => 1,
+	signature =>
+		{ desc     => "Returns a list of valid authority browse/startswith axes",
+		  params   => [
+              { name => 'full', desc => 'Optional. If true, return array containing the full object for each axis, sorted by code. Otherwise just return an array of the codes.', type => 'number' }
+          ],
+		  'return' => { desc => 'Axis codes or whole axes, see "full" param', type => 'array' }
+		}
 );
 
 sub axis_authority_browse {
diff --git a/Open-ILS/web/opac/skin/default/js/advanced.js b/Open-ILS/web/opac/skin/default/js/advanced.js
index d292c7f..08e9b22 100644
--- a/Open-ILS/web/opac/skin/default/js/advanced.js
+++ b/Open-ILS/web/opac/skin/default/js/advanced.js
@@ -7,6 +7,7 @@ function advInit() {
 	/* propogate these? */
 
 	depthSelInit(); 
+	authoritySelInit(); 
 	setEnterFunc( $n( $('advanced.marc.tbody'), 'advanced.marc.value'), advMARCRun );
 
 	unHideMe($('adv_quick_search_sidebar'));
@@ -16,12 +17,31 @@ function advInit() {
 		setSelector($('adv_quick_type'), 'tcn'); */
 
 	setEnterFunc($('adv_quick_text'), advGenericSearch);
+	setEnterFunc($('authority_browse_term'), advAuthorityBrowse);
 
 	unHideMe($('adv_marc_search_sidebar'));
 	unHideMe($('adv_authority_browse_sidebar'));
 }
 
 
+function authoritySelInit() {
+    dojo.require("openils.Util");
+    fieldmapper.standardRequest(
+        ["open-ils.supercat", "open-ils.supercat.authority.browse_axis_list"], {
+            "params": [true /* whole objects */], 
+            "async": true,
+            "oncomplete": function(r) {
+                if ((r = openils.Util.readResponse(r))) {
+                    dojo.empty("authority_browse_axis");
+                    dojo.forEach(r, function(axis) {
+                        dojo.create("option", {"innerHTML": axis.name(), "value": axis.code()}, "authority_browse_axis");
+                    });
+                }
+            }
+        }
+    );
+}
+
 function advAddMARC() {
 	var newt = $('adv_sdbar_table').cloneNode(true);
 	newt.id = "";
@@ -175,7 +195,7 @@ function advDrawBarcode(r) {
     location.href = buildOPACLink(args);
 }
 
-function authBrowseSubmit() {
+function advAuthorityBrowse() {
     var selector = dojo.byId("authority_browse_axis");
     var args = {"page": AUTHBROWSE};
     args[PARAM_AUTHORITY_BROWSE_AXIS] =
diff --git a/Open-ILS/web/opac/skin/default/js/authbrowse.js b/Open-ILS/web/opac/skin/default/js/authbrowse.js
index ea711b3..69dc516 100644
--- a/Open-ILS/web/opac/skin/default/js/authbrowse.js
+++ b/Open-ILS/web/opac/skin/default/js/authbrowse.js
@@ -1 +1,50 @@
-alert("test 1");
+dojo.require("openils.CGI");
+dojo.require("MARC.FixedFields");
+dojo.require("openils.AuthorityControlSet");
+var cgi;
+
+attachEvt("common", "init", doAuthorityBrowse);
+
+/* repeatable, supports all args or no args */
+function doAuthorityBrowse(axis, term, page, per_page) {
+    console.log("doAuthorityBrowse 1");
+    if (!axis) {
+        if (!cgi) cgi = new openils.CGI();
+        axis = cgi.param(PARAM_AUTHORITY_BROWSE_AXIS);
+        term = cgi.param(PARAM_AUTHORITY_BROWSE_TERM);
+        page = 0;
+        per_page = 20;
+    }
+    console.log("doAuthorityBrowse 2");
+
+    var url = '/opac/extras/browse/marcxml/authority.'
+        + axis
+        + '/1' /* this will be OU if OU ever means anything for authorities */
+        + '/' + term /* FIXME urlescape or however it's spelt */
+        + '/' + page
+        + '/' + per_page
+    ;
+    dojo.xhrGet({
+        "url": url,
+        "handleAs": "xml",
+        "content": {"format": "marcxml"},
+        "preventCache": true,
+        "load": displayAuthorityRecords
+    });
+}
+
+function displayAuthorityRecords(doc) {
+    console.log("displayAuthorityRecords");
+    dojo.query("record", doc).forEach(
+        function(record) {
+            console.log("record");
+            var m = new MARC.Record({"xml": record});
+            dojo.create(
+                "div", {
+                    "innerHTML": "record here, Subj is " +
+                        m.extractFixedField("Subj")
+                }, "test-holder"
+            );
+        }
+    );
+}
diff --git a/Open-ILS/web/opac/skin/default/xml/common/sidebar.xml b/Open-ILS/web/opac/skin/default/xml/common/sidebar.xml
index e7352a5..4bd6c53 100644
--- a/Open-ILS/web/opac/skin/default/xml/common/sidebar.xml
+++ b/Open-ILS/web/opac/skin/default/xml/common/sidebar.xml
@@ -115,20 +115,13 @@
         </div>
 
         <div style="text-align: left">
-            <select id="authority_browse_axis">
-                <!-- there's a supercat method
-                     open-ils.supercat.authority.browse_axis_list to get us 
-                     this list dynamically, but how do we get that with XML
-                     api? or do we? -->
-                <option value="author">Author</option>
-                <option value="subject">Subject</option>
-                <option value="title">Title</option>
-                <option value="topic">Topic</option>
-            </select>
-            <input id="authority_browse_term" />
+            <select id="authority_browse_axis"></select><input
+                id="authority_browse_term" type="text" size="16"/>
         </div>
 
-        <a id="authority_browse_submit" class="classic_link" href="javascript:authBrowseSubmit();">&common.submit;</a>
+        <div style="margin-top: 8px;">
+            <a id="authority_browse_submit" class="classic_link" href="javascript:advAuthorityBrowse();">&common.submit;</a>
+        </div>
     </div>
 
 	<div id='adv_marc_search_sidebar' class='sidebar_chunk hide_me' 
diff --git a/Open-ILS/web/opac/skin/default/xml/page_authbrowse.xml b/Open-ILS/web/opac/skin/default/xml/page_authbrowse.xml
index 6dc6ce0..69675eb 100644
--- a/Open-ILS/web/opac/skin/default/xml/page_authbrowse.xml
+++ b/Open-ILS/web/opac/skin/default/xml/page_authbrowse.xml
@@ -1,6 +1,5 @@
 <div id='canvas_main' class='canvas' style='margin-top: 20px;'>
 	<script language='javascript' type='text/javascript' src='<!--#echo var="OILS_OPAC_JS_HOST"-->/skin/default/js/authbrowse.js'></script>
-    Boo.
+    Records: <div id="test-holder">
+    </div>
 </div>
-
-

commit 6b419fe6abe7c779bf97c262776e446f829f9e8e
Author: Mike Rylander <mrylander at gmail.com>
Date:   Mon Jun 27 10:12:33 2011 -0400

    Add function to set Control Set by Thesaurus Code
    
    Signed-off-by: Mike Rylander <mrylander at gmail.com>

diff --git a/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js b/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
index 9993c72..ae650af 100644
--- a/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
+++ b/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
@@ -173,6 +173,15 @@ if(!dojo._hasResource["openils.AuthorityControlSet"]) {
             return openils.AuthorityControlSet._controlsets[''+this.controlSetId(x)];
         },
 
+        controlSetByThesaurusCode: function (x) {
+            var thes = dojo.filter(
+                openils.AuthorityControlSet._thesaurus_list,
+                function (at) { return at.code() == x }
+            )[0];
+
+            return this.controlSet(thes.controlSet());
+        },
+
         bibFieldByTag: function (x) {
             var me = this;
             return dojo.filter(

commit e675b8540174233d534473251151721d435cf636
Author: Mike Rylander <mrylander at gmail.com>
Date:   Mon Jun 27 10:03:34 2011 -0400

    Normalize fixed field names to OCLC values where they exist (what catalogers are used to)
    
    Signed-off-by: Mike Rylander <mrylander at gmail.com>

diff --git a/Open-ILS/web/js/dojo/MARC/FixedFields.js b/Open-ILS/web/js/dojo/MARC/FixedFields.js
index 536d8f8..7e25080 100644
--- a/Open-ILS/web/js/dojo/MARC/FixedFields.js
+++ b/Open-ILS/web/js/dojo/MARC/FixedFields.js
@@ -83,6 +83,20 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
                 COM : {start : 6, len : 1, def : ' ' }
             }
         },
+        RecStat : {
+            ldr : {
+                BKS : {start : 5, len : 1, def : 'n' },
+                SER : {start : 5, len : 1, def : 'n' },
+                VIS : {start : 5, len : 1, def : 'n' },
+                MIX : {start : 5, len : 1, def : 'n' },
+                MAP : {start : 5, len : 1, def : 'n' },
+                SCO : {start : 5, len : 1, def : 'n' },
+                REC : {start : 5, len : 1, def : 'n' },
+                COM : {start : 5, len : 1, def : 'n' },
+                MFHD: {start : 5, len : 1, def : 'n' },
+                AUT : {start : 5, len : 1, def : 'n' }
+            }
+        },
         Type : {
             ldr : {
                 BKS : {start : 6, len : 1, def : 'a' },
@@ -329,7 +343,7 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
                 SER : {start : 16, len : 1, def : ' ' }
             }
         },
-        "GeoDiv" : {
+        "GeoSubd" : {
             "_8" : {
                 "AUT" : {"start" : 6, "len" : 1, "def" : ' ' }
             }
@@ -344,7 +358,7 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
                 "AUT" : {"start" : 8, "len" : 1, "def" : ' ' }
             }
         },
-        "Kind" : {
+        "Auth/Ref" : {
             "_8" : {
                 "AUT" : {"start" : 9, "len" : 1, "def" : ' ' }
             }
@@ -354,12 +368,12 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
                 "AUT" : {"start" : 10, "len" : 1, "def" : ' ' }
             }
         },
-        "SHSys" : {
+        "Subj" : {
             "_8" : {
                 "AUT" : {"start" : 11, "len" : 1, "def" : ' ' }
             }
         },
-        "SerType" : {
+        "Series" : {
             "_8" : {
                 "AUT" : {"start" : 12, "len" : 1, "def" : ' ' }
             }
@@ -369,17 +383,17 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
                 "AUT" : {"start" : 13, "len" : 1, "def" : ' ' }
             }
         },
-        "HeadMain" : {
+        "NameUse" : {
             "_8" : {
                 "AUT" : {"start" : 14, "len" : 1, "def" : ' ' }
             }
         },
-        "HeadSubj" : {
+        "SubjUse" : {
             "_8" : {
                 "AUT" : {"start" : 15, "len" : 1, "def" : ' ' }
             }
         },
-        "HeadSer" : {
+        "SerUse" : {
             "_8" : {
                 "AUT" : {"start" : 16, "len" : 1, "def" : ' ' }
             }
@@ -389,27 +403,27 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
                 "AUT" : {"start" : 17, "len" : 1, "def" : ' ' }
             }
         },
-        "TypeGov" : {
+        "GovtAgn" : {
             "_8" : {
                 "AUT" : {"start" : 28, "len" : 1, "def" : ' ' }
             }
         },
-        "RefEval" : {
+        "RefStatus" : {
             "_8" : {
                 "AUT" : {"start" : 29, "len" : 1, "def" : ' ' }
             }
         },
-        "RecUpd" : {
+        "UpdStatus" : {
             "_8" : {
                 "AUT" : {"start" : 31, "len" : 1, "def" : ' ' }
             }
         },
-        "NameDiff" : {
+        "Name" : {
             "_8" : {
                 "AUT" : {"start" : 32, "len" : 1, "def" : ' ' }
             }
         },
-        "Level" : {
+        "Status" : {
             "_8" : {
                 "AUT" : {"start" : 33, "len" : 1, "def" : ' ' }
             }
@@ -419,7 +433,7 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
                 "AUT" : {"start" : 38, "len" : 1, "def" : ' ' }
             }
         },
-        "CatSrc" : {
+        "Source" : {
             "_8" : {
                 "AUT" : {"start" : 39, "len" : 1, "def" : ' ' }
             }

commit 796f3b49b99d5237f6367f81a30983f5b74ca4cc
Author: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>
Date:   Thu Jun 23 18:04:28 2011 -0400

    config ui trivial improvements, scratching out a place for a browse UI

diff --git a/Open-ILS/examples/fm_IDL.xml b/Open-ILS/examples/fm_IDL.xml
index 052c802..e89d46e 100644
--- a/Open-ILS/examples/fm_IDL.xml
+++ b/Open-ILS/examples/fm_IDL.xml
@@ -1853,7 +1853,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 
 	<class id="aba" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="authority::browse_axis" oils_persist:tablename="authority.browse_axis" reporter:label="Authority Browse Axis">
 		<fields oils_persist:primary="code">
-			<field reporter:label="Code" name="code" reporter:datatype="id" reporter:selector="name"/>
+			<field reporter:label="Code" name="code" reporter:datatype="id" reporter:selector="name" oils_obj:validate="^\S+$"/>
 			<field reporter:label="Name" name="name" reporter:datatype="text" oils_persist:i18n="true" oils_obj:required="true"/>
 			<field reporter:label="Description" name="description" reporter:datatype="text"/>
 			<field reporter:label="Authority Fields" name="fields" reporter:datatype="link" oils_persist:virtual="true"/>
diff --git a/Open-ILS/web/Makefile.am b/Open-ILS/web/Makefile.am
index 38c7ac8..92d1fd8 100644
--- a/Open-ILS/web/Makefile.am
+++ b/Open-ILS/web/Makefile.am
@@ -52,7 +52,7 @@ webcore-install:
 	cp @top_srcdir@/Open-ILS/xsl/*.xsl $(DESTDIR)$(XSLDIR)
 	cp -r $(DESTDIR)$(WEBDIR)/opac/skin/default/* $(DESTDIR)$(WEBDIR)/opac/skin/craftsman/
 	cp -r @top_srcdir@/Open-ILS/web/opac/skin/craftsman/* $(DESTDIR)$(WEBDIR)/opac/skin/craftsman/
-	for i in mresult.xml rresult.xml rdetail.xml advanced.xml myopac.xml cnbrowse.xml; do \
+	for i in mresult.xml rresult.xml rdetail.xml advanced.xml myopac.xml cnbrowse.xml authbrowse.xml; do \
 		cd $(DESTDIR)$(WEBDIR)/opac/skin/default/xml/ && rm -f $$i && $(LN_S) index.xml $$i; \
 	done
 	for i in mresult.xml rresult.xml rdetail.xml advanced.xml myopac.xml cnbrowse.xml; do \
diff --git a/Open-ILS/web/js/ui/default/cat/authority/list.js b/Open-ILS/web/js/ui/default/cat/authority/list.js
index c602139..591bfb8 100644
--- a/Open-ILS/web/js/ui/default/cat/authority/list.js
+++ b/Open-ILS/web/js/ui/default/cat/authority/list.js
@@ -326,7 +326,7 @@ function displayRecords(parms) {
 
     dojo.query("#authlist-div div").orphan();
 
-    var url = '/opac/extras/browse/marcxml/'
+    var url = '/opac/extras/browse/marcxml/authority.'
         + dijit.byId('authAxis').attr('value')
         // + '/' + dijit.byId('authOU').attr('value')
         + '/1' // replace with preceding line if OUs gain some meaning
diff --git a/Open-ILS/web/opac/common/js/config.js b/Open-ILS/web/opac/common/js/config.js
index 3c4c52d..21b20fa 100644
--- a/Open-ILS/web/opac/common/js/config.js
+++ b/Open-ILS/web/opac/common/js/config.js
@@ -47,6 +47,8 @@ var PARAM_PUBD_AFTER = 'pda';
 var PARAM_PUBD_BETWEEN = 'pdt';
 var PARAM_PUBD_DURING = 'pdd';
 var PARAM_NOPERSIST_SEARCH = 'nps';
+var PARAM_AUTHORITY_BROWSE_AXIS = "ax";
+var PARAM_AUTHORITY_BROWSE_TERM = "bt";
 
 /* URL param values (see comments above) */
 var TERM;  
@@ -113,6 +115,7 @@ var HOME			= "home";
 var BBAGS		= "bbags";
 var REQITEMS	= "reqitems";
 var CNBROWSE	= "cnbrowse";
+var AUTHBROWSE	= "authbrowse";
 
 /* search type (STYPE) options */
 var STYPE_AUTHOR	= "author";
@@ -225,6 +228,7 @@ config.page[RDETAIL]		= "rdetail.xml";
 config.page[BBAGS]		= "bbags.xml";
 config.page[REQITEMS]	= "reqitems.xml";
 config.page[CNBROWSE]	= "cnbrowse.xml";
+config.page[AUTHBROWSE]	= "authbrowse.xml";
 
 /* themes */
 config.themes = {};
diff --git a/Open-ILS/web/opac/locale/en-US/lang.dtd b/Open-ILS/web/opac/locale/en-US/lang.dtd
index 9236215..7cbb97d 100644
--- a/Open-ILS/web/opac/locale/en-US/lang.dtd
+++ b/Open-ILS/web/opac/locale/en-US/lang.dtd
@@ -789,6 +789,8 @@
 <!ENTITY staff.main.menu.admin.server_admin.authority.control_set.accesskey "C">
 <!ENTITY staff.main.menu.admin.server_admin.authority.browse_axis.label "Browse Axes">
 <!ENTITY staff.main.menu.admin.server_admin.authority.browse_axis.accesskey "B">
+<!ENTITY staff.main.menu.admin.server_admin.authority.thesaurus.label "Thesauri">
+<!ENTITY staff.main.menu.admin.server_admin.authority.thesaurus.accesskey "T">
 
 <!ENTITY staff.main.menu.admin.server_admin.booking.label "Booking">
 <!ENTITY staff.main.menu.admin.server_admin.booking.accesskey "B">
diff --git a/Open-ILS/web/opac/locale/en-US/opac.dtd b/Open-ILS/web/opac/locale/en-US/opac.dtd
index d5be2c2..e60841d 100644
--- a/Open-ILS/web/opac/locale/en-US/opac.dtd
+++ b/Open-ILS/web/opac/locale/en-US/opac.dtd
@@ -411,6 +411,7 @@ Please see a librarian to renew your account.">
 <!ENTITY sidebar.relevantSeries.headerLabel "Relevant Series">
 <!ENTITY sidebar.relevantReviews.headerLabel "Reviews">
 <!ENTITY sidebar.quick.search "Quick Search">
+<!ENTITY sidebar.authority.browse "Authority Browse">
 <!ENTITY sidebar.copy.not.found "No copy with the requested barcode was found">
 
 <!--	================================================================= 
@@ -438,6 +439,7 @@ Please see a librarian to renew your account.">
 <!ENTITY opac.title.advanced "Evergreen Advanced Search">
 <!ENTITY opac.title.reqitems "Evergreen Request Items">
 <!ENTITY opac.title.cnbrowse "Evergreen Call Number Browse">
+<!ENTITY opac.title.authbrowse "Evergreen Authority Record Browse">
 
 
 <!ENTITY opac.holds.forMe "Place this hold for myself">
diff --git a/Open-ILS/web/opac/skin/default/js/advanced.js b/Open-ILS/web/opac/skin/default/js/advanced.js
index 0e898e4..d292c7f 100644
--- a/Open-ILS/web/opac/skin/default/js/advanced.js
+++ b/Open-ILS/web/opac/skin/default/js/advanced.js
@@ -18,6 +18,7 @@ function advInit() {
 	setEnterFunc($('adv_quick_text'), advGenericSearch);
 
 	unHideMe($('adv_marc_search_sidebar'));
+	unHideMe($('adv_authority_browse_sidebar'));
 }
 
 
@@ -174,5 +175,13 @@ function advDrawBarcode(r) {
     location.href = buildOPACLink(args);
 }
 
-
+function authBrowseSubmit() {
+    var selector = dojo.byId("authority_browse_axis");
+    var args = {"page": AUTHBROWSE};
+    args[PARAM_AUTHORITY_BROWSE_AXIS] =
+        selector.options[selector.selectedIndex].value;
+    args[PARAM_AUTHORITY_BROWSE_TERM] =
+        dojo.byId("authority_browse_term").value;
+    location.href = buildOPACLink(args);
+}
 
diff --git a/Open-ILS/web/opac/skin/default/js/authbrowse.js b/Open-ILS/web/opac/skin/default/js/authbrowse.js
new file mode 100644
index 0000000..ea711b3
--- /dev/null
+++ b/Open-ILS/web/opac/skin/default/js/authbrowse.js
@@ -0,0 +1 @@
+alert("test 1");
diff --git a/Open-ILS/web/opac/skin/default/xml/common/js_common.xml b/Open-ILS/web/opac/skin/default/xml/common/js_common.xml
index ab8edbb..498e5df 100644
--- a/Open-ILS/web/opac/skin/default/xml/common/js_common.xml
+++ b/Open-ILS/web/opac/skin/default/xml/common/js_common.xml
@@ -5,7 +5,7 @@
     type='text/javascript'></script>
 <!--#else-->
 <script language='javascript'  
-    src='/IDL2js?mvr,bre,aou,aout,pgt,lasso,cmf,cmc,cmsa,cam,cifm,clfm,citm,cblvl,ccs'
+    src='/IDL2js?mvr,bre,aou,aout,pgt,lasso,cmf,cmc,cmsa,cam,cifm,clfm,citm,cblvl,ccs,aba'
     type='text/javascript'></script>
 <!--#endif-->
 
diff --git a/Open-ILS/web/opac/skin/default/xml/common/sidebar.xml b/Open-ILS/web/opac/skin/default/xml/common/sidebar.xml
index 39c0a94..e7352a5 100644
--- a/Open-ILS/web/opac/skin/default/xml/common/sidebar.xml
+++ b/Open-ILS/web/opac/skin/default/xml/common/sidebar.xml
@@ -106,6 +106,31 @@
 		</div>
 	</div>
 
+    <div id='adv_authority_browse_sidebar' style='text-align: center'
+        class='sidebar_chunk hide_me'>
+
+        <hr />
+        <div class='adv_quick_search color_4'>
+            <b>&sidebar.authority.browse;</b>
+        </div>
+
+        <div style="text-align: left">
+            <select id="authority_browse_axis">
+                <!-- there's a supercat method
+                     open-ils.supercat.authority.browse_axis_list to get us 
+                     this list dynamically, but how do we get that with XML
+                     api? or do we? -->
+                <option value="author">Author</option>
+                <option value="subject">Subject</option>
+                <option value="title">Title</option>
+                <option value="topic">Topic</option>
+            </select>
+            <input id="authority_browse_term" />
+        </div>
+
+        <a id="authority_browse_submit" class="classic_link" href="javascript:authBrowseSubmit();">&common.submit;</a>
+    </div>
+
 	<div id='adv_marc_search_sidebar' class='sidebar_chunk hide_me' 
 		style='text-align:center; margin-top: 20px;'> 
 		<hr/>
diff --git a/Open-ILS/web/opac/skin/default/xml/page_authbrowse.xml b/Open-ILS/web/opac/skin/default/xml/page_authbrowse.xml
new file mode 100644
index 0000000..6dc6ce0
--- /dev/null
+++ b/Open-ILS/web/opac/skin/default/xml/page_authbrowse.xml
@@ -0,0 +1,6 @@
+<div id='canvas_main' class='canvas' style='margin-top: 20px;'>
+	<script language='javascript' type='text/javascript' src='<!--#echo var="OILS_OPAC_JS_HOST"-->/skin/default/js/authbrowse.js'></script>
+    Boo.
+</div>
+
+
diff --git a/Open-ILS/web/opac/skin/default/xml/setenv.xml b/Open-ILS/web/opac/skin/default/xml/setenv.xml
index e64b270..ac2975d 100644
--- a/Open-ILS/web/opac/skin/default/xml/setenv.xml
+++ b/Open-ILS/web/opac/skin/default/xml/setenv.xml
@@ -25,6 +25,9 @@
 <!--#elif expr="$DOCUMENT_NAME='reqitems.xml'"-->
 	<!--#set var='OILS_TITLE' value='opac.title.reqitems'-->
 
+<!--#elif expr="$DOCUMENT_NAME='authbrowse.xml'"-->
+	<!--#set var='OILS_TITLE' value='opac.title.cnbrowse'-->
+
 <!--#elif expr="$DOCUMENT_NAME='cnbrowse.xml'"-->
 	<!--#set var='OILS_TITLE' value='opac.title.cnbrowse'-->
 
diff --git a/Open-ILS/web/templates/default/conify/global/cat/authority/thesaurus.tt2 b/Open-ILS/web/templates/default/conify/global/cat/authority/thesaurus.tt2
index b8f80f7..883cb28 100644
--- a/Open-ILS/web/templates/default/conify/global/cat/authority/thesaurus.tt2
+++ b/Open-ILS/web/templates/default/conify/global/cat/authority/thesaurus.tt2
@@ -22,6 +22,12 @@
                 query="{id: '*'}"
                 fmClass="at"
                 editOnEnter="true">
+            <thead>
+                <tr>
+                    <th field="control_set" get="get_control_set"
+                        formatter="format_control_set"></th>
+                </tr>
+            </thead>
         </table>
     </div>
 </div>
@@ -37,9 +43,38 @@
         dojo.i18n.getLocalization("openils.authority", "authority");
 
     var cgi, pcrud;
+    var control_set;
+
+    function get_control_set(rowidx, item) {
+        if (item) {
+            /* I'm /sure/ there's a better way to do the following */
+            this._tmp = openils.widget.AutoGrid.defaultGetter;
+            var ordinary = this._tmp(rowidx, item); 
+            delete this._tmp;
+
+            if (control_set) {
+                return ordinary;
+            } else {
+                var id = this.grid.store.getValue(item, "control_set");
+                return {
+                    "id": id, "text": ordinary
+                };
+            }
+        }
+    }
+
+    function format_control_set(f) {
+        if (typeof f == "object") {
+            return '<a href="' + oilsBasePath +
+                '/conify/global/cat/authority/control_set?focus=' + f.id +
+                '">' + f.text + "</a>";
+        } else {
+            return f;
+        }
+
+    }
 
     function my_init() {
-        var control_set;
         var where = {"code": {"!=": null}};
 
         cgi = new openils.CGI();
diff --git a/Open-ILS/xul/staff_client/chrome/content/main/menu.js b/Open-ILS/xul/staff_client/chrome/content/main/menu.js
index e0e1453..5420b7e 100644
--- a/Open-ILS/xul/staff_client/chrome/content/main/menu.js
+++ b/Open-ILS/xul/staff_client/chrome/content/main/menu.js
@@ -967,6 +967,10 @@ main.menu.prototype = {
                 ['oncommand'],
                 function(event) { open_eg_web_page('conify/global/cat/authority/browse_axis', null, event); }
             ],
+            'cmd_server_admin_authority_thesaurus': [
+                ['oncommand'],
+                function(event) { open_eg_web_page('conify/global/cat/authority/thesaurus', null, event); }
+            ],
             'cmd_server_admin_booking_resource': [
                 ['oncommand'],
                 function(event) { open_eg_web_page('conify/global/booking/resource', null, event); }
diff --git a/Open-ILS/xul/staff_client/chrome/content/main/menu_frame_menus.xul b/Open-ILS/xul/staff_client/chrome/content/main/menu_frame_menus.xul
index 8f59ae8..2218ae8 100644
--- a/Open-ILS/xul/staff_client/chrome/content/main/menu_frame_menus.xul
+++ b/Open-ILS/xul/staff_client/chrome/content/main/menu_frame_menus.xul
@@ -201,6 +201,7 @@
              />
 
     <command id="cmd_server_admin_authority_control_set" />
+    <command id="cmd_server_admin_authority_thesaurus" />
     <command id="cmd_server_admin_authority_browse_axis" />
 
     <command id="cmd_server_admin_booking_resource" />
@@ -527,6 +528,7 @@
                     <menupopup id="main.menu.admin.server.authority.popup">
                         <menuitem label="&staff.main.menu.admin.server_admin.authority.control_set.label;" command="cmd_server_admin_authority_control_set" accesskey="&staff.main.menu.admin.server_admin.authority.control_set.accesskey;"/>
                         <menuitem label="&staff.main.menu.admin.server_admin.authority.browse_axis.label;" command="cmd_server_admin_authority_browse_axis" accesskey="&staff.main.menu.admin.server_admin.authority.browse_axis.accesskey;"/>
+                        <menuitem label="&staff.main.menu.admin.server_admin.authority.thesaurus.label;" command="cmd_server_admin_authority_thesaurus" accesskey="&staff.main.menu.admin.server_admin.authority.thesaurus.accesskey;"/>
                     </menupopup>
                 </menu>
 

commit 2be66e212c390f9e1bf46235c57f06467b4e9afc
Author: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>
Date:   Wed Jun 22 17:22:54 2011 -0400

    Fix minor glitch when trying to create new authority fields
    
    The Autogrid can handle empty arrays as values for acsaf.bib_fields and
    acsaf.axis_maps, but can't handle undefined.
    
    Signed-off-by: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>

diff --git a/Open-ILS/web/templates/default/conify/global/cat/authority/control_set_authority_field.tt2 b/Open-ILS/web/templates/default/conify/global/cat/authority/control_set_authority_field.tt2
index 2f60bcc..ed260df 100644
--- a/Open-ILS/web/templates/default/conify/global/cat/authority/control_set_authority_field.tt2
+++ b/Open-ILS/web/templates/default/conify/global/cat/authority/control_set_authority_field.tt2
@@ -117,7 +117,12 @@
                 {"create": control_set.id()};
         }
 
-        acsaf_grid.onPostCreate = function(o) { acsaf_cache[o.id()] = o; };
+        acsaf_grid.onPostCreate = function(o) {
+            o.bib_fields([]);
+            o.axis_maps([]);
+            acsaf_cache[o.id()] = o;
+        };
+
         acsaf_grid.dataLoader = acsaf_grid_loader;
         acsaf_grid_loader();
     }

commit e881cbb4731884f5eb7572a43a8ff7cda5de6f0f
Author: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>
Date:   Wed Jun 22 16:49:35 2011 -0400

    Move the authority control set config interfaces back into conify
    
    Really, that's where they make sense.  And they're done.
    
    Signed-off-by: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>

diff --git a/Open-ILS/web/js/ui/default/cat/authority/common.js b/Open-ILS/web/js/ui/default/conify/global/cat/authority/common.js
similarity index 87%
rename from Open-ILS/web/js/ui/default/cat/authority/common.js
rename to Open-ILS/web/js/ui/default/conify/global/cat/authority/common.js
index bb30b48..13fdfdb 100644
--- a/Open-ILS/web/js/ui/default/cat/authority/common.js
+++ b/Open-ILS/web/js/ui/default/conify/global/cat/authority/common.js
@@ -1,8 +1,8 @@
 /* To be used by interfaces for editing child tables of acs. */
 function render_control_set_metadata(control_set) {
     var anchor = dojo.byId("control-set-metadata");
-    anchor.href = oilsBasePath + "/cat/authority/control_set?focus=" +
-        control_set.id();
+    anchor.href = oilsBasePath +
+        "/conify/global/cat/authority/control_set?focus=" + control_set.id();
     anchor.innerHTML = dojo.string.substitute(
         localeStrings.CONTROL_SET_METADATA, [
             control_set.id(), control_set.name(), control_set.description()
@@ -19,7 +19,7 @@ function render_control_set_metadata(control_set) {
 function render_authority_field_metadata(authority_field, control_set_id) {
     var anchor = dojo.byId("authority-field-metadata");
     var href = oilsBasePath +
-        "/cat/authority/control_set_authority_field?focus=" +
+        "/conify/global/cat/authority/control_set_authority_field?focus=" +
         authority_field.id();
     if (control_set_id) href += "&acs=" + control_set_id;
 
diff --git a/Open-ILS/web/templates/default/conify/global/authority/authority_field.tt2.old b/Open-ILS/web/templates/default/conify/global/authority/authority_field.tt2.old
deleted file mode 100644
index 2ae8cc8..0000000
--- a/Open-ILS/web/templates/default/conify/global/authority/authority_field.tt2.old
+++ /dev/null
@@ -1,40 +0,0 @@
-[% WRAPPER default/base.tt2 %]
-[% ctx.page_title = 'Configure Control Set Authority Fields' %]
-<div dojoType="dijit.layout.ContentPane" layoutAlign="client">
-    <div dojoType="dijit.layout.ContentPane" layoutAlign="top" class='oils-header-panel'>
-        <div>Thesauri</div>
-        <div>
-            <button dojoType='dijit.form.Button' onClick='acsafGrid.showCreateDialog()'>New Control Set Authority Field</button>
-            <button dojoType='dijit.form.Button' onClick='acsafGrid.deleteSelected()'>Delete Selected</button>
-        </div>
-    </div>
-    <div>
-    <table  jsId="acsafGrid"
-            dojoType="openils.widget.AutoGrid"
-            autoHeight='true'
-            fieldOrder="['control_set','name','tag','sf_list','description','main_entry']"
-            suppressFields="['id']"
-            suppressEditFields="['id']"
-            query="{id: '*'}"
-            fmClass='acsaf'
-            editOnEnter='true'/>
-</div>
-
-<script type="text/javascript">
-    dojo.require("openils.widget.PCrudAutocompleteBox");
-    dojo.require('openils.widget.AutoGrid');
-
-    openils.Util.addOnLoad(
-        function() {
-            acsafGrid.overrideEditWidgets.control_set =
-                new openils.widget.PCrudAutocompleteBox({
-                    "fmclass": "acs", "searchAttr": "name"
-                });
-            acsafGrid.overrideEditWidgets.control_set.shove = {"create": ""};
-            acsafGrid.loadAll({order_by:{acsaf : 'name'}}, {"id": {"!=": null}});
-        }
-    );
-</script>
-[% END %]
-
-
diff --git a/Open-ILS/web/templates/default/conify/global/authority/bib_field.tt2.old b/Open-ILS/web/templates/default/conify/global/authority/bib_field.tt2.old
deleted file mode 100644
index 4023d73..0000000
--- a/Open-ILS/web/templates/default/conify/global/authority/bib_field.tt2.old
+++ /dev/null
@@ -1,40 +0,0 @@
-[% WRAPPER default/base.tt2 %]
-[% ctx.page_title = 'Configure Control Set Bibliographic Fields' %]
-<div dojoType="dijit.layout.ContentPane" layoutAlign="client">
-    <div dojoType="dijit.layout.ContentPane" layoutAlign="top" class='oils-header-panel'>
-        <div>Thesauri</div>
-        <div>
-            <button dojoType='dijit.form.Button' onClick='acsbfGrid.showCreateDialog()'>New Control Set Bibliographic Field</button>
-            <button dojoType='dijit.form.Button' onClick='acsbfGrid.deleteSelected()'>Delete Selected</button>
-        </div>
-    </div>
-    <div>
-    <table  jsId="acsbfGrid"
-            dojoType="openils.widget.AutoGrid"
-            autoHeight='true'
-            fieldOrder="['tag','authority_field']"
-            suppressFields="['id']"
-            suppressEditFields="['id']"
-            query="{id: '*'}"
-            fmClass='acsbf'
-            editOnEnter='true'/>
-</div>
-
-<script type="text/javascript">
-    dojo.require("openils.widget.PCrudAutocompleteBox");
-    dojo.require('openils.widget.AutoGrid');
-
-    openils.Util.addOnLoad(
-        function() {
-            acsbfGrid.overrideEditWidgets.authority_field =
-                new openils.widget.PCrudAutocompleteBox({
-                    "fmclass": "acsaf", "searchAttr": "name"
-                });
-            acsbfGrid.overrideEditWidgets.authority_field.shove = {"create": ""};
-            acsbfGrid.loadAll({order_by:{acsbf : 'tag'}}, {"id": {"!=": null}});
-        }
-    );
-</script>
-[% END %]
-
-
diff --git a/Open-ILS/web/templates/default/conify/global/authority/control_set.tt2.old b/Open-ILS/web/templates/default/conify/global/authority/control_set.tt2.old
deleted file mode 100644
index c072d1c..0000000
--- a/Open-ILS/web/templates/default/conify/global/authority/control_set.tt2.old
+++ /dev/null
@@ -1,34 +0,0 @@
-[% WRAPPER default/base.tt2 %]
-[% ctx.page_title = 'Configure Authority Control Sets' %]
-<div dojoType="dijit.layout.ContentPane" layoutAlign="client">
-    <div dojoType="dijit.layout.ContentPane" layoutAlign="top" class='oils-header-panel'>
-        <div>Control Sets</div>
-        <div>
-            <button dojoType='dijit.form.Button' onClick='ctlSetGrid.showCreateDialog()'>New Control Set</button>
-            <button dojoType='dijit.form.Button' onClick='ctlSetGrid.deleteSelected()'>Delete Selected</button>
-        </div>
-    </div>
-    <div>
-    <table  jsId="ctlSetGrid"
-            dojoType="openils.widget.AutoGrid"
-            autoHeight='true'
-            fieldOrder="['name','description']"
-            suppressFields="['id']"
-            suppressEditFields="['id']"
-            query="{id: '*'}"
-            fmClass='acs'
-            editOnEnter='true'/>
-</div>
-
-<script type="text/javascript">
-    dojo.require('openils.widget.AutoGrid');
-    openils.Util.addOnLoad(
-        function() {
-            ctlSetGrid.loadAll({order_by:{acs : 'name'}}, {"id": {"!=": null}});
-        }
-    );
-
-</script>
-[% END %]
-
-
diff --git a/Open-ILS/web/templates/default/conify/global/authority/thesaurus.tt2.old b/Open-ILS/web/templates/default/conify/global/authority/thesaurus.tt2.old
deleted file mode 100644
index 8061f92..0000000
--- a/Open-ILS/web/templates/default/conify/global/authority/thesaurus.tt2.old
+++ /dev/null
@@ -1,38 +0,0 @@
-[% WRAPPER default/base.tt2 %]
-[% ctx.page_title = 'Configure Authority Thesaurus' %]
-<div dojoType="dijit.layout.ContentPane" layoutAlign="client">
-    <div dojoType="dijit.layout.ContentPane" layoutAlign="top" class='oils-header-panel'>
-        <div>Thesauri</div>
-        <div>
-            <button dojoType='dijit.form.Button' onClick='thesGrid.showCreateDialog()'>New Thesaurus</button>
-            <button dojoType='dijit.form.Button' onClick='thesGrid.deleteSelected()'>Delete Selected</button>
-        </div>
-    </div>
-    <div>
-    <table  jsId="thesGrid"
-            dojoType="openils.widget.AutoGrid"
-            autoHeight='true'
-            fieldOrder="['code','name','description','control_set]"
-            query="{code:'*'}"
-            fmClass='at'
-            editOnEnter='true'/>
-</div>
-
-<script type="text/javascript">
-    dojo.require("openils.widget.PCrudAutocompleteBox");
-    dojo.require('openils.widget.AutoGrid');
-
-    openils.Util.addOnLoad(
-        function() {
-            thesGrid.overrideEditWidgets.control_set =
-                new openils.widget.PCrudAutocompleteBox({
-                    "fmclass": "acs", "searchAttr": "name"
-                });
-            thesGrid.overrideEditWidgets.control_set.shove = {"create": ""};
-            thesGrid.loadAll({order_by:{at : 'name'}}, {"id": {"!=": null}});
-        }
-    );
-</script>
-[% END %]
-
-
diff --git a/Open-ILS/web/templates/default/cat/authority/browse_axis.tt2 b/Open-ILS/web/templates/default/conify/global/cat/authority/browse_axis.tt2
similarity index 100%
rename from Open-ILS/web/templates/default/cat/authority/browse_axis.tt2
rename to Open-ILS/web/templates/default/conify/global/cat/authority/browse_axis.tt2
diff --git a/Open-ILS/web/templates/default/cat/authority/browse_axis_authority_field_map.tt2 b/Open-ILS/web/templates/default/conify/global/cat/authority/browse_axis_authority_field_map.tt2
similarity index 96%
rename from Open-ILS/web/templates/default/cat/authority/browse_axis_authority_field_map.tt2
rename to Open-ILS/web/templates/default/conify/global/cat/authority/browse_axis_authority_field_map.tt2
index c12dfa8..8bb1af1 100644
--- a/Open-ILS/web/templates/default/cat/authority/browse_axis_authority_field_map.tt2
+++ b/Open-ILS/web/templates/default/conify/global/cat/authority/browse_axis_authority_field_map.tt2
@@ -26,7 +26,7 @@
     </div>
 </div>
 <script type="text/javascript"
-    src="[% ctx.media_prefix %]/js/ui/default/cat/authority/common.js"></script>
+    src="[% ctx.media_prefix %]/js/ui/default/conify/global/cat/authority/common.js"></script>
 <script type="text/javascript">
     dojo.require("openils.widget.AutoGrid");
     dojo.require("openils.CGI");
diff --git a/Open-ILS/web/templates/default/cat/authority/control_set.tt2 b/Open-ILS/web/templates/default/conify/global/cat/authority/control_set.tt2
similarity index 95%
rename from Open-ILS/web/templates/default/cat/authority/control_set.tt2
rename to Open-ILS/web/templates/default/conify/global/cat/authority/control_set.tt2
index 4d1e97d..69ba1d2 100644
--- a/Open-ILS/web/templates/default/cat/authority/control_set.tt2
+++ b/Open-ILS/web/templates/default/conify/global/cat/authority/control_set.tt2
@@ -44,10 +44,10 @@
                 acs_cache[id].authority_fields().length : 0;
 
             return "<a href='" + oilsBasePath +
-                "/cat/authority/thesaurus?acs=" + id + "'>" +
+                "/conify/global/cat/authority/thesaurus?acs=" + id + "'>" +
                 dojo.string.substitute(localeStrings.THESAURI, [tlen]) +
                 "</a> &nbsp;" + " <a href='" + oilsBasePath +
-                "/cat/authority/control_set_authority_field?acs=" +
+                "/conify/global/cat/authority/control_set_authority_field?acs=" +
                 id + "'>" +
                 dojo.string.substitute(localeStrings.AUTHORITY_FIELDS, [alen]) +
                 "</a>";
diff --git a/Open-ILS/web/templates/default/cat/authority/control_set_authority_field.tt2 b/Open-ILS/web/templates/default/conify/global/cat/authority/control_set_authority_field.tt2
similarity index 98%
rename from Open-ILS/web/templates/default/cat/authority/control_set_authority_field.tt2
rename to Open-ILS/web/templates/default/conify/global/cat/authority/control_set_authority_field.tt2
index b4c88cf..2f60bcc 100644
--- a/Open-ILS/web/templates/default/cat/authority/control_set_authority_field.tt2
+++ b/Open-ILS/web/templates/default/conify/global/cat/authority/control_set_authority_field.tt2
@@ -34,7 +34,7 @@
     </div>
 </div>
 <script type="text/javascript"
-    src="[% ctx.media_prefix %]/js/ui/default/cat/authority/common.js"></script>
+    src="[% ctx.media_prefix %]/js/ui/default/conify/global/cat/authority/common.js"></script>
 <script type="text/javascript">
     dojo.require("openils.widget.AutoGrid");
     dojo.require("openils.CGI");
diff --git a/Open-ILS/web/templates/default/cat/authority/control_set_bib_field.tt2 b/Open-ILS/web/templates/default/conify/global/cat/authority/control_set_bib_field.tt2
similarity index 96%
rename from Open-ILS/web/templates/default/cat/authority/control_set_bib_field.tt2
rename to Open-ILS/web/templates/default/conify/global/cat/authority/control_set_bib_field.tt2
index 6cca21b..28b9916 100644
--- a/Open-ILS/web/templates/default/cat/authority/control_set_bib_field.tt2
+++ b/Open-ILS/web/templates/default/conify/global/cat/authority/control_set_bib_field.tt2
@@ -26,7 +26,7 @@
     </div>
 </div>
 <script type="text/javascript"
-    src="[% ctx.media_prefix %]/js/ui/default/cat/authority/common.js"></script>
+    src="[% ctx.media_prefix %]/js/ui/default/conify/global/cat/authority/common.js"></script>
 <script type="text/javascript">
     dojo.require("openils.widget.AutoGrid");
     dojo.require("openils.CGI");
diff --git a/Open-ILS/web/templates/default/cat/authority/thesaurus.tt2 b/Open-ILS/web/templates/default/conify/global/cat/authority/thesaurus.tt2
similarity index 95%
rename from Open-ILS/web/templates/default/cat/authority/thesaurus.tt2
rename to Open-ILS/web/templates/default/conify/global/cat/authority/thesaurus.tt2
index 5e4c2bd..b8f80f7 100644
--- a/Open-ILS/web/templates/default/cat/authority/thesaurus.tt2
+++ b/Open-ILS/web/templates/default/conify/global/cat/authority/thesaurus.tt2
@@ -26,7 +26,7 @@
     </div>
 </div>
 <script type="text/javascript"
-    src="[% ctx.media_prefix %]/js/ui/default/cat/authority/common.js"></script>
+    src="[% ctx.media_prefix %]/js/ui/default/conify/global/cat/authority/common.js"></script>
 <script type="text/javascript">
     dojo.require("openils.widget.AutoGrid");
     dojo.require("openils.CGI");
diff --git a/Open-ILS/xul/staff_client/chrome/content/main/menu.js b/Open-ILS/xul/staff_client/chrome/content/main/menu.js
index de70805..e0e1453 100644
--- a/Open-ILS/xul/staff_client/chrome/content/main/menu.js
+++ b/Open-ILS/xul/staff_client/chrome/content/main/menu.js
@@ -961,11 +961,11 @@ main.menu.prototype = {
             ],
             'cmd_server_admin_authority_control_set': [
                 ['oncommand'],
-                function(event) { open_eg_web_page('cat/authority/control_set', null, event); }
+                function(event) { open_eg_web_page('conify/global/cat/authority/control_set', null, event); }
             ],
             'cmd_server_admin_authority_browse_axis': [
                 ['oncommand'],
-                function(event) { open_eg_web_page('cat/authority/browse_axis', null, event); }
+                function(event) { open_eg_web_page('conify/global/cat/authority/browse_axis', null, event); }
             ],
             'cmd_server_admin_booking_resource': [
                 ['oncommand'],

commit b95e14356c1ff9d150d2cc75aebf1f1fbb650845
Author: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>
Date:   Wed Jun 22 16:25:59 2011 -0400

    Axis-field map editor and editor for the axes themselves
    
    The editor for the axes themselves is accessed directly from staff
    client menu.  Everything else is reached indirectly from the control set
    editor.
    
    Signed-off-by: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>

diff --git a/Open-ILS/web/js/dojo/openils/authority/nls/authority.js b/Open-ILS/web/js/dojo/openils/authority/nls/authority.js
index 4c448c8..f7d2e24 100644
--- a/Open-ILS/web/js/dojo/openils/authority/nls/authority.js
+++ b/Open-ILS/web/js/dojo/openils/authority/nls/authority.js
@@ -19,5 +19,6 @@
     "THESAURI": "Thesauri (${0})",
     "AUTHORITY_FIELDS": "Authority Fields (${0})",
     "CONTROL_SET_METADATA": "(${0}) ${1} / ${2}",
-    "AUTHORITY_FIELD_METADATA": "${3} (${1} ‡${2}) ${4}"
+    "AUTHORITY_FIELD_METADATA": "${3} (${1} ‡${2}) ${4}",
+    "NONE_LINK": "[None]"
 }
diff --git a/Open-ILS/web/opac/locale/en-US/lang.dtd b/Open-ILS/web/opac/locale/en-US/lang.dtd
index f5e0502..9236215 100644
--- a/Open-ILS/web/opac/locale/en-US/lang.dtd
+++ b/Open-ILS/web/opac/locale/en-US/lang.dtd
@@ -787,6 +787,8 @@
 <!ENTITY staff.main.menu.admin.server_admin.authority.accesskey "U">
 <!ENTITY staff.main.menu.admin.server_admin.authority.control_set.label "Control Sets">
 <!ENTITY staff.main.menu.admin.server_admin.authority.control_set.accesskey "C">
+<!ENTITY staff.main.menu.admin.server_admin.authority.browse_axis.label "Browse Axes">
+<!ENTITY staff.main.menu.admin.server_admin.authority.browse_axis.accesskey "B">
 
 <!ENTITY staff.main.menu.admin.server_admin.booking.label "Booking">
 <!ENTITY staff.main.menu.admin.server_admin.booking.accesskey "B">
diff --git a/Open-ILS/web/templates/default/cat/authority/browse_axis.tt2 b/Open-ILS/web/templates/default/cat/authority/browse_axis.tt2
new file mode 100644
index 0000000..fc31b6e
--- /dev/null
+++ b/Open-ILS/web/templates/default/cat/authority/browse_axis.tt2
@@ -0,0 +1,33 @@
+[% WRAPPER default/base.tt2 %]
+[% ctx.page_title = "Configure Authority Browse Axes" %]
+<div dojoType="dijit.layout.ContentPane" layoutAlign="client">
+    <div dojoType="dijit.layout.ContentPane" layoutAlign="top" class="oils-header-panel">
+        <div>Browse Axes</div>
+        <div>
+            <button dojoType="dijit.form.Button" onClick="aba_grid.showCreateDialog()">New Browse Axis</button>
+            <button dojoType="dijit.form.Button" onClick="aba_grid.deleteSelected()">Delete Selected</button>
+        </div>
+    </div>
+    <div>
+        <table  jsId="aba_grid"
+                dojoType="openils.widget.AutoGrid"
+                autoHeight="true"
+                defaultCellWidth="'auto'"
+                fieldOrder="['code','name','description']"
+                suppressEditFields="['id']"
+                query="{id: '*'}"
+                fmClass="aba"
+                editOnEnter="true">
+        </table>
+    </div>
+</div>
+<script type="text/javascript">
+    dojo.require("openils.widget.AutoGrid");
+
+    function my_init() {
+        aba_grid.loadAll({"order_by": {"aba": "code"}});
+    }
+
+    openils.Util.addOnLoad(my_init);
+</script>
+[% END %]
diff --git a/Open-ILS/web/templates/default/cat/authority/browse_axis_authority_field_map.tt2 b/Open-ILS/web/templates/default/cat/authority/browse_axis_authority_field_map.tt2
new file mode 100644
index 0000000..c12dfa8
--- /dev/null
+++ b/Open-ILS/web/templates/default/cat/authority/browse_axis_authority_field_map.tt2
@@ -0,0 +1,71 @@
+[% WRAPPER default/base.tt2 %]
+[% ctx.page_title = "Configure Browse Axis-Authority Field Maps" %]
+<div dojoType="dijit.layout.ContentPane" layoutAlign="client">
+    <div dojoType="dijit.layout.ContentPane" layoutAlign="top" class="oils-header-panel">
+        <div>Browse Axis-Authority Field Maps</div>
+        <div>
+            <button dojoType="dijit.form.Button" onClick="abaafm_grid.showCreateDialog()">New Browse Axis-Authority Field Map</button>
+            <button dojoType="dijit.form.Button" onClick="abaafm_grid.deleteSelected()">Delete Selected</button>
+        </div>
+    </div>
+    <div id="authority-field-metadata-holder" class="hidden">
+        Showing only browse axis-authority field maps linked to authority field:
+        <a id="authority-field-metadata"></a>
+    </div>
+    <div>
+        <table  jsId="abaafm_grid"
+                dojoType="openils.widget.AutoGrid"
+                autoHeight="true"
+                defaultCellWidth="'auto'"
+                suppressEditFields="['id']"
+                fieldOrder="['axis','field']"
+                query="{id: '*'}"
+                fmClass="abaafm"
+                editOnEnter="true">
+        </table>
+    </div>
+</div>
+<script type="text/javascript"
+    src="[% ctx.media_prefix %]/js/ui/default/cat/authority/common.js"></script>
+<script type="text/javascript">
+    dojo.require("openils.widget.AutoGrid");
+    dojo.require("openils.CGI");
+    dojo.require("openils.PermaCrud");
+
+    dojo.requireLocalization("openils.authority", "authority");
+    var localeStrings =
+        dojo.i18n.getLocalization("openils.authority", "authority");
+
+    var cgi, pcrud;
+
+    function my_init() {
+        var authority_field, control_set_id;
+        var where = {"id": {"!=": null}};
+
+        cgi = new openils.CGI();
+        pcrud = new openils.PermaCrud();
+
+        authority_field = cgi.param("acsaf");
+        control_set_id = cgi.param("acs");
+
+        if (authority_field) {
+            /* This block not only limits the scope of our search for abaafm
+               objects, but makes sure that we create/update only abaafm's
+               that link back to the authority field (acsaf) we're interested
+               in.  */
+            authority_field = pcrud.retrieve("acsaf", authority_field);
+            where.field = authority_field.id();
+            render_authority_field_metadata(authority_field, control_set_id);
+
+            abaafm_grid.overrideEditWidgets.field =
+                new dijit.form.TextBox({"disabled": true});
+            abaafm_grid.overrideEditWidgets.field.shove =
+                {"create": authority_field.id()};
+        }
+
+        abaafm_grid.loadAll({"order_by": {"abaafm": "axis"}}, where);
+    }
+
+    openils.Util.addOnLoad(my_init);
+</script>
+[% END %]
diff --git a/Open-ILS/web/templates/default/cat/authority/control_set_authority_field.tt2 b/Open-ILS/web/templates/default/cat/authority/control_set_authority_field.tt2
index 740d408..b4c88cf 100644
--- a/Open-ILS/web/templates/default/cat/authority/control_set_authority_field.tt2
+++ b/Open-ILS/web/templates/default/cat/authority/control_set_authority_field.tt2
@@ -24,8 +24,10 @@
                 editOnEnter="true">
             <thead>
                 <tr>
-                    <th field="bib_fields" name="Controlled Bib Fields" get="get_just_id" formatter="format_bib_fields"></th>
-                    <th field="axis_maps" name="Axes"></th>
+                    <th field="bib_fields" name="Controlled Bib Fields"
+                        get="get_just_id" formatter="format_bib_fields"></th>
+                    <th field="axis_maps" name="Axes"
+                        get="get_just_id" formatter="format_axis_maps"></th>
                 </tr>
             </thead>
         </table>
@@ -74,11 +76,24 @@
         if (item) return this.grid.store.getValue(item, "id");
     }
 
+    function format_axis_maps(id) {
+        if (id) {
+            var text = acsaf_cache[id].axis_maps().map(
+                function(f) { return f.axis().name(); }
+            ).sort().join(", ") || localeStrings.NONE_LINK;
+            var href = "browse_axis_authority_field_map?";
+            if (control_set)
+                href += "acs=" + control_set.id() + "&amp;";
+            href += "acsaf=" + id;
+            return "<a href='" + href + "'>"  + text + "</a>";
+        }
+    }
+
     function format_bib_fields(id) {
         if (id) {
             var text = acsaf_cache[id].bib_fields().map(
                 function(f) { return f.tag(); }
-            ).sort().join(", ");
+            ).sort().join(", ") || localeStrings.NONE_LINK;
             var href = "control_set_bib_field?";
             if (control_set)
                 href += "acs=" + control_set.id() + "&amp;";
diff --git a/Open-ILS/xul/staff_client/chrome/content/main/menu.js b/Open-ILS/xul/staff_client/chrome/content/main/menu.js
index 728c7d5..de70805 100644
--- a/Open-ILS/xul/staff_client/chrome/content/main/menu.js
+++ b/Open-ILS/xul/staff_client/chrome/content/main/menu.js
@@ -963,6 +963,10 @@ main.menu.prototype = {
                 ['oncommand'],
                 function(event) { open_eg_web_page('cat/authority/control_set', null, event); }
             ],
+            'cmd_server_admin_authority_browse_axis': [
+                ['oncommand'],
+                function(event) { open_eg_web_page('cat/authority/browse_axis', null, event); }
+            ],
             'cmd_server_admin_booking_resource': [
                 ['oncommand'],
                 function(event) { open_eg_web_page('conify/global/booking/resource', null, event); }
diff --git a/Open-ILS/xul/staff_client/chrome/content/main/menu_frame_menus.xul b/Open-ILS/xul/staff_client/chrome/content/main/menu_frame_menus.xul
index d1279c1..8f59ae8 100644
--- a/Open-ILS/xul/staff_client/chrome/content/main/menu_frame_menus.xul
+++ b/Open-ILS/xul/staff_client/chrome/content/main/menu_frame_menus.xul
@@ -201,6 +201,7 @@
              />
 
     <command id="cmd_server_admin_authority_control_set" />
+    <command id="cmd_server_admin_authority_browse_axis" />
 
     <command id="cmd_server_admin_booking_resource" />
     <command id="cmd_server_admin_booking_resource_type" />
@@ -525,6 +526,7 @@
                 <menu id="main.menu.admin.server.authority" label="&staff.main.menu.admin.server_admin.authority.label;" accesskey="&staff.main.menu.admin.server_admin.authority.accesskey;">
                     <menupopup id="main.menu.admin.server.authority.popup">
                         <menuitem label="&staff.main.menu.admin.server_admin.authority.control_set.label;" command="cmd_server_admin_authority_control_set" accesskey="&staff.main.menu.admin.server_admin.authority.control_set.accesskey;"/>
+                        <menuitem label="&staff.main.menu.admin.server_admin.authority.browse_axis.label;" command="cmd_server_admin_authority_browse_axis" accesskey="&staff.main.menu.admin.server_admin.authority.browse_axis.accesskey;"/>
                     </menupopup>
                 </menu>
 

commit c6c3223f585b9f3c36a2d46d1a828dbcd376709a
Author: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>
Date:   Wed Jun 22 14:04:14 2011 -0400

    Add bib field editor.  Also make all the editors written so far...
    
    ... for authority control sets-related objects do the right thing to
    help users create/edit new child objects linked to the right parent
    table without extra effort.
    
    Signed-off-by: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>

diff --git a/Open-ILS/web/js/dojo/openils/authority/nls/authority.js b/Open-ILS/web/js/dojo/openils/authority/nls/authority.js
index 9fef602..4c448c8 100644
--- a/Open-ILS/web/js/dojo/openils/authority/nls/authority.js
+++ b/Open-ILS/web/js/dojo/openils/authority/nls/authority.js
@@ -18,5 +18,6 @@
     "MERGE_RESULT_SUCCESS": "Record merge is complete.",
     "THESAURI": "Thesauri (${0})",
     "AUTHORITY_FIELDS": "Authority Fields (${0})",
-    "CONTROL_SET_METADATA": "(${0}) ${1} / ${2}"
+    "CONTROL_SET_METADATA": "(${0}) ${1} / ${2}",
+    "AUTHORITY_FIELD_METADATA": "${3} (${1} ‡${2}) ${4}"
 }
diff --git a/Open-ILS/web/js/ui/default/cat/authority/common.js b/Open-ILS/web/js/ui/default/cat/authority/common.js
index d8d8a37..bb30b48 100644
--- a/Open-ILS/web/js/ui/default/cat/authority/common.js
+++ b/Open-ILS/web/js/ui/default/cat/authority/common.js
@@ -1,3 +1,4 @@
+/* To be used by interfaces for editing child tables of acs. */
 function render_control_set_metadata(control_set) {
     var anchor = dojo.byId("control-set-metadata");
     anchor.href = oilsBasePath + "/cat/authority/control_set?focus=" +
@@ -9,3 +10,27 @@ function render_control_set_metadata(control_set) {
     );
     openils.Util.show("control-set-metadata-holder");
 }
+
+/* To be used by interfaces for editing child tables of acsaf.  They not
+ * only want to know what acsaf they belong to, but for convenience they
+ * should also have handy the acs id to which their parent acsaf belongs,
+ * so they can provide the most helpful "back" link.
+ */
+function render_authority_field_metadata(authority_field, control_set_id) {
+    var anchor = dojo.byId("authority-field-metadata");
+    var href = oilsBasePath +
+        "/cat/authority/control_set_authority_field?focus=" +
+        authority_field.id();
+    if (control_set_id) href += "&acs=" + control_set_id;
+
+    anchor.href = href;
+    anchor.innerHTML = dojo.string.substitute(
+        localeStrings.AUTHORITY_FIELD_METADATA, [
+            "id", "tag", "sf_list", "name", "description"
+        ].map(function(k) {
+            var v = authority_field[k]();
+            return (v == null) ? "" : v;
+        })
+    );
+    openils.Util.show("authority-field-metadata-holder");
+}
diff --git a/Open-ILS/web/templates/default/cat/authority/control_set_authority_field.tt2 b/Open-ILS/web/templates/default/cat/authority/control_set_authority_field.tt2
index 6bf734e..740d408 100644
--- a/Open-ILS/web/templates/default/cat/authority/control_set_authority_field.tt2
+++ b/Open-ILS/web/templates/default/cat/authority/control_set_authority_field.tt2
@@ -1,7 +1,4 @@
 [% WRAPPER default/base.tt2 %]
-<style type="text/css">
-    .control-set-metadata-holder { text-align: left }
-</style>
 [% ctx.page_title = "Configure Authority Authority Fields" %]
 <div dojoType="dijit.layout.ContentPane" layoutAlign="client">
     <div dojoType="dijit.layout.ContentPane" layoutAlign="top" class="oils-header-panel">
@@ -27,7 +24,7 @@
                 editOnEnter="true">
             <thead>
                 <tr>
-                    <th field="bib_fields" name="Controlled Bib Fields"></th>
+                    <th field="bib_fields" name="Controlled Bib Fields" get="get_just_id" formatter="format_bib_fields"></th>
                     <th field="axis_maps" name="Axes"></th>
                 </tr>
             </thead>
@@ -73,6 +70,22 @@
         );
     }
 
+    function get_just_id(row_index, item) {
+        if (item) return this.grid.store.getValue(item, "id");
+    }
+
+    function format_bib_fields(id) {
+        if (id) {
+            var text = acsaf_cache[id].bib_fields().map(
+                function(f) { return f.tag(); }
+            ).sort().join(", ");
+            var href = "control_set_bib_field?";
+            if (control_set)
+                href += "acs=" + control_set.id() + "&amp;";
+            href += "acsaf=" + id;
+            return "<a href='" + href + "'>"  + text + "</a>";
+        }
+    }
 
     function my_init() {
         cgi = new openils.CGI();
@@ -82,10 +95,11 @@
         if (control_set) {
             control_set = pcrud.retrieve("acs", control_set);
             render_control_set_metadata(control_set);
-            /* XXX TODO
-               when browsing by control_set, make it impossible to
-               create/edit acsaf objects with any other control_set.
-               */
+
+            acsaf_grid.overrideEditWidgets.control_set =
+                new dijit.form.TextBox({"disabled": true});
+            acsaf_grid.overrideEditWidgets.control_set.shove =
+                {"create": control_set.id()};
         }
 
         acsaf_grid.onPostCreate = function(o) { acsaf_cache[o.id()] = o; };
diff --git a/Open-ILS/web/templates/default/cat/authority/control_set_bib_field.tt2 b/Open-ILS/web/templates/default/cat/authority/control_set_bib_field.tt2
new file mode 100644
index 0000000..6cca21b
--- /dev/null
+++ b/Open-ILS/web/templates/default/cat/authority/control_set_bib_field.tt2
@@ -0,0 +1,71 @@
+[% WRAPPER default/base.tt2 %]
+[% ctx.page_title = "Configure Authority Control Set Bib Fields" %]
+<div dojoType="dijit.layout.ContentPane" layoutAlign="client">
+    <div dojoType="dijit.layout.ContentPane" layoutAlign="top" class="oils-header-panel">
+        <div>Control Set Bib Fields</div>
+        <div>
+            <button dojoType="dijit.form.Button" onClick="acsbf_grid.showCreateDialog()">New Control Set Bib Field</button>
+            <button dojoType="dijit.form.Button" onClick="acsbf_grid.deleteSelected()">Delete Selected</button>
+        </div>
+    </div>
+    <div id="authority-field-metadata-holder" class="hidden">
+        Showing only control set bib fields linked to authority field:
+        <a id="authority-field-metadata"></a>
+    </div>
+    <div>
+        <table  jsId="acsbf_grid"
+                dojoType="openils.widget.AutoGrid"
+                autoHeight="true"
+                defaultCellWidth="'auto'"
+                suppressEditFields="['id']"
+                fieldOrder="['tag','authority_field']"
+                query="{id: '*'}"
+                fmClass="acsbf"
+                editOnEnter="true">
+        </table>
+    </div>
+</div>
+<script type="text/javascript"
+    src="[% ctx.media_prefix %]/js/ui/default/cat/authority/common.js"></script>
+<script type="text/javascript">
+    dojo.require("openils.widget.AutoGrid");
+    dojo.require("openils.CGI");
+    dojo.require("openils.PermaCrud");
+
+    dojo.requireLocalization("openils.authority", "authority");
+    var localeStrings =
+        dojo.i18n.getLocalization("openils.authority", "authority");
+
+    var cgi, pcrud;
+
+    function my_init() {
+        var authority_field, control_set_id;
+        var where = {"id": {"!=": null}};
+
+        cgi = new openils.CGI();
+        pcrud = new openils.PermaCrud();
+
+        authority_field = cgi.param("acsaf");
+        control_set_id = cgi.param("acs");
+
+        if (authority_field) {
+            /* This block not only limits the scope of our search for acsbf
+               objects, but makes sure that we create/update only acsbf's
+               that link back to the authority field (acsaf) we're interested
+               in.  */
+            authority_field = pcrud.retrieve("acsaf", authority_field);
+            where.authority_field = authority_field.id();
+            render_authority_field_metadata(authority_field, control_set_id);
+
+            acsbf_grid.overrideEditWidgets.authority_field =
+                new dijit.form.TextBox({"disabled": true});
+            acsbf_grid.overrideEditWidgets.authority_field.shove =
+                {"create": authority_field.id()};
+        }
+
+        acsbf_grid.loadAll({"order_by": {"acsbf": "tag"}}, where);
+    }
+
+    openils.Util.addOnLoad(my_init);
+</script>
+[% END %]
diff --git a/Open-ILS/web/templates/default/cat/authority/thesaurus.tt2 b/Open-ILS/web/templates/default/cat/authority/thesaurus.tt2
index 7f41066..5e4c2bd 100644
--- a/Open-ILS/web/templates/default/cat/authority/thesaurus.tt2
+++ b/Open-ILS/web/templates/default/cat/authority/thesaurus.tt2
@@ -1,7 +1,4 @@
 [% WRAPPER default/base.tt2 %]
-<style type="text/css">
-    .control-set-metadata-holder { text-align: left }
-</style>
 [% ctx.page_title = "Configure Authority Thesauri" %]
 <div dojoType="dijit.layout.ContentPane" layoutAlign="client">
     <div dojoType="dijit.layout.ContentPane" layoutAlign="top" class="oils-header-panel">
@@ -53,6 +50,11 @@
             control_set = pcrud.retrieve("acs", control_set);
             where.control_set = control_set.id();
             render_control_set_metadata(control_set);
+
+            at_grid.overrideEditWidgets.control_set =
+                new dijit.form.TextBox({"disabled": true});
+            at_grid.overrideEditWidgets.control_set.shove =
+                {"create": control_set.id()};
         }
 
         at_grid.loadAll({"order_by": {"at": "code"}}, where);

commit a80f625b27a794866f7121ec4ea52f1268993c56
Author: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>
Date:   Wed Jun 22 10:50:06 2011 -0400

    Ability to return to specific authority.control_set or
    
    to specific authority.control_set_authority_field from a child table.
    Other improvements heading toward finishing authority control set config UI
    
    Signed-off-by: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>

diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Cat/Authority.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Cat/Authority.pm
index 937aee7..696a446 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Cat/Authority.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Cat/Authority.pm
@@ -238,7 +238,7 @@ __PACKAGE__->register_method(
         "params" => [
             {"name" => "limit",  "desc" => "limit (optional; default 15)", "type" => "number"},
             {"name" => "offset",  "desc" => "offset doptional; default 0)", "type" => "number"},
-            {"name" => "id",  "desc" => "acs id (optional; default all)", "type" => "number"}
+            {"name" => "focus",  "desc" => "optionally make sure the acs object with ID matching this value comes at the top of the result set (only works with offset 0)", "type" => "number"}
         ]
     }
 );
@@ -248,19 +248,32 @@ sub retrieve_acs {
     my $self = shift;
     my $client = shift;
 
-    my ($limit, $offset, $id) = map int, @_;
+    my ($limit, $offset, $focus) = map int, @_;
 
     $limit ||= 15;
     $offset ||= 0;
-    $id ||= undef;
+    $focus ||= undef;
 
     my $e = new_editor;
-    my $where = {"id" => ($id ? $id : {"!=" => undef})};
+    my $order_by = [
+        {"class" => "acs", "field" => "name"}
+    ];
+
+    # Here is the magic that let's us say that a given acsaf
+    # will be our first result.
+    unshift @$order_by, {
+        "class" => "acs", "field" => "id",
+        "transform" => "numeric_eq", "params" => [$focus],
+        "direction" => "desc"
+    } if $focus;
+
     my $sets = $e->search_authority_control_set([
-        $where, {
+        {"id" => {"!=" => undef}}, {
             "flesh" => 1,
             "flesh_fields" => {"acs" => [qw/thesauri authority_fields/]},
-            "order_by" => {"acs" => "name"}
+            "order_by" => $order_by,
+            "limit" => $limit,
+            "offset" => $offset
         }
     ]) or return $e->die_event;
 
@@ -270,4 +283,67 @@ sub retrieve_acs {
     return undef;
 }
 
+__PACKAGE__->register_method(
+    "method" => "retrieve_acsaf",
+    "api_name" => "open-ils.cat.authority.control_set_authority_field.retrieve",
+    "api_level" => 1,
+    "stream" => 1,
+    "argc" => 2,
+    "signature" => {
+        "desc" => q/Retrieve authority.control_set_authority_field objects with
+        fleshed bib_fields and axes/,
+        "params" => [
+            {"name" => "limit",  "desc" => "limit (optional; default 15)", "type" => "number"},
+            {"name" => "offset",  "desc" => "offset (optional; default 0)", "type" => "number"},
+            {"name" => "control_set",  "desc" => "optionally constrain by value of acsaf.control_set field", "type" => "number"},
+            {"name" => "focus", "desc" => "optionally make sure the acsaf object with ID matching this value comes at the top of the result set (only works with offset 0)"}
+        ]
+    }
+);
+
+sub retrieve_acsaf {
+    my $self = shift;
+    my $client = shift;
+
+    my ($limit, $offset, $control_set, $focus) = map int, @_;
+
+    $limit ||= 15;
+    $offset ||= 0;
+    $control_set ||= undef;
+    $focus ||= undef;
+
+    my $e = new_editor;
+    my $where = {
+        "control_set" => ($control_set ? $control_set : {"!=" => undef})
+    };
+    my $order_by = [
+        {"class" => "acsaf", "field" => "main_entry", "direction" => "desc"},
+        {"class" => "acsaf", "field" => "id"}
+    ];
+
+    unshift @$order_by, {
+        "class" => "acsaf", "field" => "id",
+        "transform" => "numeric_eq", "params" => [$focus],
+        "direction" => "desc"
+    } if $focus;
+
+    my $fields = $e->search_authority_control_set_authority_field([
+        $where, {
+            "flesh" => 2,
+            "flesh_fields" => {
+                "acsaf" => ["bib_fields", "axis_maps"],
+                "abaafm" => ["axis"]
+            },
+            "order_by" => $order_by,
+            "limit" => $limit,
+            "offset" => $offset
+        }
+    ]) or return $e->die_event;
+
+    $e->disconnect;
+
+    $client->respond($_) foreach @$fields;
+    return undef;
+}
+
 1;
diff --git a/Open-ILS/web/js/ui/default/cat/authority/common.js b/Open-ILS/web/js/ui/default/cat/authority/common.js
new file mode 100644
index 0000000..d8d8a37
--- /dev/null
+++ b/Open-ILS/web/js/ui/default/cat/authority/common.js
@@ -0,0 +1,11 @@
+function render_control_set_metadata(control_set) {
+    var anchor = dojo.byId("control-set-metadata");
+    anchor.href = oilsBasePath + "/cat/authority/control_set?focus=" +
+        control_set.id();
+    anchor.innerHTML = dojo.string.substitute(
+        localeStrings.CONTROL_SET_METADATA, [
+            control_set.id(), control_set.name(), control_set.description()
+        ]
+    );
+    openils.Util.show("control-set-metadata-holder");
+}
diff --git a/Open-ILS/web/templates/default/cat/authority/control_set.tt2 b/Open-ILS/web/templates/default/cat/authority/control_set.tt2
index d763b61..4d1e97d 100644
--- a/Open-ILS/web/templates/default/cat/authority/control_set.tt2
+++ b/Open-ILS/web/templates/default/cat/authority/control_set.tt2
@@ -29,10 +29,12 @@
 
 <script type="text/javascript">
     dojo.require("openils.widget.AutoGrid");
+    dojo.require("openils.CGI");
     dojo.requireLocalization("openils.authority", "authority");
     var localeStrings =
         dojo.i18n.getLocalization("openils.authority", "authority");
     var acs_cache = {};
+    var cgi;
 
     function format_acs_id(id) {
         if (id) {
@@ -59,7 +61,7 @@
         fieldmapper.standardRequest(
             ["open-ils.cat", "open-ils.cat.authority.control_set.retrieve"], {
                 "async": true,
-                "params": [acs_grid.displayLimit, acs_grid.displayOffset],
+                "params": [acs_grid.displayLimit, acs_grid.displayOffset, cgi.param("focus")],
                 "onresponse": function(r) {
                     if (r = openils.Util.readResponse(r)) {
                         acs_cache[r.id()] = r;
@@ -75,6 +77,8 @@
 
     openils.Util.addOnLoad(
         function() {
+            cgi = new openils.CGI();
+
             acs_grid.onPostCreate = function(obj) {acs_cache[obj.id()] = obj;};
             acs_grid.dataLoader = acs_grid_loader;
             acs_grid_loader();
diff --git a/Open-ILS/web/templates/default/cat/authority/control_set_authority_field.tt2 b/Open-ILS/web/templates/default/cat/authority/control_set_authority_field.tt2
index 17e70cf..6bf734e 100644
--- a/Open-ILS/web/templates/default/cat/authority/control_set_authority_field.tt2
+++ b/Open-ILS/web/templates/default/cat/authority/control_set_authority_field.tt2
@@ -7,29 +7,35 @@
     <div dojoType="dijit.layout.ContentPane" layoutAlign="top" class="oils-header-panel">
         <div>Authority Fields</div>
         <div>
-            <button dojoType="dijit.form.Button" onClick="acsaf_grid.showCreateDialog()">New Authority Fields</button>
+            <button dojoType="dijit.form.Button" onClick="acsaf_grid.showCreateDialog()">New Authority Field</button>
             <button dojoType="dijit.form.Button" onClick="acsaf_grid.deleteSelected()">Delete Selected</button>
         </div>
     </div>
     <div id="control-set-metadata-holder" class="hidden">
-        Showing only authority fields linked to
-        <a href="control_set">control set</a>:
-        <span id="control-set-metadata"></span>
+        Showing only authority fields linked to control set:
+        <a id="control-set-metadata"></a>
     </div>
     <div>
         <table  jsId="acsaf_grid"
                 dojoType="openils.widget.AutoGrid"
                 autoHeight="true"
-                defaultCellWidth="'auto'"
-                fieldOrder="['id','name','description','main_entry','control_set','tag','sf_list']"
+                defaultCellWidth="'12%'"
+                fieldOrder="['id','name','description','main_entry','control_set','tag','sf_list','bib_fields','axis_maps']"
                 suppressEditFields="['id']"
                 query="{id: '*'}"
                 fmClass="acsaf"
                 editOnEnter="true">
+            <thead>
+                <tr>
+                    <th field="bib_fields" name="Controlled Bib Fields"></th>
+                    <th field="axis_maps" name="Axes"></th>
+                </tr>
+            </thead>
         </table>
     </div>
 </div>
-
+<script type="text/javascript"
+    src="[% ctx.media_prefix %]/js/ui/default/cat/authority/common.js"></script>
 <script type="text/javascript">
     dojo.require("openils.widget.AutoGrid");
     dojo.require("openils.CGI");
@@ -39,42 +45,52 @@
     var localeStrings =
         dojo.i18n.getLocalization("openils.authority", "authority");
 
-    var cgi, pcrud;
+    var cgi, pcrud, control_set;
+    var acsaf_cache = {};
 
-    function render_control_set_metadata(control_set) {
-        var span = dojo.byId("control-set-metadata");
-        span.innerHTML = dojo.string.substitute(
-            localeStrings.CONTROL_SET_METADATA, [
-                control_set.id(), control_set.name(), control_set.description()
-            ]
+    function acsaf_grid_loader() {
+        acsaf_cache = {};
+        acsaf_grid.resetStore();
+        acsaf_grid.showLoadProgressIndicator();
+        fieldmapper.standardRequest(
+            ["open-ils.cat",
+                "open-ils.cat.authority.control_set_authority_field.retrieve"],{
+                "async": true,
+                "params": [
+                    acsaf_grid.displayLimit, acsaf_grid.displayOffset,
+                    control_set.id(), cgi.param("focus")
+                ],
+                "onresponse": function(r) {
+                    if (r = openils.Util.readResponse(r)) {
+                        acsaf_cache[r.id()] = r;
+                        acsaf_grid.store.newItem(r.toStoreItem());
+                    }
+                },
+                "oncomplete": function() {
+                    acsaf_grid.hideLoadProgressIndicator();
+                }
+            }
         );
-        openils.Util.show("control-set-metadata-holder");
     }
 
-    function my_init() {
-        var control_set;
-        var where = {"id": {"!=": null}};
 
+    function my_init() {
         cgi = new openils.CGI();
         pcrud = new openils.PermaCrud();
 
         control_set = cgi.param("acs");
         if (control_set) {
             control_set = pcrud.retrieve("acs", control_set);
-            where.control_set = control_set.id();
             render_control_set_metadata(control_set);
             /* XXX TODO
-               1) put render_control_set_metadata() somewhere that it doesn't
-               have to be repeated.
-               2) when browsing by control_set, make it impossible to
+               when browsing by control_set, make it impossible to
                create/edit acsaf objects with any other control_set.
                */
         }
 
-        acsaf_grid.loadAll(
-            {"order_by": {"acsaf": ["main_entry DESC", "id"]}},
-            where
-        );
+        acsaf_grid.onPostCreate = function(o) { acsaf_cache[o.id()] = o; };
+        acsaf_grid.dataLoader = acsaf_grid_loader;
+        acsaf_grid_loader();
     }
 
     openils.Util.addOnLoad(my_init);
diff --git a/Open-ILS/web/templates/default/cat/authority/thesaurus.tt2 b/Open-ILS/web/templates/default/cat/authority/thesaurus.tt2
index 0c62dab..7f41066 100644
--- a/Open-ILS/web/templates/default/cat/authority/thesaurus.tt2
+++ b/Open-ILS/web/templates/default/cat/authority/thesaurus.tt2
@@ -12,8 +12,8 @@
         </div>
     </div>
     <div id="control-set-metadata-holder" class="hidden">
-        Showing only thesauri linked to <a href="control_set">control set</a>:
-        <span id="control-set-metadata"></span>
+        Showing only thesauri linked to control set:
+        <a id="control-set-metadata"></a>
     </div>
     <div>
         <table  jsId="at_grid"
@@ -28,7 +28,8 @@
         </table>
     </div>
 </div>
-
+<script type="text/javascript"
+    src="[% ctx.media_prefix %]/js/ui/default/cat/authority/common.js"></script>
 <script type="text/javascript">
     dojo.require("openils.widget.AutoGrid");
     dojo.require("openils.CGI");
@@ -40,16 +41,6 @@
 
     var cgi, pcrud;
 
-    function render_control_set_metadata(control_set) {
-        var span = dojo.byId("control-set-metadata");
-        span.innerHTML = dojo.string.substitute(
-            localeStrings.CONTROL_SET_METADATA, [
-                control_set.id(), control_set.name(), control_set.description()
-            ]
-        );
-        openils.Util.show("control-set-metadata-holder");
-    }
-
     function my_init() {
         var control_set;
         var where = {"code": {"!=": null}};

commit f634d30849f91bd51ef9fbfcbba639ad658a1c1c
Author: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>
Date:   Tue Jun 21 14:22:26 2011 -0400

    Editor for authority fields
    
    Due to time constraints (and AutoGrid limitations) a click-through UI
    with separate pages for separate objects used by the new authority
    control sets feature is necessary for now rather than a comprehensive
    interface with multiple grids on the same page.
    
    Signed-off-by: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>

diff --git a/Open-ILS/web/templates/default/cat/authority/control_set_authority_field.tt2 b/Open-ILS/web/templates/default/cat/authority/control_set_authority_field.tt2
new file mode 100644
index 0000000..17e70cf
--- /dev/null
+++ b/Open-ILS/web/templates/default/cat/authority/control_set_authority_field.tt2
@@ -0,0 +1,82 @@
+[% WRAPPER default/base.tt2 %]
+<style type="text/css">
+    .control-set-metadata-holder { text-align: left }
+</style>
+[% ctx.page_title = "Configure Authority Authority Fields" %]
+<div dojoType="dijit.layout.ContentPane" layoutAlign="client">
+    <div dojoType="dijit.layout.ContentPane" layoutAlign="top" class="oils-header-panel">
+        <div>Authority Fields</div>
+        <div>
+            <button dojoType="dijit.form.Button" onClick="acsaf_grid.showCreateDialog()">New Authority Fields</button>
+            <button dojoType="dijit.form.Button" onClick="acsaf_grid.deleteSelected()">Delete Selected</button>
+        </div>
+    </div>
+    <div id="control-set-metadata-holder" class="hidden">
+        Showing only authority fields linked to
+        <a href="control_set">control set</a>:
+        <span id="control-set-metadata"></span>
+    </div>
+    <div>
+        <table  jsId="acsaf_grid"
+                dojoType="openils.widget.AutoGrid"
+                autoHeight="true"
+                defaultCellWidth="'auto'"
+                fieldOrder="['id','name','description','main_entry','control_set','tag','sf_list']"
+                suppressEditFields="['id']"
+                query="{id: '*'}"
+                fmClass="acsaf"
+                editOnEnter="true">
+        </table>
+    </div>
+</div>
+
+<script type="text/javascript">
+    dojo.require("openils.widget.AutoGrid");
+    dojo.require("openils.CGI");
+    dojo.require("openils.PermaCrud");
+
+    dojo.requireLocalization("openils.authority", "authority");
+    var localeStrings =
+        dojo.i18n.getLocalization("openils.authority", "authority");
+
+    var cgi, pcrud;
+
+    function render_control_set_metadata(control_set) {
+        var span = dojo.byId("control-set-metadata");
+        span.innerHTML = dojo.string.substitute(
+            localeStrings.CONTROL_SET_METADATA, [
+                control_set.id(), control_set.name(), control_set.description()
+            ]
+        );
+        openils.Util.show("control-set-metadata-holder");
+    }
+
+    function my_init() {
+        var control_set;
+        var where = {"id": {"!=": null}};
+
+        cgi = new openils.CGI();
+        pcrud = new openils.PermaCrud();
+
+        control_set = cgi.param("acs");
+        if (control_set) {
+            control_set = pcrud.retrieve("acs", control_set);
+            where.control_set = control_set.id();
+            render_control_set_metadata(control_set);
+            /* XXX TODO
+               1) put render_control_set_metadata() somewhere that it doesn't
+               have to be repeated.
+               2) when browsing by control_set, make it impossible to
+               create/edit acsaf objects with any other control_set.
+               */
+        }
+
+        acsaf_grid.loadAll(
+            {"order_by": {"acsaf": ["main_entry DESC", "id"]}},
+            where
+        );
+    }
+
+    openils.Util.addOnLoad(my_init);
+</script>
+[% END %]

commit e3fa59368c8e8a3b1d26c442e58b1fe57526611c
Author: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>
Date:   Tue Jun 21 14:08:55 2011 -0400

    Thesauri editor

diff --git a/Open-ILS/web/js/dojo/openils/authority/nls/authority.js b/Open-ILS/web/js/dojo/openils/authority/nls/authority.js
index f7ea8a0..9fef602 100644
--- a/Open-ILS/web/js/dojo/openils/authority/nls/authority.js
+++ b/Open-ILS/web/js/dojo/openils/authority/nls/authority.js
@@ -17,5 +17,6 @@
     "SAVE_RESULT_SUCCESS": "Record was saved.",
     "MERGE_RESULT_SUCCESS": "Record merge is complete.",
     "THESAURI": "Thesauri (${0})",
-    "AUTHORITY_FIELDS": "Authority Fields (${0})"
+    "AUTHORITY_FIELDS": "Authority Fields (${0})",
+    "CONTROL_SET_METADATA": "(${0}) ${1} / ${2}"
 }
diff --git a/Open-ILS/web/templates/default/cat/authority/control_set.tt2 b/Open-ILS/web/templates/default/cat/authority/control_set.tt2
index 095578d..d763b61 100644
--- a/Open-ILS/web/templates/default/cat/authority/control_set.tt2
+++ b/Open-ILS/web/templates/default/cat/authority/control_set.tt2
@@ -42,10 +42,10 @@
                 acs_cache[id].authority_fields().length : 0;
 
             return "<a href='" + oilsBasePath +
-                "/conify/global/authority/thesaurus?id=" + id + "'>" +
+                "/cat/authority/thesaurus?acs=" + id + "'>" +
                 dojo.string.substitute(localeStrings.THESAURI, [tlen]) +
                 "</a> &nbsp;" + " <a href='" + oilsBasePath +
-                "/conify/global/authority/control_set_authority_field?id=" +
+                "/cat/authority/control_set_authority_field?acs=" +
                 id + "'>" +
                 dojo.string.substitute(localeStrings.AUTHORITY_FIELDS, [alen]) +
                 "</a>";
diff --git a/Open-ILS/web/templates/default/cat/authority/thesaurus.tt2 b/Open-ILS/web/templates/default/cat/authority/thesaurus.tt2
new file mode 100644
index 0000000..0c62dab
--- /dev/null
+++ b/Open-ILS/web/templates/default/cat/authority/thesaurus.tt2
@@ -0,0 +1,72 @@
+[% WRAPPER default/base.tt2 %]
+<style type="text/css">
+    .control-set-metadata-holder { text-align: left }
+</style>
+[% ctx.page_title = "Configure Authority Thesauri" %]
+<div dojoType="dijit.layout.ContentPane" layoutAlign="client">
+    <div dojoType="dijit.layout.ContentPane" layoutAlign="top" class="oils-header-panel">
+        <div>Thesauri</div>
+        <div>
+            <button dojoType="dijit.form.Button" onClick="at_grid.showCreateDialog()">New Thesaurus</button>
+            <button dojoType="dijit.form.Button" onClick="at_grid.deleteSelected()">Delete Selected</button>
+        </div>
+    </div>
+    <div id="control-set-metadata-holder" class="hidden">
+        Showing only thesauri linked to <a href="control_set">control set</a>:
+        <span id="control-set-metadata"></span>
+    </div>
+    <div>
+        <table  jsId="at_grid"
+                dojoType="openils.widget.AutoGrid"
+                autoHeight="true"
+                defaultCellWidth="'auto'"
+                fieldOrder="['code','control_set','name','description']"
+                suppressEditFields="['id']"
+                query="{id: '*'}"
+                fmClass="at"
+                editOnEnter="true">
+        </table>
+    </div>
+</div>
+
+<script type="text/javascript">
+    dojo.require("openils.widget.AutoGrid");
+    dojo.require("openils.CGI");
+    dojo.require("openils.PermaCrud");
+
+    dojo.requireLocalization("openils.authority", "authority");
+    var localeStrings =
+        dojo.i18n.getLocalization("openils.authority", "authority");
+
+    var cgi, pcrud;
+
+    function render_control_set_metadata(control_set) {
+        var span = dojo.byId("control-set-metadata");
+        span.innerHTML = dojo.string.substitute(
+            localeStrings.CONTROL_SET_METADATA, [
+                control_set.id(), control_set.name(), control_set.description()
+            ]
+        );
+        openils.Util.show("control-set-metadata-holder");
+    }
+
+    function my_init() {
+        var control_set;
+        var where = {"code": {"!=": null}};
+
+        cgi = new openils.CGI();
+        pcrud = new openils.PermaCrud();
+
+        control_set = cgi.param("acs");
+        if (control_set) {
+            control_set = pcrud.retrieve("acs", control_set);
+            where.control_set = control_set.id();
+            render_control_set_metadata(control_set);
+        }
+
+        at_grid.loadAll({"order_by": {"at": "code"}}, where);
+    }
+
+    openils.Util.addOnLoad(my_init);
+</script>
+[% END %]

commit ade9dc1af909b8a31e98b1c6df2a63af3b4aeba8
Author: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>
Date:   Tue Jun 21 12:43:52 2011 -0400

    moving stuff where it goes

diff --git a/Open-ILS/web/templates/default/authority/control_set.tt2 b/Open-ILS/web/templates/default/cat/authority/control_set.tt2
similarity index 93%
rename from Open-ILS/web/templates/default/authority/control_set.tt2
rename to Open-ILS/web/templates/default/cat/authority/control_set.tt2
index 3c408da..095578d 100644
--- a/Open-ILS/web/templates/default/authority/control_set.tt2
+++ b/Open-ILS/web/templates/default/cat/authority/control_set.tt2
@@ -29,9 +29,9 @@
 
 <script type="text/javascript">
     dojo.require("openils.widget.AutoGrid");
-    dojo.requireLocalization('openils.authority', 'authority');
+    dojo.requireLocalization("openils.authority", "authority");
     var localeStrings =
-        dojo.i18n.getLocalization('openils.authority', 'authority');
+        dojo.i18n.getLocalization("openils.authority", "authority");
     var acs_cache = {};
 
     function format_acs_id(id) {
@@ -78,7 +78,6 @@
             acs_grid.onPostCreate = function(obj) {acs_cache[obj.id()] = obj;};
             acs_grid.dataLoader = acs_grid_loader;
             acs_grid_loader();
-            //acs_grid.loadAll({order_by:{acs : "name"}}, {"id": {"!=": null}});
         }
     );
 </script>
diff --git a/Open-ILS/xul/staff_client/chrome/content/main/menu.js b/Open-ILS/xul/staff_client/chrome/content/main/menu.js
index 3caf9d6..728c7d5 100644
--- a/Open-ILS/xul/staff_client/chrome/content/main/menu.js
+++ b/Open-ILS/xul/staff_client/chrome/content/main/menu.js
@@ -961,7 +961,7 @@ main.menu.prototype = {
             ],
             'cmd_server_admin_authority_control_set': [
                 ['oncommand'],
-                function(event) { open_eg_web_page('authority/control_set', null, event); }
+                function(event) { open_eg_web_page('cat/authority/control_set', null, event); }
             ],
             'cmd_server_admin_booking_resource': [
                 ['oncommand'],

commit 580fed6d32cd8113c6d45a6c36fa97e28cce9f78
Author: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>
Date:   Tue Jun 21 10:27:11 2011 -0400

    conify type interfaces in progress.
    
    not completely deleting old unfinished ones yet; there are probably
    things to salvage
    
    Signed-off-by: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>

diff --git a/Open-ILS/examples/fm_IDL.xml b/Open-ILS/examples/fm_IDL.xml
index 621606e..052c802 100644
--- a/Open-ILS/examples/fm_IDL.xml
+++ b/Open-ILS/examples/fm_IDL.xml
@@ -1759,7 +1759,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 	</class>
 
 	<class id="acs" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="authority::control_set" oils_persist:tablename="authority.control_set" reporter:label="Authority Control Set">
-		<fields oils_persist:primary="id" oils_persist:sequence="authority.contol_set_id_seq">
+		<fields oils_persist:primary="id" oils_persist:sequence="authority.control_set_id_seq">
 			<field reporter:label="Control Set ID" name="id" reporter:datatype="id" reporter:selector="name"/>
 			<field reporter:label="Name" name="name" reporter:datatype="text" oils_persist:i18n="true" oils_obj:required="true" />
 			<field reporter:label="Description" name="description" reporter:datatype="text" oils_persist:i18n="true" />
@@ -1772,16 +1772,16 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 		</links>
 		<permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
 			<actions>
-				<create permission="CREATE_AUTHORITY_CONTROLSET" global_required="true"/>
+				<create permission="CREATE_AUTHORITY_CONTROL_SET" global_required="true"/>
 				<retrieve/>
-				<update permission="UPDATE_AUTHORITY_CONTROLSET" global_required="true"/>
-				<delete permission="DELETE_AUTHORITY_CONTROLSET" global_required="true"/>
+				<update permission="UPDATE_AUTHORITY_CONTROL_SET" global_required="true"/>
+				<delete permission="DELETE_AUTHORITY_CONTROL_SET" global_required="true"/>
 			</actions>
 		</permacrud>
 	</class>
 
 	<class id="acsaf" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="authority::control_set_authority_field" oils_persist:tablename="authority.control_set_authority_field" reporter:label="Authority Control Set Authority Field">
-		<fields oils_persist:primary="id" oils_persist:sequence="authority.contol_set_authority_field_id_seq">
+		<fields oils_persist:primary="id" oils_persist:sequence="authority.control_set_authority_field_id_seq">
 			<field reporter:label="Control Set Authority Field ID" name="id" reporter:datatype="id" reporter:selector="name"/>
 			<field reporter:label="Main Entry" name="main_entry" reporter:datatype="link"/>
 			<field reporter:label="Control Set" name="control_set" reporter:datatype="link"/>
@@ -1804,16 +1804,16 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 		</links>
 		<permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
 			<actions>
-				<create permission="CREATE_AUTHORITY_CONTROLSET" global_required="true"/>
+				<create permission="CREATE_AUTHORITY_CONTROL_SET" global_required="true"/>
 				<retrieve/>
-				<update permission="UPDATE_AUTHORITY_CONTROLSET" global_required="true"/>
-				<delete permission="UPDATE_AUTHORITY_CONTROLSET" global_required="true"/>
+				<update permission="UPDATE_AUTHORITY_CONTROL_SET" global_required="true"/>
+				<delete permission="UPDATE_AUTHORITY_CONTROL_SET" global_required="true"/>
 			</actions>
 		</permacrud>
 	</class>
 
 	<class id="acsbf" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="authority::control_set_bib_field" oils_persist:tablename="authority.control_set_bib_field" reporter:label="Authority Control Set Bib Field">
-		<fields oils_persist:primary="id" oils_persist:sequence="authority.contol_set_bib_field_id_seq">
+		<fields oils_persist:primary="id" oils_persist:sequence="authority.control_set_bib_field_id_seq">
 			<field reporter:label="Controlled Bib Field ID" name="id" reporter:datatype="id" reporter:selector="name"/>
 			<field reporter:label="Controlling Authority Field" name="authority_field" reporter:datatype="link"/>
 			<field reporter:label="Tag" name="tag" reporter:datatype="text" oils_obj:required="true" oils_obj:validate="^.{3}$"/>
@@ -1823,10 +1823,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 		</links>
 		<permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
 			<actions>
-				<create permission="CREATE_AUTHORITY_CONTROLSET" global_required="true"/>
+				<create permission="CREATE_AUTHORITY_CONTROL_SET" global_required="true"/>
 				<retrieve/>
-				<update permission="UPDATE_AUTHORITY_CONTROLSET" global_required="true"/>
-				<delete permission="UPDATE_AUTHORITY_CONTROLSET" global_required="true"/>
+				<update permission="UPDATE_AUTHORITY_CONTROL_SET" global_required="true"/>
+				<delete permission="UPDATE_AUTHORITY_CONTROL_SET" global_required="true"/>
 			</actions>
 		</permacrud>
 	</class>
@@ -1843,10 +1843,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 		</links>
 		<permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
 			<actions>
-				<create permission="CREATE_AUTHORITY_CONTROLSET" global_required="true"/>
+				<create permission="CREATE_AUTHORITY_CONTROL_SET" global_required="true"/>
 				<retrieve/>
-				<update permission="UPDATE_AUTHORITY_CONTROLSET" global_required="true"/>
-				<delete permission="UPDATE_AUTHORITY_CONTROLSET" global_required="true"/>
+				<update permission="UPDATE_AUTHORITY_CONTROL_SET" global_required="true"/>
+				<delete permission="UPDATE_AUTHORITY_CONTROL_SET" global_required="true"/>
 			</actions>
 		</permacrud>
 	</class>
@@ -1865,10 +1865,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 		</links>
 		<permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
 			<actions>
-				<create permission="CREATE_AUTHORITY_CONTROLSET" global_required="true"/>
+				<create permission="CREATE_AUTHORITY_CONTROL_SET" global_required="true"/>
 				<retrieve/>
-				<update permission="UPDATE_AUTHORITY_CONTROLSET" global_required="true"/>
-				<delete permission="UPDATE_AUTHORITY_CONTROLSET" global_required="true"/>
+				<update permission="UPDATE_AUTHORITY_CONTROL_SET" global_required="true"/>
+				<delete permission="UPDATE_AUTHORITY_CONTROL_SET" global_required="true"/>
 			</actions>
 		</permacrud>
 	</class>
@@ -1885,10 +1885,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
         </links>
         <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
             <actions>
-                <create permission="CREATE_AUTHORITY_CONTROLSET" global_required="true"/>
+                <create permission="CREATE_AUTHORITY_CONTROL_SET" global_required="true"/>
                 <retrieve/>
-                <update permission="UPDATE_AUTHORITY_CONTROLSET" global_required="true"/>
-                <delete permission="UPDATE_AUTHORITY_CONTROLSET" global_required="true"/>
+                <update permission="UPDATE_AUTHORITY_CONTROL_SET" global_required="true"/>
+                <delete permission="UPDATE_AUTHORITY_CONTROL_SET" global_required="true"/>
             </actions>
         </permacrud>
     </class>
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Cat/Authority.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Cat/Authority.pm
index 9e60557..937aee7 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Cat/Authority.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Cat/Authority.pm
@@ -226,4 +226,48 @@ sub count_linked_bibs {
     return $link_count;
 }
 
+__PACKAGE__->register_method(
+    "method" => "retrieve_acs",
+    "api_name" => "open-ils.cat.authority.control_set.retrieve",
+    "api_level" => 1,
+    "stream" => 1,
+    "argc" => 2,
+    "signature" => {
+        "desc" => q/Retrieve authority.control_set objects with fleshed
+        thesauri and authority fields/,
+        "params" => [
+            {"name" => "limit",  "desc" => "limit (optional; default 15)", "type" => "number"},
+            {"name" => "offset",  "desc" => "offset doptional; default 0)", "type" => "number"},
+            {"name" => "id",  "desc" => "acs id (optional; default all)", "type" => "number"}
+        ]
+    }
+);
+
+# XXX I don't think this really needs to be protected by perms, or does it?
+sub retrieve_acs {
+    my $self = shift;
+    my $client = shift;
+
+    my ($limit, $offset, $id) = map int, @_;
+
+    $limit ||= 15;
+    $offset ||= 0;
+    $id ||= undef;
+
+    my $e = new_editor;
+    my $where = {"id" => ($id ? $id : {"!=" => undef})};
+    my $sets = $e->search_authority_control_set([
+        $where, {
+            "flesh" => 1,
+            "flesh_fields" => {"acs" => [qw/thesauri authority_fields/]},
+            "order_by" => {"acs" => "name"}
+        }
+    ]) or return $e->die_event;
+
+    $e->disconnect;
+
+    $client->respond($_) foreach @$sets;
+    return undef;
+}
+
 1;
diff --git a/Open-ILS/web/js/dojo/openils/authority/nls/authority.js b/Open-ILS/web/js/dojo/openils/authority/nls/authority.js
index 732b433..f7ea8a0 100644
--- a/Open-ILS/web/js/dojo/openils/authority/nls/authority.js
+++ b/Open-ILS/web/js/dojo/openils/authority/nls/authority.js
@@ -15,5 +15,7 @@
     "CONFIRM_DELETE_RESULT": "Deleted authority record # ${0}.",
     "SAVE": "Save",
     "SAVE_RESULT_SUCCESS": "Record was saved.",
-    "MERGE_RESULT_SUCCESS": "Record merge is complete."
+    "MERGE_RESULT_SUCCESS": "Record merge is complete.",
+    "THESAURI": "Thesauri (${0})",
+    "AUTHORITY_FIELDS": "Authority Fields (${0})"
 }
diff --git a/Open-ILS/web/js/dojo/openils/widget/AutoGrid.js b/Open-ILS/web/js/dojo/openils/widget/AutoGrid.js
index 9e5be71..ab42a00 100644
--- a/Open-ILS/web/js/dojo/openils/widget/AutoGrid.js
+++ b/Open-ILS/web/js/dojo/openils/widget/AutoGrid.js
@@ -208,7 +208,7 @@ if(!dojo._hasResource['openils.widget.AutoGrid']) {
 
                     var entry = existing.filter(function(i){return (i.field == field.name)})[0];
                     if(entry) {
-                        entry.name = field.label;
+                        entry.name = entry.name || field.label;
                     } else {
                         // unless specifically requested, hide sequence fields
                         if(!this.showSequenceFields && field.name == this.fmIDL.pkey && this.fmIDL.pkey_sequence)
diff --git a/Open-ILS/web/opac/locale/en-US/lang.dtd b/Open-ILS/web/opac/locale/en-US/lang.dtd
index 6352be9..f5e0502 100644
--- a/Open-ILS/web/opac/locale/en-US/lang.dtd
+++ b/Open-ILS/web/opac/locale/en-US/lang.dtd
@@ -783,6 +783,11 @@
 <!ENTITY staff.main.menu.admin.server_admin.acq.exchange_rate.label "Exchange Rates">
 <!ENTITY staff.main.menu.admin.server_admin.acq.exchange_rate.accesskey "X">
 
+<!ENTITY staff.main.menu.admin.server_admin.authority.label "Authorities">
+<!ENTITY staff.main.menu.admin.server_admin.authority.accesskey "U">
+<!ENTITY staff.main.menu.admin.server_admin.authority.control_set.label "Control Sets">
+<!ENTITY staff.main.menu.admin.server_admin.authority.control_set.accesskey "C">
+
 <!ENTITY staff.main.menu.admin.server_admin.booking.label "Booking">
 <!ENTITY staff.main.menu.admin.server_admin.booking.accesskey "B">
 <!ENTITY staff.main.menu.admin.server_admin.booking.resource.label "Resources">
diff --git a/Open-ILS/web/templates/default/authority/control_set.tt2 b/Open-ILS/web/templates/default/authority/control_set.tt2
new file mode 100644
index 0000000..3c408da
--- /dev/null
+++ b/Open-ILS/web/templates/default/authority/control_set.tt2
@@ -0,0 +1,85 @@
+[% WRAPPER default/base.tt2 %]
+[% ctx.page_title = "Configure Authority Control Sets" %]
+<div dojoType="dijit.layout.ContentPane" layoutAlign="client">
+    <div dojoType="dijit.layout.ContentPane" layoutAlign="top" class="oils-header-panel">
+        <div>Control Sets</div>
+        <div>
+            <button dojoType="dijit.form.Button" onClick="acs_grid.showCreateDialog()">New Control Set</button>
+            <button dojoType="dijit.form.Button" onClick="acs_grid.deleteSelected()">Delete Selected</button>
+        </div>
+    </div>
+    <div>
+    <table  jsId="acs_grid"
+            dojoType="openils.widget.AutoGrid"
+            autoHeight="true"
+            defaultCellWidth="'auto'"
+            fieldOrder="['name','description','id']"
+            suppressEditFields="['id']"
+            query="{id: '*'}"
+            fmClass="acs"
+            editOnEnter="true">
+            <thead>
+                <tr>
+                    <th name="Other properties"
+                        field="id" formatter="format_acs_id"></th>
+                </tr>
+            </thead>
+    </table>
+</div>
+
+<script type="text/javascript">
+    dojo.require("openils.widget.AutoGrid");
+    dojo.requireLocalization('openils.authority', 'authority');
+    var localeStrings =
+        dojo.i18n.getLocalization('openils.authority', 'authority');
+    var acs_cache = {};
+
+    function format_acs_id(id) {
+        if (id) {
+            var tlen = acs_cache[id].thesauri() ?
+                acs_cache[id].thesauri().length : 0;
+            var alen = acs_cache[id].authority_fields() ?
+                acs_cache[id].authority_fields().length : 0;
+
+            return "<a href='" + oilsBasePath +
+                "/conify/global/authority/thesaurus?id=" + id + "'>" +
+                dojo.string.substitute(localeStrings.THESAURI, [tlen]) +
+                "</a> &nbsp;" + " <a href='" + oilsBasePath +
+                "/conify/global/authority/control_set_authority_field?id=" +
+                id + "'>" +
+                dojo.string.substitute(localeStrings.AUTHORITY_FIELDS, [alen]) +
+                "</a>";
+        }
+    }
+
+    function acs_grid_loader() {
+        acs_cache = {};
+        acs_grid.resetStore();
+        acs_grid.showLoadProgressIndicator();
+        fieldmapper.standardRequest(
+            ["open-ils.cat", "open-ils.cat.authority.control_set.retrieve"], {
+                "async": true,
+                "params": [acs_grid.displayLimit, acs_grid.displayOffset],
+                "onresponse": function(r) {
+                    if (r = openils.Util.readResponse(r)) {
+                        acs_cache[r.id()] = r;
+                        acs_grid.store.newItem(r.toStoreItem());
+                    }
+                },
+                "oncomplete": function() {
+                    acs_grid.hideLoadProgressIndicator();
+                }
+            }
+        );
+    }
+
+    openils.Util.addOnLoad(
+        function() {
+            acs_grid.onPostCreate = function(obj) {acs_cache[obj.id()] = obj;};
+            acs_grid.dataLoader = acs_grid_loader;
+            acs_grid_loader();
+            //acs_grid.loadAll({order_by:{acs : "name"}}, {"id": {"!=": null}});
+        }
+    );
+</script>
+[% END %]
diff --git a/Open-ILS/web/templates/default/conify/global/authority/authority_field.tt2 b/Open-ILS/web/templates/default/conify/global/authority/authority_field.tt2.old
similarity index 100%
rename from Open-ILS/web/templates/default/conify/global/authority/authority_field.tt2
rename to Open-ILS/web/templates/default/conify/global/authority/authority_field.tt2.old
diff --git a/Open-ILS/web/templates/default/conify/global/authority/bib_field.tt2 b/Open-ILS/web/templates/default/conify/global/authority/bib_field.tt2.old
similarity index 100%
rename from Open-ILS/web/templates/default/conify/global/authority/bib_field.tt2
rename to Open-ILS/web/templates/default/conify/global/authority/bib_field.tt2.old
diff --git a/Open-ILS/web/templates/default/conify/global/authority/control_set.tt2 b/Open-ILS/web/templates/default/conify/global/authority/control_set.tt2.old
similarity index 100%
rename from Open-ILS/web/templates/default/conify/global/authority/control_set.tt2
rename to Open-ILS/web/templates/default/conify/global/authority/control_set.tt2.old
diff --git a/Open-ILS/web/templates/default/conify/global/authority/thesaurus.tt2 b/Open-ILS/web/templates/default/conify/global/authority/thesaurus.tt2.old
similarity index 100%
rename from Open-ILS/web/templates/default/conify/global/authority/thesaurus.tt2
rename to Open-ILS/web/templates/default/conify/global/authority/thesaurus.tt2.old
diff --git a/Open-ILS/xul/staff_client/chrome/content/main/menu.js b/Open-ILS/xul/staff_client/chrome/content/main/menu.js
index 79949f4..3caf9d6 100644
--- a/Open-ILS/xul/staff_client/chrome/content/main/menu.js
+++ b/Open-ILS/xul/staff_client/chrome/content/main/menu.js
@@ -959,6 +959,10 @@ main.menu.prototype = {
                 ['oncommand'],
                 function(event) { open_eg_web_page('conify/global/config/usr_setting_type', null, event); }
             ],
+            'cmd_server_admin_authority_control_set': [
+                ['oncommand'],
+                function(event) { open_eg_web_page('authority/control_set', null, event); }
+            ],
             'cmd_server_admin_booking_resource': [
                 ['oncommand'],
                 function(event) { open_eg_web_page('conify/global/booking/resource', null, event); }
@@ -1157,8 +1161,11 @@ main.menu.prototype = {
             'cmd_authority_manage' : [
                 ['oncommand'],
                 function(event) {
-                    obj.data.stash_retrieve();
-                    obj.command_tab(event,obj.url_prefix(urls.AUTHORITY_MANAGE),{},{});
+                    open_eg_web_page(
+                        urls.AUTHORITY_MANAGE,
+                        "menu.cmd_authority_manage.tab",
+                        event
+                    );
                 }
             ],
 
diff --git a/Open-ILS/xul/staff_client/chrome/content/main/menu_frame_menus.xul b/Open-ILS/xul/staff_client/chrome/content/main/menu_frame_menus.xul
index 741c0ce..d1279c1 100644
--- a/Open-ILS/xul/staff_client/chrome/content/main/menu_frame_menus.xul
+++ b/Open-ILS/xul/staff_client/chrome/content/main/menu_frame_menus.xul
@@ -199,6 +199,9 @@
     <command id="cmd_server_admin_config_rule_age_hold_protect"
              perm="ADMIN_AGE_PROTECT_RULE"
              />
+
+    <command id="cmd_server_admin_authority_control_set" />
+
     <command id="cmd_server_admin_booking_resource" />
     <command id="cmd_server_admin_booking_resource_type" />
     <command id="cmd_server_admin_booking_resource_attr" />
@@ -518,6 +521,13 @@
                         <menuitem label="&staff.main.menu.admin.server_admin.acq.cancel_reason.label;" accesskey="&staff.main.menu.admin.server_admin.acq.cancel_reason.accesskey;" command="cmd_server_admin_acq_cancel_reason"/>
                     </menupopup>
                 </menu>
+
+                <menu id="main.menu.admin.server.authority" label="&staff.main.menu.admin.server_admin.authority.label;" accesskey="&staff.main.menu.admin.server_admin.authority.accesskey;">
+                    <menupopup id="main.menu.admin.server.authority.popup">
+                        <menuitem label="&staff.main.menu.admin.server_admin.authority.control_set.label;" command="cmd_server_admin_authority_control_set" accesskey="&staff.main.menu.admin.server_admin.authority.control_set.accesskey;"/>
+                    </menupopup>
+                </menu>
+
                 <menu id="main.menu.admin.server.booking" label="&staff.main.menu.admin.server_admin.booking.label;" accesskey="&staff.main.menu.admin.server_admin.booking.accesskey;">
                     <menupopup id="main.menu.admin.server.booking.popup">
                         <menuitem label="&staff.main.menu.admin.server_admin.booking.resource.label;" command="cmd_server_admin_booking_resource" accesskey="&staff.main.menu.admin.server_admin.booking.resource.accesskey;"/>
diff --git a/Open-ILS/xul/staff_client/chrome/locale/en-US/offline.properties b/Open-ILS/xul/staff_client/chrome/locale/en-US/offline.properties
index eceebc7..753da58 100644
--- a/Open-ILS/xul/staff_client/chrome/locale/en-US/offline.properties
+++ b/Open-ILS/xul/staff_client/chrome/locale/en-US/offline.properties
@@ -251,6 +251,7 @@ menu.cmd_booking_reservation_pickup.tab=Reservation Pickup
 menu.cmd_booking_reservation_return.tab=Reservation Return
 menu.cmd_booking_pull_list.tab=Booking Pull List
 menu.cmd_booking_capture.tab=Booking Capture
+menu.cmd_authority_manage.tab=Manage Authorities
 menu.local_admin.barcode_completion.tab=Barcode Completion
 menu.local_admin.circ_matrix_matchpoint.tab=Circulation Policies
 menu.local_admin.hold_matrix_matchpoint.tab=Hold Policies

commit 382e517182fcbd4c37778bd21dd567f1f0e6df4a
Author: Mike Rylander <mrylander at gmail.com>
Date:   Wed Jun 15 15:45:10 2011 -0400

    Put thesaurus-z handling back in
    
    Signed-off-by: Mike Rylander <mrylander at gmail.com>

diff --git a/Open-ILS/src/sql/Pg/011.schema.authority.sql b/Open-ILS/src/sql/Pg/011.schema.authority.sql
index b2b462e..3e6fda0 100644
--- a/Open-ILS/src/sql/Pg/011.schema.authority.sql
+++ b/Open-ILS/src/sql/Pg/011.schema.authority.sql
@@ -176,6 +176,10 @@ BEGIN
         EXIT WHEN heading_text <> '';
     END LOOP;
 
+    IF thes_code = 'z' THEN
+        thes_code := oils_xpath_string('//*[@tag="040"]/*[@code="f"][1]', marcxml);
+    END IF;
+
     IF heading_text <> '' THEN
         IF no_thesaurus IS TRUE THEN
             heading_text := tag_used || ' ' || public.naco_normalize(heading_text);

commit 41eb0560ca9810d9d1b6c5342c384aa56aef43c5
Author: Mike Rylander <mrylander at gmail.com>
Date:   Fri Jun 3 10:29:52 2011 -0400

    Beginnings of the config interfaces
    
    Signed-off-by: Mike Rylander <mrylander at gmail.com>

diff --git a/Open-ILS/web/templates/default/conify/global/authority/authority_field.tt2 b/Open-ILS/web/templates/default/conify/global/authority/authority_field.tt2
new file mode 100644
index 0000000..2ae8cc8
--- /dev/null
+++ b/Open-ILS/web/templates/default/conify/global/authority/authority_field.tt2
@@ -0,0 +1,40 @@
+[% WRAPPER default/base.tt2 %]
+[% ctx.page_title = 'Configure Control Set Authority Fields' %]
+<div dojoType="dijit.layout.ContentPane" layoutAlign="client">
+    <div dojoType="dijit.layout.ContentPane" layoutAlign="top" class='oils-header-panel'>
+        <div>Thesauri</div>
+        <div>
+            <button dojoType='dijit.form.Button' onClick='acsafGrid.showCreateDialog()'>New Control Set Authority Field</button>
+            <button dojoType='dijit.form.Button' onClick='acsafGrid.deleteSelected()'>Delete Selected</button>
+        </div>
+    </div>
+    <div>
+    <table  jsId="acsafGrid"
+            dojoType="openils.widget.AutoGrid"
+            autoHeight='true'
+            fieldOrder="['control_set','name','tag','sf_list','description','main_entry']"
+            suppressFields="['id']"
+            suppressEditFields="['id']"
+            query="{id: '*'}"
+            fmClass='acsaf'
+            editOnEnter='true'/>
+</div>
+
+<script type="text/javascript">
+    dojo.require("openils.widget.PCrudAutocompleteBox");
+    dojo.require('openils.widget.AutoGrid');
+
+    openils.Util.addOnLoad(
+        function() {
+            acsafGrid.overrideEditWidgets.control_set =
+                new openils.widget.PCrudAutocompleteBox({
+                    "fmclass": "acs", "searchAttr": "name"
+                });
+            acsafGrid.overrideEditWidgets.control_set.shove = {"create": ""};
+            acsafGrid.loadAll({order_by:{acsaf : 'name'}}, {"id": {"!=": null}});
+        }
+    );
+</script>
+[% END %]
+
+
diff --git a/Open-ILS/web/templates/default/conify/global/authority/bib_field.tt2 b/Open-ILS/web/templates/default/conify/global/authority/bib_field.tt2
new file mode 100644
index 0000000..4023d73
--- /dev/null
+++ b/Open-ILS/web/templates/default/conify/global/authority/bib_field.tt2
@@ -0,0 +1,40 @@
+[% WRAPPER default/base.tt2 %]
+[% ctx.page_title = 'Configure Control Set Bibliographic Fields' %]
+<div dojoType="dijit.layout.ContentPane" layoutAlign="client">
+    <div dojoType="dijit.layout.ContentPane" layoutAlign="top" class='oils-header-panel'>
+        <div>Thesauri</div>
+        <div>
+            <button dojoType='dijit.form.Button' onClick='acsbfGrid.showCreateDialog()'>New Control Set Bibliographic Field</button>
+            <button dojoType='dijit.form.Button' onClick='acsbfGrid.deleteSelected()'>Delete Selected</button>
+        </div>
+    </div>
+    <div>
+    <table  jsId="acsbfGrid"
+            dojoType="openils.widget.AutoGrid"
+            autoHeight='true'
+            fieldOrder="['tag','authority_field']"
+            suppressFields="['id']"
+            suppressEditFields="['id']"
+            query="{id: '*'}"
+            fmClass='acsbf'
+            editOnEnter='true'/>
+</div>
+
+<script type="text/javascript">
+    dojo.require("openils.widget.PCrudAutocompleteBox");
+    dojo.require('openils.widget.AutoGrid');
+
+    openils.Util.addOnLoad(
+        function() {
+            acsbfGrid.overrideEditWidgets.authority_field =
+                new openils.widget.PCrudAutocompleteBox({
+                    "fmclass": "acsaf", "searchAttr": "name"
+                });
+            acsbfGrid.overrideEditWidgets.authority_field.shove = {"create": ""};
+            acsbfGrid.loadAll({order_by:{acsbf : 'tag'}}, {"id": {"!=": null}});
+        }
+    );
+</script>
+[% END %]
+
+
diff --git a/Open-ILS/web/templates/default/conify/global/authority/control_set.tt2 b/Open-ILS/web/templates/default/conify/global/authority/control_set.tt2
new file mode 100644
index 0000000..c072d1c
--- /dev/null
+++ b/Open-ILS/web/templates/default/conify/global/authority/control_set.tt2
@@ -0,0 +1,34 @@
+[% WRAPPER default/base.tt2 %]
+[% ctx.page_title = 'Configure Authority Control Sets' %]
+<div dojoType="dijit.layout.ContentPane" layoutAlign="client">
+    <div dojoType="dijit.layout.ContentPane" layoutAlign="top" class='oils-header-panel'>
+        <div>Control Sets</div>
+        <div>
+            <button dojoType='dijit.form.Button' onClick='ctlSetGrid.showCreateDialog()'>New Control Set</button>
+            <button dojoType='dijit.form.Button' onClick='ctlSetGrid.deleteSelected()'>Delete Selected</button>
+        </div>
+    </div>
+    <div>
+    <table  jsId="ctlSetGrid"
+            dojoType="openils.widget.AutoGrid"
+            autoHeight='true'
+            fieldOrder="['name','description']"
+            suppressFields="['id']"
+            suppressEditFields="['id']"
+            query="{id: '*'}"
+            fmClass='acs'
+            editOnEnter='true'/>
+</div>
+
+<script type="text/javascript">
+    dojo.require('openils.widget.AutoGrid');
+    openils.Util.addOnLoad(
+        function() {
+            ctlSetGrid.loadAll({order_by:{acs : 'name'}}, {"id": {"!=": null}});
+        }
+    );
+
+</script>
+[% END %]
+
+
diff --git a/Open-ILS/web/templates/default/conify/global/authority/thesaurus.tt2 b/Open-ILS/web/templates/default/conify/global/authority/thesaurus.tt2
new file mode 100644
index 0000000..8061f92
--- /dev/null
+++ b/Open-ILS/web/templates/default/conify/global/authority/thesaurus.tt2
@@ -0,0 +1,38 @@
+[% WRAPPER default/base.tt2 %]
+[% ctx.page_title = 'Configure Authority Thesaurus' %]
+<div dojoType="dijit.layout.ContentPane" layoutAlign="client">
+    <div dojoType="dijit.layout.ContentPane" layoutAlign="top" class='oils-header-panel'>
+        <div>Thesauri</div>
+        <div>
+            <button dojoType='dijit.form.Button' onClick='thesGrid.showCreateDialog()'>New Thesaurus</button>
+            <button dojoType='dijit.form.Button' onClick='thesGrid.deleteSelected()'>Delete Selected</button>
+        </div>
+    </div>
+    <div>
+    <table  jsId="thesGrid"
+            dojoType="openils.widget.AutoGrid"
+            autoHeight='true'
+            fieldOrder="['code','name','description','control_set]"
+            query="{code:'*'}"
+            fmClass='at'
+            editOnEnter='true'/>
+</div>
+
+<script type="text/javascript">
+    dojo.require("openils.widget.PCrudAutocompleteBox");
+    dojo.require('openils.widget.AutoGrid');
+
+    openils.Util.addOnLoad(
+        function() {
+            thesGrid.overrideEditWidgets.control_set =
+                new openils.widget.PCrudAutocompleteBox({
+                    "fmclass": "acs", "searchAttr": "name"
+                });
+            thesGrid.overrideEditWidgets.control_set.shove = {"create": ""};
+            thesGrid.loadAll({order_by:{at : 'name'}}, {"id": {"!=": null}});
+        }
+    );
+</script>
+[% END %]
+
+

commit fe16ee4245a7df991ce645967a6ffdd798c13f46
Author: Mike Rylander <mrylander at gmail.com>
Date:   Mon May 30 23:49:18 2011 -0400

    Move RULE down so that the named tables actually exist
    
    Signed-off-by: Mike Rylander <mrylander at gmail.com>

diff --git a/Open-ILS/src/sql/Pg/011.schema.authority.sql b/Open-ILS/src/sql/Pg/011.schema.authority.sql
index 35fd6e3..b2b462e 100644
--- a/Open-ILS/src/sql/Pg/011.schema.authority.sql
+++ b/Open-ILS/src/sql/Pg/011.schema.authority.sql
@@ -83,7 +83,6 @@ CREATE INDEX authority_record_deleted_idx ON authority.record_entry(deleted) WHE
 CREATE TRIGGER a_marcxml_is_well_formed BEFORE INSERT OR UPDATE ON authority.record_entry FOR EACH ROW EXECUTE PROCEDURE biblio.check_marcxml_well_formed();
 CREATE TRIGGER b_maintain_901 BEFORE INSERT OR UPDATE ON authority.record_entry FOR EACH ROW EXECUTE PROCEDURE evergreen.maintain_901();
 CREATE TRIGGER c_maintain_control_numbers BEFORE INSERT OR UPDATE ON authority.record_entry FOR EACH ROW EXECUTE PROCEDURE maintain_control_numbers();
-CREATE RULE protect_authority_rec_delete AS ON DELETE TO authority.record_entry DO INSTEAD (UPDATE authority.record_entry SET deleted = TRUE WHERE OLD.id = authority.record_entry.id; DELETE FROM authority.full_rec WHERE record = OLD.id);
 
 CREATE TABLE authority.bib_linking (
     id          BIGSERIAL   PRIMARY KEY,
@@ -139,6 +138,8 @@ CREATE INDEX authority_full_rec_value_tpo_index ON authority.full_rec (value tex
 /* But we still need this (boooo) for paging using >, <, etc */
 CREATE INDEX authority_full_rec_value_index ON authority.full_rec (value);
 
+CREATE RULE protect_authority_rec_delete AS ON DELETE TO authority.record_entry DO INSTEAD (UPDATE authority.record_entry SET deleted = TRUE WHERE OLD.id = authority.record_entry.id; DELETE FROM authority.full_rec WHERE record = OLD.id);
+
 -- Intended to be used in a unique index on authority.record_entry like so:
 -- CREATE UNIQUE INDEX unique_by_heading_and_thesaurus
 --   ON authority.record_entry (authority.normalize_heading(marc))

commit 3f4e0e6834a35d8bfca9b1e14fb51306f049e7f5
Author: Mike Rylander <mrylander at gmail.com>
Date:   Sun May 29 20:30:27 2011 -0400

    Switch authority startwith index back to the pre-checking-deletedness version
    
    Signed-off-by: Mike Rylander <mrylander at gmail.com>

diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/SuperCat.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/SuperCat.pm
index ff3d558..1f0a46a 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/SuperCat.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/SuperCat.pm
@@ -1660,11 +1660,8 @@ sub authority_tag_sf_startwith {
         my $before = $_storage->request(
             "open-ils.cstore.json_query.atomic",
             { select    => { afr => [qw/record value/] },
-              from      => { 'afr', 'are' },
-              where     => {
-                '+afr' => { tag => \@ref_tags, subfield => $subfield, value => { '<' => $value } },
-                '+are' => { deleted => 'f' }
-              },
+              from      => 'afr',
+              where     => { tag => \@ref_tags, subfield => $subfield, value => { '<' => $value } },
               order_by  => { afr => { value => 'desc' } },
               limit     => $ref_limit,
               offset    => $offset,
@@ -1677,11 +1674,8 @@ sub authority_tag_sf_startwith {
         my $after = $_storage->request(
             "open-ils.cstore.json_query.atomic",
             { select    => { afr => [qw/record value/] },
-              from      => { 'afr', 'are' },
-              where     => {
-                '+afr' => { tag => \@ref_tags, subfield => $subfield, value => { '>=' => $value } },
-                '+are' => { deleted => 'f' }
-              },
+              from      => 'afr',
+              where     => { tag => \@ref_tags, subfield => $subfield, value => { '>=' => $value } },
               order_by  => { afr => { value => 'asc' } },
               limit     => $ref_limit,
               offset    => $offset,

commit 71948964b5361b5084f762a518c7cd23a37c3f92
Author: Mike Rylander <mrylander at gmail.com>
Date:   Sat May 28 12:23:24 2011 -0400

    correcting template generation; filter out subfields that we do not use in the authority record
    
    Signed-off-by: Mike Rylander <mrylander at gmail.com>

diff --git a/Open-ILS/src/sql/Pg/011.schema.authority.sql b/Open-ILS/src/sql/Pg/011.schema.authority.sql
index 4493332..35fd6e3 100644
--- a/Open-ILS/src/sql/Pg/011.schema.authority.sql
+++ b/Open-ILS/src/sql/Pg/011.schema.authority.sql
@@ -242,7 +242,7 @@ DECLARE
     auth_id             INT DEFAULT oils_xpath_string('//*[@tag="901"]/*[local-name()="subfield" and @code="c"]', source_xml)::INT;
     replace_data        XML[] DEFAULT '{}'::XML[];
     replace_rules       TEXT[] DEFAULT '{}'::TEXT[];
-    auth_field          TEXT;
+    auth_field          XML[];
 BEGIN
     IF auth_id IS NULL THEN
         RETURN NULL;
@@ -252,8 +252,8 @@ BEGIN
     SELECT COALESCE(control_set,1) INTO cset FROM authority.record_entry WHERE id = auth_id;
 
     FOR main_entry IN SELECT * FROM authority.control_set_authority_field WHERE control_set = cset LOOP
-        auth_field := XPATH('//*[@tag="'||main_entry.tag||'"][1]',source_xml);
-        IF ARRAY_LENGTH(auth_field) > 0 THEN
+        auth_field := XPATH('//*[@tag="'||main_entry.tag||'"][1]',source_xml::XML);
+        IF ARRAY_LENGTH(auth_field,1) > 0 THEN
             FOR bib_field IN SELECT * FROM authority.control_set_bib_field WHERE authority_field = main_entry.id LOOP
                 replace_data := replace_data || XMLELEMENT( name datafield, XMLATTRIBUTES(bib_field.tag AS tag), XPATH('//*[local-name()="subfield"]',auth_field[1])::XML[]);
                 replace_rules := replace_rules || ( bib_field.tag || main_entry.sf_list || E'[0~\\)' || auth_id || '$]' );
diff --git a/Open-ILS/src/sql/Pg/012.schema.vandelay.sql b/Open-ILS/src/sql/Pg/012.schema.vandelay.sql
index 8095e3b..9906804 100644
--- a/Open-ILS/src/sql/Pg/012.schema.vandelay.sql
+++ b/Open-ILS/src/sql/Pg/012.schema.vandelay.sql
@@ -979,7 +979,7 @@ CREATE OR REPLACE FUNCTION vandelay.add_field ( target_xml TEXT, source_xml TEXT
                         if (exists($fields{$f}{match})) {
                             next unless (grep { $_ =~ $fields{$f}{match}{re} } $to_field->subfield($fields{$f}{match}{sf}));
                         }
-                        my @new_sf = map { ($_ => $from_field->subfield($_)) } @{$fields{$f}{sf}};
+                        my @new_sf = map { ($_ => $from_field->subfield($_)) } grep { defined($from_field->subfield($_)) } @{$fields{$f}{sf}};
                         $to_field->add_subfields( @new_sf );
                     }
                 }

commit 3f8c866509587b066109a1051f82df0aef9d2b79
Author: Mike Rylander <mrylander at gmail.com>
Date:   Sat May 28 11:27:04 2011 -0400

    Minor bug fixes (alignment of fm classes, etc); Do not check deletedness, just remove the afr data upon "delete" of an authority; We still need the non-tpo index on afr.value
    
    Signed-off-by: Mike Rylander <mrylander at gmail.com>

diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/SuperCat.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/SuperCat.pm
index e04e5fb..ff3d558 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/SuperCat.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/SuperCat.pm
@@ -892,7 +892,7 @@ sub grab_authority_browse_axes {
     unless(scalar(keys(%authority_browse_axis_cache))) {
         my $axes = new_editor->search_authority_browse_axis([
             { code => { '<>' => undef } },
-            { flesh => 2, flesh_fields => { aba => ['fields'], acsafm => ['bib_fields','sub_entries'] } }
+            { flesh => 2, flesh_fields => { aba => ['fields'], acsaf => ['bib_fields','sub_entries'] } }
         ]);
         $authority_browse_axis_cache{$_->code} = $_ for (@$axes);
     }
@@ -1116,11 +1116,8 @@ sub authority_tag_sf_browse {
         my $before = $_storage->request(
             "open-ils.cstore.json_query.atomic",
             { select    => { afr => [qw/record value/] },
-              from      => { 'are', 'afr' },
-              where     => {
-                '+afr' => { tag => \@ref_tags, subfield => $subfield, value => { '<' => $value } },
-                '+are' => { 'deleted' => 'f' }
-              },
+              from      => 'afr',
+              where     => { tag => \@ref_tags, subfield => $subfield, value => { '<' => $value } },
               order_by  => { afr => { value => 'desc' } },
               limit     => $before_limit,
               offset    => abs($page) * $page_size - $before_offset,
@@ -1133,11 +1130,8 @@ sub authority_tag_sf_browse {
         my $after = $_storage->request(
             "open-ils.cstore.json_query.atomic",
             { select    => { afr => [qw/record value/] },
-              from      => { 'are', 'afr' },
-              where     => {
-                '+afr' => { tag => \@ref_tags, subfield => $subfield, value => { '>=' => $value } },
-                '+are' => { 'deleted' => 'f' }
-              },
+              from      => 'afr',
+              where     => { tag => \@ref_tags, subfield => $subfield, value => { '>=' => $value } },
               order_by  => { afr => { value => 'asc' } },
               limit     => $after_limit,
               offset    => abs($page) * $page_size - $after_offset,
diff --git a/Open-ILS/src/sql/Pg/011.schema.authority.sql b/Open-ILS/src/sql/Pg/011.schema.authority.sql
index a06cce3..4493332 100644
--- a/Open-ILS/src/sql/Pg/011.schema.authority.sql
+++ b/Open-ILS/src/sql/Pg/011.schema.authority.sql
@@ -83,7 +83,7 @@ CREATE INDEX authority_record_deleted_idx ON authority.record_entry(deleted) WHE
 CREATE TRIGGER a_marcxml_is_well_formed BEFORE INSERT OR UPDATE ON authority.record_entry FOR EACH ROW EXECUTE PROCEDURE biblio.check_marcxml_well_formed();
 CREATE TRIGGER b_maintain_901 BEFORE INSERT OR UPDATE ON authority.record_entry FOR EACH ROW EXECUTE PROCEDURE evergreen.maintain_901();
 CREATE TRIGGER c_maintain_control_numbers BEFORE INSERT OR UPDATE ON authority.record_entry FOR EACH ROW EXECUTE PROCEDURE maintain_control_numbers();
-CREATE RULE protect_authority_rec_delete AS ON DELETE TO authority.record_entry DO INSTEAD (UPDATE authority.record_entry SET deleted = TRUE WHERE OLD.id = authority.record_entry.id);
+CREATE RULE protect_authority_rec_delete AS ON DELETE TO authority.record_entry DO INSTEAD (UPDATE authority.record_entry SET deleted = TRUE WHERE OLD.id = authority.record_entry.id; DELETE FROM authority.full_rec WHERE record = OLD.id);
 
 CREATE TABLE authority.bib_linking (
     id          BIGSERIAL   PRIMARY KEY,
@@ -136,6 +136,8 @@ CREATE TRIGGER authority_full_rec_fti_trigger
 CREATE INDEX authority_full_rec_index_vector_idx ON authority.full_rec USING GIST (index_vector);
 /* Enable LIKE to use an index for database clusters with locales other than C or POSIX */
 CREATE INDEX authority_full_rec_value_tpo_index ON authority.full_rec (value text_pattern_ops);
+/* But we still need this (boooo) for paging using >, <, etc */
+CREATE INDEX authority_full_rec_value_index ON authority.full_rec (value);
 
 -- Intended to be used in a unique index on authority.record_entry like so:
 -- CREATE UNIQUE INDEX unique_by_heading_and_thesaurus
diff --git a/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js b/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
index bbae912..9993c72 100644
--- a/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
+++ b/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
@@ -151,17 +151,6 @@ if(!dojo._hasResource["openils.AuthorityControlSet"]) {
 
                 });
 
-                openils.AuthorityControlSet._browse_axis_by_name = {};
-                dojo.forEach( openils.AuthorityControlSet._browse_axis_list, function (ba) {
-                    ba.maps(
-                        dojo.filter(
-                            openils.AuthorityControlSet._browse_field_map_list,
-                            function (m) { m.axis() == ba.code }
-                        )
-                    );
-                    openils.AuthorityControlSet._browse_axis_by_name[ba.code()] = ba;
-                });
-                
                 if (this.controlSetList().length > 0)
                     delete openils.AuthorityControlSet._controlsets['-1'];
 
@@ -203,8 +192,8 @@ if(!dojo._hasResource["openils.AuthorityControlSet"]) {
                     openils.AuthorityControlSet._browse_axis_by_name[bname].maps(),
                     function (m) {
                         if (dojo.filter(
-                                m.field().bib_fields,
-                                function (b) { return b.tag == t }
+                                m.field().bib_fields(),
+                                function (b) { return b.tag() == t }
                             ).length > 0
                         ) blist.push(bname);
                     }
diff --git a/Open-ILS/xul/staff_client/server/cat/marcedit.js b/Open-ILS/xul/staff_client/server/cat/marcedit.js
index 8f32593..3925acb 100644
--- a/Open-ILS/xul/staff_client/server/cat/marcedit.js
+++ b/Open-ILS/xul/staff_client/server/cat/marcedit.js
@@ -1513,7 +1513,7 @@ function getAuthorityContextMenu (target, sf) {
     }
 
     if (sf.toString().replace(/\s*/, '')) {
-        browseAuthority(sf_popup, menu_id, target, sf, 20, page);
+        return browseAuthority(sf_popup, menu_id, target, sf, 20, page);
     }
 
     return true;
@@ -1668,8 +1668,12 @@ function browseAuthority (sf_popup, menu_id, target, sf, limit, page) {
     // Sets will change that
 
     var axis_list = acs.bibFieldBrowseAxes( sf.parent(). at tag.toString() );
+
     // No matching tag means no authorities to search - shortcut
-    if (axis_list.length == 0) return;
+    if (axis_list.length == 0) {
+        target.setAttribute('context', 'clipboard');
+        return false;
+    }
 
     var type = 'authority.' + axis_list[0]; // Just take the first for now
                                             // TODO support multiple axes ... loop?

commit cf5a35ed963692a7e265224f65adadba9ee2ce58
Author: Mike Rylander <mrylander at gmail.com>
Date:   Fri May 27 21:12:18 2011 -0400

    Heading normalization bug; Use CStoreEditor, not Editor; syntax-y bugs
    
    Signed-off-by: Mike Rylander <mrylander at gmail.com>

diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Search/Authority.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Search/Authority.pm
index a93dbb6..3dc14d8 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Search/Authority.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Search/Authority.pm
@@ -6,7 +6,7 @@ use OpenILS::Utils::Fieldmapper;
 use OpenILS::Application::AppUtils;
 use XML::LibXML;
 use XML::LibXSLT;
-use OpenILS::Utils::Editor q/:funcs/;
+use OpenILS::Utils::CStoreEditor q/:funcs/;
 use OpenSRF::Utils::Logger qw/$logger/;
 
 use OpenSRF::Utils::JSON;
diff --git a/Open-ILS/src/sql/Pg/011.schema.authority.sql b/Open-ILS/src/sql/Pg/011.schema.authority.sql
index 4620c75..a06cce3 100644
--- a/Open-ILS/src/sql/Pg/011.schema.authority.sql
+++ b/Open-ILS/src/sql/Pg/011.schema.authority.sql
@@ -166,7 +166,7 @@ BEGIN
         tag_used := acsaf.tag;
         FOR sf IN SELECT * FROM regexp_split_to_table(acsaf.sf_list,'') LOOP
             tmp_text := oils_xpath_string('//*[@tag="'||tag_used||'"]/*[@code="'||sf||'"]', marcxml);
-            IF tmp_text IS NOT NULL THEN
+            IF tmp_text IS NOT NULL AND tmp_text <> '' THEN
                 heading_text := heading_text || E'\u2021' || sf || ' ' || tmp_text;
             END IF;
         END LOOP;
diff --git a/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js b/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
index 9f290f7..bbae912 100644
--- a/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
+++ b/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
@@ -187,13 +187,13 @@ if(!dojo._hasResource["openils.AuthorityControlSet"]) {
         bibFieldByTag: function (x) {
             var me = this;
             return dojo.filter(
-                me.controlSet().bib_fields(),
+                me.controlSet().bib_fields,
                 function (bf) { if (bf.tag() == x) return true }
             )[0];
         },
 
         bibFields: function (x) {
-            return this.controlSet(x).bib_fields();
+            return this.controlSet(x).bib_fields;
         },
 
         bibFieldBrowseAxes : function (t) {
@@ -203,7 +203,7 @@ if(!dojo._hasResource["openils.AuthorityControlSet"]) {
                     openils.AuthorityControlSet._browse_axis_by_name[bname].maps(),
                     function (m) {
                         if (dojo.filter(
-                                m.field().bib_fields(),
+                                m.field().bib_fields,
                                 function (b) { return b.tag == t }
                             ).length > 0
                         ) blist.push(bname);
@@ -241,20 +241,20 @@ if(!dojo._hasResource["openils.AuthorityControlSet"]) {
         },
 
         bibToAuthority : function (field) {
-            var b_field = this.bibFieldByTag(field.tag());
+            var b_field = this.bibFieldByTag(field.tag);
 
             if (b_field) { // construct an marc authority record
                 af = b_field.authority_field();
                 var m = new MARC.Record ({rtype:'AUT'});
-                m.appendField(
+                m.appendFields(
                     new MARC.Field ({
                         tag : af.tag(),
                         ind1: field.ind1,
                         ind2: field.ind2,
-                        subfields: dojo.filter(
+                        subfields: [dojo.filter(
                             field.subfields,
                             function (sf) { return (af.sf_list().indexOf(sf[0]) > -1) }
-                        )
+                        )]
                     })
                 );
 
@@ -274,7 +274,7 @@ if(!dojo._hasResource["openils.AuthorityControlSet"]) {
                 function (acs_id) {
                     var acs = me.controlSet(acs_id);
                     var x = me.bibToAuthority(field);
-                    if (x) auth_list.push({acs_id : m.toXmlString()});
+                    if (x) { var foo = {}; foo[acs_id] = x; auth_list.push(foo); }
                 }
             );
             this.controlSetId(old_acs);
diff --git a/Open-ILS/xul/staff_client/server/cat/marcedit.js b/Open-ILS/xul/staff_client/server/cat/marcedit.js
index f05eba4..8f32593 100644
--- a/Open-ILS/xul/staff_client/server/cat/marcedit.js
+++ b/Open-ILS/xul/staff_client/server/cat/marcedit.js
@@ -1503,7 +1503,7 @@ function getAuthorityContextMenu (target, sf) {
 
     var found_acs = [];
     dojo.forEach( acs.controlSetList(), function (acs_id) {
-        if (ac.controlSet(acs_id).control_map[sf.parent(). at tag]) found_acs.push(acs_id);
+        if (acs.controlSet(acs_id).control_map[sf.parent(). at tag]) found_acs.push(acs_id);
     });
 
     if (!found_acs.length) {
@@ -1578,10 +1578,12 @@ function validateAuthority (button) {
         var row = rows[i];
         var tag = row.firstChild;
 
-        for (var acs_id in acs.controlSetList()) {
+	var done = false;
+        dojo.forEach(acs.controlSetList(), function (acs_id) {
+            if (done) return;
             var control_map = acs.controlSet(acs_id).control_map;
     
-            if (!control_map[tag.value]) continue
+            if (!control_map[tag.value]) return;
             button.setAttribute('label', label + ' - ' + tag.value);
     
             var ind1 = tag.nextSibling;
@@ -1614,8 +1616,8 @@ function validateAuthority (button) {
                 }
             }
 
-            if (matches.length) break;
-        }
+            if (matches.length) done = true;
+        });
     }
 
     button.setAttribute('label', label);

commit 3f47c3f331d2cf45153cf0590eb462c2c36b718a
Author: Mike Rylander <mrylander at gmail.com>
Date:   Fri May 27 16:38:43 2011 -0400

    General bug fixes and formatting cleanup
    
    Signed-off-by: Mike Rylander <mrylander at gmail.com>

diff --git a/Open-ILS/examples/fm_IDL.xml b/Open-ILS/examples/fm_IDL.xml
index fa82ffb..621606e 100644
--- a/Open-ILS/examples/fm_IDL.xml
+++ b/Open-ILS/examples/fm_IDL.xml
@@ -1764,9 +1764,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 			<field reporter:label="Name" name="name" reporter:datatype="text" oils_persist:i18n="true" oils_obj:required="true" />
 			<field reporter:label="Description" name="description" reporter:datatype="text" oils_persist:i18n="true" />
 			<field reporter:label="Controlling Authority Fields" name="authority_fields" reporter:datatype="link" oils_persist:virtual="true"/>
+			<field reporter:label="Thesauri" name="thesauri" reporter:datatype="link" oils_persist:virtual="true"/>
 		</fields>
 		<links>
 			<link field="authority_fields" reltype="has_many" key="control_set" map="" class="acsaf"/>
+			<link field="thesauri" reltype="has_many" key="control_set" map="" class="at"/>
 		</links>
 		<permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
 			<actions>
@@ -1784,6 +1786,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 			<field reporter:label="Main Entry" name="main_entry" reporter:datatype="link"/>
 			<field reporter:label="Control Set" name="control_set" reporter:datatype="link"/>
 			<field reporter:label="Tag" name="tag" reporter:datatype="text" oils_obj:required="true" oils_obj:validate="^.{3}$"/>
+			<field reporter:label="Subfield List" name="sf_list" reporter:datatype="text" />
 			<field reporter:label="Name" name="name" reporter:datatype="text" oils_persist:i18n="true" oils_obj:required="true" />
 			<field reporter:label="Description" name="description" reporter:datatype="text" oils_persist:i18n="true" />
 			<field reporter:label="Subordinate Entries" name="sub_entries" reporter:datatype="link" oils_persist:virtual="true"/>
@@ -1873,7 +1876,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
     <class id="abaafm" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="authority::browse_axis_authority_field_map" oils_persist:tablename="authority.browse_axis_authority_field_map" reporter:label="Authority Browse Axis Field Map">
         <fields oils_persist:primary="id" oils_persist:sequence="authority.browse_axis_authority_field_map_id_seq">
             <field reporter:label="Axis Authority Field Map ID" name="id" reporter:datatype="id"/>
-            <field reporter:label="Authority Field" name="authority_field" oils_obj:required="true" reporter:datatype="link"/>
+            <field reporter:label="Authority Field" name="field" oils_obj:required="true" reporter:datatype="link"/>
             <field reporter:label="Axis" name="axis" reporter:datatype="link" oils_obj:required="true"/>
         </fields>
         <links>
diff --git a/Open-ILS/web/js/dojo/MARC/FixedFields.js b/Open-ILS/web/js/dojo/MARC/FixedFields.js
index ae75271..536d8f8 100644
--- a/Open-ILS/web/js/dojo/MARC/FixedFields.js
+++ b/Open-ILS/web/js/dojo/MARC/FixedFields.js
@@ -44,7 +44,7 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
                 MAP : {start : 15, len : 3, def : ' ' },
                 SCO : {start : 15, len : 3, def : ' ' },
                 REC : {start : 15, len : 3, def : ' ' },
-                COM : {start : 15, len : 3, def : ' ' },
+                COM : {start : 15, len : 3, def : ' ' }
             }
         },
         Lang : {
@@ -56,7 +56,7 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
                 MAP : {start : 35, len : 3, def : ' ' },
                 SCO : {start : 35, len : 3, def : ' ' },
                 REC : {start : 35, len : 3, def : ' ' },
-                COM : {start : 35, len : 3, def : ' ' },
+                COM : {start : 35, len : 3, def : ' ' }
             }
         },
         MRec : {
@@ -68,7 +68,7 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
                 MAP : {start : 38, len : 1, def : ' ' },
                 SCO : {start : 38, len : 1, def : ' ' },
                 REC : {start : 38, len : 1, def : ' ' },
-                COM : {start : 38, len : 1, def : ' ' },
+                COM : {start : 38, len : 1, def : ' ' }
             }
         },
         DtSt : {
@@ -80,7 +80,7 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
                 MAP : {start : 6, len : 1, def : ' ' },
                 SCO : {start : 6, len : 1, def : ' ' },
                 REC : {start : 6, len : 1, def : ' ' },
-                COM : {start : 6, len : 1, def : ' ' },
+                COM : {start : 6, len : 1, def : ' ' }
             }
         },
         Type : {
@@ -107,7 +107,7 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
                 MAP : {start : 8, len : 1, def : ' ' },
                 SCO : {start : 8, len : 1, def : ' ' },
                 REC : {start : 8, len : 1, def : ' ' },
-                COM : {start : 8, len : 1, def : ' ' },
+                COM : {start : 8, len : 1, def : ' ' }
             }
         },
         BLvl : {
@@ -119,7 +119,7 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
                 MAP : {start : 7, len : 1, def : 'm' },
                 SCO : {start : 7, len : 1, def : 'm' },
                 REC : {start : 7, len : 1, def : 'm' },
-                COM : {start : 7, len : 1, def : 'm' },
+                COM : {start : 7, len : 1, def : 'm' }
             }
         },
         Desc : {
@@ -131,7 +131,7 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
                 MAP : {start : 18, len : 1, def : ' ' },
                 SCO : {start : 18, len : 1, def : ' ' },
                 REC : {start : 18, len : 1, def : ' ' },
-                COM : {start : 18, len : 1, def : ' ' },
+                COM : {start : 18, len : 1, def : ' ' }
             }
         },
         Item : {
@@ -155,20 +155,30 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
         },
         TMat : {
             _8 : {
-                VIS : {start : 33, len : 1, def : ' ' },
+                VIS : {start : 33, len : 1, def : ' ' }
             },
             _6 : {
-                VIS : {start : 16, len : 1, def : ' ' },
+                VIS : {start : 16, len : 1, def : ' ' }
+            }
+        },
+        TrAr : {
+            _8 : {
+                SCO : {start : 33, len : 1, def : ' ' },
+                REC : {start : 33, len : 1, def : 'n' }
+            },
+            _6 : {
+                SCO : {start : 16, len : 1, def : ' ' },
+                REC : {start : 16, len : 1, def : 'n' }
             }
         },
         Indx : {
             _8 : {
                 BKS : {start : 31, len : 1, def : '0' },
-                MAP : {start : 31, len : 1, def : '0' },
+                MAP : {start : 31, len : 1, def : '0' }
             },
             _6 : {
                 BKS : {start : 14, len : 1, def : '0' },
-                MAP : {start : 14, len : 1, def : '0' },
+                MAP : {start : 14, len : 1, def : '0' }
             }
         },
         Date1 : {
@@ -180,8 +190,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
                 MAP : {start : 7, len : 4, def : ' ' },
                 SCO : {start : 7, len : 4, def : ' ' },
                 REC : {start : 7, len : 4, def : ' ' },
-                COM : {start : 7, len : 4, def : ' ' },
-            },
+                COM : {start : 7, len : 4, def : ' ' }
+            }
         },
         Date2 : {
             _8 : {
@@ -192,49 +202,49 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
                 MAP : {start : 11, len : 4, def : ' ' },
                 SCO : {start : 11, len : 4, def : ' ' },
                 REC : {start : 11, len : 4, def : ' ' },
-                COM : {start : 11, len : 4, def : ' ' },
-            },
+                COM : {start : 11, len : 4, def : ' ' }
+            }
         },
         LitF : {
             _8 : {
-                BKS : {start : 33, len : 1, def : '0' },
+                BKS : {start : 33, len : 1, def : '0' }
             },
             _6 : {
-                BKS : {start : 16, len : 1, def : '0' },
+                BKS : {start : 16, len : 1, def : '0' }
             }
         },
         Biog : {
             _8 : {
-                BKS : {start : 34, len : 1, def : ' ' },
+                BKS : {start : 34, len : 1, def : ' ' }
             },
             _6 : {
-                BKS : {start : 17, len : 1, def : ' ' },
+                BKS : {start : 17, len : 1, def : ' ' }
             }
         },
         Ills : {
             _8 : {
-                BKS : {start : 18, len : 4, def : ' ' },
+                BKS : {start : 18, len : 4, def : ' ' }
             },
             _6 : {
-                BKS : {start : 1, len : 4, def : ' ' },
+                BKS : {start : 1, len : 4, def : ' ' }
             }
         },
         Fest : {
             _8 : {
-                BKS : {start : 30, len : 1, def : '0' },
+                BKS : {start : 30, len : 1, def : '0' }
             },
             _6 : {
-                BKS : {start : 13, len : 1, def : '0' },
+                BKS : {start : 13, len : 1, def : '0' }
             }
         },
         Conf : {
             _8 : {
                 BKS : {start : 24, len : 4, def : ' ' },
-                SER : {start : 25, len : 3, def : ' ' },
+                SER : {start : 25, len : 3, def : ' ' }
             },
             _6 : {
                 BKS : {start : 7, len : 4, def : ' ' },
-                SER : {start : 8, len : 3, def : ' ' },
+                SER : {start : 8, len : 3, def : ' ' }
             }
         },
         GPub : {
@@ -243,16 +253,28 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
                 SER : {start : 28, len : 1, def : ' ' },
                 VIS : {start : 28, len : 1, def : ' ' },
                 MAP : {start : 28, len : 1, def : ' ' },
-                COM : {start : 28, len : 1, def : ' ' },
+                COM : {start : 28, len : 1, def : ' ' }
             },
             _6 : {
                 BKS : {start : 11, len : 1, def : ' ' },
                 SER : {start : 11, len : 1, def : ' ' },
                 VIS : {start : 11, len : 1, def : ' ' },
                 MAP : {start : 11, len : 1, def : ' ' },
-                COM : {start : 11, len : 1, def : ' ' },
+                COM : {start : 11, len : 1, def : ' ' }
             }
         },
+        Srce : {
+            _8 : {
+                BKS : {start : 39, len : 1, def : 'd' },
+                SER : {start : 39, len : 1, def : 'd' },
+                VIS : {start : 39, len : 1, def : 'd' },
+                SCO : {start : 39, len : 1, def : 'd' },
+                REC : {start : 39, len : 1, def : 'd' },
+                COM : {start : 39, len : 1, def : 'd' },
+                MFHD : {start : 39, len : 1, def : 'd' },
+                "AUT" : {"start" : 39, "len" : 1, "def" : 'd' }
+            }
+	},
         Audn : {
             _8 : {
                 BKS : {start : 22, len : 1, def : ' ' },
@@ -260,7 +282,7 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
                 VIS : {start : 22, len : 1, def : ' ' },
                 SCO : {start : 22, len : 1, def : ' ' },
                 REC : {start : 22, len : 1, def : ' ' },
-                COM : {start : 22, len : 1, def : ' ' },
+                COM : {start : 22, len : 1, def : ' ' }
             },
             _6 : {
                 BKS : {start : 5, len : 1, def : ' ' },
@@ -268,7 +290,7 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
                 VIS : {start : 5, len : 1, def : ' ' },
                 SCO : {start : 5, len : 1, def : ' ' },
                 REC : {start : 5, len : 1, def : ' ' },
-                COM : {start : 5, len : 1, def : ' ' },
+                COM : {start : 5, len : 1, def : ' ' }
             }
         },
         Form : {
@@ -279,7 +301,7 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
                 MIX : {start : 23, len : 1, def : ' ' },
                 MAP : {start : 29, len : 1, def : ' ' },
                 SCO : {start : 23, len : 1, def : ' ' },
-                REC : {start : 23, len : 1, def : ' ' },
+                REC : {start : 23, len : 1, def : ' ' }
             },
             _6 : {
                 BKS : {start : 6, len : 1, def : ' ' },
@@ -288,23 +310,23 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
                 MIX : {start : 6, len : 1, def : ' ' },
                 MAP : {start : 12, len : 1, def : ' ' },
                 SCO : {start : 6, len : 1, def : ' ' },
-                REC : {start : 6, len : 1, def : ' ' },
+                REC : {start : 6, len : 1, def : ' ' }
             }
         },
         'S/L' : {
             _8 : {
-                SER : {start : 34, len : 1, def : '0' },
+                SER : {start : 34, len : 1, def : '0' }
             },
             _6 : {
-                SER : {start : 17, len : 1, def : '0' },
+                SER : {start : 17, len : 1, def : '0' }
             }
         },
         'Alph' : {
             _8 : {
-                SER : {start : 33, len : 1, def : ' ' },
+                SER : {start : 33, len : 1, def : ' ' }
             },
             _6 : {
-                SER : {start : 16, len : 1, def : ' ' },
+                SER : {start : 16, len : 1, def : ' ' }
             }
         },
         "GeoDiv" : {
@@ -421,8 +443,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						o : "Optical disk",
     						r : "Remote",
     						u : "Unspecified",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			d : {	start : 3,
     				len   : 1,
@@ -434,8 +456,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						m : "Mixed",
     						n : "Not applicable",
     						u : "Unknown",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			e : {	start : 4,
     				len   : 1,
@@ -449,32 +471,32 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						o : "5 1/4 in.",
     						u : "Unknown",
     						v : "8 in.",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			f : {	start : 5,
     				len   : 1,
     				label : "Sound",
     				values: {	' ' : "No sound (Silent)",
     						a   : "Sound",
-    						u   : "Unknown",
-    				},
+    						u   : "Unknown"
+    				}
     			},
     			g : {	start : 6,
     				len   : 3,
     				label : "Image bit depth",
     				values: {	mmm   : "Multiple",
     						nnn   : "Not applicable",
-    						'---' : "Unknown",
-    				},
+    						'---' : "Unknown"
+    				}
     			},
     			h : {	start : 9,
     				len   : 1,
     				label : "File formats",
     				values: {	a : "One file format",
     						m : "Multiple file formats",
-    						u : "Unknown",
-    				},
+    						u : "Unknown"
+    				}
     			},
     			i : {	start : 10,
     				len   : 1,
@@ -482,8 +504,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     				values: {	a : "Absent",
     						n : "Not applicable",
     						p : "Present",
-    						u : "Unknown",
-    				},
+    						u : "Unknown"
+    				}
     			},
     			j : {	start : 11,
     				len   : 1,
@@ -494,8 +516,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						d : "File reproduced from an intermediate (not microform)",
     						m : "Mixed",
     						n : "Not applicable",
-    						u : "Unknown",
-    				},
+    						u : "Unknown"
+    				}
     			},
     			k : {	start : 12,
     				len   : 1,
@@ -504,8 +526,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						b : "Lossless",
     						d : "Lossy",
     						m : "Mixed",
-    						u : "Unknown",
-    				},
+    						u : "Unknown"
+    				}
     			},
     			l : {	start : 13,
     				len   : 1,
@@ -514,10 +536,10 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						n : "Not applicable",
     						p : "Preservation",
     						r : "Replacement",
-    						u : "Unknown",
-    				},
-    			},
-    		},
+    						u : "Unknown"
+    				}
+    			}
+    		}
     	},
     	d : {
     		label     : "Globe",
@@ -530,15 +552,15 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						c : "Terrestrial globe",
     						e : "Earth moon globe",
     						u : "Unspecified",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			d : {	start : 3,
     				len   : 1,
     				label : "Color",
     				values: {	a : "One color",
-    						c : "Multicolored",
-    				},
+    						c : "Multicolored"
+    				}
     			},
     			e : {	start : 4,
     				len   : 1,
@@ -552,8 +574,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						g : "Textile",
     						p : "Plaster",
     						u : "Unknown",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			f : {	start : 5,
     				len   : 1,
@@ -561,10 +583,10 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     				values: {	f : "Facsimile",
     						n : "Not applicable",
     						u : "Unknown",
-    						z : "Other",
-    				},
-    			},
-    		},
+    						z : "Other"
+    				}
+    			}
+    		}
     	},
     	a : {
     		label     : "Map",
@@ -581,15 +603,15 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						s : "Section",
     						u : "Unspecified",
     						y : "View",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			d : {	start : 3,
     				len   : 1,
     				label : "Color",
     				values: {	a : "One color",
-    						c : "Multicolored",
-    				},
+    						c : "Multicolored"
+    				}
     			},
     			e : {	start : 4,
     				len   : 1,
@@ -608,8 +630,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						t : "Non-flexible base photographic medium, negative",
     						u : "Unknown",
     						y : "Other photographic medium",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			f : {	start : 5,
     				len   : 1,
@@ -617,8 +639,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     				values: {	f : "Facsimile",
     						n : "Not applicable",
     						u : "Unknown",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			g : {	start : 6,
     				len   : 1,
@@ -628,8 +650,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						c : "Pre-production",
     						d : "Film",
     						u : "Unknown",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			h : {	start : 7,
     				len   : 1,
@@ -637,10 +659,10 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     				values: {	a : "Positive",
     						b : "Negative",
     						m : "Mixed",
-    						n : "Not applicable",
-    				},
-    			},
-    		},
+    						n : "Not applicable"
+    				}
+    			}
+    		}
     	},
     	h : {
     		label     : "Microform",
@@ -656,8 +678,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						f : "Microfiche cassette",
     						g : "Microopaque",
     						u : "Unspecified",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			d : {	start : 3,
     				len   : 1,
@@ -665,8 +687,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     				values: {	a : "Positive",
     						b : "Negative",
     						m : "Mixed",
-    						u : "Unknown",
-    				},
+    						u : "Unknown"
+    				}
     			},
     			e : {	start : 4,
     				len   : 1,
@@ -681,8 +703,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						o : "6 x 9 in. (16 x 23 cm.)",
     						p : "3 1/4 x 7 3/8 in. (9 x 19 cm.)",
     						u : "Unknown",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			f : {	start : 5,
     				len   : 4,
@@ -693,8 +715,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						d : "Very high (61-90x)",
     						e : "Ultra (90x-)",
     						u : "Unknown",
-    						v : "Reduction ratio varies",
-    				},
+    						v : "Reduction ratio varies"
+    				}
     			},
     			g : {	start : 9,
     				len   : 1,
@@ -703,8 +725,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						c : "Multicolored",
     						m : "Mixed",
     						u : "Unknown",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			h : {	start : 10,
     				len   : 1,
@@ -715,8 +737,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						m : "Mixed",
     						n : "Not applicable",
     						u : "Unknown",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			i : {	start : 11,
     				len   : 1,
@@ -725,8 +747,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						b : "Printing master",
     						c : "Service copy",
     						m : "Mixed generation",
-    						u : "Unknown",
-    				},
+    						u : "Unknown"
+    				}
     			},
     			j : {	start : 12,
     				len   : 1,
@@ -741,10 +763,10 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						r : "Safety base, mixed",
     						t : "Safety base, triacetate",
     						u : "Unknown",
-    						z : "Other",
-    				},
-    			},
-    		},
+    						z : "Other"
+    				}
+    			}
+    		}
     	},
     	m : {
     		label     : "Motion Picture",
@@ -756,8 +778,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						f : "Film cassette",
     						r : "Film reel",
     						u : "Unspecified",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			d : {	start : 3,
     				len   : 1,
@@ -767,8 +789,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						h : "Hand-colored",
     						m : "Mixed",
     						u : "Unknown",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			e : {	start : 4,
     				len   : 1,
@@ -780,16 +802,16 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						e : "Other-wide screen format",
     						f : "Standard. silent aperture, full frame",
     						u : "Unknown",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			f : {	start : 5,
     				len   : 1,
     				label : "Sound on medium or separate",
     				values: {	a : "Sound on medium",
     						b : "Sound separate from medium",
-    						u : "Unknown",
-    				},
+    						u : "Unknown"
+    				}
     			},
     			g : {	start : 6,
     				len   : 1,
@@ -804,8 +826,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						h : "Videotape",
     						i : "Videodisc",
     						u : "Unknown",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			h : {	start : 7,
     				len   : 1,
@@ -818,8 +840,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						f : "35 mm.",
     						g : "70 mm.",
     						u : "Unknown",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			i : {	start : 8,
     				len   : 1,
@@ -830,8 +852,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						q : "Multichannel, surround or quadraphonic",
     						s : "Stereophonic",
     						u : "Unknown",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			j : {	start : 9,
     				len   : 1,
@@ -844,10 +866,10 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						f : "Title bands/inter-title rolls",
     						g : "Production rolls",
     						n : "Not applicable",
-    						z : "Other",
-    				},
-    			},
-    		},
+    						z : "Other"
+    				}
+    			}
+    		}
     	},
     	k : {
     		label     : "Non-projected Graphic",
@@ -867,8 +889,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						n : "Chart",
     						o : "Flash/activity card",
     						u : "Unspecified",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			d : {	start : 3,
     				len   : 1,
@@ -879,8 +901,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						h : "Hand-colored",
     						m : "Mixed",
     						u : "Unknown",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			e : {	start : 4,
     				len   : 1,
@@ -901,8 +923,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						s : "Stone",
     						t : "Wood",
     						u : "Unknown",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			f : {	start : 5,
     				len   : 1,
@@ -923,10 +945,10 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						s : "Stone",
     						t : "Wood",
     						u : "Unknown",
-    						z : "Other",
-    				},
-    			},
-    		},
+    						z : "Other"
+    				}
+    			}
+    		}
     	},
     	g : {
     		label     : "Projected Graphic",
@@ -940,8 +962,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						o : "Filmstrip roll",
     						s : "Slide",
     						t : "Transparency",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			d : {	start : 3,
     				len   : 1,
@@ -952,8 +974,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						m : "Mixed",
     						n : "Not applicable",
     						u : "Unknown",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			e : {	start : 4,
     				len   : 1,
@@ -965,16 +987,16 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						m : "Mixed collection",
     						o : "Paper",
     						u : "Unknown",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			f : {	start : 5,
     				len   : 1,
     				label : "Sound on medium or separate",
     				values: {	a : "Sound on medium",
     						b : "Sound separate from medium",
-    						u : "Unknown",
-    				},
+    						u : "Unknown"
+    				}
     			},
     			g : {	start : 6,
     				len   : 1,
@@ -989,8 +1011,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						h : "Videotape",
     						i : "Videodisc",
     						u : "Unknown",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			h : {	start : 7,
     				len   : 1,
@@ -1011,8 +1033,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						x : "10 x 10 in. (26 x 26 cm.)",
     						y : "7 x 7 in. (18 x 18 cm.)",
     						u : "Unknown",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			i : {	start : 8,
     				len   : 1,
@@ -1025,10 +1047,10 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						k : "Synthetics and glass",
     						m : "Mixed collection",
     						u : "Unknown",
-    						z : "Other",
-    				},
-    			},
-    		},
+    						z : "Other"
+    				}
+    			}
+    		}
     	},
     	r : {
     		label     : "Remote-sensing Image",
@@ -1036,7 +1058,7 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     			b : {	start : 1,
     				len   : 1,
     				label : "SMD",
-    				values: { u : "Unspecified" },
+    				values: { u : "Unspecified" }
     			},
     			d : {	start : 3,
     				len   : 1,
@@ -1046,8 +1068,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						c : "Spaceborne",
     						n : "Not applicable",
     						u : "Unknown",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			e : {	start : 4,
     				len   : 1,
@@ -1056,8 +1078,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						b : "High oblique",
     						c : "Vertical",
     						n : "Not applicable",
-    						u : "Unknown",
-    				},
+    						u : "Unknown"
+    				}
     			},
     			f : {	start : 5,
     				len   : 1,
@@ -1073,8 +1095,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						8 : "80-89%",
     						9 : "90-100%",
     						n : "Not applicable",
-    						u : "Unknown",
-    				},
+    						u : "Unknown"
+    				}
     			},
     			g : {	start : 6,
     				len   : 1,
@@ -1090,8 +1112,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						i : "Submersible remote-sensing device",
     						n : "Not applicable",
     						u : "Unknown",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			h : {	start : 7,
     				len   : 1,
@@ -1102,8 +1124,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						m : "Mixed uses",
     						n : "Not applicable",
     						u : "Unknown",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			i : {	start : 8,
     				len   : 1,
@@ -1111,8 +1133,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     				values: {	a : "Active",
     						b : "Passive",
     						u : "Unknown",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			j : {	start : 9,
     				len   : 2,
@@ -1157,10 +1179,10 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						rc : "Bouger",
     						rd : "Isostatic",
     						sa : "Magnetic field",
-    						ta : "Radiometric surveys",
-    				},
-    			},
-    		},
+    						ta : "Radiometric surveys"
+    				}
+    			}
+    		}
     	},
     	s : {
     		label     : "Sound Recording",
@@ -1177,8 +1199,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						t : "Sound-tape reel",
     						u : "Unspecified",
     						w : "Wire recording",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			d : {	start : 3,
     				len   : 1,
@@ -1198,8 +1220,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						p : "15 ips",
     						r : "30 ips",
     						u : "Unknown",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			e : {	start : 4,
     				len   : 1,
@@ -1208,8 +1230,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						q : "Quadraphonic",
     						s : "Stereophonic",
     						u : "Unknown",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			f : {	start : 5,
     				len   : 1,
@@ -1218,8 +1240,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						n : "Not applicable",
     						s : "Coarse/standard",
     						u : "Unknown",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			g : {	start : 6,
     				len   : 1,
@@ -1236,8 +1258,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						s : "2 3/4 x 4 in.",
     						n : "Not applicable",
     						u : "Unknown",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			h : {	start : 7,
     				len   : 1,
@@ -1248,8 +1270,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						o : "1/2 in.",
     						p : "1 in.",
     						u : "Unknown",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			i : {	start : 8,
     				len   : 1,
@@ -1262,8 +1284,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						f : "16 track",
     						n : "Not applicable",
     						u : "Unknown",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			m : {	start : 12,
     				len   : 1,
@@ -1278,8 +1300,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						h : "CX encoded",
     						n : "Not applicable",
     						u : "Unknown",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			n : {	start : 13,
     				len   : 1,
@@ -1289,10 +1311,10 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						d : "Digital storage",
     						e : "Analog electrical storage",
     						u : "Unknown",
-    						z : "Other",
-    				},
-    			},
-    		},
+    						z : "Other"
+    				}
+    			}
+    		}
     	},
     	f : {
     		label     : "Tactile Material",
@@ -1305,8 +1327,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						c : "Combination",
     						d : "Tactile, with no writing system",
     						u : "Unspecified",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			d : {	start : 3,
     				len   : 2,
@@ -1319,8 +1341,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						m : "Multiple braille types",
     						n : "Not applicable",
     						u : "Unknown",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			e : {	start : 4,
     				len   : 1,
@@ -1330,8 +1352,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						m : "Combination",
     						n : "Not applicable",
     						u : "Unknown",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			f : {	start : 6,
     				len   : 3,
@@ -1350,8 +1372,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						l : "Vertical score",
     						n : "Not applicable",
     						u : "Unknown",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			g : {	start : 9,
     				len   : 1,
@@ -1360,10 +1382,10 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						b : "Jumbo or enlarged braille",
     						n : "Not applicable",
     						u : "Unknown",
-    						z : "Other",
-    				},
-    			},
-    		},
+    						z : "Other"
+    				}
+    			}
+    		}
     	},
     	v : {
     		label     : "Videorecording",
@@ -1376,8 +1398,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						f : "Videocassette",
     						r : "Videoreel",
     						u : "Unspecified",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			d : {	start : 3,
     				len   : 1,
@@ -1387,8 +1409,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						m : "Mixed",
     						n : "Not applicable",
     						u : "Unknown",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			e : {	start : 4,
     				len   : 1,
@@ -1410,16 +1432,16 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						q : "Hi-8 mm.",
     						u : "Unknown",
     						v : "DVD",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			f : {	start : 5,
     				len   : 1,
     				label : "Sound on medium or separate",
     				values: {	a : "Sound on medium",
     						b : "Sound separate from medium",
-    						u : "Unknown",
-    				},
+    						u : "Unknown"
+    				}
     			},
     			g : {	start : 6,
     				len   : 1,
@@ -1434,8 +1456,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						h : "Videotape",
     						i : "Videodisc",
     						u : "Unknown",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			h : {	start : 7,
     				len   : 1,
@@ -1447,8 +1469,8 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						q : "2 in.",
     						r : "3/4 in.",
     						u : "Unknown",
-    						z : "Other",
-    				},
+    						z : "Other"
+    				}
     			},
     			i : {	start : 8,
     				len   : 1,
@@ -1459,11 +1481,11 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     						q : "Multichannel, surround or quadraphonic",
     						s : "Stereophonic",
     						u : "Unknown",
-    						z : "Other",
-    				},
-    			},
-    		},
-    	},
+    						z : "Other"
+    				}
+    			}
+    		}
+    	}
     };
     
     MARC.Record.prototype.recordType = function () {
@@ -1482,7 +1504,7 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     MARC.Record.prototype.videorecordingFormatName = function () {
     	var _7 = this.field('007').data;
     
-    	if (_7.match(/^v/)) {
+    	if (_7 && _7.match(/^v/)) {
     		var _v_e = _7.substr(
     			MARC.Record._physical_characteristics.v.subfields.e.start,
     			MARC.Record._physical_characteristics.v.subfields.e.len
@@ -1497,7 +1519,7 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     MARC.Record.prototype.videorecordingFormatCode = function () {
     	var _7 = this.field('007').data;
     
-    	if (_7.match(/^v/)) {
+    	if (_7 && _7.match(/^v/)) {
     		return _7.substr(
     			MARC.Record._physical_characteristics.v.subfields.e.start,
     			MARC.Record._physical_characteristics.v.subfields.e.len
@@ -1508,6 +1530,7 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     }
     
     MARC.Record.prototype.extractFixedField = function (field, dflt) {
+	if (!MARC.Record._ff_pos[field]) return null;
     
     	var _l = this.leader;
     	var _8 = this.field('008').data;
@@ -1517,14 +1540,14 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     
     	var val;
     
-    	if (MARC.Record._ff_pos[field].ldr) {
+    	if (MARC.Record._ff_pos[field].ldr && _l) {
     		if (MARC.Record._ff_pos[field].ldr[rtype]) {
     			val = _l.substr(
     				MARC.Record._ff_pos[field].ldr[rtype].start,
     				MARC.Record._ff_pos[field].ldr[rtype].len
     			);
     		}
-    	} else if (MARC.Record._ff_pos[field]._8) {
+    	} else if (MARC.Record._ff_pos[field]._8 && _8) {
     		if (MARC.Record._ff_pos[field]._8[rtype]) {
     			val = _8.substr(
     				MARC.Record._ff_pos[field]._8[rtype].start,
@@ -1533,7 +1556,7 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     		}
     	}
     
-    	if (!val && MARC.Record._ff_pos[field]._6) {
+    	if (!val && MARC.Record._ff_pos[field]._6 && _6) {
     		if (MARC.Record._ff_pos[field]._6[rtype]) {
     			val = _6.substr(
     				MARC.Record._ff_pos[field]._6[rtype].start,
@@ -1546,23 +1569,23 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
             val = '';
             var d;
             var p;
-            if (MARC.Record._ff_pos[name].ldr && MARC.Record._ff_pos[name].ldr[rtype]) {
-                d = MARC.Record._ff_pos[name].ldr[rtype].def;
+            if (MARC.Record._ff_pos[field].ldr && MARC.Record._ff_pos[field].ldr[rtype]) {
+                d = MARC.Record._ff_pos[field].ldr[rtype].def;
                 p = 'ldr';
             }
 
-            if (MARC.Record._ff_pos[name]._8 && MARC.Record._ff_pos[name]._8[rtype]) {
-                d = MARC.Record._ff_pos[name]._8[rtype].def;
+            if (MARC.Record._ff_pos[field]._8 && MARC.Record._ff_pos[field]._8[rtype]) {
+                d = MARC.Record._ff_pos[field]._8[rtype].def;
                 p = '_8';
             }
 
-            if (!val && MARC.Record._ff_pos[name]._6 && MARC.Record._ff_pos[name]._6[rtype]) {
-                d = MARC.Record._ff_pos[name]._6[rtype].def;
+            if (!val && MARC.Record._ff_pos[field]._6 && MARC.Record._ff_pos[field]._6[rtype]) {
+                d = MARC.Record._ff_pos[field]._6[rtype].def;
                 p = '_6';
             }
 
             if (p) {
-                for (var j = 0; j < MARC.Record._ff_pos[name][p][rtype].len; j++) {
+                for (var j = 0; j < MARC.Record._ff_pos[field][p][rtype].len; j++) {
                     val += d;
                 }
             } else {
@@ -1574,6 +1597,7 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     }
 
     MARC.Record.prototype.setFixedField = function (field, value) {
+	if (!MARC.Record._ff_pos[field]) return null;
     
     	var _l = this.leader;
     	var _8 = this.field('008').data;
@@ -1583,7 +1607,7 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     
     	var val;
     
-    	if (MARC.Record._ff_pos[field].ldr) {
+    	if (MARC.Record._ff_pos[field].ldr && _l) {
     		if (MARC.Record._ff_pos[field].ldr[rtype]) { // It's in the leader
                 val = value.substr(0, MARC.Record._ff_pos[field].ldr[rtype].len);
                 this.leader =
@@ -1594,7 +1618,7 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
                         + MARC.Record._ff_pos[field].ldr[rtype].len
                     );
     		}
-    	} else if (MARC.Record._ff_pos[field]._8) {
+    	} else if (MARC.Record._ff_pos[field]._8 && _8) {
     		if (MARC.Record._ff_pos[field]._8[rtype]) { // Nope, it's in the 008
                 val = value.substr(0, MARC.Record._ff_pos[field]._8[rtype].len);
                 this.field('008').update(
@@ -1608,7 +1632,7 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     		}
     	}
     
-    	if (!val && MARC.Record._ff_pos[field]._6) {
+    	if (!val && MARC.Record._ff_pos[field]._6 && _6) {
     		if (MARC.Record._ff_pos[field]._6[rtype]) { // ok, maybe the 006?
                 val = value.substr(0, MARC.Record._ff_pos[field]._6[rtype].len);
                 this.field('006').update(
diff --git a/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js b/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
index 46ad394..9f290f7 100644
--- a/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
+++ b/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
@@ -34,7 +34,7 @@ if(!dojo._hasResource["openils.AuthorityControlSet"]) {
 
                 // TODO -- push the raw tree into the oils cache for later reuse
 
-                var pcrud = new openils.PermaCrud();
+                var pcrud = new openils.PermaCrud({authtoken : ses()});
 
                 // fetch everything up front...
                 openils.AuthorityControlSet._control_set_list = pcrud.retrieveAll('acs');
@@ -114,11 +114,11 @@ if(!dojo._hasResource["openils.AuthorityControlSet"]) {
                         );
 
                         dojo.forEach( acsbf_list, function (csbf) {
-                            // link the main entry if we're subordinate
+                            // link the authority field to the bib field
                             if (csbf.authority_field()) {
                                 csbf.authority_field(
                                     dojo.filter(acsaf_list, function (x) {
-                                        return x.a() == csbf.authority_field();
+                                        return x.id() == csbf.authority_field();
                                     })[0]
                                 );
                             }
@@ -131,7 +131,7 @@ if(!dojo._hasResource["openils.AuthorityControlSet"]) {
                                 dojo.forEach( // loop over the maps
                                     dojo.filter( // filtering to just this field's mapps
                                         ba.maps(),
-                                        function (m) { return m.field() == csfa.id() }
+                                        function (m) { return m.field() == csaf.id() }
                                     ),
                                     function (fm) { fm.field( csaf ); csaf.axis_maps().push( fm ) } // and set the field
                                 )
@@ -154,7 +154,7 @@ if(!dojo._hasResource["openils.AuthorityControlSet"]) {
                 openils.AuthorityControlSet._browse_axis_by_name = {};
                 dojo.forEach( openils.AuthorityControlSet._browse_axis_list, function (ba) {
                     ba.maps(
-                        dojo.fitler(
+                        dojo.filter(
                             openils.AuthorityControlSet._browse_field_map_list,
                             function (m) { m.axis() == ba.code }
                         )

commit 509eb848ebf06e4dc45b3b03f7cea8929b6faab1
Author: berick <berick at esilibrary.com>
Date:   Thu May 26 15:34:07 2011 -0400

    Repaired syntax errors in SuperCat.pm
    
    Signed-off-by: berick <berick at esilibrary.com>

diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/SuperCat.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/SuperCat.pm
index f733760..e04e5fb 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/SuperCat.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/SuperCat.pm
@@ -922,7 +922,7 @@ sub axis_authority_browse {
     for my $f (@{$authority_browse_axis_cache{$axis}->fields}) {
         push @tags, $f->tag;
         if ($refs) {
-            push @tags, $_->tag for @{$f-sub_entries};
+            push @tags, $_->tag for @{$f->sub_entries};
         }
     }
 
@@ -1477,7 +1477,7 @@ sub axis_authority_startwith {
     for my $f (@{$authority_browse_axis_cache{$axis}->fields}) {
         push @tags, $f->tag;
         if ($refs) {
-            push @tags, $_->tag for @{$f-sub_entries};
+            push @tags, $_->tag for @{$f->sub_entries};
         }
     }
 

commit 1cdc294001f2d05f3701a04eed7c98957957c763
Author: berick <berick at esilibrary.com>
Date:   Thu May 26 15:13:48 2011 -0400

    Repaired syntax errors and thinkos
    
     * Syntax in AuthorityControlSet.js
     * Protect against empty kwargs hash
     * marcedit.js fixes: Load dojo class before use; Load in my_init(), before which dojo is not defined
    
    Signed-off-by: berick <berick at esilibrary.com>

diff --git a/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js b/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
index 4c8eb88..46ad394 100644
--- a/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
+++ b/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
@@ -28,6 +28,8 @@ if(!dojo._hasResource["openils.AuthorityControlSet"]) {
 
         constructor : function(kwargs) {
 
+            kwargs = kwargs || {};
+
             if (!openils.AuthorityControlSet._remote_loaded) {
 
                 // TODO -- push the raw tree into the oils cache for later reuse
@@ -51,7 +53,7 @@ if(!dojo._hasResource["openils.AuthorityControlSet"]) {
                         )
                     );
                     openils.AuthorityControlSet._browse_axis_by_name[ba.code()] = ba;
-                );
+                });
 
                 // loop over each acs
                 dojo.forEach( openils.AuthorityControlSet._control_set_list, function (cs) {
@@ -107,7 +109,7 @@ if(!dojo._hasResource["openils.AuthorityControlSet"]) {
                         csaf.bib_fields( acsbf_list );
 
                         openils.AuthorityControlSet._controlsets[''+cs.id()].bib_fields = [].concat(
-                            openils.AuthorityControlSet._controlsets[''+cs.id()].bib_fields
+                            openils.AuthorityControlSet._controlsets[''+cs.id()].bib_fields,
                             acsbf_list
                         );
 
@@ -142,7 +144,8 @@ if(!dojo._hasResource["openils.AuthorityControlSet"]) {
                     dojo.forEach( openils.AuthorityControlSet._controlsets[''+cs.id()].bib_fields, function (bf) {
                         openils.AuthorityControlSet._controlsets[''+cs.id()].control_map[bf.tag()] = {};
                         dojo.forEach( bf.authority_field().sf_list().split(''), function (sf_code) {
-                            openils.AuthorityControlSet._controlsets[''+cs.id()].control_map[bf.tag()][sf_code] = { bf.authority_field().tag() : sf_code };
+                            openils.AuthorityControlSet._controlsets[''+cs.id()].control_map[bf.tag()][sf_code] = {};
+                            openils.AuthorityControlSet._controlsets[''+cs.id()].control_map[bf.tag()][sf_code][bf.authority_field().tag()] = sf_code;
                         });
                     });
 
@@ -292,7 +295,7 @@ if(!dojo._hasResource["openils.AuthorityControlSet"]) {
 
     openils.AuthorityControlSet._controlsets = {
         // static sorta-LoC setup ... to be overwritten with server data 
-        -1 : {
+        '-1' : {
             id : -1,
             name : 'Static LoC legacy mapping',
             description : 'Legacy mapping provided as a default',
diff --git a/Open-ILS/xul/staff_client/server/cat/marcedit.js b/Open-ILS/xul/staff_client/server/cat/marcedit.js
index deb2ee3..f05eba4 100644
--- a/Open-ILS/xul/staff_client/server/cat/marcedit.js
+++ b/Open-ILS/xul/staff_client/server/cat/marcedit.js
@@ -42,7 +42,7 @@ var show_auth_menu = false;
 
 function $(id) { return document.getElementById(id); }
 
-var acs = new openils.AuthorityControlSet ();
+var acs; // AuthorityControlSet
 
 function mangle_005() {
     var now = new Date();
@@ -155,6 +155,9 @@ function my_init() {
         JSAN.errorLevel = "die"; // none, warn, or die
         JSAN.addRepository('/xul/server/');
 
+        dojo.require('openils.AuthorityControlSet');
+        acs = new openils.AuthorityControlSet ();
+
         // Fake xulG for standalone...
         try {
             window.xulG.record;

commit 4e1432dc5f5c1f0353b7a02564b555367366e3e7
Author: berick <berick at esilibrary.com>
Date:   Thu May 26 14:44:48 2011 -0400

    Protect against empty lists of linked bib searches
    
    Instead of returning undef when passed an empty list of bibs, always
    return an array from
    open-ils.cat.authority.records.count_linked_bibs
    Apart from consistency, this prevents JS errors in the Manage
    Authorities UI.
    
    Signed-off-by: berick <berick at esilibrary.com>

diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Cat/Authority.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Cat/Authority.pm
index 1995edf..9e60557 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Cat/Authority.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Cat/Authority.pm
@@ -194,7 +194,7 @@ sub count_linked_bibs {
 
     my $editor = new_editor();
 
-    my $link_count;
+    my $link_count = [];
     my @clean_records;
     for my $auth ( @$records ) {
         # Protection against SQL injection? Might be overkill.

commit 6b02e30519a690dc0b27cca9679a078c919c463e
Author: Mike Rylander <mrylander at gmail.com>
Date:   Mon May 16 14:00:04 2011 -0400

    SQL typo cleanup
    
    Signed-off-by: Mike Rylander <mrylander at gmail.com>

diff --git a/Open-ILS/src/sql/Pg/011.schema.authority.sql b/Open-ILS/src/sql/Pg/011.schema.authority.sql
index c67b15d..4620c75 100644
--- a/Open-ILS/src/sql/Pg/011.schema.authority.sql
+++ b/Open-ILS/src/sql/Pg/011.schema.authority.sql
@@ -163,11 +163,11 @@ BEGIN
 
     heading_text := '';
     FOR acsaf IN SELECT * FROM authority.control_set_authority_field WHERE control_set = cset AND main_entry IS NULL LOOP
-        tag_use := acsaf.tag;
+        tag_used := acsaf.tag;
         FOR sf IN SELECT * FROM regexp_split_to_table(acsaf.sf_list,'') LOOP
             tmp_text := oils_xpath_string('//*[@tag="'||tag_used||'"]/*[@code="'||sf||'"]', marcxml);
             IF tmp_text IS NOT NULL THEN
-                heading_text := heading_text || E'\U2021' || sf || ' ' || tmp_text;
+                heading_text := heading_text || E'\u2021' || sf || ' ' || tmp_text;
             END IF;
         END LOOP;
         EXIT WHEN heading_text <> '';
@@ -253,7 +253,7 @@ BEGIN
         auth_field := XPATH('//*[@tag="'||main_entry.tag||'"][1]',source_xml);
         IF ARRAY_LENGTH(auth_field) > 0 THEN
             FOR bib_field IN SELECT * FROM authority.control_set_bib_field WHERE authority_field = main_entry.id LOOP
-                replace_data := replace_data || XMLELEMENT( name datafield, bib_field.tag AS tag, XPATH('//*[local-name()="subfield"]',auth_field[1])::XML[]);
+                replace_data := replace_data || XMLELEMENT( name datafield, XMLATTRIBUTES(bib_field.tag AS tag), XPATH('//*[local-name()="subfield"]',auth_field[1])::XML[]);
                 replace_rules := replace_rules || ( bib_field.tag || main_entry.sf_list || E'[0~\\)' || auth_id || '$]' );
             END LOOP;
             EXIT;
@@ -262,17 +262,15 @@ BEGIN
 
     RETURN XMLELEMENT(
         name record,
-        XMLATTRIBUTES('http://www.loc.gov/MARC21/slim' AS xmlns)
+        XMLATTRIBUTES('http://www.loc.gov/MARC21/slim' AS xmlns),
         XMLELEMENT( name leader, '00881nam a2200193   4500'),
         replace_data,
         XMLELEMENT(
             name datafield,
-            '905' AS tag,
-            ' ' AS ind1,
-            ' ' AS ind2,
+            XMLATTRIBUTES( '905' AS tag, ' ' AS ind1, ' ' AS ind2),
             XMLELEMENT(
                 name subfield,
-                'r' AS code,
+                XMLATTRIBUTES('r' AS code),
                 ARRAY_TO_STRING(replace_rules,',')
             )
         )
diff --git a/Open-ILS/src/sql/Pg/950.data.seed-values.sql b/Open-ILS/src/sql/Pg/950.data.seed-values.sql
index fb96efb..d59cd8c 100644
--- a/Open-ILS/src/sql/Pg/950.data.seed-values.sql
+++ b/Open-ILS/src/sql/Pg/950.data.seed-values.sql
@@ -9482,7 +9482,7 @@ INSERT INTO authority.browse_axis_authority_field_map (axis,field) VALUES
     ('subject', 7 ),
     ('subject', 12);
 
-INSERT INTO authority.control_set_bib_field (tag, authority_field) VALUES
+INSERT INTO authority.control_set_bib_field (tag, authority_field) 
     SELECT '100', id FROM authority.control_set_authority_field WHERE tag IN ('100')
         UNION
     SELECT '600', id FROM authority.control_set_authority_field WHERE tag IN ('100','180','181','182','185')
@@ -9541,6 +9541,6 @@ INSERT INTO authority.thesaurus (code, name, control_set) VALUES
     ('r', oils_i18n_gettext('r','Art and Architecture Thesaurus','at','name'), 1),
     ('s', oils_i18n_gettext('s','Sears List of Subject Headings','at','name'), 1),
     ('v', oils_i18n_gettext('v','Repertoire de vedettes-matiere','at','name'), 1),
-    ('z', oils_i18n_gettext('z','Other','at','name') 1),
-    ('|', oils_i18n_gettext('|','No attempt to code','at','name') 1);
+    ('z', oils_i18n_gettext('z','Other','at','name'), 1),
+    ('|', oils_i18n_gettext('|','No attempt to code','at','name'), 1);
 
diff --git a/Open-ILS/src/sql/Pg/999.functions.global.sql b/Open-ILS/src/sql/Pg/999.functions.global.sql
index e5e0974..0561596 100644
--- a/Open-ILS/src/sql/Pg/999.functions.global.sql
+++ b/Open-ILS/src/sql/Pg/999.functions.global.sql
@@ -1456,7 +1456,7 @@ BEGIN
                 vandelay.marc21_extract_fixed_field(marc,'RecStat'),
                 vandelay.marc21_extract_fixed_field(marc,'ELvl'),
                 vandelay.marc21_extract_fixed_field(marc,'Subj')
-          FROM  authority.record
+          FROM  authority.record_entry
           WHERE id = auth_id;
     RETURN;
 END;

commit 45916bdead2f8821acec6601dd186d6ac0839912
Author: Mike Rylander <mrylander at gmail.com>
Date:   Thu May 12 11:10:42 2011 -0400

    Use the configured set of authority browse axes in the authority browse interfaces

diff --git a/Open-ILS/web/js/ui/default/cat/authority/list.js b/Open-ILS/web/js/ui/default/cat/authority/list.js
index 2500872..c602139 100644
--- a/Open-ILS/web/js/ui/default/cat/authority/list.js
+++ b/Open-ILS/web/js/ui/default/cat/authority/list.js
@@ -14,6 +14,7 @@ dojo.require('openils.CGI');
 dojo.require('openils.PermaCrud');
 dojo.require('openils.XUL');
 dojo.require('openils.widget.OrgUnitFilteringSelect');
+dojo.require("openils.widget.PCrudAutocompleteBox");
 dojo.requireLocalization("openils.authority", "authority");
 var auth_strings = dojo.i18n.getLocalization("openils.authority", "authority");
 
diff --git a/Open-ILS/web/templates/default/cat/authority/list.tt2 b/Open-ILS/web/templates/default/cat/authority/list.tt2
index 67a1fa7..cfc341f 100644
--- a/Open-ILS/web/templates/default/cat/authority/list.tt2
+++ b/Open-ILS/web/templates/default/cat/authority/list.tt2
@@ -10,12 +10,19 @@
     </span>
     <span style="white-space: nowrap;">
         <label for="authAxis">Authority type: </label>
-        <select type="text" name="authAxis" value="" dojoType="dijit.form.FilteringSelect" trim="true" id="authAxis" propercase="false" style="width: 10em;">
-            <option value="authority.author">Author</option>
-            <option value="authority.subject">Subject</option>
-            <option value="authority.title">Title</option>
-            <option value="authority.topic">Topic</option>
-        </select>
+        <input
+            id="authAxis"
+            name="authAxis"
+            jsId="authAxis"
+            dojoType="openils.widget.PCrudAutocompleteBox"
+            fmclass="aba"
+            searchAttr="name"
+            fetchProperties="{ sort: [{attribute:'name'}] }"
+            propercase="false"
+            hasDownArrow="true"
+            store_options="{ honor_retrieve_all:true }"
+            trim="true"
+        />
     </span>
 <!-- Not currently useful - see authOUListInit() above -->
 <!--    <label for="authOU">Library: </label><select dojoType="openils.widget.OrgUnitFilteringSelect" id="authOU" name="authOU" searchAttr="shortname" labelAttr="shortname"></select> -->

commit aefd51031be384e5db8e9da63682f70be95fdc2c
Author: Mike Rylander <mrylander at gmail.com>
Date:   Thu May 12 10:18:58 2011 -0400

    Use the new singular methods that accept an axis as a param for browse and startwith

diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/SuperCat.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/SuperCat.pm
index d3a6ae8..e148565 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/SuperCat.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/SuperCat.pm
@@ -234,7 +234,13 @@ sub child_init {
         }
     }
 
-    for my $basic_axis ( qw/authority.title authority.author authority.subject authority.topic/ ) {
+    my $auth_axes = $supercat
+        ->request("open-ils.supercat.authority.browse_axis_list")
+        ->gather(1);
+
+
+    for my $axis ( @$auth_axes ) {
+        my $basic_axis = 'authority.' . $axis;
         for my $browse_axis ( ($basic_axis, $basic_axis . ".refs") ) {
             {
                 my $__f = 'marcxml';
@@ -529,6 +535,7 @@ sub unapi {
         $type = 'authority' if ($scheme =~ /^authority/o);
         $command = 'retrieve';
         $command = 'browse' if (grep { $scheme eq $_ } qw/call_number title author subject topic authority.title authority.author authority.subject authority.topic series item-age/);
+        $command = 'browse' if ($scheme =~ /^authority/);
     }
 
     if ($paging) {
@@ -1551,15 +1558,26 @@ sub string_browse {
     $string =~ s/\+/ /go;
     $string =~ s/'//go;
 
-    my $tree = $supercat->request(
-        "open-ils.supercat.$axis.browse",
-        $string,
-        (($axis =~ /^authority/) ? () : ($site)),
-        $page_size,
-        $page,
-        $status,
-        $cpLoc
-    )->gather(1);
+    my $tree;
+    if ($axis =~ /^authority/) {
+        $tree = $supercat->request(
+            "open-ils.supercat.authority.browse.by_axis",
+            $axis,
+            $string,
+            $page_size,
+            $page
+        )->gather(1);
+    } else {
+        $tree = $supercat->request(
+            "open-ils.supercat.$axis.browse",
+            $string,
+            $site,
+            $page_size,
+            $page,
+            $status,
+            $cpLoc
+        )->gather(1);
+    }
 
     (my $norm_format = $format) =~ s/(-full|-uris)$//o;
 
@@ -1616,15 +1634,26 @@ sub string_startwith {
     $string =~ s/\+/ /go;
     $string =~ s/'//go;
 
-    my $tree = $supercat->request(
-        "open-ils.supercat.$axis.startwith",
-        $string,
-        (($axis =~ /^authority/) ? () : ($site)),
-        $page_size,
-        $page,
-        $status,
-        $cpLoc
-    )->gather(1);
+    my $tree;
+    if ($axis =~ /^authority/) {
+        $tree = $supercat->request(
+            "open-ils.supercat.authority.startwith.by_axis",
+            $axis,
+            $string,
+            $page_size,
+            $page
+        )->gather(1);
+    } else {
+        $tree = $supercat->request(
+            "open-ils.supercat.$axis.startwith",
+            $string,
+            $site,
+            $page_size,
+            $page,
+            $status,
+            $cpLoc
+        )->gather(1);
+    }
 
     (my $norm_format = $format) =~ s/(-full|-uris)$//o;
 
@@ -2081,7 +2110,11 @@ sub return_auth_response {
         $recs = [ int($term) ];
     } else {
         $recs = $supercat->request(
-            "open-ils.supercat.authority.$qualifier.startwith", $term, $page_size, $page
+            "open-ils.supercat.authority.startwith.by_axis",
+            $qualifier,
+            $term,
+            $page_size,
+            $page
         )->gather(1);
     }
 

commit 106520e58aa7ab388f575242a89bfe299ec0a5d1
Author: Mike Rylander <mrylander at gmail.com>
Date:   Thu May 12 10:18:15 2011 -0400

    Add method for returning valid authority browse axes

diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/SuperCat.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/SuperCat.pm
index a8a8717..f733760 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/SuperCat.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/SuperCat.pm
@@ -887,21 +887,36 @@ Returns a list of the requested org-scoped record IDs held
 		}
 );
 
+sub grab_authority_browse_axes {
+
+    unless(scalar(keys(%authority_browse_axis_cache))) {
+        my $axes = new_editor->search_authority_browse_axis([
+            { code => { '<>' => undef } },
+            { flesh => 2, flesh_fields => { aba => ['fields'], acsafm => ['bib_fields','sub_entries'] } }
+        ]);
+        $authority_browse_axis_cache{$_->code} = $_ for (@$axes);
+    }
+
+    return [keys %authority_browse_axis_cache];
+}
+__PACKAGE__->register_method(
+	method    => 'grab_authority_browse_axes',
+	api_name  => 'open-ils.supercat.authority.browse_axis_list',
+	api_level => 1,
+	argc      => 0,
+	note      => "Returns a list of valid authority browse/startswith axes"
+);
+
 sub axis_authority_browse {
 	my $self = shift;
 	my $client = shift;
     my $axis = shift;
 
+    $axis =~ s/^authority\.//;
     $axis =~ s/(\.refs)$//;
     my $refs = $1;
 
-    unless(scalar(keys(%authority_browse_axis_cache))) {
-        my $axes = new_editor->search_authority_browse_axis([
-            { code => { '<>' => undef } },
-            {flesh => 4, flesh_fields => { aba => ['fields'], acsafm => ['sub_entries'] } }
-        ]);
-        $authority_browse_axis_cache{$_->code} = $_ for (@$axes);
-    }
+    return undef unless ( grep { /$axis/ } @{ grab_authority_browse_axes() } );
 
     my @tags;
     for my $f (@{$authority_browse_axis_cache{$axis}->fields}) {
@@ -929,6 +944,8 @@ __PACKAGE__->register_method(
 		}
 );
 
+=pod
+
 sub general_authority_browse {
 	my $self = shift;
 	my $client = shift;
@@ -1055,6 +1072,8 @@ __PACKAGE__->register_method(
 		}
 );
 
+=cut
+
 sub authority_tag_sf_browse {
     my $self = shift;
     my $client = shift;
@@ -1448,16 +1467,11 @@ sub axis_authority_startwith {
 	my $client = shift;
     my $axis = shift;
 
+    $axis =~ s/^authority\.//;
     $axis =~ s/(\.refs)$//;
     my $refs = $1;
 
-    unless(scalar(keys(%authority_browse_axis_cache))) {
-        my $axes = new_editor->search_authority_browse_axis([
-            { code => { '<>' => undef } },
-            {flesh => 4, flesh_fields => { aba => ['fields'], acsafm => ['sub_entries'] } }
-        ]);
-        $authority_browse_axis_cache{$_->code} = $_ for (@$axes);
-    }
+    return undef unless ( grep { /$axis/ } @{ grab_authority_browse_axes() } );
 
     my @tags;
     for my $f (@{$authority_browse_axis_cache{$axis}->fields}) {
@@ -1485,6 +1499,8 @@ __PACKAGE__->register_method(
 		}
 );
 
+=pod
+
 sub general_authority_startwith {
 	my $self = shift;
 	my $client = shift;
@@ -1611,6 +1627,8 @@ __PACKAGE__->register_method(
 		}
 );
 
+=cut
+
 sub authority_tag_sf_startwith {
     my $self = shift;
     my $client = shift;

commit 0cd95625806247edb1350af52ac35cfda3710c14
Author: Mike Rylander <mrylander at gmail.com>
Date:   Wed May 11 20:28:39 2011 -0400

    Browse axis based browse and startswith methods; minor documentation corrections

diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/SuperCat.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/SuperCat.pm
index a0a634a..a8a8717 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/SuperCat.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/SuperCat.pm
@@ -36,12 +36,16 @@ use OpenSRF::Utils::Logger qw($logger);
 # ... and this is our OpenILS object (en|de)coder and psuedo-ORM package.
 use OpenILS::Utils::Fieldmapper;
 
+use OpenILS::Utils::CStoreEditor q/:funcs/;
+
+
 our (
   $_parser,
   $_xslt,
   %record_xslt,
   %metarecord_xslt,
   %holdings_data_cache,
+  %authority_browse_axis_cache,
 );
 
 sub child_init {
@@ -883,6 +887,48 @@ Returns a list of the requested org-scoped record IDs held
 		}
 );
 
+sub axis_authority_browse {
+	my $self = shift;
+	my $client = shift;
+    my $axis = shift;
+
+    $axis =~ s/(\.refs)$//;
+    my $refs = $1;
+
+    unless(scalar(keys(%authority_browse_axis_cache))) {
+        my $axes = new_editor->search_authority_browse_axis([
+            { code => { '<>' => undef } },
+            {flesh => 4, flesh_fields => { aba => ['fields'], acsafm => ['sub_entries'] } }
+        ]);
+        $authority_browse_axis_cache{$_->code} = $_ for (@$axes);
+    }
+
+    my @tags;
+    for my $f (@{$authority_browse_axis_cache{$axis}->fields}) {
+        push @tags, $f->tag;
+        if ($refs) {
+            push @tags, $_->tag for @{$f-sub_entries};
+        }
+    }
+
+    return authority_tag_sf_browse($self, $client, \@tags, 'a', @_); # XXX TODO figure out something more correct for the subfield param
+}
+__PACKAGE__->register_method(
+	method    => 'axis_authority_browse',
+	api_name  => 'open-ils.supercat.authority.browse.by_axis',
+	api_level => 1,
+	argc      => 2,
+	signature =>
+		{ desc     => "Returns a list of the requested authority record IDs held",
+		  params   =>
+		  	[ { name => 'axis', desc => 'The target axis', type => 'string' },
+		  	  { name => 'value', desc => 'The target value', type => 'string' },
+			  { name => 'page_size', desc => 'Count of records to retrieve, default is 9', type => 'number' },
+			  { name => 'page', desc => 'The page of records retrieved, calculated based on page_size.  Can be positive, negative or 0.', type => 'number' }, ],
+		  'return' => { desc => 'Authority Record IDs that are near the target string', type => 'array' }
+		}
+);
+
 sub general_authority_browse {
 	my $self = shift;
 	my $client = shift;
@@ -1397,6 +1443,48 @@ Returns a list of the requested org-scoped record IDs held
 		}
 );
 
+sub axis_authority_startwith {
+	my $self = shift;
+	my $client = shift;
+    my $axis = shift;
+
+    $axis =~ s/(\.refs)$//;
+    my $refs = $1;
+
+    unless(scalar(keys(%authority_browse_axis_cache))) {
+        my $axes = new_editor->search_authority_browse_axis([
+            { code => { '<>' => undef } },
+            {flesh => 4, flesh_fields => { aba => ['fields'], acsafm => ['sub_entries'] } }
+        ]);
+        $authority_browse_axis_cache{$_->code} = $_ for (@$axes);
+    }
+
+    my @tags;
+    for my $f (@{$authority_browse_axis_cache{$axis}->fields}) {
+        push @tags, $f->tag;
+        if ($refs) {
+            push @tags, $_->tag for @{$f-sub_entries};
+        }
+    }
+
+    return authority_tag_sf_startwith($self, $client, \@tags, 'a', @_); # XXX TODO figure out something more correct for the subfield param
+}
+__PACKAGE__->register_method(
+	method    => 'axis_authority_startwith',
+	api_name  => 'open-ils.supercat.authority.startwith.by_axis',
+	api_level => 1,
+	argc      => 2,
+	signature =>
+		{ desc     => "Returns a list of the requested authority record IDs held",
+		  params   =>
+		  	[ { name => 'axis', desc => 'The target axis', type => 'string' },
+		  	  { name => 'value', desc => 'The target value', type => 'string' },
+			  { name => 'page_size', desc => 'Count of records to retrieve, default is 10', type => 'number' },
+			  { name => 'page', desc => 'The page of records retrieved, calculated based on page_size.  Can be positive, negative or 0.', type => 'number' }, ],
+		  'return' => { desc => 'Authority Record IDs that are near the target string', type => 'array' }
+		}
+);
+
 sub general_authority_startwith {
 	my $self = shift;
 	my $client = shift;
@@ -1412,7 +1500,7 @@ __PACKAGE__->register_method(
 		{ desc     => "Returns a list of the requested authority record IDs held",
 		  params   =>
 		  	[ { name => 'value', desc => 'The target title', type => 'string' },
-			  { name => 'page_size', desc => 'Count of records to retrieve, default is 9', type => 'number' },
+			  { name => 'page_size', desc => 'Count of records to retrieve, default is 10', type => 'number' },
 			  { name => 'page', desc => 'The page of records retrieved, calculated based on page_size.  Can be positive, negative or 0.', type => 'number' }, ],
 		  'return' => { desc => 'Authority Record IDs that are near the target string', type => 'array' }
 		}
@@ -1427,7 +1515,7 @@ __PACKAGE__->register_method(
 		{ desc     => "Returns a list of the requested authority record IDs held",
 		  params   =>
 		  	[ { name => 'value', desc => 'The target author', type => 'string' },
-			  { name => 'page_size', desc => 'Count of records to retrieve, default is 9', type => 'number' },
+			  { name => 'page_size', desc => 'Count of records to retrieve, default is 10', type => 'number' },
 			  { name => 'page', desc => 'The page of records retrieved, calculated based on page_size.  Can be positive, negative or 0.', type => 'number' }, ],
 		  'return' => { desc => 'Authority Record IDs that are near the target string', type => 'array' }
 		}
@@ -1442,7 +1530,7 @@ __PACKAGE__->register_method(
 		{ desc     => "Returns a list of the requested authority record IDs held",
 		  params   =>
 		  	[ { name => 'value', desc => 'The target subject', type => 'string' },
-			  { name => 'page_size', desc => 'Count of records to retrieve, default is 9', type => 'number' },
+			  { name => 'page_size', desc => 'Count of records to retrieve, default is 10', type => 'number' },
 			  { name => 'page', desc => 'The page of records retrieved, calculated based on page_size.  Can be positive, negative or 0.', type => 'number' }, ],
 		  'return' => { desc => 'Authority Record IDs that are near the target string', type => 'array' }
 		}
@@ -1457,7 +1545,7 @@ __PACKAGE__->register_method(
 		{ desc     => "Returns a list of the requested authority record IDs held",
 		  params   =>
 		  	[ { name => 'value', desc => 'The target topical subject', type => 'string' },
-			  { name => 'page_size', desc => 'Count of records to retrieve, default is 9', type => 'number' },
+			  { name => 'page_size', desc => 'Count of records to retrieve, default is 10', type => 'number' },
 			  { name => 'page', desc => 'The page of records retrieved, calculated based on page_size.  Can be positive, negative or 0.', type => 'number' }, ],
 		  'return' => { desc => 'Authority Record IDs that are near the target string', type => 'array' }
 		}
@@ -1472,7 +1560,7 @@ __PACKAGE__->register_method(
 		{ desc     => "Returns a list of the requested authority record IDs held, including see (4xx) and see also (5xx) references",
 		  params   =>
 		  	[ { name => 'value', desc => 'The target title', type => 'string' },
-			  { name => 'page_size', desc => 'Count of records to retrieve, default is 9', type => 'number' },
+			  { name => 'page_size', desc => 'Count of records to retrieve, default is 10', type => 'number' },
 			  { name => 'page', desc => 'The page of records retrieved, calculated based on page_size.  Can be positive, negative or 0.', type => 'number' }, ],
 		  'return' => { desc => 'Authority Record IDs that are near the target string', type => 'array' }
 		}
@@ -1487,7 +1575,7 @@ __PACKAGE__->register_method(
 		{ desc     => "Returns a list of the requested authority record IDs held, including see (4xx) and see also (5xx) references",
 		  params   =>
 		  	[ { name => 'value', desc => 'The target author', type => 'string' },
-			  { name => 'page_size', desc => 'Count of records to retrieve, default is 9', type => 'number' },
+			  { name => 'page_size', desc => 'Count of records to retrieve, default is 10', type => 'number' },
 			  { name => 'page', desc => 'The page of records retrieved, calculated based on page_size.  Can be positive, negative or 0.', type => 'number' }, ],
 		  'return' => { desc => 'Authority Record IDs that are near the target string', type => 'array' }
 		}
@@ -1502,7 +1590,7 @@ __PACKAGE__->register_method(
 		{ desc     => "Returns a list of the requested authority record IDs held, including see (4xx) and see also (5xx) references",
 		  params   =>
 		  	[ { name => 'value', desc => 'The target subject', type => 'string' },
-			  { name => 'page_size', desc => 'Count of records to retrieve, default is 9', type => 'number' },
+			  { name => 'page_size', desc => 'Count of records to retrieve, default is 10', type => 'number' },
 			  { name => 'page', desc => 'The page of records retrieved, calculated based on page_size.  Can be positive, negative or 0.', type => 'number' }, ],
 		  'return' => { desc => 'Authority Record IDs that are near the target string', type => 'array' }
 		}
@@ -1517,7 +1605,7 @@ __PACKAGE__->register_method(
 		{ desc     => "Returns a list of the requested authority record IDs held, including see (4xx) and see also (5xx) references",
 		  params   =>
 		  	[ { name => 'value', desc => 'The target topical subject', type => 'string' },
-			  { name => 'page_size', desc => 'Count of records to retrieve, default is 9', type => 'number' },
+			  { name => 'page_size', desc => 'Count of records to retrieve, default is 10', type => 'number' },
 			  { name => 'page', desc => 'The page of records retrieved, calculated based on page_size.  Can be positive, negative or 0.', type => 'number' }, ],
 		  'return' => { desc => 'Authority Record IDs that are near the target string', type => 'array' }
 		}
@@ -1627,7 +1715,7 @@ Returns a list of the requested authority record IDs held
 				  desc => 'The target string',
 				  type => 'string' },
 				{ name => 'page_size',
-				  desc => 'Count of call numbers to retrieve, default is 9',
+				  desc => 'Count of call numbers to retrieve, default is 10',
 				  type => 'number' },
 				{ name => 'page',
 				  desc => 'The page of call numbers to retrieve, calculated based on page_size.  Can be positive, negative or 0.',

commit 3a63f4579eed4582fd6dc0d910dcdc301737108c
Author: Mike Rylander <mrylander at gmail.com>
Date:   Wed May 11 19:31:36 2011 -0400

    Use ACS utility functions instead of hard-wired mapping

diff --git a/Open-ILS/xul/staff_client/server/cat/marcedit.js b/Open-ILS/xul/staff_client/server/cat/marcedit.js
index 00c76b7..deb2ee3 100644
--- a/Open-ILS/xul/staff_client/server/cat/marcedit.js
+++ b/Open-ILS/xul/staff_client/server/cat/marcedit.js
@@ -1659,37 +1659,15 @@ function browseAuthority (sf_popup, menu_id, target, sf, limit, page) {
 
     // map tag + subfield to the appropriate authority browse axis:
     // currently authority.author, authority.subject, authority.title, authority.topic
-    // based on mappings in OpenILS::Application::SuperCat
+    // based on mappings in OpenILS::Application::SuperCat, though Authority Control
+    // Sets will change that
 
-    var type;
-
-    // Map based on replacing the first char of the selected tag with '1'
-    switch ('1' + (sf.parent(). at tag.toString()).substring(1)) {
-        case "130":
-            type = 'authority.title';
-            break;
-
-        case "100":
-        case "110":
-        case "111":
-            type = 'authority.author';
-            break;
-
-        case "150":
-            type = 'authority.topic';
-            break;
-
-        case "148":
-        case "151":
-        case "155":
-            type = 'authority.subject';
-            break;
-
-        // No matching tag means no authorities to search - shortcut
-        default:
-            return;
-    }
+    var axis_list = acs.bibFieldBrowseAxes( sf.parent(). at tag.toString() );
+    // No matching tag means no authorities to search - shortcut
+    if (axis_list.length == 0) return;
 
+    var type = 'authority.' + axis_list[0]; // Just take the first for now
+                                            // TODO support multiple axes ... loop?
     if (!limit) {
         limit = 10;
     }

commit de741e118148e9593f218bae37c09eebdbd965e0
Author: Mike Rylander <mrylander at gmail.com>
Date:   Wed May 11 19:31:15 2011 -0400

    Fetch ACS stuff up front; enhance inter-object mapping per IDL; utility functions

diff --git a/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js b/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
index 4fc1d0b..4c8eb88 100644
--- a/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
+++ b/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
@@ -33,10 +33,28 @@ if(!dojo._hasResource["openils.AuthorityControlSet"]) {
                 // TODO -- push the raw tree into the oils cache for later reuse
 
                 var pcrud = new openils.PermaCrud();
-                var acs_list = pcrud.retrieveAll('acs');
+
+                // fetch everything up front...
+                openils.AuthorityControlSet._control_set_list = pcrud.retrieveAll('acs');
+                openils.AuthorityControlSet._thesaurus_list = pcrud.retrieveAll('at');
+                openils.AuthorityControlSet._authority_field_list = pcrud.retrieveAll('acsaf');
+                openils.AuthorityControlSet._bib_field_list = pcrud.retrieveAll('acsbf');
+                openils.AuthorityControlSet._browse_axis_list = pcrud.retrieveAll('aba');
+                openils.AuthorityControlSet._browse_field_map_list = pcrud.retrieveAll('abaafm');
+
+                openils.AuthorityControlSet._browse_axis_by_name = {};
+                dojo.forEach( openils.AuthorityControlSet._browse_axis_list, function (ba) {
+                    ba.maps(
+                        dojo.filter(
+                            openils.AuthorityControlSet._browse_field_map_list,
+                            function (m) { return m.axis() == ba.code() }
+                        )
+                    );
+                    openils.AuthorityControlSet._browse_axis_by_name[ba.code()] = ba;
+                );
 
                 // loop over each acs
-                dojo.forEach( acs_list, function (cs) {
+                dojo.forEach( openils.AuthorityControlSet._control_set_list, function (cs) {
                     openils.AuthorityControlSet._controlsets[''+cs.id()] = {
                         id : cs.id(),
                         name : cs.name(),
@@ -48,13 +66,23 @@ if(!dojo._hasResource["openils.AuthorityControlSet"]) {
                     };
 
                     // grab the authority fields
-                    var acsaf_list = pcrud.search('acsaf', {control_set : cs.id()});
-                    var at_list = pcrud.search('at', {control_set : cs.id()});
+                    var acsaf_list = dojo.filter(
+                        openils.AuthorityControlSet._authority_field_list,
+                        function (af) { return af.control_set() == cs.id() }
+                    );
+
+                    var at_list = dojo.filter(
+                        openils.AuthorityControlSet._thesaurus_list,
+                        function (at) { return at.control_set() == cs.id() }
+                    );
+
                     openils.AuthorityControlSet._controlsets[''+cs.id()].raw.authority_fields( acsaf_list );
                     openils.AuthorityControlSet._controlsets[''+cs.id()].raw.thesauri( at_list );
 
                     // and loop over each
                     dojo.forEach( acsaf_list, function (csaf) {
+                        csaf.axis_maps([]);
+
                         // link the main entry if we're subordinate
                         if (csaf.main_entry()) {
                             csaf.main_entry(
@@ -68,11 +96,14 @@ if(!dojo._hasResource["openils.AuthorityControlSet"]) {
                         csaf.sub_entries(
                             dojo.filter(acsaf_list, function (x) {
                                 return x.main_entry() == csaf.id();
-                            })[0]
+                            })
                         );
 
                         // now, bib fields
-                        var acsbf_list = pcrud.search('acsbf', {authority_field : csaf.id()});
+                        var acsbf_list = dojo.filter(
+                            openils.AuthorityControlSet._bib_field_list,
+                            function (b) { return b.authority_field() == csaf.id() }
+                        );
                         csaf.bib_fields( acsbf_list );
 
                         openils.AuthorityControlSet._controlsets[''+cs.id()].bib_fields = [].concat(
@@ -91,6 +122,20 @@ if(!dojo._hasResource["openils.AuthorityControlSet"]) {
                             }
     
                         });
+
+                        dojo.forEach( // for each axis
+                            openils.AuthorityControlSet._browse_axis_list,
+                            function (ba) {
+                                dojo.forEach( // loop over the maps
+                                    dojo.filter( // filtering to just this field's mapps
+                                        ba.maps(),
+                                        function (m) { return m.field() == csfa.id() }
+                                    ),
+                                    function (fm) { fm.field( csaf ); csaf.axis_maps().push( fm ) } // and set the field
+                                )
+                            }
+                        );
+
                     });
 
                     // build the authority_tag_map
@@ -100,8 +145,19 @@ if(!dojo._hasResource["openils.AuthorityControlSet"]) {
                             openils.AuthorityControlSet._controlsets[''+cs.id()].control_map[bf.tag()][sf_code] = { bf.authority_field().tag() : sf_code };
                         });
                     });
+
                 });
 
+                openils.AuthorityControlSet._browse_axis_by_name = {};
+                dojo.forEach( openils.AuthorityControlSet._browse_axis_list, function (ba) {
+                    ba.maps(
+                        dojo.fitler(
+                            openils.AuthorityControlSet._browse_field_map_list,
+                            function (m) { m.axis() == ba.code }
+                        )
+                    );
+                    openils.AuthorityControlSet._browse_axis_by_name[ba.code()] = ba;
+                });
                 
                 if (this.controlSetList().length > 0)
                     delete openils.AuthorityControlSet._controlsets['-1'];
@@ -128,7 +184,7 @@ if(!dojo._hasResource["openils.AuthorityControlSet"]) {
         bibFieldByTag: function (x) {
             var me = this;
             return dojo.filter(
-                me.controlSet()].bib_fields(),
+                me.controlSet().bib_fields(),
                 function (bf) { if (bf.tag() == x) return true }
             )[0];
         },
@@ -137,6 +193,23 @@ if(!dojo._hasResource["openils.AuthorityControlSet"]) {
             return this.controlSet(x).bib_fields();
         },
 
+        bibFieldBrowseAxes : function (t) {
+            var blist = [];
+            for (var bname in openils.AuthorityControlSet._browse_axis_by_name) {
+                dojo.forEach(
+                    openils.AuthorityControlSet._browse_axis_by_name[bname].maps(),
+                    function (m) {
+                        if (dojo.filter(
+                                m.field().bib_fields(),
+                                function (b) { return b.tag == t }
+                            ).length > 0
+                        ) blist.push(bname);
+                    }
+                );
+            }
+            return blist;
+        },
+
         authorityFields: function (x) {
             return this.controlSet(x).raw.authority_fields();
         },

commit 750fcec8604c3054a68d99c2a1e4be6b5b05add7
Author: Mike Rylander <mrylander at gmail.com>
Date:   Wed May 11 19:30:05 2011 -0400

    Add axis_maps virtual field to control set authority field

diff --git a/Open-ILS/examples/fm_IDL.xml b/Open-ILS/examples/fm_IDL.xml
index 13c18ae..fa82ffb 100644
--- a/Open-ILS/examples/fm_IDL.xml
+++ b/Open-ILS/examples/fm_IDL.xml
@@ -1789,8 +1789,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 			<field reporter:label="Subordinate Entries" name="sub_entries" reporter:datatype="link" oils_persist:virtual="true"/>
 			<field reporter:label="Controlled Bib Fields" name="bib_fields" reporter:datatype="link" oils_persist:virtual="true"/>
 			<field reporter:label="Thesauri" name="thesauri" reporter:datatype="link" oils_persist:virtual="true"/>
+			<field reporter:label="Browse Axis Maps" name="axis_maps" reporter:datatype="link" oils_persist:virtual="true"/>
 		</fields>
 		<links>
+			<link field="axis_maps" reltype="has_many" key="field" map="" class="abaafm"/>
 			<link field="control_set" reltype="has_a" key="id" map="" class="acs"/>
 			<link field="bib_fields" reltype="has_many" key="authority_field" map="" class="acsbf"/>
 			<link field="thesauri" reltype="has_many" key="control_set" map="" class="at"/>

commit 5ed4a1ffebf9c7191123f642d2865bf2de3b63d7
Author: Mike Rylander <mrylander at gmail.com>
Date:   Wed May 11 17:06:45 2011 -0400

    Adding tables for browse axis mapping

diff --git a/Open-ILS/examples/fm_IDL.xml b/Open-ILS/examples/fm_IDL.xml
index 7e032c1..13c18ae 100644
--- a/Open-ILS/examples/fm_IDL.xml
+++ b/Open-ILS/examples/fm_IDL.xml
@@ -1846,6 +1846,48 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 		</permacrud>
 	</class>
 
+	<class id="aba" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="authority::browse_axis" oils_persist:tablename="authority.browse_axis" reporter:label="Authority Browse Axis">
+		<fields oils_persist:primary="code">
+			<field reporter:label="Code" name="code" reporter:datatype="id" reporter:selector="name"/>
+			<field reporter:label="Name" name="name" reporter:datatype="text" oils_persist:i18n="true" oils_obj:required="true"/>
+			<field reporter:label="Description" name="description" reporter:datatype="text"/>
+			<field reporter:label="Authority Fields" name="fields" reporter:datatype="link" oils_persist:virtual="true"/>
+			<field reporter:label="Authority Field Maps" name="maps" reporter:datatype="link" oils_persist:virtual="true"/>
+		</fields>
+		<links>
+			<link field="fields" reltype="has_many" key="axis" map="field" class="abaafm"/>
+			<link field="maps" reltype="has_many" key="axis" map="" class="abaafm"/>
+		</links>
+		<permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
+			<actions>
+				<create permission="CREATE_AUTHORITY_CONTROLSET" global_required="true"/>
+				<retrieve/>
+				<update permission="UPDATE_AUTHORITY_CONTROLSET" global_required="true"/>
+				<delete permission="UPDATE_AUTHORITY_CONTROLSET" global_required="true"/>
+			</actions>
+		</permacrud>
+	</class>
+
+    <class id="abaafm" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="authority::browse_axis_authority_field_map" oils_persist:tablename="authority.browse_axis_authority_field_map" reporter:label="Authority Browse Axis Field Map">
+        <fields oils_persist:primary="id" oils_persist:sequence="authority.browse_axis_authority_field_map_id_seq">
+            <field reporter:label="Axis Authority Field Map ID" name="id" reporter:datatype="id"/>
+            <field reporter:label="Authority Field" name="authority_field" oils_obj:required="true" reporter:datatype="link"/>
+            <field reporter:label="Axis" name="axis" reporter:datatype="link" oils_obj:required="true"/>
+        </fields>
+        <links>
+            <link field="field" reltype="has_a" key="id" map="" class="acsaf"/>
+            <link field="axis" reltype="has_a" key="code" map="" class="aba"/>
+        </links>
+        <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
+            <actions>
+                <create permission="CREATE_AUTHORITY_CONTROLSET" global_required="true"/>
+                <retrieve/>
+                <update permission="UPDATE_AUTHORITY_CONTROLSET" global_required="true"/>
+                <delete permission="UPDATE_AUTHORITY_CONTROLSET" global_required="true"/>
+            </actions>
+        </permacrud>
+    </class>
+
 	<class id="are" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="authority::record_entry" oils_persist:tablename="authority.record_entry" reporter:label="Authority Record Entry">
 		<fields oils_persist:primary="id" oils_persist:sequence="authority.record_entry_id_seq">
 			<field name="active" reporter:datatype="bool"/>
diff --git a/Open-ILS/src/sql/Pg/011.schema.authority.sql b/Open-ILS/src/sql/Pg/011.schema.authority.sql
index 9d595fc..c67b15d 100644
--- a/Open-ILS/src/sql/Pg/011.schema.authority.sql
+++ b/Open-ILS/src/sql/Pg/011.schema.authority.sql
@@ -51,6 +51,18 @@ CREATE TABLE authority.thesaurus (
     description TEXT                     -- i18n
 );
 
+CREATE TABLE authority.browse_axis (
+    code        TEXT    PRIMARY KEY,
+    name        TEXT    UNIQUE NOT NULL, -- i18n
+    description TEXT
+);
+
+CREATE TABLE authority.browse_axis_authority_field_map (
+    id          SERIAL  PRIMARY KEY,
+    axis        TEXT    NOT NULL REFERENCES authority.browse_axis (code) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
+    field       INT     NOT NULL REFERENCES authority.control_set_authority_field (id) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED
+);
+
 CREATE TABLE authority.record_entry (
     id              BIGSERIAL    PRIMARY KEY,
     create_date     TIMESTAMP WITH TIME ZONE    NOT NULL DEFAULT now(),
diff --git a/Open-ILS/src/sql/Pg/950.data.seed-values.sql b/Open-ILS/src/sql/Pg/950.data.seed-values.sql
index 6100def..fb96efb 100644
--- a/Open-ILS/src/sql/Pg/950.data.seed-values.sql
+++ b/Open-ILS/src/sql/Pg/950.data.seed-values.sql
@@ -9465,6 +9465,22 @@ INSERT INTO authority.control_set_authority_field (id, control_set, main_entry,
     (71, 1, 11, '485', 'ivwxyz4', oils_i18n_gettext('71','See Also Tracing -- Form Subdivision','acsaf','name')),
     (72, 1, 12, '448', 'aivwxyz4', oils_i18n_gettext('72','See Also Tracing -- Chronological Term','acsaf','name'));
 
+INSERT INTO authority.browse_axis (code,name,description) VALUES
+    ('title','Title','Title axis'),
+    ('author','Author','Author axis'),
+    ('subject','Subject','Subject axis'),
+    ('topic','Topic','Topic Subject axis');
+
+INSERT INTO authority.browse_axis_authority_field_map (axis,field) VALUES
+    ('author',  1 ),
+    ('author',  2 ),
+    ('author',  3 ),
+    ('title',   4 ),
+    ('topic',   5 ),
+    ('subject', 5 ),
+    ('subject', 6 ),
+    ('subject', 7 ),
+    ('subject', 12);
 
 INSERT INTO authority.control_set_bib_field (tag, authority_field) VALUES
     SELECT '100', id FROM authority.control_set_authority_field WHERE tag IN ('100')

commit 655fcbd6e50d1f76c555c2af686a5fb9ce7065c0
Author: Mike Rylander <mrylander at gmail.com>
Date:   Wed May 11 13:24:17 2011 -0400

    Use MARC.FixedFields.setFixedField and validate by startwith search against simple_normalized_heading

diff --git a/Open-ILS/xul/staff_client/server/cat/marcedit.js b/Open-ILS/xul/staff_client/server/cat/marcedit.js
index 19a582d..00c76b7 100644
--- a/Open-ILS/xul/staff_client/server/cat/marcedit.js
+++ b/Open-ILS/xul/staff_client/server/cat/marcedit.js
@@ -815,41 +815,12 @@ function updateFixedFields (element) {
     var new_value = element.value;
 
     var marc_rec = new MARC.Record ({ delimiter : '$', marcxml : xml_record.toXMLString() });
-    var rtype = marc_rec.recordType();
+    marc_rec.setFixedField(element.getAttribute('name'), new_value);
 
-    var parts = {
-        ldr : marc_rec.leader(),
-        _6 : marc_rec.field('006');
-        _7 : marc_rec.field('007');
-        _8 : marc_rec.field('008');
-    };
-
-    var name = element.getAttribute('name');
-    for (var i in MARC.Record._ff_pos[name]) {
-
-        if (!MARC.Record._ff_pos[name][i][rtype]) continue;
-        if (!parts[i]) {
-            // we're missing the required field.  Add it now.
-
-            var newfield;
-            if (i == '_6') newfield = '006';
-            else if (i == '_7') newfield = '007';
-            else if (i == '_8') newfield = '008';
-            else continue;
-
-            createControlField(newfield,'                                        ');
-            parts[i] = xml_record.controlfield.(@tag==newfield).toString();
-        }
-
-        var before = parts[i].substr(0, MARC.Record._ff_pos[name][i][rtype].start);
-        var after = parts[i].substr(MARC.Record._ff_pos[name][i][rtype].start + MARC.Record._ff_pos[name][i][rtype].len);
-
-        for (var j = 0; new_value.length < MARC.Record._ff_pos[name][i][rtype].len; j++) {
-            new_value += MARC.Record._ff_pos[name][i][rtype].def;
-        }
-
-        recGrid.getElementsByAttribute('tag',i)[0].lastChild.value = before + new_value + after;
-    }
+    var xml_string = marc_rec.toXmlString();
+    xml_record = new XML( xml_string );
+    if (xml_record..record[0]) xml_record = xml_record..record[0];
+    loadRecord();
 
     return true;
 }
@@ -1614,34 +1585,24 @@ function validateAuthority (button) {
             var ind2 = ind1.nextSibling;
             var subfields = ind2.nextSibling.childNodes;
     
-            var tags = {};
-    
+            var sf_list = [];
             for (var j = 0; j < subfields.length; j++) {
                 var sf = subfields[j];
-                var sf_code = sf.childNodes[1].value;
-                var sf_value = sf.childNodes[2].value;
-    
-                if (!control_map[tag.value][sf_code]) continue;
-    
-                var found = 0;
-                for (var a_tag in control_map[tag.value][sf_code]) {
-                    if (!tags[a_tag]) tags[a_tag] = [];
-                    tags[a_tag].push({ term : sf_value, subfield : sf_code });
-                }
-    
-            }
-    
-            for (var val_tag in tags) {
-                var auth_data = validateBibField( acs_id, [val_tag], tags[val_tag]);
-                var res = new XML( auth_data.responseText );
-                found = parseInt(res.gw::payload.gw::string.toString());
-                if (found) break;
+                sf_list.push( sf.childNodes[1].value );
+                sf_list.push( sf.childNodes[2].value );
             }
+
+            var matches = acs.findMatchingAuthorities(
+                new MARC.Field({
+                    'tag'       : tag.value,
+                    'subfields' : sf_list
+                })
+            );
     
             // XXX If adt, etc should be validated separately from vxz, etc then move this up into the above for loop
             for (var j = 0; j < subfields.length; j++) {
                 var sf = subfields[j];
-                if (!found) {
+                if (!matches.length) {
                     dojo.removeClass(sf.childNodes[2], 'marcValidated');
                     dojo.addClass(sf.childNodes[2], 'marcUnvalidated');
                 } else {
@@ -1650,7 +1611,7 @@ function validateAuthority (button) {
                 }
             }
 
-            if (found) break;
+            if (matches.length) break;
         }
     }
 
@@ -1660,6 +1621,7 @@ function validateAuthority (button) {
 }
 
 
+/*
 function validateBibField (tags, searches) {
     var url = "/gateway?input_format=json&format=xml&service=open-ils.search&method=open-ils.search.authority.validate.tag";
     url += '&param="tags"&param=' + js2JSON(tags);
@@ -1673,6 +1635,8 @@ function validateBibField (tags, searches) {
     return req;
 
 }
+*/
+
 function searchAuthority (term, tag, sf, limit) {
     var url = "/gateway?input_format=json&format=xml&service=open-ils.search&method=open-ils.search.authority.fts";
     url += '&param="term"&param="' + term + '"';
@@ -1689,6 +1653,7 @@ function searchAuthority (term, tag, sf, limit) {
 
 }
 
+/* TODO new authority browse support for context sets, and use that here */
 function browseAuthority (sf_popup, menu_id, target, sf, limit, page) {
     dojo.require('dojox.xml.parser');
 

commit 1e7663696b09c43379510faff416e94a9b1827ae
Author: Mike Rylander <mrylander at gmail.com>
Date:   Wed May 11 12:54:16 2011 -0400

    Function to find authority records matching a MARC field

diff --git a/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js b/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
index c89d490..4fc1d0b 100644
--- a/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
+++ b/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
@@ -204,6 +204,13 @@ if(!dojo._hasResource["openils.AuthorityControlSet"]) {
             this.controlSetId(old_acs);
 
             return auth_list;
+        },
+
+        findMatchingAuthorities : function (field) {
+            return fieldmapper.standardRequest(
+                [ 'open-ils.search', 'open-ils.search.authority.simple_heading.from_xml.batch.atomic' ],
+                this.bibToAuthorities(field)
+            );
         }
 
     });

commit d2e334b617523cd6a559238b38d0a0808a36a377
Author: Mike Rylander <mrylander at gmail.com>
Date:   Wed May 11 12:52:04 2011 -0400

    adjust parameters and documentation note

diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Search/Authority.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Search/Authority.pm
index 87b63dd..a93dbb6 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Search/Authority.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Search/Authority.pm
@@ -87,15 +87,13 @@ __PACKAGE__->register_method(
         api_name	=> "open-ils.search.authority.simple_heading.from_xml",
         argc		=> 1, 
         stream      => 1,
-        note		=> "Searches authority data by main entry using marcxml, returning 'are' ids",
+        note		=> "Searches authority data by main entry using marcxml, returning 'are' ids; params are marcxml and optional control-set-id",
 );
 
 sub search_authority_batch_by_simple_normalize_heading {
     my $self = shift;
     my $client = shift;
-    my $search_set = shift;
-
-    $search_set = [$search_set] unless (ref($search_set) =~ /ARRAY/);
+    my $search_set = [@_];
 
     my $m = $self->method_lookup('open-ils.search.authority.simple_heading.from_xml.atomic');
 
@@ -112,7 +110,7 @@ __PACKAGE__->register_method(
         api_name	=> "open-ils.search.authority.simple_heading.from_xml.batch",
         argc		=> 1, 
         stream      => 1,
-        note		=> "Searches authority data by main entry using marcxml, in control-set batches, returning 'are' ids",
+        note		=> "Searches authority data by main entry using marcxml, in control-set batches, returning 'are' ids; params are hashes of { control-set-id => marcxml }",
 );
 
 

commit df89ecb9bfe15027d0c15c157c29b2f1649b4384
Author: Mike Rylander <mrylander at gmail.com>
Date:   Wed May 11 12:31:13 2011 -0400

    use the new transformed-value starwith operator

diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Search/Authority.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Search/Authority.pm
index 7618f5c..87b63dd 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Search/Authority.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Search/Authority.pm
@@ -71,7 +71,7 @@ sub search_authority_by_simple_normalize_heading {
         from   => 'are',
         where  => {
             deleted => 'f',
-            marc => { '=' => {
+            marc => { 'startwith' => {
                 transform => 'authority.simple_normalize_heading',
                 value     => [ 'authority.simple_normalize_heading' => $marcxml ]
             }},

commit 731f2e7c2fc1af4060b97656f2637fab05b0ebe2
Author: Mike Rylander <mrylander at gmail.com>
Date:   Wed May 11 12:30:08 2011 -0400

    add a special startwith op for use with transformed values (cannot do it another way currently)

diff --git a/Open-ILS/src/c-apps/oils_sql.c b/Open-ILS/src/c-apps/oils_sql.c
index 3f8157d..b79c579 100644
--- a/Open-ILS/src/c-apps/oils_sql.c
+++ b/Open-ILS/src/c-apps/oils_sql.c
@@ -2765,16 +2765,25 @@ static char* searchFieldTransformPredicate( const ClassInfo* class_info, osrfHas
 		right_parens = ")";
 	}
 
+	const char* right_percent = "";
+	const char* real_op       = op;
+
+	if( !strcasecmp( op, "startwith") ) {
+		real_op = "like";
+		right_percent = "|| '%'";
+	}
+
 	growing_buffer* sql_buf = buffer_init( 32 );
 
 	buffer_fadd(
 		sql_buf,
-		"%s%s %s %s %s %s%s",
+		"%s%s %s %s %s%s %s%s",
 		left_parens,
 		field_transform,
-		op,
+		real_op,
 		left_parens,
 		value,
+		right_percent,
 		right_parens,
 		right_parens
 	);

commit fb6f9fd5c7059b21650eb472ed3650994556bb73
Author: Mike Rylander <mrylander at gmail.com>
Date:   Mon May 9 19:36:12 2011 -0400

    Methods for searching by marcxml, constrained (or not) by control set

diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Search/Authority.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Search/Authority.pm
index 37bc763..7618f5c 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Search/Authority.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Search/Authority.pm
@@ -60,6 +60,61 @@ __PACKAGE__->register_method(
         note		=> "Searches authority data for existing controlled terms and crossrefs",
 );              
 
+sub search_authority_by_simple_normalize_heading {
+    my $self = shift;
+    my $client = shift;
+    my $marcxml = shift;
+    my $controlset = shift;
+
+    my $query = {
+        select => { are => ['id'] },
+        from   => 'are',
+        where  => {
+            deleted => 'f',
+            marc => { '=' => {
+                transform => 'authority.simple_normalize_heading',
+                value     => [ 'authority.simple_normalize_heading' => $marcxml ]
+            }},
+            defined($controlset) ? ( control_set => $controlset ) : ()
+        }
+    };
+
+    $client->respond($_->{id}) for @{ new_editor()->json_query( $query ) };
+    $client->respond_complete;
+}
+__PACKAGE__->register_method(
+        method		=> "search_authority_by_simple_normalize_heading",
+        api_name	=> "open-ils.search.authority.simple_heading.from_xml",
+        argc		=> 1, 
+        stream      => 1,
+        note		=> "Searches authority data by main entry using marcxml, returning 'are' ids",
+);
+
+sub search_authority_batch_by_simple_normalize_heading {
+    my $self = shift;
+    my $client = shift;
+    my $search_set = shift;
+
+    $search_set = [$search_set] unless (ref($search_set) =~ /ARRAY/);
+
+    my $m = $self->method_lookup('open-ils.search.authority.simple_heading.from_xml.atomic');
+
+    for my $s ( @$search_set ) {
+        for my $k ( keys %$s ) {
+            $client->respond( { $k => $m->run( $s->{$k}, $k ) } );
+        }
+    }
+
+    $client->respond_complete;
+}
+__PACKAGE__->register_method(
+        method		=> "search_authority_batch_by_simple_normalize_heading",
+        api_name	=> "open-ils.search.authority.simple_heading.from_xml.batch",
+        argc		=> 1, 
+        stream      => 1,
+        note		=> "Searches authority data by main entry using marcxml, in control-set batches, returning 'are' ids",
+);
+
 
 sub crossref_authority {
 	my $self = shift;

commit 635e304d9b111851d4b57f2b9d8a2844ce918f1b
Author: Mike Rylander <mrylander at gmail.com>
Date:   Mon May 9 18:48:53 2011 -0400

    Add an index using authority.simple_normalize_heading for search

diff --git a/Open-ILS/src/sql/Pg/800.fkeys.sql b/Open-ILS/src/sql/Pg/800.fkeys.sql
index ad05dd7..4395c64 100644
--- a/Open-ILS/src/sql/Pg/800.fkeys.sql
+++ b/Open-ILS/src/sql/Pg/800.fkeys.sql
@@ -120,5 +120,6 @@ ALTER TABLE config.org_unit_setting_type ADD CONSTRAINT update_perm_fkey FOREIGN
 ALTER TABLE config.barcode_completion ADD CONSTRAINT config_barcode_completion_org_unit_fkey FOREIGN KEY (org_unit) REFERENCES actor.org_unit (id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
 
 CREATE INDEX by_heading_and_thesaurus ON authority.record_entry (authority.normalize_heading(marc)) WHERE deleted IS FALSE or deleted = FALSE;
+CREATE INDEX by_heading ON authority.record_entry (authority.simple_normalize_heading(marc)) WHERE deleted IS FALSE or deleted = FALSE;
 
 COMMIT;

commit 36c64ccf37bb8e245c84cfb79ffc549bde59346b
Author: Mike Rylander <mrylander at gmail.com>
Date:   Mon May 9 18:19:19 2011 -0400

    Variant of authority.normalize_heading which ignores thesaurus for comparing slim auth records generated from bibs

diff --git a/Open-ILS/src/sql/Pg/011.schema.authority.sql b/Open-ILS/src/sql/Pg/011.schema.authority.sql
index 72d31f6..9d595fc 100644
--- a/Open-ILS/src/sql/Pg/011.schema.authority.sql
+++ b/Open-ILS/src/sql/Pg/011.schema.authority.sql
@@ -129,7 +129,7 @@ CREATE INDEX authority_full_rec_value_tpo_index ON authority.full_rec (value tex
 -- CREATE UNIQUE INDEX unique_by_heading_and_thesaurus
 --   ON authority.record_entry (authority.normalize_heading(marc))
 --   WHERE deleted IS FALSE or deleted = FALSE;
-CREATE OR REPLACE FUNCTION authority.normalize_heading( marcxml TEXT ) RETURNS TEXT AS $func$
+CREATE OR REPLACE FUNCTION authority.normalize_heading( marcxml TEXT, no_thesaurus BOOL ) RETURNS TEXT AS $func$
 DECLARE
     acsaf           authority.control_set_authority_field%ROWTYPE;
     tag_used        TEXT;
@@ -162,7 +162,11 @@ BEGIN
     END LOOP;
 
     IF heading_text <> '' THEN
-        heading_text := tag_used || '_' || thes_code || ' ' || public.naco_normalize(heading_text);
+        IF no_thesaurus IS TRUE THEN
+            heading_text := tag_used || ' ' || public.naco_normalize(heading_text);
+        ELSE
+            heading_text := tag_used || '_' || thes_code || ' ' || public.naco_normalize(heading_text);
+        END IF;
     ELSE
         heading_text := 'NOHEADING_' || thes_code || ' ' || MD5(marcxml);
     END IF;
@@ -171,6 +175,14 @@ BEGIN
 END;
 $func$ LANGUAGE PLPGSQL IMMUTABLE;
 
+CREATE OR REPLACE FUNCTION authority.simple_normalize_heading( marcxml TEXT ) RETURNS TEXT AS $func$
+    SELECT authority.normalize_heading($1, TRUE);
+$func$ LANGUAGE SQL IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION authority.normalize_heading( marcxml TEXT ) RETURNS TEXT AS $func$
+    SELECT authority.normalize_heading($1, FALSE);
+$func$ LANGUAGE SQL IMMUTABLE;
+
 COMMENT ON FUNCTION authority.normalize_heading( TEXT ) IS $$
 Extract the authority heading, thesaurus, and NACO-normalized values
 from an authority record. The primary purpose is to build a unique

commit c923eac2cd5c6d758ae84f5774775a6c2ad06ae9
Author: Mike Rylander <mrylander at gmail.com>
Date:   Mon May 9 16:35:30 2011 -0400

    functions for converting bibs to authorities based on ACS

diff --git a/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js b/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
index 695c1ed..c89d490 100644
--- a/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
+++ b/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
@@ -125,12 +125,24 @@ if(!dojo._hasResource["openils.AuthorityControlSet"]) {
             return openils.AuthorityControlSet._controlsets[''+this.controlSetId(x)];
         },
 
+        bibFieldByTag: function (x) {
+            var me = this;
+            return dojo.filter(
+                me.controlSet()].bib_fields(),
+                function (bf) { if (bf.tag() == x) return true }
+            )[0];
+        },
+
+        bibFields: function (x) {
+            return this.controlSet(x).bib_fields();
+        },
+
         authorityFields: function (x) {
-            return openils.AuthorityControlSet._controlsets[''+this.controlSetId(x)].raw.authority_fields();
+            return this.controlSet(x).raw.authority_fields();
         },
 
         thesauri: function (x) {
-            return openils.AuthorityControlSet._controlsets[''+this.controlSetId(x)].raw.thesauri();
+            return this.controlSet(x).raw.thesauri();
         },
 
         controlSetList : function () {
@@ -142,13 +154,56 @@ if(!dojo._hasResource["openils.AuthorityControlSet"]) {
         },
 
         findControlSetsForTag : function (tag) {
+            var me = this;
             var old_acs = this.controlSetId();
             var acs_list = dojo.filter(
-                this.controlSetList(),
-                function(acs_id) { return (this.controlSet(acs_id).control_map[tag]) }
+                me.controlSetList(),
+                function(acs_id) { return (me.controlSet(acs_id).control_map[tag]) }
             );
             this.controlSetId(old_acs);
             return acs_list;
+        },
+
+        bibToAuthority : function (field) {
+            var b_field = this.bibFieldByTag(field.tag());
+
+            if (b_field) { // construct an marc authority record
+                af = b_field.authority_field();
+                var m = new MARC.Record ({rtype:'AUT'});
+                m.appendField(
+                    new MARC.Field ({
+                        tag : af.tag(),
+                        ind1: field.ind1,
+                        ind2: field.ind2,
+                        subfields: dojo.filter(
+                            field.subfields,
+                            function (sf) { return (af.sf_list().indexOf(sf[0]) > -1) }
+                        )
+                    })
+                );
+
+                return m.toXmlString();
+            }
+
+            return null;
+        },
+
+        bibToAuthorities : function (field) {
+            var auth_list = [];
+            var me = this;
+
+            var old_acs = this.controlSetId();
+            dojo.forEach(
+                me.controlSetList(),
+                function (acs_id) {
+                    var acs = me.controlSet(acs_id);
+                    var x = me.bibToAuthority(field);
+                    if (x) auth_list.push({acs_id : m.toXmlString()});
+                }
+            );
+            this.controlSetId(old_acs);
+
+            return auth_list;
         }
 
     });
@@ -161,7 +216,7 @@ if(!dojo._hasResource["openils.AuthorityControlSet"]) {
             id : -1,
             name : 'Static LoC legacy mapping',
             description : 'Legacy mapping provided as a default',
-            contorl_map : {
+            control_map : {
                 100 : {
                     'a' : { 100 : 'a' },
                     'd' : { 100 : 'd' },

commit 3e6438abe4008b89b11497c32ae466e565d8bb3f
Author: Mike Rylander <mrylander at gmail.com>
Date:   Mon May 9 15:17:41 2011 -0400

    Move the AuthorityControlSet module into openils -- it loads data from the server

diff --git a/Open-ILS/web/js/dojo/MARC/AuthorityControlSet.js b/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
similarity index 88%
rename from Open-ILS/web/js/dojo/MARC/AuthorityControlSet.js
rename to Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
index 5abafc6..695c1ed 100644
--- a/Open-ILS/web/js/dojo/MARC/AuthorityControlSet.js
+++ b/Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
@@ -15,20 +15,20 @@
  * ---------------------------------------------------------------------------
  */
 
-if(!dojo._hasResource["MARC.AuthorityControlSet"]) {
+if(!dojo._hasResource["openils.AuthorityControlSet"]) {
 
     dojo.require('openils.PermaCrud');
     dojo.require('MARC.FixedFields');
 
-    dojo._hasResource["MARC.AuthorityControlSet"] = true;
-    dojo.provide("MARC.AuthorityControlSet");
-    dojo.declare('MARC.AuthorityControlSet', null, {
+    dojo._hasResource["openils.AuthorityControlSet"] = true;
+    dojo.provide("openils.AuthorityControlSet");
+    dojo.declare('openils.AuthorityControlSet', null, {
 
         _controlset : null,
 
         constructor : function(kwargs) {
 
-            if (!MARC.AuthorityControlSet._remote_loaded) {
+            if (!openils.AuthorityControlSet._remote_loaded) {
 
                 // TODO -- push the raw tree into the oils cache for later reuse
 
@@ -37,7 +37,7 @@ if(!dojo._hasResource["MARC.AuthorityControlSet"]) {
 
                 // loop over each acs
                 dojo.forEach( acs_list, function (cs) {
-                    MARC.AuthorityControlSet._controlsets[''+cs.id()] = {
+                    openils.AuthorityControlSet._controlsets[''+cs.id()] = {
                         id : cs.id(),
                         name : cs.name(),
                         description : cs.description(),
@@ -50,8 +50,8 @@ if(!dojo._hasResource["MARC.AuthorityControlSet"]) {
                     // grab the authority fields
                     var acsaf_list = pcrud.search('acsaf', {control_set : cs.id()});
                     var at_list = pcrud.search('at', {control_set : cs.id()});
-                    MARC.AuthorityControlSet._controlsets[''+cs.id()].raw.authority_fields( acsaf_list );
-                    MARC.AuthorityControlSet._controlsets[''+cs.id()].raw.thesauri( at_list );
+                    openils.AuthorityControlSet._controlsets[''+cs.id()].raw.authority_fields( acsaf_list );
+                    openils.AuthorityControlSet._controlsets[''+cs.id()].raw.thesauri( at_list );
 
                     // and loop over each
                     dojo.forEach( acsaf_list, function (csaf) {
@@ -75,8 +75,8 @@ if(!dojo._hasResource["MARC.AuthorityControlSet"]) {
                         var acsbf_list = pcrud.search('acsbf', {authority_field : csaf.id()});
                         csaf.bib_fields( acsbf_list );
 
-                        MARC.AuthorityControlSet._controlsets[''+cs.id()].bib_fields = [].concat(
-                            MARC.AuthorityControlSet._controlsets[''+cs.id()].bib_fields
+                        openils.AuthorityControlSet._controlsets[''+cs.id()].bib_fields = [].concat(
+                            openils.AuthorityControlSet._controlsets[''+cs.id()].bib_fields
                             acsbf_list
                         );
 
@@ -94,19 +94,19 @@ if(!dojo._hasResource["MARC.AuthorityControlSet"]) {
                     });
 
                     // build the authority_tag_map
-                    dojo.forEach( MARC.AuthorityControlSet._controlsets[''+cs.id()].bib_fields, function (bf) {
-                        MARC.AuthorityControlSet._controlsets[''+cs.id()].control_map[bf.tag()] = {};
+                    dojo.forEach( openils.AuthorityControlSet._controlsets[''+cs.id()].bib_fields, function (bf) {
+                        openils.AuthorityControlSet._controlsets[''+cs.id()].control_map[bf.tag()] = {};
                         dojo.forEach( bf.authority_field().sf_list().split(''), function (sf_code) {
-                            MARC.AuthorityControlSet._controlsets[''+cs.id()].control_map[bf.tag()][sf_code] = { bf.authority_field().tag() : sf_code };
+                            openils.AuthorityControlSet._controlsets[''+cs.id()].control_map[bf.tag()][sf_code] = { bf.authority_field().tag() : sf_code };
                         });
                     });
                 });
 
                 
                 if (this.controlSetList().length > 0)
-                    delete MARC.AuthorityControlSet._controlsets['-1'];
+                    delete openils.AuthorityControlSet._controlsets['-1'];
 
-                MARC.AuthorityControlSet._remote_loaded = true;
+                openils.AuthorityControlSet._remote_loaded = true;
             }
 
             if (kwargs.controlSet) {
@@ -122,20 +122,20 @@ if(!dojo._hasResource["MARC.AuthorityControlSet"]) {
         },
 
         controlSet: function (x) {
-            return MARC.AuthorityControlSet._controlsets[''+this.controlSetId(x)];
+            return openils.AuthorityControlSet._controlsets[''+this.controlSetId(x)];
         },
 
         authorityFields: function (x) {
-            return MARC.AuthorityControlSet._controlsets[''+this.controlSetId(x)].raw.authority_fields();
+            return openils.AuthorityControlSet._controlsets[''+this.controlSetId(x)].raw.authority_fields();
         },
 
         thesauri: function (x) {
-            return MARC.AuthorityControlSet._controlsets[''+this.controlSetId(x)].raw.thesauri();
+            return openils.AuthorityControlSet._controlsets[''+this.controlSetId(x)].raw.thesauri();
         },
 
         controlSetList : function () {
             var l = [];
-            for (var i in MARC.AuthorityControlSet._controlsets) {
+            for (var i in openils.AuthorityControlSet._controlsets) {
                 l.push(i);
             }
             return l;
@@ -153,9 +153,9 @@ if(!dojo._hasResource["MARC.AuthorityControlSet"]) {
 
     });
 
-    MARC.AuthorityControlSet._remote_loaded = false;
+    openils.AuthorityControlSet._remote_loaded = false;
 
-    MARC.AuthorityControlSet._controlsets = {
+    openils.AuthorityControlSet._controlsets = {
         // static sorta-LoC setup ... to be overwritten with server data 
         -1 : {
             id : -1,
diff --git a/Open-ILS/xul/staff_client/server/cat/marcedit.js b/Open-ILS/xul/staff_client/server/cat/marcedit.js
index b8b3460..19a582d 100644
--- a/Open-ILS/xul/staff_client/server/cat/marcedit.js
+++ b/Open-ILS/xul/staff_client/server/cat/marcedit.js
@@ -42,6 +42,8 @@ var show_auth_menu = false;
 
 function $(id) { return document.getElementById(id); }
 
+var acs = new openils.AuthorityControlSet ();
+
 function mangle_005() {
     var now = new Date();
     var y = now.getUTCFullYear();
@@ -1243,116 +1245,6 @@ function getContextMenu (target, type) {
     return true;
 }
 
-var authority_tag_map = {
-    100 : ['[100,500,700]',100],
-    700 : ['[100,500,700]',100],
-    800 : ['[100,500,700]',100],
-    110 : ['[110,510,710]',110],
-    610 : ['[110,510,710]',110],
-    710 : ['[110,510,710]',110],
-    810 : ['[110,510,710]',110],
-    111 : ['[111,511,711]',111],
-    611 : ['[111,511,711]',111],
-    711 : ['[111,511,711]',111],
-    811 : ['[111,511,711]',111],
-    240 : ['[130,530,730]',130],
-    130 : ['[130,530,730]',130],
-    730 : ['[130,530,730]',130],
-    830 : ['[130,530,730]',130],
-    600 : ['[100,500,580,581,582,585,700,780,781,782,785]',100],
-    630 : ['[130,530,730]',130],
-    648 : ['[148,548]',148],
-    650 : ['[150,550,580,581,582,585,750,780,781,782,785]',150],
-    651 : ['[151,551,580,581,582,585,751,780,781,782,785]',151],
-    655 : ['[155,555,580,581,582,585,755,780,781,782,785]',155]
-};
-
-function getAuthorityContextMenu (target, sf) {
-    var menu_id = sf.parent(). at tag + ':' + sf. at code + '-authority-context-' + sf;
-
-    var page = 0;
-    var old = dojo.byId( menu_id );
-    if (old) {
-        page = auth_pages[menu_id];
-        old.parentNode.removeChild(old);
-    } else {
-        auth_pages[menu_id] = 0;
-    }
-
-    var sf_popup = createPopup({ id : menu_id, flex : 1 });
-
-    sf_popup.addEventListener("popuphiding", function(event) {
-        if (show_auth_menu) {
-            show_auth_menu = false;
-            getAuthorityContextMenu(target, sf);
-            dojo.byId(menu_id).openPopup();
-        }  
-    }, false);
-
-    context_menus.appendChild( sf_popup );
-
-    if (!authority_tag_map[sf.parent(). at tag]) {
-        sf_popup.appendChild(createLabel( { value : $('catStrings').getString('staff.cat.marcedit.not_authority_field.label') } ) );
-        target.setAttribute('context', 'clipboard');
-        return false;
-    }
-
-    if (sf.toString().replace(/\s*/, '')) {
-        browseAuthority(sf_popup, menu_id, target, sf, 20, page);
-    }
-
-    return true;
-}
-
-/* Apply the complete 1xx */
-function applyFullAuthority ( target, ui_sf, e4x_sf ) {
-    var new_vals = dojo.query('*[tag^="1"]', target);
-    return applyAuthority( target, ui_sf, e4x_sf, new_vals );
-}
-
-function applySelectedAuthority ( target, ui_sf, e4x_sf ) {
-    var new_vals = target.getElementsByAttribute('checked','true');
-    return applyAuthority( target, ui_sf, e4x_sf, new_vals );
-}
-
-function applyAuthority ( target, ui_sf, e4x_sf, new_vals ) {
-    var field = e4x_sf.parent();
-
-    for (var i = 0; i < new_vals.length; i++) {
-
-        var sf_list = field.subfield;
-        for (var j in sf_list) {
-
-            if (sf_list[j]. at code == new_vals[i].getAttribute('subfield')) {
-                sf_list[j] = new_vals[i].getAttribute('value');
-                new_vals[i].setAttribute('subfield','');
-                break;
-            }
-        }
-    }
-
-    for (var i = 0; i < new_vals.length; i++) {
-        if (!new_vals[i].getAttribute('subfield')) continue;
-
-        var val = new_vals[i].getAttribute('value');
-
-        var sf = <subfield code="" xmlns="http://www.loc.gov/MARC21/slim">{val}</subfield>;
-        sf. at code = new_vals[i].getAttribute('subfield');
-
-        field.insertChildAfter(field.subfield[field.subfield.length() - 1], sf);
-    }
-
-    var row = marcDatafield( field );
-
-    var node = ui_sf;
-    while (node.nodeName != 'row') {
-        node = node.parentNode;
-    }
-
-    node.parentNode.replaceChild( row, node );
-    return true;
-}
-
 var control_map = {
     100 : {
         'a' : { 100 : 'a' },
@@ -1611,6 +1503,97 @@ var control_map = {
     }
 };
 
+function getAuthorityContextMenu (target, sf) {
+    var menu_id = sf.parent(). at tag + ':' + sf. at code + '-authority-context-' + sf;
+
+    var page = 0;
+    var old = dojo.byId( menu_id );
+    if (old) {
+        page = auth_pages[menu_id];
+        old.parentNode.removeChild(old);
+    } else {
+        auth_pages[menu_id] = 0;
+    }
+
+    var sf_popup = createPopup({ id : menu_id, flex : 1 });
+
+    sf_popup.addEventListener("popuphiding", function(event) {
+        if (show_auth_menu) {
+            show_auth_menu = false;
+            getAuthorityContextMenu(target, sf);
+            dojo.byId(menu_id).openPopup();
+        }  
+    }, false);
+
+    context_menus.appendChild( sf_popup );
+
+    var found_acs = [];
+    dojo.forEach( acs.controlSetList(), function (acs_id) {
+        if (ac.controlSet(acs_id).control_map[sf.parent(). at tag]) found_acs.push(acs_id);
+    });
+
+    if (!found_acs.length) {
+        sf_popup.appendChild(createLabel( { value : $('catStrings').getString('staff.cat.marcedit.not_authority_field.label') } ) );
+        target.setAttribute('context', 'clipboard');
+        return false;
+    }
+
+    if (sf.toString().replace(/\s*/, '')) {
+        browseAuthority(sf_popup, menu_id, target, sf, 20, page);
+    }
+
+    return true;
+}
+
+/* Apply the complete 1xx */
+function applyFullAuthority ( target, ui_sf, e4x_sf ) {
+    var new_vals = dojo.query('*[tag^="1"]', target);
+    return applyAuthority( target, ui_sf, e4x_sf, new_vals );
+}
+
+function applySelectedAuthority ( target, ui_sf, e4x_sf ) {
+    var new_vals = target.getElementsByAttribute('checked','true');
+    return applyAuthority( target, ui_sf, e4x_sf, new_vals );
+}
+
+function applyAuthority ( target, ui_sf, e4x_sf, new_vals ) {
+    var field = e4x_sf.parent();
+
+    for (var i = 0; i < new_vals.length; i++) {
+
+        var sf_list = field.subfield;
+        for (var j in sf_list) {
+
+            if (sf_list[j]. at code == new_vals[i].getAttribute('subfield')) {
+                sf_list[j] = new_vals[i].getAttribute('value');
+                new_vals[i].setAttribute('subfield','');
+                break;
+            }
+        }
+    }
+
+    for (var i = 0; i < new_vals.length; i++) {
+        if (!new_vals[i].getAttribute('subfield')) continue;
+
+        var val = new_vals[i].getAttribute('value');
+
+        var sf = <subfield code="" xmlns="http://www.loc.gov/MARC21/slim">{val}</subfield>;
+        sf. at code = new_vals[i].getAttribute('subfield');
+
+        field.insertChildAfter(field.subfield[field.subfield.length() - 1], sf);
+    }
+
+    var row = marcDatafield( field );
+
+    var node = ui_sf;
+    while (node.nodeName != 'row') {
+        node = node.parentNode;
+    }
+
+    node.parentNode.replaceChild( row, node );
+    return true;
+}
+
 function validateAuthority (button) {
     var grid = document.getElementById('recGrid');
     var label = button.getAttribute('label');
@@ -1621,48 +1604,54 @@ function validateAuthority (button) {
         var row = rows[i];
         var tag = row.firstChild;
 
-        if (!control_map[tag.value]) continue
-        button.setAttribute('label', label + ' - ' + tag.value);
-
-        var ind1 = tag.nextSibling;
-        var ind2 = ind1.nextSibling;
-        var subfields = ind2.nextSibling.childNodes;
-
-        var tags = {};
-
-        for (var j = 0; j < subfields.length; j++) {
-            var sf = subfields[j];
-            var sf_code = sf.childNodes[1].value;
-            var sf_value = sf.childNodes[2].value;
-
-            if (!control_map[tag.value][sf_code]) continue;
-
-            var found = 0;
-            for (var a_tag in control_map[tag.value][sf_code]) {
-                if (!tags[a_tag]) tags[a_tag] = [];
-                tags[a_tag].push({ term : sf_value, subfield : sf_code });
+        for (var acs_id in acs.controlSetList()) {
+            var control_map = acs.controlSet(acs_id).control_map;
+    
+            if (!control_map[tag.value]) continue
+            button.setAttribute('label', label + ' - ' + tag.value);
+    
+            var ind1 = tag.nextSibling;
+            var ind2 = ind1.nextSibling;
+            var subfields = ind2.nextSibling.childNodes;
+    
+            var tags = {};
+    
+            for (var j = 0; j < subfields.length; j++) {
+                var sf = subfields[j];
+                var sf_code = sf.childNodes[1].value;
+                var sf_value = sf.childNodes[2].value;
+    
+                if (!control_map[tag.value][sf_code]) continue;
+    
+                var found = 0;
+                for (var a_tag in control_map[tag.value][sf_code]) {
+                    if (!tags[a_tag]) tags[a_tag] = [];
+                    tags[a_tag].push({ term : sf_value, subfield : sf_code });
+                }
+    
+            }
+    
+            for (var val_tag in tags) {
+                var auth_data = validateBibField( acs_id, [val_tag], tags[val_tag]);
+                var res = new XML( auth_data.responseText );
+                found = parseInt(res.gw::payload.gw::string.toString());
+                if (found) break;
+            }
+    
+            // XXX If adt, etc should be validated separately from vxz, etc then move this up into the above for loop
+            for (var j = 0; j < subfields.length; j++) {
+                var sf = subfields[j];
+                if (!found) {
+                    dojo.removeClass(sf.childNodes[2], 'marcValidated');
+                    dojo.addClass(sf.childNodes[2], 'marcUnvalidated');
+                } else {
+                    dojo.removeClass(sf.childNodes[2], 'marcUnvalidated');
+                    dojo.addClass(sf.childNodes[2], 'marcValidated');
+                }
             }
 
-        }
-
-        for (var val_tag in tags) {
-            var auth_data = validateBibField( [val_tag], tags[val_tag]);
-            var res = new XML( auth_data.responseText );
-            found = parseInt(res.gw::payload.gw::string.toString());
             if (found) break;
         }
-
-        // XXX If adt, etc should be validated separately from vxz, etc then move this up into the above for loop
-        for (var j = 0; j < subfields.length; j++) {
-            var sf = subfields[j];
-            if (!found) {
-                dojo.removeClass(sf.childNodes[2], 'marcValidated');
-                dojo.addClass(sf.childNodes[2], 'marcUnvalidated');
-            } else {
-                dojo.removeClass(sf.childNodes[2], 'marcUnvalidated');
-                dojo.addClass(sf.childNodes[2], 'marcValidated');
-            }
-        }
     }
 
     button.setAttribute('label', label);

commit 2151d7ea85b4c70c89ee6c928c9291441525c29f
Author: Mike Rylander <mrylander at gmail.com>
Date:   Mon May 9 15:15:41 2011 -0400

    Utility methods

diff --git a/Open-ILS/web/js/dojo/MARC/AuthorityControlSet.js b/Open-ILS/web/js/dojo/MARC/AuthorityControlSet.js
index 1acfadd..5abafc6 100644
--- a/Open-ILS/web/js/dojo/MARC/AuthorityControlSet.js
+++ b/Open-ILS/web/js/dojo/MARC/AuthorityControlSet.js
@@ -49,7 +49,9 @@ if(!dojo._hasResource["MARC.AuthorityControlSet"]) {
 
                     // grab the authority fields
                     var acsaf_list = pcrud.search('acsaf', {control_set : cs.id()});
+                    var at_list = pcrud.search('at', {control_set : cs.id()});
                     MARC.AuthorityControlSet._controlsets[''+cs.id()].raw.authority_fields( acsaf_list );
+                    MARC.AuthorityControlSet._controlsets[''+cs.id()].raw.thesauri( at_list );
 
                     // and loop over each
                     dojo.forEach( acsaf_list, function (csaf) {
@@ -123,12 +125,30 @@ if(!dojo._hasResource["MARC.AuthorityControlSet"]) {
             return MARC.AuthorityControlSet._controlsets[''+this.controlSetId(x)];
         },
 
+        authorityFields: function (x) {
+            return MARC.AuthorityControlSet._controlsets[''+this.controlSetId(x)].raw.authority_fields();
+        },
+
+        thesauri: function (x) {
+            return MARC.AuthorityControlSet._controlsets[''+this.controlSetId(x)].raw.thesauri();
+        },
+
         controlSetList : function () {
             var l = [];
             for (var i in MARC.AuthorityControlSet._controlsets) {
                 l.push(i);
             }
             return l;
+        },
+
+        findControlSetsForTag : function (tag) {
+            var old_acs = this.controlSetId();
+            var acs_list = dojo.filter(
+                this.controlSetList(),
+                function(acs_id) { return (this.controlSet(acs_id).control_map[tag]) }
+            );
+            this.controlSetId(old_acs);
+            return acs_list;
         }
 
     });

commit 52f13d946eaa663b6f7a94d69150347b2aa3408e
Author: Mike Rylander <mrylander at gmail.com>
Date:   Mon May 9 15:13:41 2011 -0400

    Bug fixes; Add a method for setting fixed fields; Set the Type FF when rtype=AUT

diff --git a/Open-ILS/web/js/dojo/MARC/FixedFields.js b/Open-ILS/web/js/dojo/MARC/FixedFields.js
index 9a92c30..ae75271 100644
--- a/Open-ILS/web/js/dojo/MARC/FixedFields.js
+++ b/Open-ILS/web/js/dojo/MARC/FixedFields.js
@@ -1480,7 +1480,7 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     }
     
     MARC.Record.prototype.videorecordingFormatName = function () {
-    	var _7 = this.field('007');
+    	var _7 = this.field('007').data;
     
     	if (_7.match(/^v/)) {
     		var _v_e = _7.substr(
@@ -1495,7 +1495,7 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     }
     
     MARC.Record.prototype.videorecordingFormatCode = function () {
-    	var _7 = this.field('007');
+    	var _7 = this.field('007').data;
     
     	if (_7.match(/^v/)) {
     		return _7.substr(
@@ -1509,9 +1509,9 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
     
     MARC.Record.prototype.extractFixedField = function (field, dflt) {
     
-    	var _l = this.field('007');
-    	var _8 = this.field('008');
-    	var _6 = this.field('006');
+    	var _l = this.leader;
+    	var _8 = this.field('008').data;
+    	var _6 = this.field('006').data;
     
     	var rtype = this.recordType();
     
@@ -1572,4 +1572,56 @@ if(!dojo._hasResource["MARC.FixedFields"]) {
 
     	return val;
     }
+
+    MARC.Record.prototype.setFixedField = function (field, value) {
+    
+    	var _l = this.leader;
+    	var _8 = this.field('008').data;
+    	var _6 = this.field('006').data;
+    
+    	var rtype = this.recordType();
+    
+    	var val;
+    
+    	if (MARC.Record._ff_pos[field].ldr) {
+    		if (MARC.Record._ff_pos[field].ldr[rtype]) { // It's in the leader
+                val = value.substr(0, MARC.Record._ff_pos[field].ldr[rtype].len);
+                this.leader =
+                    _l.substring(0, MARC.Record._ff_pos[field].ldr[rtype].start) +
+                    val +
+                    _l.substring(
+                        MARC.Record._ff_pos[field].ldr[rtype].start
+                        + MARC.Record._ff_pos[field].ldr[rtype].len
+                    );
+    		}
+    	} else if (MARC.Record._ff_pos[field]._8) {
+    		if (MARC.Record._ff_pos[field]._8[rtype]) { // Nope, it's in the 008
+                val = value.substr(0, MARC.Record._ff_pos[field]._8[rtype].len);
+                this.field('008').update(
+                    _8.substring(0, MARC.Record._ff_pos[field]._8[rtype].start) +
+                    val +
+                    _8.substring(
+                        MARC.Record._ff_pos[field]._8[rtype].start
+                        + MARC.Record._ff_pos[field]._8[rtype].len
+                    )
+                );
+    		}
+    	}
+    
+    	if (!val && MARC.Record._ff_pos[field]._6) {
+    		if (MARC.Record._ff_pos[field]._6[rtype]) { // ok, maybe the 006?
+                val = value.substr(0, MARC.Record._ff_pos[field]._6[rtype].len);
+                this.field('006').update(
+                    _6.substring(0, MARC.Record._ff_pos[field]._6[rtype].start) +
+                    val +
+                    _6.substring(
+                        MARC.Record._ff_pos[field]._6[rtype].start
+                        + MARC.Record._ff_pos[field]._6[rtype].len
+                    )
+                );
+    		}
+    	}
+
+    	return val;
+    }
 } 
diff --git a/Open-ILS/web/js/dojo/MARC/Record.js b/Open-ILS/web/js/dojo/MARC/Record.js
index 3aea14c..8bb6a1b 100644
--- a/Open-ILS/web/js/dojo/MARC/Record.js
+++ b/Open-ILS/web/js/dojo/MARC/Record.js
@@ -43,6 +43,12 @@ if(!dojo._hasResource["MARC.Record"]) {
                 this.fromBreaker(kwargs.marcbreaker);
                 if (this.onLoad) this.onLoad();
             }
+
+            if (kwargs.rtype == 'AUT') {
+                dojo.require('MARC.FixedFields');
+                this.setFixedField('Type','z');
+            }
+
         },
 
         title : function () { return this.subfield('245','a') },

commit bfd2f1fbc65368a799731adaeb5d863e61f1c4cf
Author: Mike Rylander <mrylander at gmail.com>
Date:   Mon May 9 15:12:04 2011 -0400

    Move the function to before its first use

diff --git a/Open-ILS/src/sql/Pg/011.schema.authority.sql b/Open-ILS/src/sql/Pg/011.schema.authority.sql
index 993c0f3..72d31f6 100644
--- a/Open-ILS/src/sql/Pg/011.schema.authority.sql
+++ b/Open-ILS/src/sql/Pg/011.schema.authority.sql
@@ -125,6 +125,59 @@ CREATE INDEX authority_full_rec_index_vector_idx ON authority.full_rec USING GIS
 /* Enable LIKE to use an index for database clusters with locales other than C or POSIX */
 CREATE INDEX authority_full_rec_value_tpo_index ON authority.full_rec (value text_pattern_ops);
 
+-- Intended to be used in a unique index on authority.record_entry like so:
+-- CREATE UNIQUE INDEX unique_by_heading_and_thesaurus
+--   ON authority.record_entry (authority.normalize_heading(marc))
+--   WHERE deleted IS FALSE or deleted = FALSE;
+CREATE OR REPLACE FUNCTION authority.normalize_heading( marcxml TEXT ) RETURNS TEXT AS $func$
+DECLARE
+    acsaf           authority.control_set_authority_field%ROWTYPE;
+    tag_used        TEXT;
+    sf              TEXT;
+    thes_code       TEXT;
+    cset            INT;
+    heading_text    TEXT;
+    tmp_text        TEXT;
+BEGIN
+    thes_code := vandelay.marc21_extract_fixed_field(marcxml,'Subj');
+    IF thes_code IS NULL THEN
+        thes_code := '|';
+    END IF;
+
+    SELECT control_set INTO cset FROM authority.thesaurus WHERE code = thes_code;
+    IF NOT FOUND THEN
+        cset = 1;
+    END IF;
+
+    heading_text := '';
+    FOR acsaf IN SELECT * FROM authority.control_set_authority_field WHERE control_set = cset AND main_entry IS NULL LOOP
+        tag_use := acsaf.tag;
+        FOR sf IN SELECT * FROM regexp_split_to_table(acsaf.sf_list,'') LOOP
+            tmp_text := oils_xpath_string('//*[@tag="'||tag_used||'"]/*[@code="'||sf||'"]', marcxml);
+            IF tmp_text IS NOT NULL THEN
+                heading_text := heading_text || E'\U2021' || sf || ' ' || tmp_text;
+            END IF;
+        END LOOP;
+        EXIT WHEN heading_text <> '';
+    END LOOP;
+
+    IF heading_text <> '' THEN
+        heading_text := tag_used || '_' || thes_code || ' ' || public.naco_normalize(heading_text);
+    ELSE
+        heading_text := 'NOHEADING_' || thes_code || ' ' || MD5(marcxml);
+    END IF;
+
+    RETURN heading_text;
+END;
+$func$ LANGUAGE PLPGSQL IMMUTABLE;
+
+COMMENT ON FUNCTION authority.normalize_heading( TEXT ) IS $$
+Extract the authority heading, thesaurus, and NACO-normalized values
+from an authority record. The primary purpose is to build a unique
+index to defend against duplicated authority records from the same
+thesaurus.
+$$;
+
 -- Adding indexes using oils_xpath_string() for the main entry tags described in
 -- authority.control_set_authority_field would speed this up, if we ever want to use it, though
 -- the existing index on authority.normalize_heading() helps already with a record in hand
diff --git a/Open-ILS/src/sql/Pg/020.schema.functions.sql b/Open-ILS/src/sql/Pg/020.schema.functions.sql
index d1621e6..c086a01 100644
--- a/Open-ILS/src/sql/Pg/020.schema.functions.sql
+++ b/Open-ILS/src/sql/Pg/020.schema.functions.sql
@@ -327,59 +327,6 @@ Search "up" the org_unit tree until we find the first occurrence of an
 org_unit_setting with the given name.
 $$;
 
--- Intended to be used in a unique index on authority.record_entry like so:
--- CREATE UNIQUE INDEX unique_by_heading_and_thesaurus
---   ON authority.record_entry (authority.normalize_heading(marc))
---   WHERE deleted IS FALSE or deleted = FALSE;
-CREATE OR REPLACE FUNCTION authority.normalize_heading( marcxml TEXT ) RETURNS TEXT AS $func$
-DECLARE
-    acsaf           authority.control_set_authority_field%ROWTYPE;
-    tag_used        TEXT;
-    sf              TEXT;
-    thes_code       TEXT;
-    cset            INT;
-    heading_text    TEXT;
-    tmp_text        TEXT;
-BEGIN
-    thes_code := vandelay.marc21_extract_fixed_field(marcxml,'Subj');
-    IF thes_code IS NULL THEN
-        thes_code := '|';
-    END IF;
-
-    SELECT control_set INTO cset FROM authority.thesaurus WHERE code = thes_code;
-    IF NOT FOUND THEN
-        cset = 1;
-    END IF;
-
-    heading_text := '';
-    FOR acsaf IN SELECT * FROM authority.control_set_authority_field WHERE control_set = cset AND main_entry IS NULL LOOP
-        tag_use := acsaf.tag;
-        FOR sf IN SELECT * FROM regexp_split_to_table(acsaf.sf_list,'') LOOP
-            tmp_text := oils_xpath_string('//*[@tag="'||tag_used||'"]/*[@code="'||sf||'"]', marcxml);
-            IF tmp_text IS NOT NULL THEN
-                heading_text := heading_text || E'\U2021' || sf || ' ' || tmp_text;
-            END IF;
-        END LOOP;
-        EXIT WHEN heading_text <> '';
-    END LOOP;
-
-    IF heading_text <> '' THEN
-        heading_text := tag_used || '_' || thes_code || ' ' || public.naco_normalize(heading_text);
-    ELSE
-        heading_text := 'NOHEADING_' || thes_code || ' ' || MD5(marcxml);
-    END IF;
-
-    RETURN heading_text;
-END;
-$func$ LANGUAGE PLPGSQL IMMUTABLE;
-
-COMMENT ON FUNCTION authority.normalize_heading( TEXT ) IS $$
-Extract the authority heading, thesaurus, and NACO-normalized values
-from an authority record. The primary purpose is to build a unique
-index to defend against duplicated authority records from the same
-thesaurus.
-$$;
-
 CREATE OR REPLACE FUNCTION evergreen.get_barcodes(select_ou INT, type TEXT, in_barcode TEXT) RETURNS SETOF evergreen.barcode_set AS $$
 DECLARE
     cur_barcode TEXT;
@@ -468,3 +415,4 @@ Given user input, find an appropriate barcode in the proper class.
 
 Will add prefix/suffix information to do so, and return all results.
 $$;
+

commit 1376352fb9f18b5784a20ac81889df6b0e251fe4
Author: Mike Rylander <mrylander at gmail.com>
Date:   Mon May 9 14:21:17 2011 -0400

    Only load control sets once, set the default to the first (for now... YAOUS later)

diff --git a/Open-ILS/web/js/dojo/MARC/AuthorityControlSet.js b/Open-ILS/web/js/dojo/MARC/AuthorityControlSet.js
index 9422d0e..1acfadd 100644
--- a/Open-ILS/web/js/dojo/MARC/AuthorityControlSet.js
+++ b/Open-ILS/web/js/dojo/MARC/AuthorityControlSet.js
@@ -24,7 +24,7 @@ if(!dojo._hasResource["MARC.AuthorityControlSet"]) {
     dojo.provide("MARC.AuthorityControlSet");
     dojo.declare('MARC.AuthorityControlSet', null, {
 
-        _controlset : -1,
+        _controlset : null,
 
         constructor : function(kwargs) {
 
@@ -37,7 +37,7 @@ if(!dojo._hasResource["MARC.AuthorityControlSet"]) {
 
                 // loop over each acs
                 dojo.forEach( acs_list, function (cs) {
-                    MARC.AuthorityControlSet._controlsets[cs.id()] = {
+                    MARC.AuthorityControlSet._controlsets[''+cs.id()] = {
                         id : cs.id(),
                         name : cs.name(),
                         description : cs.description(),
@@ -49,7 +49,7 @@ if(!dojo._hasResource["MARC.AuthorityControlSet"]) {
 
                     // grab the authority fields
                     var acsaf_list = pcrud.search('acsaf', {control_set : cs.id()});
-                    MARC.AuthorityControlSet._controlsets[cs.name()].raw.authority_fields( acsaf_list );
+                    MARC.AuthorityControlSet._controlsets[''+cs.id()].raw.authority_fields( acsaf_list );
 
                     // and loop over each
                     dojo.forEach( acsaf_list, function (csaf) {
@@ -73,8 +73,8 @@ if(!dojo._hasResource["MARC.AuthorityControlSet"]) {
                         var acsbf_list = pcrud.search('acsbf', {authority_field : csaf.id()});
                         csaf.bib_fields( acsbf_list );
 
-                        MARC.AuthorityControlSet._controlsets[cs.name()].bib_fields = [].concat(
-                            MARC.AuthorityControlSet._controlsets[cs.name()].bib_fields
+                        MARC.AuthorityControlSet._controlsets[''+cs.id()].bib_fields = [].concat(
+                            MARC.AuthorityControlSet._controlsets[''+cs.id()].bib_fields
                             acsbf_list
                         );
 
@@ -92,26 +92,35 @@ if(!dojo._hasResource["MARC.AuthorityControlSet"]) {
                     });
 
                     // build the authority_tag_map
-                    dojo.forEach( MARC.AuthorityControlSet._controlsets[cs.name()].bib_fields, function (bf) {
-                        MARC.AuthorityControlSet._controlsets[cs.name()].authority_tag_map[bf.tag()] = [/*XXX*/];
-                        MARC.AuthorityControlSet._controlsets[cs.name()].control_map[bf.tag()] = {/*XXX*/};
+                    dojo.forEach( MARC.AuthorityControlSet._controlsets[''+cs.id()].bib_fields, function (bf) {
+                        MARC.AuthorityControlSet._controlsets[''+cs.id()].control_map[bf.tag()] = {};
+                        dojo.forEach( bf.authority_field().sf_list().split(''), function (sf_code) {
+                            MARC.AuthorityControlSet._controlsets[''+cs.id()].control_map[bf.tag()][sf_code] = { bf.authority_field().tag() : sf_code };
+                        });
                     });
                 });
 
+                
+                if (this.controlSetList().length > 0)
+                    delete MARC.AuthorityControlSet._controlsets['-1'];
+
+                MARC.AuthorityControlSet._remote_loaded = true;
             }
 
             if (kwargs.controlSet) {
-                this._controlset = kwargs.controlSet;
+                this.controlSetId( kwargs.controlSet );
+            } else {
+                this.controlSetId( this.controlSetList().sort(function(a,b){return (a - b)}) );
             }
         },
 
         controlSetId: function (x) {
-            if (x) this._controlset = x;
+            if (x) this._controlset = ''+x;
             return this._controlset;
         },
 
         controlSet: function (x) {
-            return MARC.AuthorityControlSet._controlsets[this.controlSetId(x)];
+            return MARC.AuthorityControlSet._controlsets[''+this.controlSetId(x)];
         },
 
         controlSetList : function () {
@@ -132,29 +141,6 @@ if(!dojo._hasResource["MARC.AuthorityControlSet"]) {
             id : -1,
             name : 'Static LoC legacy mapping',
             description : 'Legacy mapping provided as a default',
-            authority_tag_map : {
-                100 : [[100,500,700],100],
-                700 : [[100,500,700],100],
-                800 : [[100,500,700],100],
-                110 : [[110,510,710],110],
-                610 : [[110,510,710],110],
-                710 : [[110,510,710],110],
-                810 : [[110,510,710],110],
-                111 : [[111,511,711],111],
-                611 : [[111,511,711],111],
-                711 : [[111,511,711],111],
-                811 : [[111,511,711],111],
-                240 : [[130,530,730],130],
-                130 : [[130,530,730],130],
-                730 : [[130,530,730],130],
-                830 : [[130,530,730],130],
-                600 : [[100,500,580,581,582,585,700,780,781,782,785],100],
-                630 : [[130,530,730],130],
-                648 : [[148,548],148],
-                650 : [[150,550,580,581,582,585,750,780,781,782,785],150],
-                651 : [[151,551,580,581,582,585,751,780,781,782,785],151],
-                655 : [[155,555,580,581,582,585,755,780,781,782,785],155]
-            },
             contorl_map : {
                 100 : {
                     'a' : { 100 : 'a' },

commit 3457b554dc84bdca171ad8458f428ca9587bcf24
Author: Mike Rylander <mrylander at gmail.com>
Date:   Fri May 6 16:53:17 2011 -0400

    Add some logic for fetching stored controlsets and switching amongst them

diff --git a/Open-ILS/web/js/dojo/MARC/AuthorityControlSet.js b/Open-ILS/web/js/dojo/MARC/AuthorityControlSet.js
index 2b3bfa4..9422d0e 100644
--- a/Open-ILS/web/js/dojo/MARC/AuthorityControlSet.js
+++ b/Open-ILS/web/js/dojo/MARC/AuthorityControlSet.js
@@ -24,288 +24,395 @@ if(!dojo._hasResource["MARC.AuthorityControlSet"]) {
     dojo.provide("MARC.AuthorityControlSet");
     dojo.declare('MARC.AuthorityControlSet', null, {
 
-        // static sorta-LoC setup ... to be overwritten with server data 
-        _loc_authority_tag_map = {
-            100 : [[100,500,700],100],
-            700 : [[100,500,700],100],
-            800 : [[100,500,700],100],
-            110 : [[110,510,710],110],
-            610 : [[110,510,710],110],
-            710 : [[110,510,710],110],
-            810 : [[110,510,710],110],
-            111 : [[111,511,711],111],
-            611 : [[111,511,711],111],
-            711 : [[111,511,711],111],
-            811 : [[111,511,711],111],
-            240 : [[130,530,730],130],
-            130 : [[130,530,730],130],
-            730 : [[130,530,730],130],
-            830 : [[130,530,730],130],
-            600 : [[100,500,580,581,582,585,700,780,781,782,785],100],
-            630 : [[130,530,730],130],
-            648 : [[148,548],148],
-            650 : [[150,550,580,581,582,585,750,780,781,782,785],150],
-            651 : [[151,551,580,581,582,585,751,780,781,782,785],151],
-            655 : [[155,555,580,581,582,585,755,780,781,782,785],155]
+        _controlset : -1,
+
+        constructor : function(kwargs) {
+
+            if (!MARC.AuthorityControlSet._remote_loaded) {
+
+                // TODO -- push the raw tree into the oils cache for later reuse
+
+                var pcrud = new openils.PermaCrud();
+                var acs_list = pcrud.retrieveAll('acs');
+
+                // loop over each acs
+                dojo.forEach( acs_list, function (cs) {
+                    MARC.AuthorityControlSet._controlsets[cs.id()] = {
+                        id : cs.id(),
+                        name : cs.name(),
+                        description : cs.description(),
+                        authority_tag_map : {},
+                        control_map : {},
+                        bib_fields : [],
+                        raw : cs
+                    };
+
+                    // grab the authority fields
+                    var acsaf_list = pcrud.search('acsaf', {control_set : cs.id()});
+                    MARC.AuthorityControlSet._controlsets[cs.name()].raw.authority_fields( acsaf_list );
+
+                    // and loop over each
+                    dojo.forEach( acsaf_list, function (csaf) {
+                        // link the main entry if we're subordinate
+                        if (csaf.main_entry()) {
+                            csaf.main_entry(
+                                dojo.filter(acsaf_list, function (x) {
+                                    return x.id() == csaf.main_entry();
+                                })[0]
+                            );
+                        }
+
+                        // link the sub entries if we're main
+                        csaf.sub_entries(
+                            dojo.filter(acsaf_list, function (x) {
+                                return x.main_entry() == csaf.id();
+                            })[0]
+                        );
+
+                        // now, bib fields
+                        var acsbf_list = pcrud.search('acsbf', {authority_field : csaf.id()});
+                        csaf.bib_fields( acsbf_list );
+
+                        MARC.AuthorityControlSet._controlsets[cs.name()].bib_fields = [].concat(
+                            MARC.AuthorityControlSet._controlsets[cs.name()].bib_fields
+                            acsbf_list
+                        );
+
+                        dojo.forEach( acsbf_list, function (csbf) {
+                            // link the main entry if we're subordinate
+                            if (csbf.authority_field()) {
+                                csbf.authority_field(
+                                    dojo.filter(acsaf_list, function (x) {
+                                        return x.a() == csbf.authority_field();
+                                    })[0]
+                                );
+                            }
+    
+                        });
+                    });
+
+                    // build the authority_tag_map
+                    dojo.forEach( MARC.AuthorityControlSet._controlsets[cs.name()].bib_fields, function (bf) {
+                        MARC.AuthorityControlSet._controlsets[cs.name()].authority_tag_map[bf.tag()] = [/*XXX*/];
+                        MARC.AuthorityControlSet._controlsets[cs.name()].control_map[bf.tag()] = {/*XXX*/};
+                    });
+                });
+
+            }
+
+            if (kwargs.controlSet) {
+                this._controlset = kwargs.controlSet;
+            }
         },
 
-        _loc_control_map = {
-            100 : {
-                'a' : { 100 : 'a' },
-                'd' : { 100 : 'd' },
-                'e' : { 100 : 'e' },
-                'q' : { 100 : 'q' }
-            },
-            110 : {
-                'a' : { 110 : 'a' },
-                'd' : { 110 : 'd' }
-            },
-            111 : {
-                'a' : { 111 : 'a' },
-                'd' : { 111 : 'd' }
-            },
-            130 : {
-                'a' : { 130 : 'a' },
-                'd' : { 130 : 'd' }
-            },
-            240 : {
-                'a' : { 130 : 'a' },
-                'd' : { 130 : 'd' }
-            },
-            400 : {
-                'a' : { 100 : 'a' },
-                'd' : { 100 : 'd' }
-            },
-            410 : {
-                'a' : { 110 : 'a' },
-                'd' : { 110 : 'd' }
-            },
-            411 : {
-                'a' : { 111 : 'a' },
-                'd' : { 111 : 'd' }
-            },
-            440 : {
-                'a' : { 130 : 'a' },
-                'n' : { 130 : 'n' },
-                'p' : { 130 : 'p' }
-            },
-            700 : {
-                'a' : { 100 : 'a' },
-                'd' : { 100 : 'd' },
-                'q' : { 100 : 'q' },
-                't' : { 100 : 't' }
-            },
-            710 : {
-                'a' : { 110 : 'a' },
-                'd' : { 110 : 'd' }
-            },
-            711 : {
-                'a' : { 111 : 'a' },
-                'c' : { 111 : 'c' },
-                'd' : { 111 : 'd' }
-            },
-            730 : {
-                'a' : { 130 : 'a' },
-                'd' : { 130 : 'd' }
-            },
-            800 : {
-                'a' : { 100 : 'a' },
-                'd' : { 100 : 'd' }
-            },
-            810 : {
-                'a' : { 110 : 'a' },
-                'd' : { 110 : 'd' }
-            },
-            811 : {
-                'a' : { 111 : 'a' },
-                'd' : { 111 : 'd' }
-            },
-            830 : {
-                'a' : { 130 : 'a' },
-                'd' : { 130 : 'd' }
+        controlSetId: function (x) {
+            if (x) this._controlset = x;
+            return this._controlset;
+        },
+
+        controlSet: function (x) {
+            return MARC.AuthorityControlSet._controlsets[this.controlSetId(x)];
+        },
+
+        controlSetList : function () {
+            var l = [];
+            for (var i in MARC.AuthorityControlSet._controlsets) {
+                l.push(i);
+            }
+            return l;
+        }
+
+    });
+
+    MARC.AuthorityControlSet._remote_loaded = false;
+
+    MARC.AuthorityControlSet._controlsets = {
+        // static sorta-LoC setup ... to be overwritten with server data 
+        -1 : {
+            id : -1,
+            name : 'Static LoC legacy mapping',
+            description : 'Legacy mapping provided as a default',
+            authority_tag_map : {
+                100 : [[100,500,700],100],
+                700 : [[100,500,700],100],
+                800 : [[100,500,700],100],
+                110 : [[110,510,710],110],
+                610 : [[110,510,710],110],
+                710 : [[110,510,710],110],
+                810 : [[110,510,710],110],
+                111 : [[111,511,711],111],
+                611 : [[111,511,711],111],
+                711 : [[111,511,711],111],
+                811 : [[111,511,711],111],
+                240 : [[130,530,730],130],
+                130 : [[130,530,730],130],
+                730 : [[130,530,730],130],
+                830 : [[130,530,730],130],
+                600 : [[100,500,580,581,582,585,700,780,781,782,785],100],
+                630 : [[130,530,730],130],
+                648 : [[148,548],148],
+                650 : [[150,550,580,581,582,585,750,780,781,782,785],150],
+                651 : [[151,551,580,581,582,585,751,780,781,782,785],151],
+                655 : [[155,555,580,581,582,585,755,780,781,782,785],155]
             },
-            600 : {
-                'a' : { 100 : 'a' },
-                'd' : { 100 : 'd' },
-                'q' : { 100 : 'q' },
-                't' : { 100 : 't' },
-                'v' : { 180 : 'v',
-                    100 : 'v',
-                    181 : 'v',
-                    182 : 'v',
-                    185 : 'v'
+            contorl_map : {
+                100 : {
+                    'a' : { 100 : 'a' },
+                    'd' : { 100 : 'd' },
+                    'e' : { 100 : 'e' },
+                    'q' : { 100 : 'q' }
                 },
-                'x' : { 180 : 'x',
-                    100 : 'x',
-                    181 : 'x',
-                    182 : 'x',
-                    185 : 'x'
+                110 : {
+                    'a' : { 110 : 'a' },
+                    'd' : { 110 : 'd' }
                 },
-                'y' : { 180 : 'y',
-                    100 : 'y',
-                    181 : 'y',
-                    182 : 'y',
-                    185 : 'y'
+                111 : {
+                    'a' : { 111 : 'a' },
+                    'd' : { 111 : 'd' }
                 },
-                'z' : { 180 : 'z',
-                    100 : 'z',
-                    181 : 'z',
-                    182 : 'z',
-                    185 : 'z'
-                }
-            },
-            610 : {
-                'a' : { 110 : 'a' },
-                'd' : { 110 : 'd' },
-                't' : { 110 : 't' },
-                'v' : { 180 : 'v',
-                    110 : 'v',
-                    181 : 'v',
-                    182 : 'v',
-                    185 : 'v'
+                130 : {
+                    'a' : { 130 : 'a' },
+                    'd' : { 130 : 'd' }
                 },
-                'x' : { 180 : 'x',
-                    110 : 'x',
-                    181 : 'x',
-                    182 : 'x',
-                    185 : 'x'
+                240 : {
+                    'a' : { 130 : 'a' },
+                    'd' : { 130 : 'd' }
                 },
-                'y' : { 180 : 'y',
-                    110 : 'y',
-                    181 : 'y',
-                    182 : 'y',
-                    185 : 'y'
+                400 : {
+                    'a' : { 100 : 'a' },
+                    'd' : { 100 : 'd' }
                 },
-                'z' : { 180 : 'z',
-                    110 : 'z',
-                    181 : 'z',
-                    182 : 'z',
-                    185 : 'z'
-                }
-            },
-            611 : {
-                'a' : { 111 : 'a' },
-                'd' : { 111 : 'd' },
-                't' : { 111 : 't' },
-                'v' : { 180 : 'v',
-                    111 : 'v',
-                    181 : 'v',
-                    182 : 'v',
-                    185 : 'v'
+                410 : {
+                    'a' : { 110 : 'a' },
+                    'd' : { 110 : 'd' }
                 },
-                'x' : { 180 : 'x',
-                    111 : 'x',
-                    181 : 'x',
-                    182 : 'x',
-                    185 : 'x'
+                411 : {
+                    'a' : { 111 : 'a' },
+                    'd' : { 111 : 'd' }
                 },
-                'y' : { 180 : 'y',
-                    111 : 'y',
-                    181 : 'y',
-                    182 : 'y',
-                    185 : 'y'
+                440 : {
+                    'a' : { 130 : 'a' },
+                    'n' : { 130 : 'n' },
+                    'p' : { 130 : 'p' }
                 },
-                'z' : { 180 : 'z',
-                    111 : 'z',
-                    181 : 'z',
-                    182 : 'z',
-                    185 : 'z'
-                }
-            },
-            630 : {
-                'a' : { 130 : 'a' },
-                'd' : { 130 : 'd' }
-            },
-            648 : {
-                'a' : { 148 : 'a' },
-                'v' : { 148 : 'v' },
-                'x' : { 148 : 'x' },
-                'y' : { 148 : 'y' },
-                'z' : { 148 : 'z' }
-            },
-            650 : {
-                'a' : { 150 : 'a' },
-                'b' : { 150 : 'b' },
-                'v' : { 180 : 'v',
-                    150 : 'v',
-                    181 : 'v',
-                    182 : 'v',
-                    185 : 'v'
+                700 : {
+                    'a' : { 100 : 'a' },
+                    'd' : { 100 : 'd' },
+                    'q' : { 100 : 'q' },
+                    't' : { 100 : 't' }
                 },
-                'x' : { 180 : 'x',
-                    150 : 'x',
-                    181 : 'x',
-                    182 : 'x',
-                    185 : 'x'
+                710 : {
+                    'a' : { 110 : 'a' },
+                    'd' : { 110 : 'd' }
                 },
-                'y' : { 180 : 'y',
-                    150 : 'y',
-                    181 : 'y',
-                    182 : 'y',
-                    185 : 'y'
+                711 : {
+                    'a' : { 111 : 'a' },
+                    'c' : { 111 : 'c' },
+                    'd' : { 111 : 'd' }
                 },
-                'z' : { 180 : 'z',
-                    150 : 'z',
-                    181 : 'z',
-                    182 : 'z',
-                    185 : 'z'
-                }
-            },
-            651 : {
-                'a' : { 151 : 'a' },
-                'v' : { 180 : 'v',
-                    151 : 'v',
-                    181 : 'v',
-                    182 : 'v',
-                    185 : 'v'
+                730 : {
+                    'a' : { 130 : 'a' },
+                    'd' : { 130 : 'd' }
                 },
-                'x' : { 180 : 'x',
-                    151 : 'x',
-                    181 : 'x',
-                    182 : 'x',
-                    185 : 'x'
+                800 : {
+                    'a' : { 100 : 'a' },
+                    'd' : { 100 : 'd' }
                 },
-                'y' : { 180 : 'y',
-                    151 : 'y',
-                    181 : 'y',
-                    182 : 'y',
-                    185 : 'y'
+                810 : {
+                    'a' : { 110 : 'a' },
+                    'd' : { 110 : 'd' }
                 },
-                'z' : { 180 : 'z',
-                    151 : 'z',
-                    181 : 'z',
-                    182 : 'z',
-                    185 : 'z'
-                }
-            },
-            655 : {
-                'a' : { 155 : 'a' },
-                'v' : { 180 : 'v',
-                    155 : 'v',
-                    181 : 'v',
-                    182 : 'v',
-                    185 : 'v'
+                811 : {
+                    'a' : { 111 : 'a' },
+                    'd' : { 111 : 'd' }
+                },
+                830 : {
+                    'a' : { 130 : 'a' },
+                    'd' : { 130 : 'd' }
                 },
-                'x' : { 180 : 'x',
-                    155 : 'x',
-                    181 : 'x',
-                    182 : 'x',
-                    185 : 'x'
+                600 : {
+                    'a' : { 100 : 'a' },
+                    'd' : { 100 : 'd' },
+                    'q' : { 100 : 'q' },
+                    't' : { 100 : 't' },
+                    'v' : { 180 : 'v',
+                        100 : 'v',
+                        181 : 'v',
+                        182 : 'v',
+                        185 : 'v'
+                    },
+                    'x' : { 180 : 'x',
+                        100 : 'x',
+                        181 : 'x',
+                        182 : 'x',
+                        185 : 'x'
+                    },
+                    'y' : { 180 : 'y',
+                        100 : 'y',
+                        181 : 'y',
+                        182 : 'y',
+                        185 : 'y'
+                    },
+                    'z' : { 180 : 'z',
+                        100 : 'z',
+                        181 : 'z',
+                        182 : 'z',
+                        185 : 'z'
+                    }
                 },
-                'y' : { 180 : 'y',
-                    155 : 'y',
-                    181 : 'y',
-                    182 : 'y',
-                    185 : 'y'
+                610 : {
+                    'a' : { 110 : 'a' },
+                    'd' : { 110 : 'd' },
+                    't' : { 110 : 't' },
+                    'v' : { 180 : 'v',
+                        110 : 'v',
+                        181 : 'v',
+                        182 : 'v',
+                        185 : 'v'
+                    },
+                    'x' : { 180 : 'x',
+                        110 : 'x',
+                        181 : 'x',
+                        182 : 'x',
+                        185 : 'x'
+                    },
+                    'y' : { 180 : 'y',
+                        110 : 'y',
+                        181 : 'y',
+                        182 : 'y',
+                        185 : 'y'
+                    },
+                    'z' : { 180 : 'z',
+                        110 : 'z',
+                        181 : 'z',
+                        182 : 'z',
+                        185 : 'z'
+                    }
                 },
-                'z' : { 180 : 'z',
-                    155 : 'z',
-                    181 : 'z',
-                    182 : 'z',
-                    185 : 'z'
+                611 : {
+                    'a' : { 111 : 'a' },
+                    'd' : { 111 : 'd' },
+                    't' : { 111 : 't' },
+                    'v' : { 180 : 'v',
+                        111 : 'v',
+                        181 : 'v',
+                        182 : 'v',
+                        185 : 'v'
+                    },
+                    'x' : { 180 : 'x',
+                        111 : 'x',
+                        181 : 'x',
+                        182 : 'x',
+                        185 : 'x'
+                    },
+                    'y' : { 180 : 'y',
+                        111 : 'y',
+                        181 : 'y',
+                        182 : 'y',
+                        185 : 'y'
+                    },
+                    'z' : { 180 : 'z',
+                        111 : 'z',
+                        181 : 'z',
+                        182 : 'z',
+                        185 : 'z'
+                    }
+                },
+                630 : {
+                    'a' : { 130 : 'a' },
+                    'd' : { 130 : 'd' }
+                },
+                648 : {
+                    'a' : { 148 : 'a' },
+                    'v' : { 148 : 'v' },
+                    'x' : { 148 : 'x' },
+                    'y' : { 148 : 'y' },
+                    'z' : { 148 : 'z' }
+                },
+                650 : {
+                    'a' : { 150 : 'a' },
+                    'b' : { 150 : 'b' },
+                    'v' : { 180 : 'v',
+                        150 : 'v',
+                        181 : 'v',
+                        182 : 'v',
+                        185 : 'v'
+                    },
+                    'x' : { 180 : 'x',
+                        150 : 'x',
+                        181 : 'x',
+                        182 : 'x',
+                        185 : 'x'
+                    },
+                    'y' : { 180 : 'y',
+                        150 : 'y',
+                        181 : 'y',
+                        182 : 'y',
+                        185 : 'y'
+                    },
+                    'z' : { 180 : 'z',
+                        150 : 'z',
+                        181 : 'z',
+                        182 : 'z',
+                        185 : 'z'
+                    }
+                },
+                651 : {
+                    'a' : { 151 : 'a' },
+                    'v' : { 180 : 'v',
+                        151 : 'v',
+                        181 : 'v',
+                        182 : 'v',
+                        185 : 'v'
+                    },
+                    'x' : { 180 : 'x',
+                        151 : 'x',
+                        181 : 'x',
+                        182 : 'x',
+                        185 : 'x'
+                    },
+                    'y' : { 180 : 'y',
+                        151 : 'y',
+                        181 : 'y',
+                        182 : 'y',
+                        185 : 'y'
+                    },
+                    'z' : { 180 : 'z',
+                        151 : 'z',
+                        181 : 'z',
+                        182 : 'z',
+                        185 : 'z'
+                    }
+                },
+                655 : {
+                    'a' : { 155 : 'a' },
+                    'v' : { 180 : 'v',
+                        155 : 'v',
+                        181 : 'v',
+                        182 : 'v',
+                        185 : 'v'
+                    },
+                    'x' : { 180 : 'x',
+                        155 : 'x',
+                        181 : 'x',
+                        182 : 'x',
+                        185 : 'x'
+                    },
+                    'y' : { 180 : 'y',
+                        155 : 'y',
+                        181 : 'y',
+                        182 : 'y',
+                        185 : 'y'
+                    },
+                    'z' : { 180 : 'z',
+                        155 : 'z',
+                        181 : 'z',
+                        182 : 'z',
+                        185 : 'z'
+                    }
                 }
             }
-        };
-        
-    });
+        }
+     };
+
 }

commit cedebcd8835579bdcd047e9a5601455036144d43
Author: Mike Rylander <mrylander at gmail.com>
Date:   Fri May 6 15:29:38 2011 -0400

    Initial move of fixed-field manipulation out to the MARC Dojo module

diff --git a/Open-ILS/web/js/dojo/MARC/FixedFields.js b/Open-ILS/web/js/dojo/MARC/FixedFields.js
new file mode 100644
index 0000000..9a92c30
--- /dev/null
+++ b/Open-ILS/web/js/dojo/MARC/FixedFields.js
@@ -0,0 +1,1575 @@
+/* ---------------------------------------------------------------------------
+ * Copyright (C) 2011  Equinox Software, Inc.
+ * Mike Rylander <miker at esilibrary.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * ---------------------------------------------------------------------------
+ */
+
+if(!dojo._hasResource["MARC.FixedFields"]) {
+
+    dojo.require('MARC.Record');
+
+    dojo._hasResource["MARC.FixedFields"] = true;
+    dojo.provide("MARC.FixedFields");
+
+    MARC.Record._recType = {
+        BKS : { Type : /[at]{1}/,    BLvl : /[acdm]{1}/ },
+        SER : { Type : /[a]{1}/,    BLvl : /[bsi]{1}/ },
+        VIS : { Type : /[gkro]{1}/,    BLvl : /[abcdmsi]{1}/ },
+        MIX : { Type : /[p]{1}/,    BLvl : /[cdi]{1}/ },
+        MAP : { Type : /[ef]{1}/,    BLvl : /[abcdmsi]{1}/ },
+        SCO : { Type : /[cd]{1}/,    BLvl : /[abcdmsi]{1}/ },
+        REC : { Type : /[ij]{1}/,    BLvl : /[abcdmsi]{1}/ },
+        COM : { Type : /[m]{1}/,    BLvl : /[abcdmsi]{1}/ },
+        AUT : { Type : /[z]{1}/,    BLvl : /.{1}/ },
+        MFHD : { Type : /[uvxy]{1}/,  BLvl : /.{1}/ }
+    };
+
+    MARC.Record._ff_pos = {
+        Ctry : {
+            _8 : {
+                BKS : {start : 15, len : 3, def : ' ' },
+                SER : {start : 15, len : 3, def : ' ' },
+                VIS : {start : 15, len : 3, def : ' ' },
+                MIX : {start : 15, len : 3, def : ' ' },
+                MAP : {start : 15, len : 3, def : ' ' },
+                SCO : {start : 15, len : 3, def : ' ' },
+                REC : {start : 15, len : 3, def : ' ' },
+                COM : {start : 15, len : 3, def : ' ' },
+            }
+        },
+        Lang : {
+            _8 : {
+                BKS : {start : 35, len : 3, def : ' ' },
+                SER : {start : 35, len : 3, def : ' ' },
+                VIS : {start : 35, len : 3, def : ' ' },
+                MIX : {start : 35, len : 3, def : ' ' },
+                MAP : {start : 35, len : 3, def : ' ' },
+                SCO : {start : 35, len : 3, def : ' ' },
+                REC : {start : 35, len : 3, def : ' ' },
+                COM : {start : 35, len : 3, def : ' ' },
+            }
+        },
+        MRec : {
+            _8 : {
+                BKS : {start : 38, len : 1, def : ' ' },
+                SER : {start : 38, len : 1, def : ' ' },
+                VIS : {start : 38, len : 1, def : ' ' },
+                MIX : {start : 38, len : 1, def : ' ' },
+                MAP : {start : 38, len : 1, def : ' ' },
+                SCO : {start : 38, len : 1, def : ' ' },
+                REC : {start : 38, len : 1, def : ' ' },
+                COM : {start : 38, len : 1, def : ' ' },
+            }
+        },
+        DtSt : {
+            _8 : {
+                BKS : {start : 6, len : 1, def : ' ' },
+                SER : {start : 6, len : 1, def : 'c' },
+                VIS : {start : 6, len : 1, def : ' ' },
+                MIX : {start : 6, len : 1, def : ' ' },
+                MAP : {start : 6, len : 1, def : ' ' },
+                SCO : {start : 6, len : 1, def : ' ' },
+                REC : {start : 6, len : 1, def : ' ' },
+                COM : {start : 6, len : 1, def : ' ' },
+            }
+        },
+        Type : {
+            ldr : {
+                BKS : {start : 6, len : 1, def : 'a' },
+                SER : {start : 6, len : 1, def : 'a' },
+                VIS : {start : 6, len : 1, def : 'g' },
+                MIX : {start : 6, len : 1, def : 'p' },
+                MAP : {start : 6, len : 1, def : 'e' },
+                SCO : {start : 6, len : 1, def : 'c' },
+                REC : {start : 6, len : 1, def : 'i' },
+                COM : {start : 6, len : 1, def : 'm' },
+                AUT : {start : 6, len : 1, def : 'z' },
+                MFHD : {start : 6, len : 1, def : 'y' }
+    
+            }
+        },
+        Ctrl : {
+            ldr : {
+                BKS : {start : 8, len : 1, def : ' ' },
+                SER : {start : 8, len : 1, def : ' ' },
+                VIS : {start : 8, len : 1, def : ' ' },
+                MIX : {start : 8, len : 1, def : ' ' },
+                MAP : {start : 8, len : 1, def : ' ' },
+                SCO : {start : 8, len : 1, def : ' ' },
+                REC : {start : 8, len : 1, def : ' ' },
+                COM : {start : 8, len : 1, def : ' ' },
+            }
+        },
+        BLvl : {
+            ldr : {
+                BKS : {start : 7, len : 1, def : 'm' },
+                SER : {start : 7, len : 1, def : 's' },
+                VIS : {start : 7, len : 1, def : 'm' },
+                MIX : {start : 7, len : 1, def : 'c' },
+                MAP : {start : 7, len : 1, def : 'm' },
+                SCO : {start : 7, len : 1, def : 'm' },
+                REC : {start : 7, len : 1, def : 'm' },
+                COM : {start : 7, len : 1, def : 'm' },
+            }
+        },
+        Desc : {
+            ldr : {
+                BKS : {start : 18, len : 1, def : ' ' },
+                SER : {start : 18, len : 1, def : ' ' },
+                VIS : {start : 18, len : 1, def : ' ' },
+                MIX : {start : 18, len : 1, def : ' ' },
+                MAP : {start : 18, len : 1, def : ' ' },
+                SCO : {start : 18, len : 1, def : ' ' },
+                REC : {start : 18, len : 1, def : ' ' },
+                COM : {start : 18, len : 1, def : ' ' },
+            }
+        },
+        Item : {
+            ldr : {
+                MFHD : {start : 18, len : 1, def : 'i' }
+            }
+        },
+        ELvl : {
+            ldr : {
+                BKS : {start : 17, len : 1, def : ' ' },
+                SER : {start : 17, len : 1, def : ' ' },
+                VIS : {start : 17, len : 1, def : ' ' },
+                MIX : {start : 17, len : 1, def : ' ' },
+                MAP : {start : 17, len : 1, def : ' ' },
+                SCO : {start : 17, len : 1, def : ' ' },
+                REC : {start : 17, len : 1, def : ' ' },
+                COM : {start : 17, len : 1, def : ' ' },
+                AUT : {start : 17, len : 1, def : 'n' },
+                MFHD : {start : 17, len : 1, def : 'u' }
+            }
+        },
+        TMat : {
+            _8 : {
+                VIS : {start : 33, len : 1, def : ' ' },
+            },
+            _6 : {
+                VIS : {start : 16, len : 1, def : ' ' },
+            }
+        },
+        Indx : {
+            _8 : {
+                BKS : {start : 31, len : 1, def : '0' },
+                MAP : {start : 31, len : 1, def : '0' },
+            },
+            _6 : {
+                BKS : {start : 14, len : 1, def : '0' },
+                MAP : {start : 14, len : 1, def : '0' },
+            }
+        },
+        Date1 : {
+            _8 : {
+                BKS : {start : 7, len : 4, def : ' ' },
+                SER : {start : 7, len : 4, def : ' ' },
+                VIS : {start : 7, len : 4, def : ' ' },
+                MIX : {start : 7, len : 4, def : ' ' },
+                MAP : {start : 7, len : 4, def : ' ' },
+                SCO : {start : 7, len : 4, def : ' ' },
+                REC : {start : 7, len : 4, def : ' ' },
+                COM : {start : 7, len : 4, def : ' ' },
+            },
+        },
+        Date2 : {
+            _8 : {
+                BKS : {start : 11, len : 4, def : ' ' },
+                SER : {start : 11, len : 4, def : '9' },
+                VIS : {start : 11, len : 4, def : ' ' },
+                MIX : {start : 11, len : 4, def : ' ' },
+                MAP : {start : 11, len : 4, def : ' ' },
+                SCO : {start : 11, len : 4, def : ' ' },
+                REC : {start : 11, len : 4, def : ' ' },
+                COM : {start : 11, len : 4, def : ' ' },
+            },
+        },
+        LitF : {
+            _8 : {
+                BKS : {start : 33, len : 1, def : '0' },
+            },
+            _6 : {
+                BKS : {start : 16, len : 1, def : '0' },
+            }
+        },
+        Biog : {
+            _8 : {
+                BKS : {start : 34, len : 1, def : ' ' },
+            },
+            _6 : {
+                BKS : {start : 17, len : 1, def : ' ' },
+            }
+        },
+        Ills : {
+            _8 : {
+                BKS : {start : 18, len : 4, def : ' ' },
+            },
+            _6 : {
+                BKS : {start : 1, len : 4, def : ' ' },
+            }
+        },
+        Fest : {
+            _8 : {
+                BKS : {start : 30, len : 1, def : '0' },
+            },
+            _6 : {
+                BKS : {start : 13, len : 1, def : '0' },
+            }
+        },
+        Conf : {
+            _8 : {
+                BKS : {start : 24, len : 4, def : ' ' },
+                SER : {start : 25, len : 3, def : ' ' },
+            },
+            _6 : {
+                BKS : {start : 7, len : 4, def : ' ' },
+                SER : {start : 8, len : 3, def : ' ' },
+            }
+        },
+        GPub : {
+            _8 : {
+                BKS : {start : 28, len : 1, def : ' ' },
+                SER : {start : 28, len : 1, def : ' ' },
+                VIS : {start : 28, len : 1, def : ' ' },
+                MAP : {start : 28, len : 1, def : ' ' },
+                COM : {start : 28, len : 1, def : ' ' },
+            },
+            _6 : {
+                BKS : {start : 11, len : 1, def : ' ' },
+                SER : {start : 11, len : 1, def : ' ' },
+                VIS : {start : 11, len : 1, def : ' ' },
+                MAP : {start : 11, len : 1, def : ' ' },
+                COM : {start : 11, len : 1, def : ' ' },
+            }
+        },
+        Audn : {
+            _8 : {
+                BKS : {start : 22, len : 1, def : ' ' },
+                SER : {start : 22, len : 1, def : ' ' },
+                VIS : {start : 22, len : 1, def : ' ' },
+                SCO : {start : 22, len : 1, def : ' ' },
+                REC : {start : 22, len : 1, def : ' ' },
+                COM : {start : 22, len : 1, def : ' ' },
+            },
+            _6 : {
+                BKS : {start : 5, len : 1, def : ' ' },
+                SER : {start : 5, len : 1, def : ' ' },
+                VIS : {start : 5, len : 1, def : ' ' },
+                SCO : {start : 5, len : 1, def : ' ' },
+                REC : {start : 5, len : 1, def : ' ' },
+                COM : {start : 5, len : 1, def : ' ' },
+            }
+        },
+        Form : {
+            _8 : {
+                BKS : {start : 23, len : 1, def : ' ' },
+                SER : {start : 23, len : 1, def : ' ' },
+                VIS : {start : 29, len : 1, def : ' ' },
+                MIX : {start : 23, len : 1, def : ' ' },
+                MAP : {start : 29, len : 1, def : ' ' },
+                SCO : {start : 23, len : 1, def : ' ' },
+                REC : {start : 23, len : 1, def : ' ' },
+            },
+            _6 : {
+                BKS : {start : 6, len : 1, def : ' ' },
+                SER : {start : 6, len : 1, def : ' ' },
+                VIS : {start : 12, len : 1, def : ' ' },
+                MIX : {start : 6, len : 1, def : ' ' },
+                MAP : {start : 12, len : 1, def : ' ' },
+                SCO : {start : 6, len : 1, def : ' ' },
+                REC : {start : 6, len : 1, def : ' ' },
+            }
+        },
+        'S/L' : {
+            _8 : {
+                SER : {start : 34, len : 1, def : '0' },
+            },
+            _6 : {
+                SER : {start : 17, len : 1, def : '0' },
+            }
+        },
+        'Alph' : {
+            _8 : {
+                SER : {start : 33, len : 1, def : ' ' },
+            },
+            _6 : {
+                SER : {start : 16, len : 1, def : ' ' },
+            }
+        },
+        "GeoDiv" : {
+            "_8" : {
+                "AUT" : {"start" : 6, "len" : 1, "def" : ' ' }
+            }
+        },
+        "Roman" : {
+            "_8" : {
+                "AUT" : {"start" : 7, "len" : 1, "def" : ' ' }
+            }
+        },
+        "CatLang" : {
+            "_8" : {
+                "AUT" : {"start" : 8, "len" : 1, "def" : ' ' }
+            }
+        },
+        "Kind" : {
+            "_8" : {
+                "AUT" : {"start" : 9, "len" : 1, "def" : ' ' }
+            }
+        },
+        "Rules" : {
+            "_8" : {
+                "AUT" : {"start" : 10, "len" : 1, "def" : ' ' }
+            }
+        },
+        "SHSys" : {
+            "_8" : {
+                "AUT" : {"start" : 11, "len" : 1, "def" : ' ' }
+            }
+        },
+        "SerType" : {
+            "_8" : {
+                "AUT" : {"start" : 12, "len" : 1, "def" : ' ' }
+            }
+        },
+        "SerNum" : {
+            "_8" : {
+                "AUT" : {"start" : 13, "len" : 1, "def" : ' ' }
+            }
+        },
+        "HeadMain" : {
+            "_8" : {
+                "AUT" : {"start" : 14, "len" : 1, "def" : ' ' }
+            }
+        },
+        "HeadSubj" : {
+            "_8" : {
+                "AUT" : {"start" : 15, "len" : 1, "def" : ' ' }
+            }
+        },
+        "HeadSer" : {
+            "_8" : {
+                "AUT" : {"start" : 16, "len" : 1, "def" : ' ' }
+            }
+        },
+        "TypeSubd" : {
+            "_8" : {
+                "AUT" : {"start" : 17, "len" : 1, "def" : ' ' }
+            }
+        },
+        "TypeGov" : {
+            "_8" : {
+                "AUT" : {"start" : 28, "len" : 1, "def" : ' ' }
+            }
+        },
+        "RefEval" : {
+            "_8" : {
+                "AUT" : {"start" : 29, "len" : 1, "def" : ' ' }
+            }
+        },
+        "RecUpd" : {
+            "_8" : {
+                "AUT" : {"start" : 31, "len" : 1, "def" : ' ' }
+            }
+        },
+        "NameDiff" : {
+            "_8" : {
+                "AUT" : {"start" : 32, "len" : 1, "def" : ' ' }
+            }
+        },
+        "Level" : {
+            "_8" : {
+                "AUT" : {"start" : 33, "len" : 1, "def" : ' ' }
+            }
+        },
+        "ModRec" : {
+            "_8" : {
+                "AUT" : {"start" : 38, "len" : 1, "def" : ' ' }
+            }
+        },
+        "CatSrc" : {
+            "_8" : {
+                "AUT" : {"start" : 39, "len" : 1, "def" : ' ' }
+            }
+        }
+    };
+    
+    MARC.Record._physical_characteristics = {
+    	c : {
+    		label     : "Electronic Resource",
+    		subfields : {
+    			b : {	start : 1,
+    				len   : 1,
+    				label : "SMD",
+    				values: {	a : "Tape Cartridge",
+    						b : "Chip cartridge",
+    						c : "Computer optical disk cartridge",
+    						f : "Tape cassette",
+    						h : "Tape reel",
+    						j : "Magnetic disk",
+    						m : "Magneto-optical disk",
+    						o : "Optical disk",
+    						r : "Remote",
+    						u : "Unspecified",
+    						z : "Other",
+    				},
+    			},
+    			d : {	start : 3,
+    				len   : 1,
+    				label : "Color",
+    				values: {	a : "One color",
+    						b : "Black-and-white",
+    						c : "Multicolored",
+    						g : "Gray scale",
+    						m : "Mixed",
+    						n : "Not applicable",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    			e : {	start : 4,
+    				len   : 1,
+    				label : "Dimensions",
+    				values: {	a : "3 1/2 in.",
+    						e : "12 in.",
+    						g : "4 3/4 in. or 12 cm.",
+    						i : "1 1/8 x 2 3/8 in.",
+    						j : "3 7/8 x 2 1/2 in.",
+    						n : "Not applicable",
+    						o : "5 1/4 in.",
+    						u : "Unknown",
+    						v : "8 in.",
+    						z : "Other",
+    				},
+    			},
+    			f : {	start : 5,
+    				len   : 1,
+    				label : "Sound",
+    				values: {	' ' : "No sound (Silent)",
+    						a   : "Sound",
+    						u   : "Unknown",
+    				},
+    			},
+    			g : {	start : 6,
+    				len   : 3,
+    				label : "Image bit depth",
+    				values: {	mmm   : "Multiple",
+    						nnn   : "Not applicable",
+    						'---' : "Unknown",
+    				},
+    			},
+    			h : {	start : 9,
+    				len   : 1,
+    				label : "File formats",
+    				values: {	a : "One file format",
+    						m : "Multiple file formats",
+    						u : "Unknown",
+    				},
+    			},
+    			i : {	start : 10,
+    				len   : 1,
+    				label : "Quality assurance target(s)",
+    				values: {	a : "Absent",
+    						n : "Not applicable",
+    						p : "Present",
+    						u : "Unknown",
+    				},
+    			},
+    			j : {	start : 11,
+    				len   : 1,
+    				label : "Antecedent/Source",
+    				values: {	a : "File reproduced from original",
+    						b : "File reproduced from microform",
+    						c : "File reproduced from electronic resource",
+    						d : "File reproduced from an intermediate (not microform)",
+    						m : "Mixed",
+    						n : "Not applicable",
+    						u : "Unknown",
+    				},
+    			},
+    			k : {	start : 12,
+    				len   : 1,
+    				label : "Level of compression",
+    				values: {	a : "Uncompressed",
+    						b : "Lossless",
+    						d : "Lossy",
+    						m : "Mixed",
+    						u : "Unknown",
+    				},
+    			},
+    			l : {	start : 13,
+    				len   : 1,
+    				label : "Reformatting quality",
+    				values: {	a : "Access",
+    						n : "Not applicable",
+    						p : "Preservation",
+    						r : "Replacement",
+    						u : "Unknown",
+    				},
+    			},
+    		},
+    	},
+    	d : {
+    		label     : "Globe",
+    		subfields : {
+    			b : {	start : 1,
+    				len   : 1,
+    				label : "SMD",
+    				values: {	a : "Celestial globe",
+    						b : "Planetary or lunar globe",
+    						c : "Terrestrial globe",
+    						e : "Earth moon globe",
+    						u : "Unspecified",
+    						z : "Other",
+    				},
+    			},
+    			d : {	start : 3,
+    				len   : 1,
+    				label : "Color",
+    				values: {	a : "One color",
+    						c : "Multicolored",
+    				},
+    			},
+    			e : {	start : 4,
+    				len   : 1,
+    				label : "Physical medium",
+    				values: {	a : "Paper",
+    						b : "Wood",
+    						c : "Stone",
+    						d : "Metal",
+    						e : "Synthetics",
+    						f : "Skins",
+    						g : "Textile",
+    						p : "Plaster",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    			f : {	start : 5,
+    				len   : 1,
+    				label : "Type of reproduction",
+    				values: {	f : "Facsimile",
+    						n : "Not applicable",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    		},
+    	},
+    	a : {
+    		label     : "Map",
+    		subfields : {
+    			b : {	start : 1,
+    				len   : 1,
+    				label : "SMD",
+    				values: {	d : "Atlas",
+    						g : "Diagram",
+    						j : "Map",
+    						k : "Profile",
+    						q : "Model",
+    						r : "Remote-sensing image",
+    						s : "Section",
+    						u : "Unspecified",
+    						y : "View",
+    						z : "Other",
+    				},
+    			},
+    			d : {	start : 3,
+    				len   : 1,
+    				label : "Color",
+    				values: {	a : "One color",
+    						c : "Multicolored",
+    				},
+    			},
+    			e : {	start : 4,
+    				len   : 1,
+    				label : "Physical medium",
+    				values: {	a : "Paper",
+    						b : "Wood",
+    						c : "Stone",
+    						d : "Metal",
+    						e : "Synthetics",
+    						f : "Skins",
+    						g : "Textile",
+    						p : "Plaster",
+    						q : "Flexible base photographic medium, positive",
+    						r : "Flexible base photographic medium, negative",
+    						s : "Non-flexible base photographic medium, positive",
+    						t : "Non-flexible base photographic medium, negative",
+    						u : "Unknown",
+    						y : "Other photographic medium",
+    						z : "Other",
+    				},
+    			},
+    			f : {	start : 5,
+    				len   : 1,
+    				label : "Type of reproduction",
+    				values: {	f : "Facsimile",
+    						n : "Not applicable",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    			g : {	start : 6,
+    				len   : 1,
+    				label : "Production/reproduction details",
+    				values: {	a : "Photocopy, blueline print",
+    						b : "Photocopy",
+    						c : "Pre-production",
+    						d : "Film",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    			h : {	start : 7,
+    				len   : 1,
+    				label : "Positive/negative",
+    				values: {	a : "Positive",
+    						b : "Negative",
+    						m : "Mixed",
+    						n : "Not applicable",
+    				},
+    			},
+    		},
+    	},
+    	h : {
+    		label     : "Microform",
+    		subfields : {
+    			b : {	start : 1,
+    				len   : 1,
+    				label : "SMD",
+    				values: {	a : "Aperture card",
+    						b : "Microfilm cartridge",
+    						c : "Microfilm cassette",
+    						d : "Microfilm reel",
+    						e : "Microfiche",
+    						f : "Microfiche cassette",
+    						g : "Microopaque",
+    						u : "Unspecified",
+    						z : "Other",
+    				},
+    			},
+    			d : {	start : 3,
+    				len   : 1,
+    				label : "Positive/negative",
+    				values: {	a : "Positive",
+    						b : "Negative",
+    						m : "Mixed",
+    						u : "Unknown",
+    				},
+    			},
+    			e : {	start : 4,
+    				len   : 1,
+    				label : "Dimensions",
+    				values: {	a : "8 mm.",
+    						e : "16 mm.",
+    						f : "35 mm.",
+    						g : "70mm.",
+    						h : "105 mm.",
+    						l : "3 x 5 in. (8 x 13 cm.)",
+    						m : "4 x 6 in. (11 x 15 cm.)",
+    						o : "6 x 9 in. (16 x 23 cm.)",
+    						p : "3 1/4 x 7 3/8 in. (9 x 19 cm.)",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    			f : {	start : 5,
+    				len   : 4,
+    				label : "Reduction ratio range/Reduction ratio",
+    				values: {	a : "Low (1-16x)",
+    						b : "Normal (16-30x)",
+    						c : "High (31-60x)",
+    						d : "Very high (61-90x)",
+    						e : "Ultra (90x-)",
+    						u : "Unknown",
+    						v : "Reduction ratio varies",
+    				},
+    			},
+    			g : {	start : 9,
+    				len   : 1,
+    				label : "Color",
+    				values: {	b : "Black-and-white",
+    						c : "Multicolored",
+    						m : "Mixed",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    			h : {	start : 10,
+    				len   : 1,
+    				label : "Emulsion on film",
+    				values: {	a : "Silver halide",
+    						b : "Diazo",
+    						c : "Vesicular",
+    						m : "Mixed",
+    						n : "Not applicable",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    			i : {	start : 11,
+    				len   : 1,
+    				label : "Quality assurance target(s)",
+    				values: {	a : "1st gen. master",
+    						b : "Printing master",
+    						c : "Service copy",
+    						m : "Mixed generation",
+    						u : "Unknown",
+    				},
+    			},
+    			j : {	start : 12,
+    				len   : 1,
+    				label : "Base of film",
+    				values: {	a : "Safety base, undetermined",
+    						c : "Safety base, acetate undetermined",
+    						d : "Safety base, diacetate",
+    						l : "Nitrate base",
+    						m : "Mixed base",
+    						n : "Not applicable",
+    						p : "Safety base, polyester",
+    						r : "Safety base, mixed",
+    						t : "Safety base, triacetate",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    		},
+    	},
+    	m : {
+    		label     : "Motion Picture",
+    		subfields : {
+    			b : {	start : 1,
+    				len   : 1,
+    				label : "SMD",
+    				values: {	a : "Film cartridge",
+    						f : "Film cassette",
+    						r : "Film reel",
+    						u : "Unspecified",
+    						z : "Other",
+    				},
+    			},
+    			d : {	start : 3,
+    				len   : 1,
+    				label : "Color",
+    				values: {	b : "Black-and-white",
+    						c : "Multicolored",
+    						h : "Hand-colored",
+    						m : "Mixed",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    			e : {	start : 4,
+    				len   : 1,
+    				label : "Motion picture presentation format",
+    				values: {	a : "Standard sound aperture, reduced frame",
+    						b : "Nonanamorphic (wide-screen)",
+    						c : "3D",
+    						d : "Anamorphic (wide-screen)",
+    						e : "Other-wide screen format",
+    						f : "Standard. silent aperture, full frame",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    			f : {	start : 5,
+    				len   : 1,
+    				label : "Sound on medium or separate",
+    				values: {	a : "Sound on medium",
+    						b : "Sound separate from medium",
+    						u : "Unknown",
+    				},
+    			},
+    			g : {	start : 6,
+    				len   : 1,
+    				label : "Medium for sound",
+    				values: {	a : "Optical sound track on motion picture film",
+    						b : "Magnetic sound track on motion picture film",
+    						c : "Magnetic audio tape in cartridge",
+    						d : "Sound disc",
+    						e : "Magnetic audio tape on reel",
+    						f : "Magnetic audio tape in cassette",
+    						g : "Optical and magnetic sound track on film",
+    						h : "Videotape",
+    						i : "Videodisc",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    			h : {	start : 7,
+    				len   : 1,
+    				label : "Dimensions",
+    				values: {	a : "Standard 8 mm.",
+    						b : "Super 8 mm./single 8 mm.",
+    						c : "9.5 mm.",
+    						d : "16 mm.",
+    						e : "28 mm.",
+    						f : "35 mm.",
+    						g : "70 mm.",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    			i : {	start : 8,
+    				len   : 1,
+    				label : "Configuration of playback channels",
+    				values: {	k : "Mixed",
+    						m : "Monaural",
+    						n : "Not applicable",
+    						q : "Multichannel, surround or quadraphonic",
+    						s : "Stereophonic",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    			j : {	start : 9,
+    				len   : 1,
+    				label : "Production elements",
+    				values: {	a : "Work print",
+    						b : "Trims",
+    						c : "Outtakes",
+    						d : "Rushes",
+    						e : "Mixing tracks",
+    						f : "Title bands/inter-title rolls",
+    						g : "Production rolls",
+    						n : "Not applicable",
+    						z : "Other",
+    				},
+    			},
+    		},
+    	},
+    	k : {
+    		label     : "Non-projected Graphic",
+    		subfields : {
+    			b : {	start : 1,
+    				len   : 1,
+    				label : "SMD",
+    				values: {	c : "Collage",
+    						d : "Drawing",
+    						e : "Painting",
+    						f : "Photo-mechanical print",
+    						g : "Photonegative",
+    						h : "Photoprint",
+    						i : "Picture",
+    						j : "Print",
+    						l : "Technical drawing",
+    						n : "Chart",
+    						o : "Flash/activity card",
+    						u : "Unspecified",
+    						z : "Other",
+    				},
+    			},
+    			d : {	start : 3,
+    				len   : 1,
+    				label : "Color",
+    				values: {	a : "One color",
+    						b : "Black-and-white",
+    						c : "Multicolored",
+    						h : "Hand-colored",
+    						m : "Mixed",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    			e : {	start : 4,
+    				len   : 1,
+    				label : "Primary support material",
+    				values: {	a : "Canvas",
+    						b : "Bristol board",
+    						c : "Cardboard/illustration board",
+    						d : "Glass",
+    						e : "Synthetics",
+    						f : "Skins",
+    						g : "Textile",
+    						h : "Metal",
+    						m : "Mixed collection",
+    						o : "Paper",
+    						p : "Plaster",
+    						q : "Hardboard",
+    						r : "Porcelain",
+    						s : "Stone",
+    						t : "Wood",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    			f : {	start : 5,
+    				len   : 1,
+    				label : "Secondary support material",
+    				values: {	a : "Canvas",
+    						b : "Bristol board",
+    						c : "Cardboard/illustration board",
+    						d : "Glass",
+    						e : "Synthetics",
+    						f : "Skins",
+    						g : "Textile",
+    						h : "Metal",
+    						m : "Mixed collection",
+    						o : "Paper",
+    						p : "Plaster",
+    						q : "Hardboard",
+    						r : "Porcelain",
+    						s : "Stone",
+    						t : "Wood",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    		},
+    	},
+    	g : {
+    		label     : "Projected Graphic",
+    		subfields : {
+    			b : {	start : 1,
+    				len   : 1,
+    				label : "SMD",
+    				values: {	c : "Film cartridge",
+    						d : "Filmstrip",
+    						f : "Film filmstrip type",
+    						o : "Filmstrip roll",
+    						s : "Slide",
+    						t : "Transparency",
+    						z : "Other",
+    				},
+    			},
+    			d : {	start : 3,
+    				len   : 1,
+    				label : "Color",
+    				values: {	b : "Black-and-white",
+    						c : "Multicolored",
+    						h : "Hand-colored",
+    						m : "Mixed",
+    						n : "Not applicable",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    			e : {	start : 4,
+    				len   : 1,
+    				label : "Base of emulsion",
+    				values: {	d : "Glass",
+    						e : "Synthetics",
+    						j : "Safety film",
+    						k : "Film base, other than safety film",
+    						m : "Mixed collection",
+    						o : "Paper",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    			f : {	start : 5,
+    				len   : 1,
+    				label : "Sound on medium or separate",
+    				values: {	a : "Sound on medium",
+    						b : "Sound separate from medium",
+    						u : "Unknown",
+    				},
+    			},
+    			g : {	start : 6,
+    				len   : 1,
+    				label : "Medium for sound",
+    				values: {	a : "Optical sound track on motion picture film",
+    						b : "Magnetic sound track on motion picture film",
+    						c : "Magnetic audio tape in cartridge",
+    						d : "Sound disc",
+    						e : "Magnetic audio tape on reel",
+    						f : "Magnetic audio tape in cassette",
+    						g : "Optical and magnetic sound track on film",
+    						h : "Videotape",
+    						i : "Videodisc",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    			h : {	start : 7,
+    				len   : 1,
+    				label : "Dimensions",
+    				values: {	a : "Standard 8 mm.",
+    						b : "Super 8 mm./single 8 mm.",
+    						c : "9.5 mm.",
+    						d : "16 mm.",
+    						e : "28 mm.",
+    						f : "35 mm.",
+    						g : "70 mm.",
+    						j : "2 x 2 in. (5 x 5 cm.)",
+    						k : "2 1/4 x 2 1/4 in. (6 x 6 cm.)",
+    						s : "4 x 5 in. (10 x 13 cm.)",
+    						t : "5 x 7 in. (13 x 18 cm.)",
+    						v : "8 x 10 in. (21 x 26 cm.)",
+    						w : "9 x 9 in. (23 x 23 cm.)",
+    						x : "10 x 10 in. (26 x 26 cm.)",
+    						y : "7 x 7 in. (18 x 18 cm.)",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    			i : {	start : 8,
+    				len   : 1,
+    				label : "Secondary support material",
+    				values: {	c : "Cardboard",
+    						d : "Glass",
+    						e : "Synthetics",
+    						h : "metal",
+    						j : "Metal and glass",
+    						k : "Synthetics and glass",
+    						m : "Mixed collection",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    		},
+    	},
+    	r : {
+    		label     : "Remote-sensing Image",
+    		subfields : {
+    			b : {	start : 1,
+    				len   : 1,
+    				label : "SMD",
+    				values: { u : "Unspecified" },
+    			},
+    			d : {	start : 3,
+    				len   : 1,
+    				label : "Altitude of sensor",
+    				values: {	a : "Surface",
+    						b : "Airborne",
+    						c : "Spaceborne",
+    						n : "Not applicable",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    			e : {	start : 4,
+    				len   : 1,
+    				label : "Attitude of sensor",
+    				values: {	a : "Low oblique",
+    						b : "High oblique",
+    						c : "Vertical",
+    						n : "Not applicable",
+    						u : "Unknown",
+    				},
+    			},
+    			f : {	start : 5,
+    				len   : 1,
+    				label : "Cloud cover",
+    				values: {	0 : "0-09%",
+    						1 : "10-19%",
+    						2 : "20-29%",
+    						3 : "30-39%",
+    						4 : "40-49%",
+    						5 : "50-59%",
+    						6 : "60-69%",
+    						7 : "70-79%",
+    						8 : "80-89%",
+    						9 : "90-100%",
+    						n : "Not applicable",
+    						u : "Unknown",
+    				},
+    			},
+    			g : {	start : 6,
+    				len   : 1,
+    				label : "Platform construction type",
+    				values: {	a : "Balloon",
+    						b : "Aircraft-low altitude",
+    						c : "Aircraft-medium altitude",
+    						d : "Aircraft-high altitude",
+    						e : "Manned spacecraft",
+    						f : "Unmanned spacecraft",
+    						g : "Land-based remote-sensing device",
+    						h : "Water surface-based remote-sensing device",
+    						i : "Submersible remote-sensing device",
+    						n : "Not applicable",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    			h : {	start : 7,
+    				len   : 1,
+    				label : "Platform use category",
+    				values: {	a : "Meteorological",
+    						b : "Surface observing",
+    						c : "Space observing",
+    						m : "Mixed uses",
+    						n : "Not applicable",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    			i : {	start : 8,
+    				len   : 1,
+    				label : "Sensor type",
+    				values: {	a : "Active",
+    						b : "Passive",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    			j : {	start : 9,
+    				len   : 2,
+    				label : "Data type",
+    				values: {	nn : "Not applicable",
+    						uu : "Unknown",
+    						zz : "Other",
+    						aa : "Visible light",
+    						da : "Near infrared",
+    						db : "Middle infrared",
+    						dc : "Far infrared",
+    						dd : "Thermal infrared",
+    						de : "Shortwave infrared (SWIR)",
+    						df : "Reflective infrared",
+    						dv : "Combinations",
+    						dz : "Other infrared data",
+    						ga : "Sidelooking airborne radar (SLAR)",
+    						gb : "Synthetic aperture radar (SAR-single frequency)",
+    						gc : "SAR-multi-frequency (multichannel)",
+    						gd : "SAR-like polarization",
+    						ge : "SAR-cross polarization",
+    						gf : "Infometric SAR",
+    						gg : "Polarmetric SAR",
+    						gu : "Passive microwave mapping",
+    						gz : "Other microwave data",
+    						ja : "Far ultraviolet",
+    						jb : "Middle ultraviolet",
+    						jc : "Near ultraviolet",
+    						jv : "Ultraviolet combinations",
+    						jz : "Other ultraviolet data",
+    						ma : "Multi-spectral, multidata",
+    						mb : "Multi-temporal",
+    						mm : "Combination of various data types",
+    						pa : "Sonar-water depth",
+    						pb : "Sonar-bottom topography images, sidescan",
+    						pc : "Sonar-bottom topography, near-surface",
+    						pd : "Sonar-bottom topography, near-bottom",
+    						pe : "Seismic surveys",
+    						pz : "Other acoustical data",
+    						ra : "Gravity anomales (general)",
+    						rb : "Free-air",
+    						rc : "Bouger",
+    						rd : "Isostatic",
+    						sa : "Magnetic field",
+    						ta : "Radiometric surveys",
+    				},
+    			},
+    		},
+    	},
+    	s : {
+    		label     : "Sound Recording",
+    		subfields : {
+    			b : {	start : 1,
+    				len   : 1,
+    				label : "SMD",
+    				values: {	d : "Sound disc",
+    						e : "Cylinder",
+    						g : "Sound cartridge",
+    						i : "Sound-track film",
+    						q : "Roll",
+    						s : "Sound cassette",
+    						t : "Sound-tape reel",
+    						u : "Unspecified",
+    						w : "Wire recording",
+    						z : "Other",
+    				},
+    			},
+    			d : {	start : 3,
+    				len   : 1,
+    				label : "Speed",
+    				values: {	a : "16 rpm",
+    						b : "33 1/3 rpm",
+    						c : "45 rpm",
+    						d : "78 rpm",
+    						e : "8 rpm",
+    						f : "1.4 mps",
+    						h : "120 rpm",
+    						i : "160 rpm",
+    						k : "15/16 ips",
+    						l : "1 7/8 ips",
+    						m : "3 3/4 ips",
+    						o : "7 1/2 ips",
+    						p : "15 ips",
+    						r : "30 ips",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    			e : {	start : 4,
+    				len   : 1,
+    				label : "Configuration of playback channels",
+    				values: {	m : "Monaural",
+    						q : "Quadraphonic",
+    						s : "Stereophonic",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    			f : {	start : 5,
+    				len   : 1,
+    				label : "Groove width or pitch",
+    				values: {	m : "Microgroove/fine",
+    						n : "Not applicable",
+    						s : "Coarse/standard",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    			g : {	start : 6,
+    				len   : 1,
+    				label : "Dimensions",
+    				values: {	a : "3 in.",
+    						b : "5 in.",
+    						c : "7 in.",
+    						d : "10 in.",
+    						e : "12 in.",
+    						f : "16 in.",
+    						g : "4 3/4 in. (12 cm.)",
+    						j : "3 7/8 x 2 1/2 in.",
+    						o : "5 1/4 x 3 7/8 in.",
+    						s : "2 3/4 x 4 in.",
+    						n : "Not applicable",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    			h : {	start : 7,
+    				len   : 1,
+    				label : "Tape width",
+    				values: {	l : "1/8 in.",
+    						m : "1/4in.",
+    						n : "Not applicable",
+    						o : "1/2 in.",
+    						p : "1 in.",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    			i : {	start : 8,
+    				len   : 1,
+    				label : "Tape configuration ",
+    				values: {	a : "Full (1) track",
+    						b : "Half (2) track",
+    						c : "Quarter (4) track",
+    						d : "8 track",
+    						e : "12 track",
+    						f : "16 track",
+    						n : "Not applicable",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    			m : {	start : 12,
+    				len   : 1,
+    				label : "Special playback",
+    				values: {	a : "NAB standard",
+    						b : "CCIR standard",
+    						c : "Dolby-B encoded, standard Dolby",
+    						d : "dbx encoded",
+    						e : "Digital recording",
+    						f : "Dolby-A encoded",
+    						g : "Dolby-C encoded",
+    						h : "CX encoded",
+    						n : "Not applicable",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    			n : {	start : 13,
+    				len   : 1,
+    				label : "Capture and storage",
+    				values: {	a : "Acoustical capture, direct storage",
+    						b : "Direct storage, not acoustical",
+    						d : "Digital storage",
+    						e : "Analog electrical storage",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    		},
+    	},
+    	f : {
+    		label     : "Tactile Material",
+    		subfields : {
+    			b : {	start : 1,
+    				len   : 1,
+    				label : "SMD",
+    				values: {	a : "Moon",
+    						b : "Braille",
+    						c : "Combination",
+    						d : "Tactile, with no writing system",
+    						u : "Unspecified",
+    						z : "Other",
+    				},
+    			},
+    			d : {	start : 3,
+    				len   : 2,
+    				label : "Class of braille writing",
+    				values: {	a : "Literary braille",
+    						b : "Format code braille",
+    						c : "Mathematics and scientific braille",
+    						d : "Computer braille",
+    						e : "Music braille",
+    						m : "Multiple braille types",
+    						n : "Not applicable",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    			e : {	start : 4,
+    				len   : 1,
+    				label : "Level of contraction",
+    				values: {	a : "Uncontracted",
+    						b : "Contracted",
+    						m : "Combination",
+    						n : "Not applicable",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    			f : {	start : 6,
+    				len   : 3,
+    				label : "Braille music format",
+    				values: {	a : "Bar over bar",
+    						b : "Bar by bar",
+    						c : "Line over line",
+    						d : "Paragraph",
+    						e : "Single line",
+    						f : "Section by section",
+    						g : "Line by line",
+    						h : "Open score",
+    						i : "Spanner short form scoring",
+    						j : "Short form scoring",
+    						k : "Outline",
+    						l : "Vertical score",
+    						n : "Not applicable",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    			g : {	start : 9,
+    				len   : 1,
+    				label : "Special physical characteristics",
+    				values: {	a : "Print/braille",
+    						b : "Jumbo or enlarged braille",
+    						n : "Not applicable",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    		},
+    	},
+    	v : {
+    		label     : "Videorecording",
+    		subfields : {
+    			b : {	start : 1,
+    				len   : 1,
+    				label : "SMD",
+    				values: { 	c : "Videocartridge",
+    						d : "Videodisc",
+    						f : "Videocassette",
+    						r : "Videoreel",
+    						u : "Unspecified",
+    						z : "Other",
+    				},
+    			},
+    			d : {	start : 3,
+    				len   : 1,
+    				label : "Color",
+    				values: {	b : "Black-and-white",
+    						c : "Multicolored",
+    						m : "Mixed",
+    						n : "Not applicable",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    			e : {	start : 4,
+    				len   : 1,
+    				label : "Videorecording format",
+    				values: {	a : "Beta",
+    						b : "VHS",
+    						c : "U-matic",
+    						d : "EIAJ",
+    						e : "Type C",
+    						f : "Quadruplex",
+    						g : "Laserdisc",
+    						h : "CED",
+    						i : "Betacam",
+    						j : "Betacam SP",
+    						k : "Super-VHS",
+    						m : "M-II",
+    						o : "D-2",
+    						p : "8 mm.",
+    						q : "Hi-8 mm.",
+    						u : "Unknown",
+    						v : "DVD",
+    						z : "Other",
+    				},
+    			},
+    			f : {	start : 5,
+    				len   : 1,
+    				label : "Sound on medium or separate",
+    				values: {	a : "Sound on medium",
+    						b : "Sound separate from medium",
+    						u : "Unknown",
+    				},
+    			},
+    			g : {	start : 6,
+    				len   : 1,
+    				label : "Medium for sound",
+    				values: {	a : "Optical sound track on motion picture film",
+    						b : "Magnetic sound track on motion picture film",
+    						c : "Magnetic audio tape in cartridge",
+    						d : "Sound disc",
+    						e : "Magnetic audio tape on reel",
+    						f : "Magnetic audio tape in cassette",
+    						g : "Optical and magnetic sound track on motion picture film",
+    						h : "Videotape",
+    						i : "Videodisc",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    			h : {	start : 7,
+    				len   : 1,
+    				label : "Dimensions",
+    				values: {	a : "8 mm.",
+    						m : "1/4 in.",
+    						o : "1/2 in.",
+    						p : "1 in.",
+    						q : "2 in.",
+    						r : "3/4 in.",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    			i : {	start : 8,
+    				len   : 1,
+    				label : "Configuration of playback channel",
+    				values: {	k : "Mixed",
+    						m : "Monaural",
+    						n : "Not applicable",
+    						q : "Multichannel, surround or quadraphonic",
+    						s : "Stereophonic",
+    						u : "Unknown",
+    						z : "Other",
+    				},
+    			},
+    		},
+    	},
+    };
+    
+    MARC.Record.prototype.recordType = function () {
+    
+    	var _t = this.leader.substr(MARC.Record._ff_pos.Type.ldr.BKS.start, MARC.Record._ff_pos.Type.ldr.BKS.len);
+    	var _b = this.leader.substr(MARC.Record._ff_pos.BLvl.ldr.BKS.start, MARC.Record._ff_pos.BLvl.ldr.BKS.len);
+    
+    	for (var t in MARC.Record._recType) {
+    		if (_t.match(MARC.Record._recType[t].Type) && _b.match(MARC.Record._recType[t].BLvl)) {
+    			return t;
+    		}
+    	}
+        return 'BKS'; // default
+    }
+    
+    MARC.Record.prototype.videorecordingFormatName = function () {
+    	var _7 = this.field('007');
+    
+    	if (_7.match(/^v/)) {
+    		var _v_e = _7.substr(
+    			MARC.Record._physical_characteristics.v.subfields.e.start,
+    			MARC.Record._physical_characteristics.v.subfields.e.len
+    		);
+    
+    		return MARC.Record._physical_characteristics.v.subfields.e.values[ _v_e ];
+    	}
+    
+    	return null;
+    }
+    
+    MARC.Record.prototype.videorecordingFormatCode = function () {
+    	var _7 = this.field('007');
+    
+    	if (_7.match(/^v/)) {
+    		return _7.substr(
+    			MARC.Record._physical_characteristics.v.subfields.e.start,
+    			MARC.Record._physical_characteristics.v.subfields.e.len
+    		);
+    	}
+    
+    	return null;
+    }
+    
+    MARC.Record.prototype.extractFixedField = function (field, dflt) {
+    
+    	var _l = this.field('007');
+    	var _8 = this.field('008');
+    	var _6 = this.field('006');
+    
+    	var rtype = this.recordType();
+    
+    	var val;
+    
+    	if (MARC.Record._ff_pos[field].ldr) {
+    		if (MARC.Record._ff_pos[field].ldr[rtype]) {
+    			val = _l.substr(
+    				MARC.Record._ff_pos[field].ldr[rtype].start,
+    				MARC.Record._ff_pos[field].ldr[rtype].len
+    			);
+    		}
+    	} else if (MARC.Record._ff_pos[field]._8) {
+    		if (MARC.Record._ff_pos[field]._8[rtype]) {
+    			val = _8.substr(
+    				MARC.Record._ff_pos[field]._8[rtype].start,
+    				MARC.Record._ff_pos[field]._8[rtype].len
+    			);
+    		}
+    	}
+    
+    	if (!val && MARC.Record._ff_pos[field]._6) {
+    		if (MARC.Record._ff_pos[field]._6[rtype]) {
+    			val = _6.substr(
+    				MARC.Record._ff_pos[field]._6[rtype].start,
+    				MARC.Record._ff_pos[field]._6[rtype].len
+    			);
+    		}
+    	}
+
+        if (!val && dflt) {
+            val = '';
+            var d;
+            var p;
+            if (MARC.Record._ff_pos[name].ldr && MARC.Record._ff_pos[name].ldr[rtype]) {
+                d = MARC.Record._ff_pos[name].ldr[rtype].def;
+                p = 'ldr';
+            }
+
+            if (MARC.Record._ff_pos[name]._8 && MARC.Record._ff_pos[name]._8[rtype]) {
+                d = MARC.Record._ff_pos[name]._8[rtype].def;
+                p = '_8';
+            }
+
+            if (!val && MARC.Record._ff_pos[name]._6 && MARC.Record._ff_pos[name]._6[rtype]) {
+                d = MARC.Record._ff_pos[name]._6[rtype].def;
+                p = '_6';
+            }
+
+            if (p) {
+                for (var j = 0; j < MARC.Record._ff_pos[name][p][rtype].len; j++) {
+                    val += d;
+                }
+            } else {
+                val = null;
+            }
+        }
+
+    	return val;
+    }
+} 
diff --git a/Open-ILS/xul/staff_client/server/cat/marcedit.js b/Open-ILS/xul/staff_client/server/cat/marcedit.js
index 9dc0137..b8b3460 100644
--- a/Open-ILS/xul/staff_client/server/cat/marcedit.js
+++ b/Open-ILS/xul/staff_client/server/cat/marcedit.js
@@ -112,8 +112,6 @@ function wrap_long_fields (node) {
 
 function set_flat_editor (useFlatText) {
 
-    dojo.require('MARC.Record');
-
     var xe = $('xul-editor');
     var te = $('text-editor');
 
@@ -136,7 +134,8 @@ function set_flat_editor (useFlatText) {
 
         // reset the xml record and rerender it
         xml_record = new XML( xml_string );
-        loadRecord(xml_record);
+        if (xml_record..record[0]) xml_record = xml_record..record[0];
+        loadRecord();
     } else {
         var xml_string = xml_record.toXMLString();
 
@@ -199,7 +198,7 @@ function my_init() {
             'mangle_005(); ' + 
             'var xml_string = xml_escape_unicode( xml_record.toXMLString() ); ' + 
             'save_attempt( xml_string ); ' +
-            'loadRecord(xml_record);'
+            'loadRecord();'
         );
 
         if (window.xulG.record.url) {
@@ -347,7 +346,7 @@ function my_init() {
         }
         req.send(null);
 
-        loadRecord(xml_record);
+        loadRecord();
 
         if (! xulG.fast_add_item) {
             document.getElementById('fastItemAdd_checkbox').hidden = true;
@@ -367,6 +366,8 @@ function my_init() {
             buildBibSourceList(authtoken, xulG.record.id);
         }
 
+        dojo.require('MARC.FixedFields');
+
     } catch(E) {
         alert('FIXME, MARC Editor, my_init: ' + E);
     }
@@ -680,13 +681,13 @@ function createMARCTextbox (element,attrs) {
                 }
             } else if (event.keyCode == 64 && event.ctrlKey) { // ctrl + F6
                 createControlField('006','                                        ');
-                loadRecord(xml_record);
+                loadRecord();
             } else if (event.keyCode == 65 && event.ctrlKey) { // ctrl + F7
                 createControlField('007','                                        ');
-                loadRecord(xml_record);
+                loadRecord();
             } else if (event.keyCode == 66 && event.ctrlKey) { // ctrl + F8
                 createControlField('008','                                        ');
-                loadRecord(xml_record);
+                loadRecord();
             }
 
             return true;
@@ -745,7 +746,7 @@ function createMARCTextbox (element,attrs) {
         'keyup', 
         function () {
             if (element.localName() == 'controlfield')
-                eval('fillFixedFields(xml_record);');
+                eval('fillFixedFields();');
         },
         true
     );
@@ -753,590 +754,6 @@ function createMARCTextbox (element,attrs) {
     return box;
 }
 
-var rec_type = {
-    BKS : { Type : /[at]{1}/,    BLvl : /[acdm]{1}/ },
-    SER : { Type : /[a]{1}/,    BLvl : /[bs]{1}/ },
-    VIS : { Type : /[gkro]{1}/,    BLvl : /[abcdms]{1}/ },
-    MIX : { Type : /[p]{1}/,    BLvl : /[cd]{1}/ },
-    MAP : { Type : /[ef]{1}/,    BLvl : /[abcdms]{1}/ },
-    SCO : { Type : /[cd]{1}/,    BLvl : /[abcdms]{1}/ },
-    REC : { Type : /[ij]{1}/,    BLvl : /[abcdms]{1}/ },
-    COM : { Type : /[m]{1}/,    BLvl : /[abcdms]{1}/ },
-    AUT : { Type : /[z]{1}/,    BLvl : /.{1}/ },
-    MFHD : { Type : /[uvxy]{1}/,  BLvl : /.{1}/ }
-};
-
-var ff_pos = {
-    TrAr : {
-        _8 : {
-            SCO : {start : 33, len : 1, def : ' ' },
-            REC : {start : 33, len : 1, def : 'n' }
-        },
-        _6 : {
-            SCO : {start : 16, len : 1, def : ' ' },
-            REC : {start : 16, len : 1, def : 'n' }
-        }
-    },
-    TMat : {
-        _8 : {
-            VIS : {start : 33, len : 1, def : ' ' }
-        },
-        _6 : {
-            VIS : {start : 16, len : 1, def : ' ' }
-        }
-    },
-    Time : {
-        _8 : {
-            VIS : {start : 18, len : 3, def : ' ' }
-        },
-        _6 : {
-            VIS : {start : 1, len : 3, def : ' ' }
-        }
-    },
-    Tech : {
-        _8 : {
-            VIS : {start : 34, len : 1, def : 'n' }
-        },
-        _6 : {
-            VIS : {start : 17, len : 1, def : 'n' }
-        }
-    },
-    SrTp : {
-        _8 : {
-            SER : {start : 21, len : 1, def : ' ' }
-        },
-        _6 : {
-            SER : {start : 4, len : 1, def : ' ' }
-        }
-    },
-    Srce : {
-        _8 : {
-            BKS : {start : 39, len : 1, def : 'd' },
-            SER : {start : 39, len : 1, def : 'd' },
-            VIS : {start : 39, len : 1, def : 'd' },
-            MIX : {start : 39, len : 1, def : 'd' },
-            MAP : {start : 39, len : 1, def : 'd' },
-            SCO : {start : 39, len : 1, def : 'd' },
-            REC : {start : 39, len : 1, def : 'd' },
-            COM : {start : 39, len : 1, def : 'd' }
-        }
-    },
-    SpFm : {
-        _8 : {
-            MAP : {start : 33, len : 2, def : ' ' }
-        },
-        _6 : {
-            MAP : {start : 16, len : 2, def : ' ' }
-        }
-    },
-    Relf : {
-        _8 : {
-            MAP : {start : 18, len : 4, def : ' ' }
-        },
-        _6 : {
-            MAP : {start : 1, len : 4, def : ' ' }
-        }
-    },
-    Regl : {
-        _8 : {
-            SER : {start : 19, len : 1, def : ' ' }
-        },
-        _6 : {
-            SER : {start : 2, len : 1, def : ' ' }
-        }
-    },
-    Proj : {
-        _8 : {
-            MAP : {start : 22, len : 2, def : ' ' }
-        },
-        _6 : {
-            MAP : {start : 5, len : 2, def : ' ' }
-        }
-    },
-    Part : {
-        _8 : {
-            SCO : {start : 21, len : 1, def : ' ' },
-            REC : {start : 21, len : 1, def : 'n' }
-        },
-        _6 : {
-            SCO : {start : 4, len : 1, def : ' ' },
-            REC : {start : 4, len : 1, def : 'n' }
-        }
-    },
-    Orig : {
-        _8 : {
-            SER : {start : 22, len : 1, def : ' ' }
-        },
-        _6 : {
-            SER : {start : 5, len : 1, def : ' ' }
-        }
-    },
-    LTxt : {
-        _8 : {
-            SCO : {start : 30, len : 2, def : ' ' },
-            REC : {start : 30, len : 2, def : ' ' }
-        },
-        _6 : {
-            SCO : {start : 13, len : 2, def : ' ' },
-            REC : {start : 13, len : 2, def : ' ' }
-        }
-    },
-    Freq : {
-        _8 : {
-            SER : {start : 18, len : 1, def : ' ' }
-        },
-        _6 : {
-            SER : {start : 1, len : 1, def : ' ' }
-        }
-    },
-    FMus : {
-        _8 : {
-            SCO : {start : 20, len : 1, def : ' ' },
-            REC : {start : 20, len : 1, def : 'n' }
-        },
-        _6 : {
-            SCO : {start : 3, len : 1, def : ' ' },
-            REC : {start : 3, len : 1, def : 'n' }
-        }
-    },
-    File : {
-        _8 : {
-            COM : {start : 26, len : 1, def : 'u' }
-        },
-        _6 : {
-            COM : {start : 9, len : 1, def : 'u' }
-        }
-    },
-    EntW : {
-        _8 : {
-            SER : {start : 24, len : 1, def : ' ' }
-        },
-        _6 : {
-            SER : {start : 7, len : 1, def : ' ' }
-        }
-    },
-    AccM : {
-        _8 : {
-            SCO : {start : 24, len : 6, def : ' ' },
-            REC : {start : 24, len : 6, def : ' ' }
-        },
-        _6 : {
-            SCO : {start : 7, len : 6, def : ' ' },
-            REC : {start : 7, len : 6, def : ' ' }
-        }
-    },
-    Comp : {
-        _8 : {
-            SCO : {start : 18, len : 2, def : ' ' },
-            REC : {start : 18, len : 2, def : ' ' }
-        },
-        _6 : {
-            SCO : {start : 1, len : 2, def : ' ' },
-            REC : {start : 1, len : 2, def : ' ' }
-        }
-    },
-    CrTp : {
-        _8 : {
-            MAP : {start : 25, len : 1, def : ' ' }
-        },
-        _6 : {
-            MAP : {start : 8, len : 1, def : ' ' }
-        }
-    },
-    Ctry : {
-        _8 : {
-            BKS : {start : 15, len : 3, def : ' ' },
-            SER : {start : 15, len : 3, def : ' ' },
-            VIS : {start : 15, len : 3, def : ' ' },
-            MIX : {start : 15, len : 3, def : ' ' },
-            MAP : {start : 15, len : 3, def : ' ' },
-            SCO : {start : 15, len : 3, def : ' ' },
-            REC : {start : 15, len : 3, def : ' ' },
-            COM : {start : 15, len : 3, def : ' ' }
-        }
-    },
-    Lang : {
-        _8 : {
-            BKS : {start : 35, len : 3, def : ' ' },
-            SER : {start : 35, len : 3, def : ' ' },
-            VIS : {start : 35, len : 3, def : ' ' },
-            MIX : {start : 35, len : 3, def : ' ' },
-            MAP : {start : 35, len : 3, def : ' ' },
-            SCO : {start : 35, len : 3, def : ' ' },
-            REC : {start : 35, len : 3, def : ' ' },
-            COM : {start : 35, len : 3, def : ' ' }
-        }
-    },
-    MRec : {
-        _8 : {
-            BKS : {start : 38, len : 1, def : ' ' },
-            SER : {start : 38, len : 1, def : ' ' },
-            VIS : {start : 38, len : 1, def : ' ' },
-            MIX : {start : 38, len : 1, def : ' ' },
-            MAP : {start : 38, len : 1, def : ' ' },
-            SCO : {start : 38, len : 1, def : ' ' },
-            REC : {start : 38, len : 1, def : ' ' },
-            COM : {start : 38, len : 1, def : ' ' }
-        }
-    },
-    DtSt : {
-        _8 : {
-            BKS : {start : 6, len : 1, def : ' ' },
-            SER : {start : 6, len : 1, def : 'c' },
-            VIS : {start : 6, len : 1, def : ' ' },
-            MIX : {start : 6, len : 1, def : ' ' },
-            MAP : {start : 6, len : 1, def : ' ' },
-            SCO : {start : 6, len : 1, def : ' ' },
-            REC : {start : 6, len : 1, def : ' ' },
-            COM : {start : 6, len : 1, def : ' ' }
-        }
-    },
-    Type : {
-        ldr : {
-            BKS : {start : 6, len : 1, def : 'a' },
-            SER : {start : 6, len : 1, def : 'a' },
-            VIS : {start : 6, len : 1, def : 'g' },
-            MIX : {start : 6, len : 1, def : 'p' },
-            MAP : {start : 6, len : 1, def : 'e' },
-            SCO : {start : 6, len : 1, def : 'c' },
-            REC : {start : 6, len : 1, def : 'i' },
-            COM : {start : 6, len : 1, def : 'm' },
-            AUT : {start : 6, len : 1, def : 'z' },
-            MFHD : {start : 6, len : 1, def : 'y' }
-        }
-    },
-    Ctrl : {
-        ldr : {
-            BKS : {start : 8, len : 1, def : ' ' },
-            SER : {start : 8, len : 1, def : ' ' },
-            VIS : {start : 8, len : 1, def : ' ' },
-            MIX : {start : 8, len : 1, def : ' ' },
-            MAP : {start : 8, len : 1, def : ' ' },
-            SCO : {start : 8, len : 1, def : ' ' },
-            REC : {start : 8, len : 1, def : ' ' },
-            COM : {start : 8, len : 1, def : ' ' }
-        }
-    },
-    BLvl : {
-        ldr : {
-            BKS : {start : 7, len : 1, def : 'm' },
-            SER : {start : 7, len : 1, def : 's' },
-            VIS : {start : 7, len : 1, def : 'm' },
-            MIX : {start : 7, len : 1, def : 'c' },
-            MAP : {start : 7, len : 1, def : 'm' },
-            SCO : {start : 7, len : 1, def : 'm' },
-            REC : {start : 7, len : 1, def : 'm' },
-            COM : {start : 7, len : 1, def : 'm' }
-        }
-    },
-    Desc : {
-        ldr : {
-            BKS : {start : 18, len : 1, def : ' ' },
-            SER : {start : 18, len : 1, def : ' ' },
-            VIS : {start : 18, len : 1, def : ' ' },
-            MIX : {start : 18, len : 1, def : ' ' },
-            MAP : {start : 18, len : 1, def : ' ' },
-            SCO : {start : 18, len : 1, def : ' ' },
-            REC : {start : 18, len : 1, def : ' ' },
-            COM : {start : 18, len : 1, def : 'i' }
-        }
-    },
-    Item : {
-        ldr : {
-            MFHD : {start : 18, len : 1, def : 'i' }
-        }
-    },
-    ELvl : {
-        ldr : {
-            BKS : {start : 17, len : 1, def : ' ' },
-            SER : {start : 17, len : 1, def : ' ' },
-            VIS : {start : 17, len : 1, def : ' ' },
-            MIX : {start : 17, len : 1, def : ' ' },
-            MAP : {start : 17, len : 1, def : ' ' },
-            SCO : {start : 17, len : 1, def : ' ' },
-            REC : {start : 17, len : 1, def : ' ' },
-            COM : {start : 17, len : 1, def : ' ' },
-            AUT : {start : 17, len : 1, def : 'n' },
-            MFHD : {start : 17, len : 1, def : 'u' }
-        }
-    },
-    Indx : {
-        _8 : {
-            BKS : {start : 31, len : 1, def : '0' },
-            MAP : {start : 31, len : 1, def : '0' }
-        },
-        _6 : {
-            BKS : {start : 14, len : 1, def : '0' },
-            MAP : {start : 14, len : 1, def : '0' }
-        }
-    },
-    Date1 : {
-        _8 : {
-            BKS : {start : 7, len : 4, def : ' ' },
-            SER : {start : 7, len : 4, def : ' ' },
-            VIS : {start : 7, len : 4, def : ' ' },
-            MIX : {start : 7, len : 4, def : ' ' },
-            MAP : {start : 7, len : 4, def : ' ' },
-            SCO : {start : 7, len : 4, def : ' ' },
-            REC : {start : 7, len : 4, def : ' ' },
-            COM : {start : 7, len : 4, def : ' ' }
-        }
-    },
-    Date2 : {
-        _8 : {
-            BKS : {start : 11, len : 4, def : ' ' },
-            SER : {start : 11, len : 4, def : '9' },
-            VIS : {start : 11, len : 4, def : ' ' },
-            MIX : {start : 11, len : 4, def : ' ' },
-            MAP : {start : 11, len : 4, def : ' ' },
-            SCO : {start : 11, len : 4, def : ' ' },
-            REC : {start : 11, len : 4, def : ' ' },
-            COM : {start : 11, len : 4, def : ' ' }
-        }
-    },
-    LitF : {
-        _8 : {
-            BKS : {start : 33, len : 1, def : '0' }
-        },
-        _6 : {
-            BKS : {start : 16, len : 1, def : '0' }
-        }
-    },
-    Biog : {
-        _8 : {
-            BKS : {start : 34, len : 1, def : ' ' }
-        },
-        _6 : {
-            BKS : {start : 17, len : 1, def : ' ' }
-        }
-    },
-    Ills : {
-        _8 : {
-            BKS : {start : 18, len : 4, def : ' ' }
-        },
-        _6 : {
-            BKS : {start : 1, len : 4, def : ' ' }
-        }
-    },
-    Fest : {
-        _8 : {
-            BKS : {start : 30, len : 1, def : '0' }
-        },
-        _6 : {
-            BKS : {start : 13, len : 1, def : '0' }
-        }
-    },
-    Conf : {
-        _8 : {
-            BKS : {start : 29, len : 1, def : '0' },
-            SER : {start : 29, len : 1, def : '0' }
-        },
-        _6 : {
-            BKS : {start : 12, len : 1, def : '0' },
-            SER : {start : 12, len : 1, def : '0' }
-        }
-    },
-    Cont : {
-        _8 : {
-            BKS : {start : 24, len : 4, def : ' ' },
-            SER : {start : 25, len : 3, def : ' ' }
-        },
-        _6 : {
-            BKS : {start : 7, len : 4, def : ' ' },
-            SER : {start : 8, len : 3, def : ' ' }
-        }
-    },
-    GPub : {
-        _8 : {
-            BKS : {start : 28, len : 1, def : ' ' },
-            SER : {start : 28, len : 1, def : ' ' },
-            VIS : {start : 28, len : 1, def : ' ' },
-            MAP : {start : 28, len : 1, def : ' ' },
-            COM : {start : 28, len : 1, def : ' ' }
-        },
-        _6 : {
-            BKS : {start : 11, len : 1, def : ' ' },
-            SER : {start : 11, len : 1, def : ' ' },
-            VIS : {start : 11, len : 1, def : ' ' },
-            MAP : {start : 11, len : 1, def : ' ' },
-            COM : {start : 11, len : 1, def : ' ' }
-        }
-    },
-    Audn : {
-        _8 : {
-            BKS : {start : 22, len : 1, def : ' ' },
-            SER : {start : 22, len : 1, def : ' ' },
-            VIS : {start : 22, len : 1, def : ' ' },
-            SCO : {start : 22, len : 1, def : ' ' },
-            REC : {start : 22, len : 1, def : ' ' },
-            COM : {start : 22, len : 1, def : ' ' }
-        },
-        _6 : {
-            BKS : {start : 5, len : 1, def : ' ' },
-            SER : {start : 5, len : 1, def : ' ' },
-            VIS : {start : 5, len : 1, def : ' ' },
-            SCO : {start : 5, len : 1, def : ' ' },
-            REC : {start : 5, len : 1, def : ' ' },
-            COM : {start : 5, len : 1, def : ' ' }
-        }
-    },
-    Form : {
-        _8 : {
-            BKS : {start : 23, len : 1, def : ' ' },
-            SER : {start : 23, len : 1, def : ' ' },
-            VIS : {start : 29, len : 1, def : ' ' },
-            MIX : {start : 23, len : 1, def : ' ' },
-            MAP : {start : 29, len : 1, def : ' ' },
-            SCO : {start : 23, len : 1, def : ' ' },
-            REC : {start : 23, len : 1, def : ' ' }
-        },
-        _6 : {
-            BKS : {start : 6, len : 1, def : ' ' },
-            SER : {start : 6, len : 1, def : ' ' },
-            VIS : {start : 12, len : 1, def : ' ' },
-            MIX : {start : 6, len : 1, def : ' ' },
-            MAP : {start : 12, len : 1, def : ' ' },
-            SCO : {start : 6, len : 1, def : ' ' },
-            REC : {start : 6, len : 1, def : ' ' }
-        }
-    },
-    'S/L' : {
-        _8 : {
-            SER : {start : 34, len : 1, def : '0' }
-        },
-        _6 : {
-            SER : {start : 17, len : 1, def : '0' }
-        }
-    },
-    'Alph' : {
-        _8 : {
-            SER : {start : 33, len : 1, def : ' ' }
-        },
-        _6 : {
-            SER : {start : 16, len : 1, def : ' ' }
-        }
-    },
-    "GeoDiv" : {
-        "_8" : {
-            "AUT" : {"start" : 6, "len" : 1, "def" : ' ' }
-        }
-    },
-    "Roman" : {
-        "_8" : {
-            "AUT" : {"start" : 7, "len" : 1, "def" : ' ' }
-        }
-    },
-    "CatLang" : {
-        "_8" : {
-            "AUT" : {"start" : 8, "len" : 1, "def" : ' ' }
-        }
-    },
-    "Kind" : {
-        "_8" : {
-            "AUT" : {"start" : 9, "len" : 1, "def" : ' ' }
-        }
-    },
-    "Rules" : {
-        "_8" : {
-            "AUT" : {"start" : 10, "len" : 1, "def" : ' ' }
-        }
-    },
-    "SHSys" : {
-        "_8" : {
-            "AUT" : {"start" : 11, "len" : 1, "def" : ' ' }
-        }
-    },
-    "SerType" : {
-        "_8" : {
-            "AUT" : {"start" : 12, "len" : 1, "def" : ' ' }
-        }
-    },
-    "SerNum" : {
-        "_8" : {
-            "AUT" : {"start" : 13, "len" : 1, "def" : ' ' }
-        }
-    },
-    "HeadMain" : {
-        "_8" : {
-            "AUT" : {"start" : 14, "len" : 1, "def" : ' ' }
-        }
-    },
-    "HeadSubj" : {
-        "_8" : {
-            "AUT" : {"start" : 15, "len" : 1, "def" : ' ' }
-        }
-    },
-    "HeadSer" : {
-        "_8" : {
-            "AUT" : {"start" : 16, "len" : 1, "def" : ' ' }
-        }
-    },
-    "TypeSubd" : {
-        "_8" : {
-            "AUT" : {"start" : 17, "len" : 1, "def" : ' ' }
-        }
-    },
-    "TypeGov" : {
-        "_8" : {
-            "AUT" : {"start" : 28, "len" : 1, "def" : ' ' }
-        }
-    },
-    "RefEval" : {
-        "_8" : {
-            "AUT" : {"start" : 29, "len" : 1, "def" : ' ' }
-        }
-    },
-    "RecUpd" : {
-        "_8" : {
-            "AUT" : {"start" : 31, "len" : 1, "def" : ' ' }
-        }
-    },
-    "NameDiff" : {
-        "_8" : {
-            "AUT" : {"start" : 32, "len" : 1, "def" : ' ' }
-        }
-    },
-    "Level" : {
-        "_8" : {
-            "AUT" : {"start" : 33, "len" : 1, "def" : ' ' }
-        }
-    },
-    "ModRec" : {
-        "_8" : {
-            "AUT" : {"start" : 38, "len" : 1, "def" : ' ' }
-        }
-    },
-    "CatSrc" : {
-        "_8" : {
-            "AUT" : {"start" : 39, "len" : 1, "def" : ' ' }
-        }
-    }
-};
-
-function recordType (rec) {
-    try {
-        var _l = rec.leader.toString();
-
-        var _t = _l.substr(ff_pos.Type.ldr.BKS.start, ff_pos.Type.ldr.BKS.len);
-        var _b = _l.substr(ff_pos.BLvl.ldr.BKS.start, ff_pos.BLvl.ldr.BKS.len);
-
-        for (var t in rec_type) {
-            if (_t.match(rec_type[t].Type) && _b.match(rec_type[t].BLvl)) {
-                document.getElementById('recordTypeLabel').value = t;
-                _record_type = t;
-                return t;
-            }
-        }
-
-        // in case we don't have a valid record type ...
-        _record_type = 'BKS';
-        return _record_type;
-
-    } catch(E) {
-        alert('FIXME, MARC Editor, recordType: ' + E);
-    }
-}
-
 function toggleFFE () {
     var grid = document.getElementById('leaderGrid');
     if (grid.hidden) {
@@ -1362,16 +779,10 @@ function changeFFEditor (type) {
 
 }
 
-function fillFixedFields (rec) {
+function fillFixedFields () {
     try {
             var grid = document.getElementById('leaderGrid');
-
-            var rtype = _record_type;
-
-            var _l = rec.leader.toString();
-            var _6 = rec.controlfield.(@tag=='006').toString();
-            var _7 = rec.controlfield.(@tag=='007').toString();
-            var _8 = rec.controlfield.(@tag=='008').toString();
+            var marc_rec = new MARC.Record ({ delimiter : '$', marcxml : xml_record.toXMLString() });
 
             var list = [];
             var pre_list = grid.getElementsByTagName('label');
@@ -1383,52 +794,9 @@ function fillFixedFields (rec) {
 
             for (var i in list) {
                 var name = list[i].getAttribute('name');
+                var value = marc_rec.extractFixedField(name, true);
 
-                if (!ff_pos[name])
-                    continue;
-
-                var value = '';
-                if ( ff_pos[name].ldr && ff_pos[name].ldr[rtype] )
-                    value = _l.substr(ff_pos[name].ldr[rtype].start, ff_pos[name].ldr[rtype].len);
-
-                if ( ff_pos[name]._8 && ff_pos[name]._8[rtype] )
-                    value = _8.substr(ff_pos[name]._8[rtype].start, ff_pos[name]._8[rtype].len);
-
-                if ( !value && ff_pos[name]._6 && ff_pos[name]._6[rtype] )
-                    value = _6.substr(ff_pos[name]._6[rtype].start, ff_pos[name]._6[rtype].len);
-
-                if ( ff_pos[name]._7 && ff_pos[name]._7[rtype] )
-                    value = _7.substr(ff_pos[name]._7[rtype].start, ff_pos[name]._7[rtype].len);
-                
-                if (!value) {
-                    var d;
-                    var p;
-                    if (ff_pos[name].ldr && ff_pos[name].ldr[rtype]) {
-                        d = ff_pos[name].ldr[rtype].def;
-                        p = 'ldr';
-                    }
-
-                    if (ff_pos[name]._8 && ff_pos[name]._8[rtype]) {
-                        d = ff_pos[name]._8[rtype].def;
-                        p = '_8';
-                    }
-
-                    if (!value && ff_pos[name]._6 && ff_pos[name]._6[rtype]) {
-                        d = ff_pos[name]._6[rtype].def;
-                        p = '_6';
-                    }
-
-                    if (ff_pos[name]._7 && ff_pos[name]._7[rtype]) {
-                        d = ff_pos[name]._7[rtype].def;
-                        p = '_7';
-                    }
-
-                    if (p && !value) {
-                        for (var j = 0; j < ff_pos[name][p][rtype].len; j++) {
-                            value += d;
-                        }
-                    }
-                }
+                if (value === null) continue;
 
                 list[i].nextSibling.value = value;
             }
@@ -1442,21 +810,22 @@ function fillFixedFields (rec) {
 function updateFixedFields (element) {
     var grid = document.getElementById('leaderGrid');
     var recGrid = document.getElementById('recGrid');
-
-    var rtype = _record_type;
     var new_value = element.value;
 
+    var marc_rec = new MARC.Record ({ delimiter : '$', marcxml : xml_record.toXMLString() });
+    var rtype = marc_rec.recordType();
+
     var parts = {
-        ldr : _record.leader,
-        _6 : _record.controlfield.(@tag=='006'),
-        _7 : _record.controlfield.(@tag=='007'),
-        _8 : _record.controlfield.(@tag=='008')
+        ldr : marc_rec.leader(),
+        _6 : marc_rec.field('006');
+        _7 : marc_rec.field('007');
+        _8 : marc_rec.field('008');
     };
 
     var name = element.getAttribute('name');
-    for (var i in ff_pos[name]) {
+    for (var i in MARC.Record._ff_pos[name]) {
 
-        if (!ff_pos[name][i][rtype]) continue;
+        if (!MARC.Record._ff_pos[name][i][rtype]) continue;
         if (!parts[i]) {
             // we're missing the required field.  Add it now.
 
@@ -1467,18 +836,17 @@ function updateFixedFields (element) {
             else continue;
 
             createControlField(newfield,'                                        ');
-            parts[i] = _record.controlfield.(@tag==newfield);
+            parts[i] = xml_record.controlfield.(@tag==newfield).toString();
         }
 
-        var before = parts[i].substr(0, ff_pos[name][i][rtype].start);
-        var after = parts[i].substr(ff_pos[name][i][rtype].start + ff_pos[name][i][rtype].len);
+        var before = parts[i].substr(0, MARC.Record._ff_pos[name][i][rtype].start);
+        var after = parts[i].substr(MARC.Record._ff_pos[name][i][rtype].start + MARC.Record._ff_pos[name][i][rtype].len);
 
-        for (var j = 0; new_value.length < ff_pos[name][i][rtype].len; j++) {
-            new_value += ff_pos[name][i][rtype].def;
+        for (var j = 0; new_value.length < MARC.Record._ff_pos[name][i][rtype].len; j++) {
+            new_value += MARC.Record._ff_pos[name][i][rtype].def;
         }
 
-        parts[i].setChildren( before + new_value + after );
-        recGrid.getElementsByAttribute('tag',i)[0].lastChild.value = parts[i].toString();
+        recGrid.getElementsByAttribute('tag',i)[0].lastChild.value = before + new_value + after;
     }
 
     return true;
@@ -1720,26 +1088,27 @@ function marcSubfield (sf) {
     );
 }
 
-function loadRecord(rec) {
+function loadRecord() {
     try {
-            _record = rec;
             var grid_rows = document.getElementById('recGrid').lastChild;
 
             while (grid_rows.firstChild) grid_rows.removeChild(grid_rows.firstChild);
 
-            grid_rows.appendChild( marcLeader( rec.leader ) );
+            grid_rows.appendChild( marcLeader( xml_record.leader ) );
 
-            for (var i in rec.controlfield) {
-                grid_rows.appendChild( marcControlfield( rec.controlfield[i] ) );
+            for (var i in xml_record.controlfield) {
+                grid_rows.appendChild( marcControlfield( xml_record.controlfield[i] ) );
             }
 
-            for (var i in rec.datafield) {
-                grid_rows.appendChild( marcDatafield( rec.datafield[i] ) );
+            for (var i in xml_record.datafield) {
+                grid_rows.appendChild( marcDatafield( xml_record.datafield[i] ) );
             }
 
             grid_rows.getElementsByAttribute('class','marcDatafieldRow')[0].firstChild.focus();
-            changeFFEditor(recordType(rec));
-            fillFixedFields(rec);
+
+            var marc_rec = new MARC.Record ({ delimiter : '$', marcxml : xml_record.toXMLString() });
+            changeFFEditor(marc_rec.recordType());
+            fillFixedFields();
     } catch(E) {
         alert('FIXME, MARC Editor, loadRecord: ' + E);
     }

commit c7f4ec8091d071ffd07e9e6ccb815c85a88b49c6
Author: Mike Rylander <mrylander at gmail.com>
Date:   Fri May 6 15:29:07 2011 -0400

    bring backend version up to date with the marc-editor embedded version

diff --git a/Open-ILS/src/javascript/backend/catalog/fixed_fields.js b/Open-ILS/src/javascript/backend/catalog/fixed_fields.js
index 4e7871c..6a67b65 100644
--- a/Open-ILS/src/javascript/backend/catalog/fixed_fields.js
+++ b/Open-ILS/src/javascript/backend/catalog/fixed_fields.js
@@ -1,277 +1,384 @@
 
 var rec_type = {
-        BKS : { Type : /[at]{1}/,	BLvl : /[acdm]{1}/ },
-	SER : { Type : /[a]{1}/,	BLvl : /[bsi]{1}/ },
-	VIS : { Type : /[gkro]{1}/,	BLvl : /[abcdmsi]{1}/ },
-	MIX : { Type : /[p]{1}/,	BLvl : /[cdi]{1}/ },
-	MAP : { Type : /[ef]{1}/,	BLvl : /[abcdmsi]{1}/ },
-	SCO : { Type : /[cd]{1}/,	BLvl : /[abcdmsi]{1}/ },
-	REC : { Type : /[ij]{1}/,	BLvl : /[abcdmsi]{1}/ },
-	COM : { Type : /[m]{1}/,	BLvl : /[abcdmsi]{1}/ }
+    BKS : { Type : /[at]{1}/,    BLvl : /[acdm]{1}/ },
+    SER : { Type : /[a]{1}/,    BLvl : /[bsi]{1}/ },
+    VIS : { Type : /[gkro]{1}/,    BLvl : /[abcdmsi]{1}/ },
+    MIX : { Type : /[p]{1}/,    BLvl : /[cdi]{1}/ },
+    MAP : { Type : /[ef]{1}/,    BLvl : /[abcdmsi]{1}/ },
+    SCO : { Type : /[cd]{1}/,    BLvl : /[abcdmsi]{1}/ },
+    REC : { Type : /[ij]{1}/,    BLvl : /[abcdmsi]{1}/ },
+    COM : { Type : /[m]{1}/,    BLvl : /[abcdmsi]{1}/ },
+    AUT : { Type : /[z]{1}/,    BLvl : /.{1}/ },
+    MFHD : { Type : /[uvxy]{1}/,  BLvl : /.{1}/ }
 };
 
 var ff_pos = {
-	Ctry : {
-		_8 : {
-			BKS : {start : 15, len : 3, def : ' ' },
-			SER : {start : 15, len : 3, def : ' ' },
-			VIS : {start : 15, len : 3, def : ' ' },
-			MIX : {start : 15, len : 3, def : ' ' },
-			MAP : {start : 15, len : 3, def : ' ' },
-			SCO : {start : 15, len : 3, def : ' ' },
-			REC : {start : 15, len : 3, def : ' ' },
-			COM : {start : 15, len : 3, def : ' ' },
-		}
-	},
-	Lang : {
-		_8 : {
-			BKS : {start : 35, len : 3, def : ' ' },
-			SER : {start : 35, len : 3, def : ' ' },
-			VIS : {start : 35, len : 3, def : ' ' },
-			MIX : {start : 35, len : 3, def : ' ' },
-			MAP : {start : 35, len : 3, def : ' ' },
-			SCO : {start : 35, len : 3, def : ' ' },
-			REC : {start : 35, len : 3, def : ' ' },
-			COM : {start : 35, len : 3, def : ' ' },
-		}
-	},
-	MRec : {
-		_8 : {
-			BKS : {start : 38, len : 1, def : ' ' },
-			SER : {start : 38, len : 1, def : ' ' },
-			VIS : {start : 38, len : 1, def : ' ' },
-			MIX : {start : 38, len : 1, def : ' ' },
-			MAP : {start : 38, len : 1, def : ' ' },
-			SCO : {start : 38, len : 1, def : ' ' },
-			REC : {start : 38, len : 1, def : ' ' },
-			COM : {start : 38, len : 1, def : ' ' },
-		}
-	},
-	DtSt : {
-		_8 : {
-			BKS : {start : 6, len : 1, def : ' ' },
-			SER : {start : 6, len : 1, def : 'c' },
-			VIS : {start : 6, len : 1, def : ' ' },
-			MIX : {start : 6, len : 1, def : ' ' },
-			MAP : {start : 6, len : 1, def : ' ' },
-			SCO : {start : 6, len : 1, def : ' ' },
-			REC : {start : 6, len : 1, def : ' ' },
-			COM : {start : 6, len : 1, def : ' ' },
-		}
-	},
-	Type : {
-		ldr : {
-			BKS : {start : 6, len : 1, def : 'a' },
-			SER : {start : 6, len : 1, def : 'a' },
-			VIS : {start : 6, len : 1, def : 'g' },
-			MIX : {start : 6, len : 1, def : 'p' },
-			MAP : {start : 6, len : 1, def : 'e' },
-			SCO : {start : 6, len : 1, def : 'c' },
-			REC : {start : 6, len : 1, def : 'i' },
-			COM : {start : 6, len : 1, def : 'm' },
-		}
-	},
-	Ctrl : {
-		ldr : {
-			BKS : {start : 8, len : 1, def : ' ' },
-			SER : {start : 8, len : 1, def : ' ' },
-			VIS : {start : 8, len : 1, def : ' ' },
-			MIX : {start : 8, len : 1, def : ' ' },
-			MAP : {start : 8, len : 1, def : ' ' },
-			SCO : {start : 8, len : 1, def : ' ' },
-			REC : {start : 8, len : 1, def : ' ' },
-			COM : {start : 8, len : 1, def : ' ' },
-		}
-	},
-	BLvl : {
-		ldr : {
-			BKS : {start : 7, len : 1, def : 'm' },
-			SER : {start : 7, len : 1, def : 's' },
-			VIS : {start : 7, len : 1, def : 'm' },
-			MIX : {start : 7, len : 1, def : 'c' },
-			MAP : {start : 7, len : 1, def : 'm' },
-			SCO : {start : 7, len : 1, def : 'm' },
-			REC : {start : 7, len : 1, def : 'm' },
-			COM : {start : 7, len : 1, def : 'm' },
-		}
-	},
-	Desc : {
-		ldr : {
-			BKS : {start : 18, len : 1, def : ' ' },
-			SER : {start : 18, len : 1, def : ' ' },
-			VIS : {start : 18, len : 1, def : ' ' },
-			MIX : {start : 18, len : 1, def : ' ' },
-			MAP : {start : 18, len : 1, def : ' ' },
-			SCO : {start : 18, len : 1, def : ' ' },
-			REC : {start : 18, len : 1, def : ' ' },
-			COM : {start : 18, len : 1, def : ' ' },
-		}
-	},
-	ELvl : {
-		ldr : {
-			BKS : {start : 17, len : 1, def : ' ' },
-			SER : {start : 17, len : 1, def : ' ' },
-			VIS : {start : 17, len : 1, def : ' ' },
-			MIX : {start : 17, len : 1, def : ' ' },
-			MAP : {start : 17, len : 1, def : ' ' },
-			SCO : {start : 17, len : 1, def : ' ' },
-			REC : {start : 17, len : 1, def : ' ' },
-			COM : {start : 17, len : 1, def : ' ' },
-		}
-	},
-	TMat : {
-		_8 : {
-			VIS : {start : 33, len : 1, def : ' ' },
-		},
-		_6 : {
-			VIS : {start : 16, len : 1, def : ' ' },
-		}
-	},
-	Indx : {
-		_8 : {
-			BKS : {start : 31, len : 1, def : '0' },
-			MAP : {start : 31, len : 1, def : '0' },
-		},
-		_6 : {
-			BKS : {start : 14, len : 1, def : '0' },
-			MAP : {start : 14, len : 1, def : '0' },
-		}
-	},
-	Date1 : {
-		_8 : {
-			BKS : {start : 7, len : 4, def : ' ' },
-			SER : {start : 7, len : 4, def : ' ' },
-			VIS : {start : 7, len : 4, def : ' ' },
-			MIX : {start : 7, len : 4, def : ' ' },
-			MAP : {start : 7, len : 4, def : ' ' },
-			SCO : {start : 7, len : 4, def : ' ' },
-			REC : {start : 7, len : 4, def : ' ' },
-			COM : {start : 7, len : 4, def : ' ' },
-		},
-	},
-	Date2 : {
-		_8 : {
-			BKS : {start : 11, len : 4, def : ' ' },
-			SER : {start : 11, len : 4, def : '9' },
-			VIS : {start : 11, len : 4, def : ' ' },
-			MIX : {start : 11, len : 4, def : ' ' },
-			MAP : {start : 11, len : 4, def : ' ' },
-			SCO : {start : 11, len : 4, def : ' ' },
-			REC : {start : 11, len : 4, def : ' ' },
-			COM : {start : 11, len : 4, def : ' ' },
-		},
-	},
-	LitF : {
-		_8 : {
-			BKS : {start : 33, len : 1, def : '0' },
-		},
-		_6 : {
-			BKS : {start : 16, len : 1, def : '0' },
-		}
-	},
-	Biog : {
-		_8 : {
-			BKS : {start : 34, len : 1, def : ' ' },
-		},
-		_6 : {
-			BKS : {start : 17, len : 1, def : ' ' },
-		}
-	},
-	Ills : {
-		_8 : {
-			BKS : {start : 18, len : 4, def : ' ' },
-		},
-		_6 : {
-			BKS : {start : 1, len : 4, def : ' ' },
-		}
-	},
-	Fest : {
-		_8 : {
-			BKS : {start : 30, len : 1, def : '0' },
-		},
-		_6 : {
-			BKS : {start : 13, len : 1, def : '0' },
-		}
-	},
-	Conf : {
-		_8 : {
-			BKS : {start : 24, len : 4, def : ' ' },
-			SER : {start : 25, len : 3, def : ' ' },
-		},
-		_6 : {
-			BKS : {start : 7, len : 4, def : ' ' },
-			SER : {start : 8, len : 3, def : ' ' },
-		}
-	},
-	GPub : {
-		_8 : {
-			BKS : {start : 28, len : 1, def : ' ' },
-			SER : {start : 28, len : 1, def : ' ' },
-			VIS : {start : 28, len : 1, def : ' ' },
-			MAP : {start : 28, len : 1, def : ' ' },
-			COM : {start : 28, len : 1, def : ' ' },
-		},
-		_6 : {
-			BKS : {start : 11, len : 1, def : ' ' },
-			SER : {start : 11, len : 1, def : ' ' },
-			VIS : {start : 11, len : 1, def : ' ' },
-			MAP : {start : 11, len : 1, def : ' ' },
-			COM : {start : 11, len : 1, def : ' ' },
-		}
-	},
-	Audn : {
-		_8 : {
-			BKS : {start : 22, len : 1, def : ' ' },
-			SER : {start : 22, len : 1, def : ' ' },
-			VIS : {start : 22, len : 1, def : ' ' },
-			SCO : {start : 22, len : 1, def : ' ' },
-			REC : {start : 22, len : 1, def : ' ' },
-			COM : {start : 22, len : 1, def : ' ' },
-		},
-		_6 : {
-			BKS : {start : 5, len : 1, def : ' ' },
-			SER : {start : 5, len : 1, def : ' ' },
-			VIS : {start : 5, len : 1, def : ' ' },
-			SCO : {start : 5, len : 1, def : ' ' },
-			REC : {start : 5, len : 1, def : ' ' },
-			COM : {start : 5, len : 1, def : ' ' },
-		}
-	},
-	Form : {
-		_8 : {
-			BKS : {start : 23, len : 1, def : ' ' },
-			SER : {start : 23, len : 1, def : ' ' },
-			VIS : {start : 29, len : 1, def : ' ' },
-			MIX : {start : 23, len : 1, def : ' ' },
-			MAP : {start : 29, len : 1, def : ' ' },
-			SCO : {start : 23, len : 1, def : ' ' },
-			REC : {start : 23, len : 1, def : ' ' },
-		},
-		_6 : {
-			BKS : {start : 6, len : 1, def : ' ' },
-			SER : {start : 6, len : 1, def : ' ' },
-			VIS : {start : 12, len : 1, def : ' ' },
-			MIX : {start : 6, len : 1, def : ' ' },
-			MAP : {start : 12, len : 1, def : ' ' },
-			SCO : {start : 6, len : 1, def : ' ' },
-			REC : {start : 6, len : 1, def : ' ' },
-		}
-	},
-	'S/L' : {
-		_8 : {
-			SER : {start : 34, len : 1, def : '0' },
-		},
-		_6 : {
-			SER : {start : 17, len : 1, def : '0' },
-		}
-	},
-	'Alph' : {
-		_8 : {
-			SER : {start : 33, len : 1, def : ' ' },
-		},
-		_6 : {
-			SER : {start : 16, len : 1, def : ' ' },
-		}
-	},
+    Ctry : {
+        _8 : {
+            BKS : {start : 15, len : 3, def : ' ' },
+            SER : {start : 15, len : 3, def : ' ' },
+            VIS : {start : 15, len : 3, def : ' ' },
+            MIX : {start : 15, len : 3, def : ' ' },
+            MAP : {start : 15, len : 3, def : ' ' },
+            SCO : {start : 15, len : 3, def : ' ' },
+            REC : {start : 15, len : 3, def : ' ' },
+            COM : {start : 15, len : 3, def : ' ' },
+        }
+    },
+    Lang : {
+        _8 : {
+            BKS : {start : 35, len : 3, def : ' ' },
+            SER : {start : 35, len : 3, def : ' ' },
+            VIS : {start : 35, len : 3, def : ' ' },
+            MIX : {start : 35, len : 3, def : ' ' },
+            MAP : {start : 35, len : 3, def : ' ' },
+            SCO : {start : 35, len : 3, def : ' ' },
+            REC : {start : 35, len : 3, def : ' ' },
+            COM : {start : 35, len : 3, def : ' ' },
+        }
+    },
+    MRec : {
+        _8 : {
+            BKS : {start : 38, len : 1, def : ' ' },
+            SER : {start : 38, len : 1, def : ' ' },
+            VIS : {start : 38, len : 1, def : ' ' },
+            MIX : {start : 38, len : 1, def : ' ' },
+            MAP : {start : 38, len : 1, def : ' ' },
+            SCO : {start : 38, len : 1, def : ' ' },
+            REC : {start : 38, len : 1, def : ' ' },
+            COM : {start : 38, len : 1, def : ' ' },
+        }
+    },
+    DtSt : {
+        _8 : {
+            BKS : {start : 6, len : 1, def : ' ' },
+            SER : {start : 6, len : 1, def : 'c' },
+            VIS : {start : 6, len : 1, def : ' ' },
+            MIX : {start : 6, len : 1, def : ' ' },
+            MAP : {start : 6, len : 1, def : ' ' },
+            SCO : {start : 6, len : 1, def : ' ' },
+            REC : {start : 6, len : 1, def : ' ' },
+            COM : {start : 6, len : 1, def : ' ' },
+        }
+    },
+    Type : {
+        ldr : {
+            BKS : {start : 6, len : 1, def : 'a' },
+            SER : {start : 6, len : 1, def : 'a' },
+            VIS : {start : 6, len : 1, def : 'g' },
+            MIX : {start : 6, len : 1, def : 'p' },
+            MAP : {start : 6, len : 1, def : 'e' },
+            SCO : {start : 6, len : 1, def : 'c' },
+            REC : {start : 6, len : 1, def : 'i' },
+            COM : {start : 6, len : 1, def : 'm' },
+            AUT : {start : 6, len : 1, def : 'z' },
+            MFHD : {start : 6, len : 1, def : 'y' }
+
+        }
+    },
+    Ctrl : {
+        ldr : {
+            BKS : {start : 8, len : 1, def : ' ' },
+            SER : {start : 8, len : 1, def : ' ' },
+            VIS : {start : 8, len : 1, def : ' ' },
+            MIX : {start : 8, len : 1, def : ' ' },
+            MAP : {start : 8, len : 1, def : ' ' },
+            SCO : {start : 8, len : 1, def : ' ' },
+            REC : {start : 8, len : 1, def : ' ' },
+            COM : {start : 8, len : 1, def : ' ' },
+        }
+    },
+    BLvl : {
+        ldr : {
+            BKS : {start : 7, len : 1, def : 'm' },
+            SER : {start : 7, len : 1, def : 's' },
+            VIS : {start : 7, len : 1, def : 'm' },
+            MIX : {start : 7, len : 1, def : 'c' },
+            MAP : {start : 7, len : 1, def : 'm' },
+            SCO : {start : 7, len : 1, def : 'm' },
+            REC : {start : 7, len : 1, def : 'm' },
+            COM : {start : 7, len : 1, def : 'm' },
+        }
+    },
+    Desc : {
+        ldr : {
+            BKS : {start : 18, len : 1, def : ' ' },
+            SER : {start : 18, len : 1, def : ' ' },
+            VIS : {start : 18, len : 1, def : ' ' },
+            MIX : {start : 18, len : 1, def : ' ' },
+            MAP : {start : 18, len : 1, def : ' ' },
+            SCO : {start : 18, len : 1, def : ' ' },
+            REC : {start : 18, len : 1, def : ' ' },
+            COM : {start : 18, len : 1, def : ' ' },
+        }
+    },
+    Item : {
+        ldr : {
+            MFHD : {start : 18, len : 1, def : 'i' }
+        }
+    },
+    ELvl : {
+        ldr : {
+            BKS : {start : 17, len : 1, def : ' ' },
+            SER : {start : 17, len : 1, def : ' ' },
+            VIS : {start : 17, len : 1, def : ' ' },
+            MIX : {start : 17, len : 1, def : ' ' },
+            MAP : {start : 17, len : 1, def : ' ' },
+            SCO : {start : 17, len : 1, def : ' ' },
+            REC : {start : 17, len : 1, def : ' ' },
+            COM : {start : 17, len : 1, def : ' ' },
+            AUT : {start : 17, len : 1, def : 'n' },
+            MFHD : {start : 17, len : 1, def : 'u' }
+        }
+    },
+    TMat : {
+        _8 : {
+            VIS : {start : 33, len : 1, def : ' ' },
+        },
+        _6 : {
+            VIS : {start : 16, len : 1, def : ' ' },
+        }
+    },
+    Indx : {
+        _8 : {
+            BKS : {start : 31, len : 1, def : '0' },
+            MAP : {start : 31, len : 1, def : '0' },
+        },
+        _6 : {
+            BKS : {start : 14, len : 1, def : '0' },
+            MAP : {start : 14, len : 1, def : '0' },
+        }
+    },
+    Date1 : {
+        _8 : {
+            BKS : {start : 7, len : 4, def : ' ' },
+            SER : {start : 7, len : 4, def : ' ' },
+            VIS : {start : 7, len : 4, def : ' ' },
+            MIX : {start : 7, len : 4, def : ' ' },
+            MAP : {start : 7, len : 4, def : ' ' },
+            SCO : {start : 7, len : 4, def : ' ' },
+            REC : {start : 7, len : 4, def : ' ' },
+            COM : {start : 7, len : 4, def : ' ' },
+        },
+    },
+    Date2 : {
+        _8 : {
+            BKS : {start : 11, len : 4, def : ' ' },
+            SER : {start : 11, len : 4, def : '9' },
+            VIS : {start : 11, len : 4, def : ' ' },
+            MIX : {start : 11, len : 4, def : ' ' },
+            MAP : {start : 11, len : 4, def : ' ' },
+            SCO : {start : 11, len : 4, def : ' ' },
+            REC : {start : 11, len : 4, def : ' ' },
+            COM : {start : 11, len : 4, def : ' ' },
+        },
+    },
+    LitF : {
+        _8 : {
+            BKS : {start : 33, len : 1, def : '0' },
+        },
+        _6 : {
+            BKS : {start : 16, len : 1, def : '0' },
+        }
+    },
+    Biog : {
+        _8 : {
+            BKS : {start : 34, len : 1, def : ' ' },
+        },
+        _6 : {
+            BKS : {start : 17, len : 1, def : ' ' },
+        }
+    },
+    Ills : {
+        _8 : {
+            BKS : {start : 18, len : 4, def : ' ' },
+        },
+        _6 : {
+            BKS : {start : 1, len : 4, def : ' ' },
+        }
+    },
+    Fest : {
+        _8 : {
+            BKS : {start : 30, len : 1, def : '0' },
+        },
+        _6 : {
+            BKS : {start : 13, len : 1, def : '0' },
+        }
+    },
+    Conf : {
+        _8 : {
+            BKS : {start : 24, len : 4, def : ' ' },
+            SER : {start : 25, len : 3, def : ' ' },
+        },
+        _6 : {
+            BKS : {start : 7, len : 4, def : ' ' },
+            SER : {start : 8, len : 3, def : ' ' },
+        }
+    },
+    GPub : {
+        _8 : {
+            BKS : {start : 28, len : 1, def : ' ' },
+            SER : {start : 28, len : 1, def : ' ' },
+            VIS : {start : 28, len : 1, def : ' ' },
+            MAP : {start : 28, len : 1, def : ' ' },
+            COM : {start : 28, len : 1, def : ' ' },
+        },
+        _6 : {
+            BKS : {start : 11, len : 1, def : ' ' },
+            SER : {start : 11, len : 1, def : ' ' },
+            VIS : {start : 11, len : 1, def : ' ' },
+            MAP : {start : 11, len : 1, def : ' ' },
+            COM : {start : 11, len : 1, def : ' ' },
+        }
+    },
+    Audn : {
+        _8 : {
+            BKS : {start : 22, len : 1, def : ' ' },
+            SER : {start : 22, len : 1, def : ' ' },
+            VIS : {start : 22, len : 1, def : ' ' },
+            SCO : {start : 22, len : 1, def : ' ' },
+            REC : {start : 22, len : 1, def : ' ' },
+            COM : {start : 22, len : 1, def : ' ' },
+        },
+        _6 : {
+            BKS : {start : 5, len : 1, def : ' ' },
+            SER : {start : 5, len : 1, def : ' ' },
+            VIS : {start : 5, len : 1, def : ' ' },
+            SCO : {start : 5, len : 1, def : ' ' },
+            REC : {start : 5, len : 1, def : ' ' },
+            COM : {start : 5, len : 1, def : ' ' },
+        }
+    },
+    Form : {
+        _8 : {
+            BKS : {start : 23, len : 1, def : ' ' },
+            SER : {start : 23, len : 1, def : ' ' },
+            VIS : {start : 29, len : 1, def : ' ' },
+            MIX : {start : 23, len : 1, def : ' ' },
+            MAP : {start : 29, len : 1, def : ' ' },
+            SCO : {start : 23, len : 1, def : ' ' },
+            REC : {start : 23, len : 1, def : ' ' },
+        },
+        _6 : {
+            BKS : {start : 6, len : 1, def : ' ' },
+            SER : {start : 6, len : 1, def : ' ' },
+            VIS : {start : 12, len : 1, def : ' ' },
+            MIX : {start : 6, len : 1, def : ' ' },
+            MAP : {start : 12, len : 1, def : ' ' },
+            SCO : {start : 6, len : 1, def : ' ' },
+            REC : {start : 6, len : 1, def : ' ' },
+        }
+    },
+    'S/L' : {
+        _8 : {
+            SER : {start : 34, len : 1, def : '0' },
+        },
+        _6 : {
+            SER : {start : 17, len : 1, def : '0' },
+        }
+    },
+    'Alph' : {
+        _8 : {
+            SER : {start : 33, len : 1, def : ' ' },
+        },
+        _6 : {
+            SER : {start : 16, len : 1, def : ' ' },
+        }
+    },
+    "GeoDiv" : {
+        "_8" : {
+            "AUT" : {"start" : 6, "len" : 1, "def" : ' ' }
+        }
+    },
+    "Roman" : {
+        "_8" : {
+            "AUT" : {"start" : 7, "len" : 1, "def" : ' ' }
+        }
+    },
+    "CatLang" : {
+        "_8" : {
+            "AUT" : {"start" : 8, "len" : 1, "def" : ' ' }
+        }
+    },
+    "Kind" : {
+        "_8" : {
+            "AUT" : {"start" : 9, "len" : 1, "def" : ' ' }
+        }
+    },
+    "Rules" : {
+        "_8" : {
+            "AUT" : {"start" : 10, "len" : 1, "def" : ' ' }
+        }
+    },
+    "SHSys" : {
+        "_8" : {
+            "AUT" : {"start" : 11, "len" : 1, "def" : ' ' }
+        }
+    },
+    "SerType" : {
+        "_8" : {
+            "AUT" : {"start" : 12, "len" : 1, "def" : ' ' }
+        }
+    },
+    "SerNum" : {
+        "_8" : {
+            "AUT" : {"start" : 13, "len" : 1, "def" : ' ' }
+        }
+    },
+    "HeadMain" : {
+        "_8" : {
+            "AUT" : {"start" : 14, "len" : 1, "def" : ' ' }
+        }
+    },
+    "HeadSubj" : {
+        "_8" : {
+            "AUT" : {"start" : 15, "len" : 1, "def" : ' ' }
+        }
+    },
+    "HeadSer" : {
+        "_8" : {
+            "AUT" : {"start" : 16, "len" : 1, "def" : ' ' }
+        }
+    },
+    "TypeSubd" : {
+        "_8" : {
+            "AUT" : {"start" : 17, "len" : 1, "def" : ' ' }
+        }
+    },
+    "TypeGov" : {
+        "_8" : {
+            "AUT" : {"start" : 28, "len" : 1, "def" : ' ' }
+        }
+    },
+    "RefEval" : {
+        "_8" : {
+            "AUT" : {"start" : 29, "len" : 1, "def" : ' ' }
+        }
+    },
+    "RecUpd" : {
+        "_8" : {
+            "AUT" : {"start" : 31, "len" : 1, "def" : ' ' }
+        }
+    },
+    "NameDiff" : {
+        "_8" : {
+            "AUT" : {"start" : 32, "len" : 1, "def" : ' ' }
+        }
+    },
+    "Level" : {
+        "_8" : {
+            "AUT" : {"start" : 33, "len" : 1, "def" : ' ' }
+        }
+    },
+    "ModRec" : {
+        "_8" : {
+            "AUT" : {"start" : 38, "len" : 1, "def" : ' ' }
+        }
+    },
+    "CatSrc" : {
+        "_8" : {
+            "AUT" : {"start" : 39, "len" : 1, "def" : ' ' }
+        }
+    }
 };
 

commit 0fec22966751d1c56070a6d21dc1a737b8f029f6
Author: Mike Rylander <mrylander at gmail.com>
Date:   Fri May 6 15:28:00 2011 -0400

    Stub of a new Dojo module for manipulating ACSs

diff --git a/Open-ILS/web/js/dojo/MARC/AuthorityControlSet.js b/Open-ILS/web/js/dojo/MARC/AuthorityControlSet.js
new file mode 100644
index 0000000..2b3bfa4
--- /dev/null
+++ b/Open-ILS/web/js/dojo/MARC/AuthorityControlSet.js
@@ -0,0 +1,311 @@
+/* vim: et:sw=4:ts=4:
+ * ---------------------------------------------------------------------------
+ * Copyright (C) 2011  Equinox Software, Inc.
+ * Mike Rylander <miker at esilibrary.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * ---------------------------------------------------------------------------
+ */
+
+if(!dojo._hasResource["MARC.AuthorityControlSet"]) {
+
+    dojo.require('openils.PermaCrud');
+    dojo.require('MARC.FixedFields');
+
+    dojo._hasResource["MARC.AuthorityControlSet"] = true;
+    dojo.provide("MARC.AuthorityControlSet");
+    dojo.declare('MARC.AuthorityControlSet', null, {
+
+        // static sorta-LoC setup ... to be overwritten with server data 
+        _loc_authority_tag_map = {
+            100 : [[100,500,700],100],
+            700 : [[100,500,700],100],
+            800 : [[100,500,700],100],
+            110 : [[110,510,710],110],
+            610 : [[110,510,710],110],
+            710 : [[110,510,710],110],
+            810 : [[110,510,710],110],
+            111 : [[111,511,711],111],
+            611 : [[111,511,711],111],
+            711 : [[111,511,711],111],
+            811 : [[111,511,711],111],
+            240 : [[130,530,730],130],
+            130 : [[130,530,730],130],
+            730 : [[130,530,730],130],
+            830 : [[130,530,730],130],
+            600 : [[100,500,580,581,582,585,700,780,781,782,785],100],
+            630 : [[130,530,730],130],
+            648 : [[148,548],148],
+            650 : [[150,550,580,581,582,585,750,780,781,782,785],150],
+            651 : [[151,551,580,581,582,585,751,780,781,782,785],151],
+            655 : [[155,555,580,581,582,585,755,780,781,782,785],155]
+        },
+
+        _loc_control_map = {
+            100 : {
+                'a' : { 100 : 'a' },
+                'd' : { 100 : 'd' },
+                'e' : { 100 : 'e' },
+                'q' : { 100 : 'q' }
+            },
+            110 : {
+                'a' : { 110 : 'a' },
+                'd' : { 110 : 'd' }
+            },
+            111 : {
+                'a' : { 111 : 'a' },
+                'd' : { 111 : 'd' }
+            },
+            130 : {
+                'a' : { 130 : 'a' },
+                'd' : { 130 : 'd' }
+            },
+            240 : {
+                'a' : { 130 : 'a' },
+                'd' : { 130 : 'd' }
+            },
+            400 : {
+                'a' : { 100 : 'a' },
+                'd' : { 100 : 'd' }
+            },
+            410 : {
+                'a' : { 110 : 'a' },
+                'd' : { 110 : 'd' }
+            },
+            411 : {
+                'a' : { 111 : 'a' },
+                'd' : { 111 : 'd' }
+            },
+            440 : {
+                'a' : { 130 : 'a' },
+                'n' : { 130 : 'n' },
+                'p' : { 130 : 'p' }
+            },
+            700 : {
+                'a' : { 100 : 'a' },
+                'd' : { 100 : 'd' },
+                'q' : { 100 : 'q' },
+                't' : { 100 : 't' }
+            },
+            710 : {
+                'a' : { 110 : 'a' },
+                'd' : { 110 : 'd' }
+            },
+            711 : {
+                'a' : { 111 : 'a' },
+                'c' : { 111 : 'c' },
+                'd' : { 111 : 'd' }
+            },
+            730 : {
+                'a' : { 130 : 'a' },
+                'd' : { 130 : 'd' }
+            },
+            800 : {
+                'a' : { 100 : 'a' },
+                'd' : { 100 : 'd' }
+            },
+            810 : {
+                'a' : { 110 : 'a' },
+                'd' : { 110 : 'd' }
+            },
+            811 : {
+                'a' : { 111 : 'a' },
+                'd' : { 111 : 'd' }
+            },
+            830 : {
+                'a' : { 130 : 'a' },
+                'd' : { 130 : 'd' }
+            },
+            600 : {
+                'a' : { 100 : 'a' },
+                'd' : { 100 : 'd' },
+                'q' : { 100 : 'q' },
+                't' : { 100 : 't' },
+                'v' : { 180 : 'v',
+                    100 : 'v',
+                    181 : 'v',
+                    182 : 'v',
+                    185 : 'v'
+                },
+                'x' : { 180 : 'x',
+                    100 : 'x',
+                    181 : 'x',
+                    182 : 'x',
+                    185 : 'x'
+                },
+                'y' : { 180 : 'y',
+                    100 : 'y',
+                    181 : 'y',
+                    182 : 'y',
+                    185 : 'y'
+                },
+                'z' : { 180 : 'z',
+                    100 : 'z',
+                    181 : 'z',
+                    182 : 'z',
+                    185 : 'z'
+                }
+            },
+            610 : {
+                'a' : { 110 : 'a' },
+                'd' : { 110 : 'd' },
+                't' : { 110 : 't' },
+                'v' : { 180 : 'v',
+                    110 : 'v',
+                    181 : 'v',
+                    182 : 'v',
+                    185 : 'v'
+                },
+                'x' : { 180 : 'x',
+                    110 : 'x',
+                    181 : 'x',
+                    182 : 'x',
+                    185 : 'x'
+                },
+                'y' : { 180 : 'y',
+                    110 : 'y',
+                    181 : 'y',
+                    182 : 'y',
+                    185 : 'y'
+                },
+                'z' : { 180 : 'z',
+                    110 : 'z',
+                    181 : 'z',
+                    182 : 'z',
+                    185 : 'z'
+                }
+            },
+            611 : {
+                'a' : { 111 : 'a' },
+                'd' : { 111 : 'd' },
+                't' : { 111 : 't' },
+                'v' : { 180 : 'v',
+                    111 : 'v',
+                    181 : 'v',
+                    182 : 'v',
+                    185 : 'v'
+                },
+                'x' : { 180 : 'x',
+                    111 : 'x',
+                    181 : 'x',
+                    182 : 'x',
+                    185 : 'x'
+                },
+                'y' : { 180 : 'y',
+                    111 : 'y',
+                    181 : 'y',
+                    182 : 'y',
+                    185 : 'y'
+                },
+                'z' : { 180 : 'z',
+                    111 : 'z',
+                    181 : 'z',
+                    182 : 'z',
+                    185 : 'z'
+                }
+            },
+            630 : {
+                'a' : { 130 : 'a' },
+                'd' : { 130 : 'd' }
+            },
+            648 : {
+                'a' : { 148 : 'a' },
+                'v' : { 148 : 'v' },
+                'x' : { 148 : 'x' },
+                'y' : { 148 : 'y' },
+                'z' : { 148 : 'z' }
+            },
+            650 : {
+                'a' : { 150 : 'a' },
+                'b' : { 150 : 'b' },
+                'v' : { 180 : 'v',
+                    150 : 'v',
+                    181 : 'v',
+                    182 : 'v',
+                    185 : 'v'
+                },
+                'x' : { 180 : 'x',
+                    150 : 'x',
+                    181 : 'x',
+                    182 : 'x',
+                    185 : 'x'
+                },
+                'y' : { 180 : 'y',
+                    150 : 'y',
+                    181 : 'y',
+                    182 : 'y',
+                    185 : 'y'
+                },
+                'z' : { 180 : 'z',
+                    150 : 'z',
+                    181 : 'z',
+                    182 : 'z',
+                    185 : 'z'
+                }
+            },
+            651 : {
+                'a' : { 151 : 'a' },
+                'v' : { 180 : 'v',
+                    151 : 'v',
+                    181 : 'v',
+                    182 : 'v',
+                    185 : 'v'
+                },
+                'x' : { 180 : 'x',
+                    151 : 'x',
+                    181 : 'x',
+                    182 : 'x',
+                    185 : 'x'
+                },
+                'y' : { 180 : 'y',
+                    151 : 'y',
+                    181 : 'y',
+                    182 : 'y',
+                    185 : 'y'
+                },
+                'z' : { 180 : 'z',
+                    151 : 'z',
+                    181 : 'z',
+                    182 : 'z',
+                    185 : 'z'
+                }
+            },
+            655 : {
+                'a' : { 155 : 'a' },
+                'v' : { 180 : 'v',
+                    155 : 'v',
+                    181 : 'v',
+                    182 : 'v',
+                    185 : 'v'
+                },
+                'x' : { 180 : 'x',
+                    155 : 'x',
+                    181 : 'x',
+                    182 : 'x',
+                    185 : 'x'
+                },
+                'y' : { 180 : 'y',
+                    155 : 'y',
+                    181 : 'y',
+                    182 : 'y',
+                    185 : 'y'
+                },
+                'z' : { 180 : 'z',
+                    155 : 'z',
+                    181 : 'z',
+                    182 : 'z',
+                    185 : 'z'
+                }
+            }
+        };
+        
+    });
+}

commit cd319a49c59f3cdc82dcaec571dc3dd957c2468c
Author: Mike Rylander <mrylander at gmail.com>
Date:   Fri May 6 12:58:17 2011 -0400

    Use unicode escape instead of raw bytes, for ease of maintenance

diff --git a/Open-ILS/src/sql/Pg/020.schema.functions.sql b/Open-ILS/src/sql/Pg/020.schema.functions.sql
index 262f6cf..d1621e6 100644
--- a/Open-ILS/src/sql/Pg/020.schema.functions.sql
+++ b/Open-ILS/src/sql/Pg/020.schema.functions.sql
@@ -357,7 +357,7 @@ BEGIN
         FOR sf IN SELECT * FROM regexp_split_to_table(acsaf.sf_list,'') LOOP
             tmp_text := oils_xpath_string('//*[@tag="'||tag_used||'"]/*[@code="'||sf||'"]', marcxml);
             IF tmp_text IS NOT NULL THEN
-                heading_text := heading_text || E'‡' || sf || ' ' || tmp_text;
+                heading_text := heading_text || E'\U2021' || sf || ' ' || tmp_text;
             END IF;
         END LOOP;
         EXIT WHEN heading_text <> '';

commit 40283f335c75a75ab2829af3e202a1d33115f44d
Author: Mike Rylander <mrylander at gmail.com>
Date:   Thu Apr 21 12:36:05 2011 -0400

    replace the perlish authority.normalize_heading with a nearly-equiv plpgsql version that understands control sets

diff --git a/Open-ILS/src/sql/Pg/020.schema.functions.sql b/Open-ILS/src/sql/Pg/020.schema.functions.sql
index f29239e..262f6cf 100644
--- a/Open-ILS/src/sql/Pg/020.schema.functions.sql
+++ b/Open-ILS/src/sql/Pg/020.schema.functions.sql
@@ -331,84 +331,47 @@ $$;
 -- CREATE UNIQUE INDEX unique_by_heading_and_thesaurus
 --   ON authority.record_entry (authority.normalize_heading(marc))
 --   WHERE deleted IS FALSE or deleted = FALSE;
-CREATE OR REPLACE FUNCTION authority.normalize_heading( TEXT ) RETURNS TEXT AS $func$
-    use strict;
-    use warnings;
-
-    use utf8;
-    use MARC::Record;
-    use MARC::File::XML (BinaryEncoding => 'UTF8');
-    use MARC::Charset;
-    use UUID::Tiny ':std';
-
-    MARC::Charset->assume_unicode(1);
-
-    my $xml = shift() or return undef;
-
-    my $r;
-
-    # Prevent errors in XML parsing from blowing out ungracefully
-    eval {
-        $r = MARC::Record->new_from_xml( $xml );
-        1;
-    } or do {
-       return 'BAD_MARCXML_' . create_uuid_as_string(UUID_MD5, $xml);
-    };
-
-    if (!$r) {
-       return 'BAD_MARCXML_' . create_uuid_as_string(UUID_MD5, $xml);
-    }
-
-    # From http://www.loc.gov/standards/sourcelist/subject.html
-    my $thes_code_map = {
-        a => 'lcsh',
-        b => 'lcshac',
-        c => 'mesh',
-        d => 'nal',
-        k => 'cash',
-        n => 'notapplicable',
-        r => 'aat',
-        s => 'sears',
-        v => 'rvm',
-    };
-
-    # Default to "No attempt to code" if the leader is horribly broken
-    my $fixed_field = $r->field('008');
-    my $thes_char = '|';
-    if ($fixed_field) { 
-        $thes_char = substr($fixed_field->data(), 11, 1) || '|';
-    }
-
-    my $thes_code = 'UNDEFINED';
-
-    if ($thes_char eq 'z') {
-        # Grab the 040 $f per http://www.loc.gov/marc/authority/ad040.html
-        $thes_code = $r->subfield('040', 'f') || 'UNDEFINED';
-    } elsif ($thes_code_map->{$thes_char}) {
-        $thes_code = $thes_code_map->{$thes_char};
-    }
-
-    my $auth_txt = '';
-    my $head = $r->field('1..');
-    if ($head) {
-        # Concatenate all of these subfields together, prefixed by their code
-        # to prevent collisions along the lines of "Fiction, North Carolina"
-        foreach my $sf ($head->subfields()) {
-            $auth_txt .= '‡' . $sf->[0] . ' ' . $sf->[1];
-        }
-    }
-    
-    if ($auth_txt) {
-        my $stmt = spi_prepare('SELECT public.naco_normalize($1) AS norm_text', 'TEXT');
-        my $result = spi_exec_prepared($stmt, $auth_txt);
-        my $norm_txt = $result->{rows}[0]->{norm_text};
-        spi_freeplan($stmt);
-        undef($stmt);
-        return $head->tag() . "_" . $thes_code . " " . $norm_txt;
-    }
-
-    return 'NOHEADING_' . $thes_code . ' ' . create_uuid_as_string(UUID_MD5, $xml);
-$func$ LANGUAGE 'plperlu' IMMUTABLE;
+CREATE OR REPLACE FUNCTION authority.normalize_heading( marcxml TEXT ) RETURNS TEXT AS $func$
+DECLARE
+    acsaf           authority.control_set_authority_field%ROWTYPE;
+    tag_used        TEXT;
+    sf              TEXT;
+    thes_code       TEXT;
+    cset            INT;
+    heading_text    TEXT;
+    tmp_text        TEXT;
+BEGIN
+    thes_code := vandelay.marc21_extract_fixed_field(marcxml,'Subj');
+    IF thes_code IS NULL THEN
+        thes_code := '|';
+    END IF;
+
+    SELECT control_set INTO cset FROM authority.thesaurus WHERE code = thes_code;
+    IF NOT FOUND THEN
+        cset = 1;
+    END IF;
+
+    heading_text := '';
+    FOR acsaf IN SELECT * FROM authority.control_set_authority_field WHERE control_set = cset AND main_entry IS NULL LOOP
+        tag_use := acsaf.tag;
+        FOR sf IN SELECT * FROM regexp_split_to_table(acsaf.sf_list,'') LOOP
+            tmp_text := oils_xpath_string('//*[@tag="'||tag_used||'"]/*[@code="'||sf||'"]', marcxml);
+            IF tmp_text IS NOT NULL THEN
+                heading_text := heading_text || E'‡' || sf || ' ' || tmp_text;
+            END IF;
+        END LOOP;
+        EXIT WHEN heading_text <> '';
+    END LOOP;
+
+    IF heading_text <> '' THEN
+        heading_text := tag_used || '_' || thes_code || ' ' || public.naco_normalize(heading_text);
+    ELSE
+        heading_text := 'NOHEADING_' || thes_code || ' ' || MD5(marcxml);
+    END IF;
+
+    RETURN heading_text;
+END;
+$func$ LANGUAGE PLPGSQL IMMUTABLE;
 
 COMMENT ON FUNCTION authority.normalize_heading( TEXT ) IS $$
 Extract the authority heading, thesaurus, and NACO-normalized values

commit 89732bcec8e8aa84b5fc1b319db2ebc781144667
Author: Mike Rylander <mrylander at gmail.com>
Date:   Mon Apr 11 11:59:39 2011 -0400

    Fix XPath in tracing links view; Replace authority overlay template building function with a PLPGSQL + SQL/XML version that is control set aware

diff --git a/Open-ILS/src/sql/Pg/011.schema.authority.sql b/Open-ILS/src/sql/Pg/011.schema.authority.sql
index e1753c1..993c0f3 100644
--- a/Open-ILS/src/sql/Pg/011.schema.authority.sql
+++ b/Open-ILS/src/sql/Pg/011.schema.authority.sql
@@ -132,7 +132,7 @@ CREATE OR REPLACE VIEW authority.tracing_links AS
     SELECT  main.record AS record,
             main.id AS main_id,
             main.tag AS main_tag,
-            oils_xpath_string('//*[@datafield="'||main.tag||'"]/*[local-name="subfield"]', are.marc) AS main_value,
+            oils_xpath_string('//*[@tag="'||main.tag||'"]/*[local-name()="subfield"]', are.marc) AS main_value,
             authority.normalize_heading(are.marc) AS normalized_main_value,
             substr(link.value,1,1) AS relationship,
             substr(link.value,2,1) AS use_restriction,
@@ -140,7 +140,7 @@ CREATE OR REPLACE VIEW authority.tracing_links AS
             substr(link.value,4,1) AS display_restriction,
             link.id AS link_id,
             link.tag AS link_tag,
-            extract_marc_field('authority.record_entry',link.record,'//*[@datafield="'||link.tag||'"]') AS link_value
+            oils_xpath_string('//*[@tag="'||link.tag||'"]/*[local-name()="subfield"]', are.marc) AS link_value
       FROM  authority.full_rec main
             JOIN authority.record_entry are ON (main.record = are.id)
             JOIN authority.control_set_authority_field main_entry
@@ -154,84 +154,54 @@ CREATE OR REPLACE VIEW authority.tracing_links AS
                     AND link.tag = sub_entry.tag
                     AND link.subfield = 'w' );
 
-
 -- Function to generate an ephemeral overlay template from an authority record
-CREATE OR REPLACE FUNCTION authority.generate_overlay_template ( TEXT, BIGINT ) RETURNS TEXT AS $func$
-
-    use MARC::Record;
-    use MARC::File::XML (BinaryEncoding => 'UTF-8');
-    use MARC::Charset;
-
-    MARC::Charset->assume_unicode(1);
-
-    my $xml = shift;
-    my $r = MARC::Record->new_from_xml( $xml );
-
-    return undef unless ($r);
-
-    my $id = shift() || $r->subfield( '901' => 'c' );
-    $id =~ s/^\s*(?:\([^)]+\))?\s*(.+)\s*?$/$1/;
-    return undef unless ($id); # We need an ID!
-
-    my $tmpl = MARC::Record->new();
-    $tmpl->encoding( 'UTF-8' );
-
-    my @rule_fields;
-    for my $field ( $r->field( '1..' ) ) { # Get main entry fields from the authority record
-
-        my $tag = $field->tag;
-        my $i1 = $field->indicator(1);
-        my $i2 = $field->indicator(2);
-        my $sf = join '', map { $_->[0] } $field->subfields;
-        my @data = map { @$_ } $field->subfields;
-
-        my @replace_them;
-
-        # Map the authority field to bib fields it can control.
-        if ($tag >= 100 and $tag <= 111) {       # names
-            @replace_them = map { $tag + $_ } (0, 300, 500, 600, 700);
-        } elsif ($tag eq '130') {                # uniform title
-            @replace_them = qw/130 240 440 730 830/;
-        } elsif ($tag >= 150 and $tag <= 155) {  # subjects
-            @replace_them = ($tag + 500);
-        } elsif ($tag >= 180 and $tag <= 185) {  # floating subdivisions
-            @replace_them = qw/100 400 600 700 800 110 410 610 710 810 111 411 611 711 811 130 240 440 730 830 650 651 655/;
-        } else {
-            next;
-        }
-
-        # Dummy up the bib-side data
-        $tmpl->append_fields(
-            map {
-                MARC::Field->new( $_, $i1, $i2, @data )
-            } @replace_them
-        );
-
-        # Construct some 'replace' rules
-        push @rule_fields, map { $_ . $sf . '[0~\)' .$id . '$]' } @replace_them;
-    }
-
-    # Insert the replace rules into the template
-    $tmpl->append_fields(
-        MARC::Field->new( '905' => ' ' => ' ' => 'r' => join(',', @rule_fields ) )
-    );
-
-    $xml = $tmpl->as_xml_record;
-    $xml =~ s/^<\?.+?\?>$//mo;
-    $xml =~ s/\n//sgo;
-    $xml =~ s/>\s+</></sgo;
-
-    return $xml;
-
-$func$ LANGUAGE PLPERLU;
-
-CREATE OR REPLACE FUNCTION authority.generate_overlay_template ( BIGINT ) RETURNS TEXT AS $func$
-    SELECT authority.generate_overlay_template( marc, id ) FROM authority.record_entry WHERE id = $1;
-$func$ LANGUAGE SQL;
+CREATE OR REPLACE FUNCTION authority.generate_overlay_template (source_xml TEXT) RETURNS TEXT AS $f$
+DECLARE
+    cset                INT;
+    main_entry          authority.control_set_authority_field%ROWTYPE;
+    bib_field           authority.control_set_bib_field%ROWTYPE;
+    auth_id             INT DEFAULT oils_xpath_string('//*[@tag="901"]/*[local-name()="subfield" and @code="c"]', source_xml)::INT;
+    replace_data        XML[] DEFAULT '{}'::XML[];
+    replace_rules       TEXT[] DEFAULT '{}'::TEXT[];
+    auth_field          TEXT;
+BEGIN
+    IF auth_id IS NULL THEN
+        RETURN NULL;
+    END IF;
+
+    -- Default to the LoC controll set
+    SELECT COALESCE(control_set,1) INTO cset FROM authority.record_entry WHERE id = auth_id;
+
+    FOR main_entry IN SELECT * FROM authority.control_set_authority_field WHERE control_set = cset LOOP
+        auth_field := XPATH('//*[@tag="'||main_entry.tag||'"][1]',source_xml);
+        IF ARRAY_LENGTH(auth_field) > 0 THEN
+            FOR bib_field IN SELECT * FROM authority.control_set_bib_field WHERE authority_field = main_entry.id LOOP
+                replace_data := replace_data || XMLELEMENT( name datafield, bib_field.tag AS tag, XPATH('//*[local-name()="subfield"]',auth_field[1])::XML[]);
+                replace_rules := replace_rules || ( bib_field.tag || main_entry.sf_list || E'[0~\\)' || auth_id || '$]' );
+            END LOOP;
+            EXIT;
+        END IF;
+    END LOOP;
 
-CREATE OR REPLACE FUNCTION authority.generate_overlay_template ( TEXT ) RETURNS TEXT AS $func$
-    SELECT authority.generate_overlay_template( $1, NULL );
-$func$ LANGUAGE SQL;
+    RETURN XMLELEMENT(
+        name record,
+        XMLATTRIBUTES('http://www.loc.gov/MARC21/slim' AS xmlns)
+        XMLELEMENT( name leader, '00881nam a2200193   4500'),
+        replace_data,
+        XMLELEMENT(
+            name datafield,
+            '905' AS tag,
+            ' ' AS ind1,
+            ' ' AS ind2,
+            XMLELEMENT(
+                name subfield,
+                'r' AS code,
+                ARRAY_TO_STRING(replace_rules,',')
+            )
+        )
+    )::TEXT;
+END;
+$f$ STABLE LANGUAGE PLPGSQL;
 
 CREATE OR REPLACE FUNCTION authority.merge_records ( target_record BIGINT, source_record BIGINT ) RETURNS INT AS $func$
 DECLARE

commit 470fa05860f0f911e40bb19b04e707f0d5e5bc7e
Author: Mike Rylander <mrylander at gmail.com>
Date:   Mon Apr 11 11:57:55 2011 -0400

    Add See From tracings to LoC authority control set

diff --git a/Open-ILS/src/sql/Pg/950.data.seed-values.sql b/Open-ILS/src/sql/Pg/950.data.seed-values.sql
index 2c38927..6100def 100644
--- a/Open-ILS/src/sql/Pg/950.data.seed-values.sql
+++ b/Open-ILS/src/sql/Pg/950.data.seed-values.sql
@@ -9423,7 +9423,7 @@ INSERT INTO authority.control_set_authority_field (id, control_set, main_entry,
     (11, 1, NULL, '185', 'vxyz', oils_i18n_gettext('11','Heading -- Form Subdivision','acsaf','name')),
     (12, 1, NULL, '148', 'avxyz', oils_i18n_gettext('12','Heading -- Chronological Term','acsaf','name')),
 
--- See Also tracings
+-- See Also From tracings
     (21, 1, 1, '500', 'abcdefiklmnopqrstvwxyz4', oils_i18n_gettext('21','See Also From Tracing -- Personal Name','acsaf','name')),
     (22, 1, 2, '510', 'abcdefgiklmnoprstvwxyz4', oils_i18n_gettext('22','See Also From Tracing -- Corporate Name','acsaf','name')),
     (23, 1, 3, '511', 'acdefgiklnpqstvwxyz4', oils_i18n_gettext('23','See Also From Tracing -- Meeting Name','acsaf','name')),
@@ -9449,7 +9449,22 @@ INSERT INTO authority.control_set_authority_field (id, control_set, main_entry,
     (49, 1, 9, '781', 'vwxyz25', oils_i18n_gettext('49','Subdivision Linking Entry -- Geographic Subdivision','acsaf','name')),
     (50, 1, 10, '782', 'vwxyz25', oils_i18n_gettext('50','Subdivision Linking Entry -- Chronological Subdivision','acsaf','name')),
     (51, 1, 11, '785', 'vwxyz25', oils_i18n_gettext('51','Subdivision Linking Entry -- Form Subdivision','acsaf','name')),
-    (52, 1, 12, '748', 'avwxyz25', oils_i18n_gettext('52','Established Heading Linking Entry -- Chronological Term','acsaf','name'));
+    (52, 1, 12, '748', 'avwxyz25', oils_i18n_gettext('52','Established Heading Linking Entry -- Chronological Term','acsaf','name')),
+
+-- See From tracings
+    (61, 1, 1, '400', 'abcdefiklmnopqrstvwxyz4', oils_i18n_gettext('61','See Also Tracing -- Personal Name','acsaf','name')),
+    (62, 1, 2, '410', 'abcdefgiklmnoprstvwxyz4', oils_i18n_gettext('62','See Also Tracing -- Corporate Name','acsaf','name')),
+    (63, 1, 3, '411', 'acdefgiklnpqstvwxyz4', oils_i18n_gettext('63','See Also Tracing -- Meeting Name','acsaf','name')),
+    (64, 1, 4, '430', 'adfgiklmnoprstvwxyz4', oils_i18n_gettext('64','See Also Tracing -- Uniform Title','acsaf','name')),
+    (65, 1, 5, '450', 'abivwxyz4', oils_i18n_gettext('65','See Also Tracing -- Topical Term','acsaf','name')),
+    (66, 1, 6, '451', 'aivwxyz4', oils_i18n_gettext('66','See Also Tracing -- Geographic Name','acsaf','name')),
+    (67, 1, 7, '455', 'aivwxyz4', oils_i18n_gettext('67','See Also Tracing -- Genre/Form Term','acsaf','name')),
+    (68, 1, 8, '480', 'ivwxyz4', oils_i18n_gettext('68','See Also Tracing -- General Subdivision','acsaf','name')),
+    (69, 1, 9, '481', 'ivwxyz4', oils_i18n_gettext('69','See Also Tracing -- Geographic Subdivision','acsaf','name')),
+    (70, 1, 10, '482', 'ivwxyz4', oils_i18n_gettext('70','See Also Tracing -- Chronological Subdivision','acsaf','name')),
+    (71, 1, 11, '485', 'ivwxyz4', oils_i18n_gettext('71','See Also Tracing -- Form Subdivision','acsaf','name')),
+    (72, 1, 12, '448', 'aivwxyz4', oils_i18n_gettext('72','See Also Tracing -- Chronological Term','acsaf','name'));
+
 
 INSERT INTO authority.control_set_bib_field (tag, authority_field) VALUES
     SELECT '100', id FROM authority.control_set_authority_field WHERE tag IN ('100')

commit 331649ac7c0e046bd3e73958ba7bec6afd5dc863
Author: Mike Rylander <mrylander at gmail.com>
Date:   Mon Apr 11 10:24:41 2011 -0400

    Use control sets to drive the tracing links view

diff --git a/Open-ILS/src/sql/Pg/011.schema.authority.sql b/Open-ILS/src/sql/Pg/011.schema.authority.sql
index ab083ea..e1753c1 100644
--- a/Open-ILS/src/sql/Pg/011.schema.authority.sql
+++ b/Open-ILS/src/sql/Pg/011.schema.authority.sql
@@ -125,29 +125,35 @@ CREATE INDEX authority_full_rec_index_vector_idx ON authority.full_rec USING GIS
 /* Enable LIKE to use an index for database clusters with locales other than C or POSIX */
 CREATE INDEX authority_full_rec_value_tpo_index ON authority.full_rec (value text_pattern_ops);
 
+-- Adding indexes using oils_xpath_string() for the main entry tags described in
+-- authority.control_set_authority_field would speed this up, if we ever want to use it, though
+-- the existing index on authority.normalize_heading() helps already with a record in hand
 CREATE OR REPLACE VIEW authority.tracing_links AS
     SELECT  main.record AS record,
             main.id AS main_id,
             main.tag AS main_tag,
-            main.value AS main_value,
+            oils_xpath_string('//*[@datafield="'||main.tag||'"]/*[local-name="subfield"]', are.marc) AS main_value,
+            authority.normalize_heading(are.marc) AS normalized_main_value,
             substr(link.value,1,1) AS relationship,
             substr(link.value,2,1) AS use_restriction,
             substr(link.value,3,1) AS deprecation,
             substr(link.value,4,1) AS display_restriction,
-            link_value.id AS link_id,
-            link_value.tag AS link_tag,
-            link_value.value AS link_value
+            link.id AS link_id,
+            link.tag AS link_tag,
+            extract_marc_field('authority.record_entry',link.record,'//*[@datafield="'||link.tag||'"]') AS link_value
       FROM  authority.full_rec main
+            JOIN authority.record_entry are ON (main.record = are.id)
+            JOIN authority.control_set_authority_field main_entry
+                ON (main_entry.tag = main.tag
+                    AND main_entry.main_entry IS NULL
+                    AND main.subfield = 'a' )
+            JOIN authority.control_set_authority_field sub_entry
+                ON (main_entry.id = sub_entry.main_entry)
             JOIN authority.full_rec link
                 ON (link.record = main.record
-                    AND link.tag in ((main.tag::int + 400)::text, (main.tag::int + 300)::text)
-                    AND link.subfield = 'w' )
-            JOIN authority.full_rec link_value
-                ON (link_value.record = main.record
-                    AND link_value.tag = link.tag
-                    AND link_value.subfield = 'a' )
-      WHERE main.tag IN ('100','110','111','130','150','151','155','180','181','182','185')
-            AND main.subfield = 'a';
+                    AND link.tag = sub_entry.tag
+                    AND link.subfield = 'w' );
+
 
 -- Function to generate an ephemeral overlay template from an authority record
 CREATE OR REPLACE FUNCTION authority.generate_overlay_template ( TEXT, BIGINT ) RETURNS TEXT AS $func$

commit 4740d69d92072017bc31fef38169b92540916546
Author: Mike Rylander <mrylander at gmail.com>
Date:   Mon Apr 11 09:23:51 2011 -0400

    Add pcrud controller to control set classes; realign IDL to match tables

diff --git a/Open-ILS/examples/fm_IDL.xml b/Open-ILS/examples/fm_IDL.xml
index 6bd96cf..7e032c1 100644
--- a/Open-ILS/examples/fm_IDL.xml
+++ b/Open-ILS/examples/fm_IDL.xml
@@ -1758,7 +1758,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 		</links>
 	</class>
 
-	<class id="acs" controller="open-ils.cstore" oils_obj:fieldmapper="authority::control_set" oils_persist:tablename="authority.control_set" reporter:label="Authority Control Set">
+	<class id="acs" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="authority::control_set" oils_persist:tablename="authority.control_set" reporter:label="Authority Control Set">
 		<fields oils_persist:primary="id" oils_persist:sequence="authority.contol_set_id_seq">
 			<field reporter:label="Control Set ID" name="id" reporter:datatype="id" reporter:selector="name"/>
 			<field reporter:label="Name" name="name" reporter:datatype="text" oils_persist:i18n="true" oils_obj:required="true" />
@@ -1778,13 +1778,15 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 		</permacrud>
 	</class>
 
-	<class id="acsaf" controller="open-ils.cstore" oils_obj:fieldmapper="authority::control_set_authority_field" oils_persist:tablename="authority.control_set_authority_field" reporter:label="Authority Control Set Authority Field">
+	<class id="acsaf" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="authority::control_set_authority_field" oils_persist:tablename="authority.control_set_authority_field" reporter:label="Authority Control Set Authority Field">
 		<fields oils_persist:primary="id" oils_persist:sequence="authority.contol_set_authority_field_id_seq">
 			<field reporter:label="Control Set Authority Field ID" name="id" reporter:datatype="id" reporter:selector="name"/>
+			<field reporter:label="Main Entry" name="main_entry" reporter:datatype="link"/>
 			<field reporter:label="Control Set" name="control_set" reporter:datatype="link"/>
 			<field reporter:label="Tag" name="tag" reporter:datatype="text" oils_obj:required="true" oils_obj:validate="^.{3}$"/>
 			<field reporter:label="Name" name="name" reporter:datatype="text" oils_persist:i18n="true" oils_obj:required="true" />
 			<field reporter:label="Description" name="description" reporter:datatype="text" oils_persist:i18n="true" />
+			<field reporter:label="Subordinate Entries" name="sub_entries" reporter:datatype="link" oils_persist:virtual="true"/>
 			<field reporter:label="Controlled Bib Fields" name="bib_fields" reporter:datatype="link" oils_persist:virtual="true"/>
 			<field reporter:label="Thesauri" name="thesauri" reporter:datatype="link" oils_persist:virtual="true"/>
 		</fields>
@@ -1792,6 +1794,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 			<link field="control_set" reltype="has_a" key="id" map="" class="acs"/>
 			<link field="bib_fields" reltype="has_many" key="authority_field" map="" class="acsbf"/>
 			<link field="thesauri" reltype="has_many" key="control_set" map="" class="at"/>
+			<link field="main_entry" reltype="has_a" key="id" map="" class="acsaf"/>
+			<link field="sub_entries" reltype="has_many" key="main_entry" map="" class="acsaf"/>
 		</links>
 		<permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
 			<actions>
@@ -1803,13 +1807,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 		</permacrud>
 	</class>
 
-	<class id="acsbf" controller="open-ils.cstore" oils_obj:fieldmapper="authority::control_set_bib_field" oils_persist:tablename="authority.control_set_bib_field" reporter:label="Authority Control Set Bib Field">
+	<class id="acsbf" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="authority::control_set_bib_field" oils_persist:tablename="authority.control_set_bib_field" reporter:label="Authority Control Set Bib Field">
 		<fields oils_persist:primary="id" oils_persist:sequence="authority.contol_set_bib_field_id_seq">
 			<field reporter:label="Controlled Bib Field ID" name="id" reporter:datatype="id" reporter:selector="name"/>
 			<field reporter:label="Controlling Authority Field" name="authority_field" reporter:datatype="link"/>
 			<field reporter:label="Tag" name="tag" reporter:datatype="text" oils_obj:required="true" oils_obj:validate="^.{3}$"/>
-			<field reporter:label="Name" name="name" reporter:datatype="text" oils_persist:i18n="true" oils_obj:required="true" />
-			<field reporter:label="Description" name="description" reporter:datatype="text" oils_persist:i18n="true" />
 		</fields>
 		<links>
 			<link field="authority_field" reltype="has_a" key="id" map="" class="acsaf"/>
@@ -1824,7 +1826,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 		</permacrud>
 	</class>
 
-	<class id="at" controller="open-ils.cstore" oils_obj:fieldmapper="authority::thesaurus" oils_persist:tablename="authority.thesaurus" reporter:label="Authority Thesaurus">
+	<class id="at" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="authority::thesaurus" oils_persist:tablename="authority.thesaurus" reporter:label="Authority Thesaurus">
 		<fields oils_persist:primary="code">
 			<field reporter:label="Thesaurus Code" name="code" reporter:datatype="id" reporter:selector="name"/>
 			<field reporter:label="Control Set" name="control_set" reporter:datatype="link"/>

commit 0196b3b5e2b5c1bab752ec763185e089efed973c
Author: Mike Rylander <mrylander at gmail.com>
Date:   Mon Apr 11 09:16:58 2011 -0400

    Trigger to map from thesaurus to control set

diff --git a/Open-ILS/src/sql/Pg/999.functions.global.sql b/Open-ILS/src/sql/Pg/999.functions.global.sql
index 553223a..e5e0974 100644
--- a/Open-ILS/src/sql/Pg/999.functions.global.sql
+++ b/Open-ILS/src/sql/Pg/999.functions.global.sql
@@ -1436,7 +1436,18 @@ BEGIN
 END;
 $func$ LANGUAGE PLPGSQL;
 
--- authority.rec_descriptor appears to be unused currently XXX
+CREATE OR REPLACE FUNCTION authority.map_thesaurus_to_control_set () RETURNS TRIGGER AS $func$
+BEGIN
+    IF NEW.control_set IS NULL THEN
+        SELECT  control_set INTO NEW.control_set
+          FROM  authority.thesaurus
+          WHERE vandelay.marc21_extract_fixed_field(NEW.marc,'Subj') = code;
+    END IF;
+
+    RETURN NEW;
+END;
+$func$ LANGUAGE PLPGSQL;
+
 CREATE OR REPLACE FUNCTION authority.reingest_authority_rec_descriptor( auth_id BIGINT ) RETURNS VOID AS $func$
 BEGIN
     DELETE FROM authority.rec_descriptor WHERE record = auth_id;
@@ -1501,6 +1512,7 @@ CREATE TRIGGER fingerprint_tgr BEFORE INSERT OR UPDATE ON biblio.record_entry FO
 CREATE TRIGGER aaa_indexing_ingest_or_delete AFTER INSERT OR UPDATE ON biblio.record_entry FOR EACH ROW EXECUTE PROCEDURE biblio.indexing_ingest_or_delete ();
 CREATE TRIGGER bbb_simple_rec_trigger AFTER INSERT OR UPDATE OR DELETE ON biblio.record_entry FOR EACH ROW EXECUTE PROCEDURE reporter.simple_rec_trigger ();
 
+CREATE TRIGGER map_thesaurus_to_control_set BEFORE INSERT OR UPDATE ON authority.record_entry FOR EACH ROW EXECUTE PROCEDURE authority.map_thesaurus_to_control_set ();
 CREATE TRIGGER aaa_auth_ingest_or_delete AFTER INSERT OR UPDATE ON authority.record_entry FOR EACH ROW EXECUTE PROCEDURE authority.indexing_ingest_or_delete ();
 
 -- Utility routines, callable via cstore

commit bfed0299bd167da616b8960d96c1fc8bda1754a1
Author: Mike Rylander <mrylander at gmail.com>
Date:   Sun Apr 10 21:33:40 2011 -0400

    Actually use authority.rec_descriptor, populating it with RecStat, ELvl and Subj (aka Thesaurus)

diff --git a/Open-ILS/src/sql/Pg/011.schema.authority.sql b/Open-ILS/src/sql/Pg/011.schema.authority.sql
index d2e5795..ab083ea 100644
--- a/Open-ILS/src/sql/Pg/011.schema.authority.sql
+++ b/Open-ILS/src/sql/Pg/011.schema.authority.sql
@@ -98,7 +98,7 @@ CREATE TABLE authority.rec_descriptor (
     id              BIGSERIAL PRIMARY KEY,
     record          BIGINT,
     record_status   TEXT,
-    char_encoding   TEXT,
+    encoding_level  TEXT,
     thesaurus       TEXT
 );
 CREATE INDEX authority_rec_descriptor_record_idx ON authority.rec_descriptor (record);
diff --git a/Open-ILS/src/sql/Pg/950.data.seed-values.sql b/Open-ILS/src/sql/Pg/950.data.seed-values.sql
index fbe3e65..2c38927 100644
--- a/Open-ILS/src/sql/Pg/950.data.seed-values.sql
+++ b/Open-ILS/src/sql/Pg/950.data.seed-values.sql
@@ -3284,6 +3284,8 @@ INSERT INTO config.marc21_rec_type_map (code, type_val, blvl_val) VALUES ('MAP',
 INSERT INTO config.marc21_rec_type_map (code, type_val, blvl_val) VALUES ('SCO','cd','abcdmsi');
 INSERT INTO config.marc21_rec_type_map (code, type_val, blvl_val) VALUES ('REC','ij','abcdmsi');
 INSERT INTO config.marc21_rec_type_map (code, type_val, blvl_val) VALUES ('COM','m','abcdmsi');
+INSERT INTO config.marc21_rec_type_map (code, type_val, blvl_val) VALUES ('AUT','z',' ');
+INSERT INTO config.marc21_rec_type_map (code, type_val, blvl_val) VALUES ('MFHD','uvxy',' ');
 
 
 ------ Physical Characteristics
@@ -4107,6 +4109,7 @@ INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, leng
 INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('ELvl', 'ldr', 'SCO', 17, 1, ' ');
 INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('ELvl', 'ldr', 'SER', 17, 1, ' ');
 INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('ELvl', 'ldr', 'VIS', 17, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('ELvl', 'ldr', 'AUT', 17, 1, ' ');
 INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Fest', '006', 'BKS', 13, 1, '0');
 INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Fest', '008', 'BKS', 30, 1, '0');
 INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Form', '006', 'BKS', 6, 1, ' ');
@@ -4169,6 +4172,8 @@ INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, leng
 INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Type', 'ldr', 'SCO', 6, 1, 'c');
 INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Type', 'ldr', 'SER', 6, 1, 'a');
 INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Type', 'ldr', 'VIS', 6, 1, 'g');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Subj', '008', 'AUT', 11, 1, '|');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('RecStat', 'ldr', 'AUT', 5, 1, 'n');
 
 -- record attributes
 INSERT INTO config.record_attr_definition (name,label,fixed_field) values ('alph','Alph','Alph');
diff --git a/Open-ILS/src/sql/Pg/999.functions.global.sql b/Open-ILS/src/sql/Pg/999.functions.global.sql
index f1ea776..553223a 100644
--- a/Open-ILS/src/sql/Pg/999.functions.global.sql
+++ b/Open-ILS/src/sql/Pg/999.functions.global.sql
@@ -1440,9 +1440,13 @@ $func$ LANGUAGE PLPGSQL;
 CREATE OR REPLACE FUNCTION authority.reingest_authority_rec_descriptor( auth_id BIGINT ) RETURNS VOID AS $func$
 BEGIN
     DELETE FROM authority.rec_descriptor WHERE record = auth_id;
---    INSERT INTO authority.rec_descriptor (record, record_status, char_encoding, thesaurus)
---        SELECT  auth_id, ;
-
+    INSERT INTO authority.rec_descriptor (record, record_status, encoding_level, thesaurus)
+        SELECT  auth_id,
+                vandelay.marc21_extract_fixed_field(marc,'RecStat'),
+                vandelay.marc21_extract_fixed_field(marc,'ELvl'),
+                vandelay.marc21_extract_fixed_field(marc,'Subj')
+          FROM  authority.record
+          WHERE id = auth_id;
     RETURN;
 END;
 $func$ LANGUAGE PLPGSQL;
@@ -1482,11 +1486,10 @@ BEGIN
     PERFORM * FROM config.internal_flag WHERE name = 'ingest.disable_authority_full_rec' AND enabled;
     IF NOT FOUND THEN
         PERFORM authority.reingest_authority_full_rec(NEW.id);
--- authority.rec_descriptor is not currently used
---        PERFORM * FROM config.internal_flag WHERE name = 'ingest.disable_authority_rec_descriptor' AND enabled;
---        IF NOT FOUND THEN
---            PERFORM authority.reingest_authority_rec_descriptor(NEW.id);
---        END IF;
+        PERFORM * FROM config.internal_flag WHERE name = 'ingest.disable_authority_rec_descriptor' AND enabled;
+        IF NOT FOUND THEN
+            PERFORM authority.reingest_authority_rec_descriptor(NEW.id);
+        END IF;
     END IF;
 
     RETURN NEW;

commit 09e928786c75e67e24bd563c44ef91d85d3dbb79
Author: Mike Rylander <mrylander at gmail.com>
Date:   Mon Apr 4 16:12:45 2011 -0400

    figure out non-authoritive fields to search based on the main_entry field on subordinate fields

diff --git a/Open-ILS/src/sql/Pg/950.data.seed-values.sql b/Open-ILS/src/sql/Pg/950.data.seed-values.sql
index c458b36..fbe3e65 100644
--- a/Open-ILS/src/sql/Pg/950.data.seed-values.sql
+++ b/Open-ILS/src/sql/Pg/950.data.seed-values.sql
@@ -9447,52 +9447,52 @@ INSERT INTO authority.control_set_authority_field (id, control_set, main_entry,
     (52, 1, 12, '748', 'avwxyz25', oils_i18n_gettext('52','Established Heading Linking Entry -- Chronological Term','acsaf','name'));
 
 INSERT INTO authority.control_set_bib_field (tag, authority_field) VALUES
-    SELECT '100', id FROM authority.control_set_authority_field WHERE tag IN ('100','500','700')
+    SELECT '100', id FROM authority.control_set_authority_field WHERE tag IN ('100')
         UNION
-    SELECT '600', id FROM authority.control_set_authority_field WHERE tag IN ('100','500','700','180','181','182','185','580','581','582','585','780','781','782','785')
+    SELECT '600', id FROM authority.control_set_authority_field WHERE tag IN ('100','180','181','182','185')
         UNION
-    SELECT '700', id FROM authority.control_set_authority_field WHERE tag IN ('100','500','700')
+    SELECT '700', id FROM authority.control_set_authority_field WHERE tag IN ('100')
         UNION
-    SELECT '800', id FROM authority.control_set_authority_field WHERE tag IN ('100','500','700')
+    SELECT '800', id FROM authority.control_set_authority_field WHERE tag IN ('100')
         UNION
 
-    SELECT '110', id FROM authority.control_set_authority_field WHERE tag IN ('110','510','710')
+    SELECT '110', id FROM authority.control_set_authority_field WHERE tag IN ('110')
         UNION
-    SELECT '610', id FROM authority.control_set_authority_field WHERE tag IN ('110','510','710')
+    SELECT '610', id FROM authority.control_set_authority_field WHERE tag IN ('110')
         UNION
-    SELECT '710', id FROM authority.control_set_authority_field WHERE tag IN ('110','510','710')
+    SELECT '710', id FROM authority.control_set_authority_field WHERE tag IN ('110')
         UNION
-    SELECT '810', id FROM authority.control_set_authority_field WHERE tag IN ('110','510','710')
+    SELECT '810', id FROM authority.control_set_authority_field WHERE tag IN ('110')
         UNION
 
-    SELECT '111', id FROM authority.control_set_authority_field WHERE tag IN ('111','511','711')
+    SELECT '111', id FROM authority.control_set_authority_field WHERE tag IN ('111')
         UNION
-    SELECT '611', id FROM authority.control_set_authority_field WHERE tag IN ('111','511','711')
+    SELECT '611', id FROM authority.control_set_authority_field WHERE tag IN ('111')
         UNION
-    SELECT '711', id FROM authority.control_set_authority_field WHERE tag IN ('111','511','711')
+    SELECT '711', id FROM authority.control_set_authority_field WHERE tag IN ('111')
         UNION
-    SELECT '811', id FROM authority.control_set_authority_field WHERE tag IN ('111','511','711')
+    SELECT '811', id FROM authority.control_set_authority_field WHERE tag IN ('111')
         UNION
 
-    SELECT '130', id FROM authority.control_set_authority_field WHERE tag IN ('130','530','730')
+    SELECT '130', id FROM authority.control_set_authority_field WHERE tag IN ('130')
         UNION
-    SELECT '240', id FROM authority.control_set_authority_field WHERE tag IN ('130','530','730')
+    SELECT '240', id FROM authority.control_set_authority_field WHERE tag IN ('130')
         UNION
-    SELECT '630', id FROM authority.control_set_authority_field WHERE tag IN ('130','530','730')
+    SELECT '630', id FROM authority.control_set_authority_field WHERE tag IN ('130')
         UNION
-    SELECT '730', id FROM authority.control_set_authority_field WHERE tag IN ('130','530','730')
+    SELECT '730', id FROM authority.control_set_authority_field WHERE tag IN ('130')
         UNION
-    SELECT '830', id FROM authority.control_set_authority_field WHERE tag IN ('130','530','730')
+    SELECT '830', id FROM authority.control_set_authority_field WHERE tag IN ('130')
         UNION
 
-    SELECT '648', id FROM authority.control_set_authority_field WHERE tag IN ('148','548','748')
+    SELECT '648', id FROM authority.control_set_authority_field WHERE tag IN ('148')
         UNION
 
-    SELECT '650', id FROM authority.control_set_authority_field WHERE tag IN ('150','550','750','180','181','182','185','580','581','582','585','780','781','782','785')
+    SELECT '650', id FROM authority.control_set_authority_field WHERE tag IN ('150','180','181','182','185')
         UNION
-    SELECT '651', id FROM authority.control_set_authority_field WHERE tag IN ('151','551','751','180','181','182','185','580','581','582','585','780','781','782','785')
+    SELECT '651', id FROM authority.control_set_authority_field WHERE tag IN ('151','180','181','182','185')
         UNION
-    SELECT '655', id FROM authority.control_set_authority_field WHERE tag IN ('155','555','755','180','181','182','185','580','581','582','585','780','781','782','785')
+    SELECT '655', id FROM authority.control_set_authority_field WHERE tag IN ('155','180','181','182','185')
 ;
 
 INSERT INTO authority.thesaurus (code, name, control_set) VALUES

commit da36fd8365210436597c7499c44bf85e5a6c6379
Author: Mike Rylander <mrylander at gmail.com>
Date:   Sun Apr 3 18:49:08 2011 -0400

    Seed data for Authority Control Sets -- LoC

diff --git a/Open-ILS/src/sql/Pg/950.data.seed-values.sql b/Open-ILS/src/sql/Pg/950.data.seed-values.sql
index c739b95..c458b36 100644
--- a/Open-ILS/src/sql/Pg/950.data.seed-values.sql
+++ b/Open-ILS/src/sql/Pg/950.data.seed-values.sql
@@ -9392,4 +9392,119 @@ INSERT INTO action_trigger.environment ( event_def, path) VALUES (
     ,( 47, 'record.queue.owner')
 ;
 
+SELECT SETVAL('authority.control_set_id_seq'::TEXT, 100);
+SELECT SETVAL('authority.control_set_authority_field_id_seq'::TEXT, 1000);
+SELECT SETVAL('authority.control_set_bib_field_id_seq'::TEXT, 1000);
+
+INSERT INTO authority.control_set (id, name, description) VALUES (
+    1,
+    oils_i18n_gettext('1','LoC','acs','name'),
+    oils_i18n_gettext('1','Library of Congress standard authority record control semantics','acs','description')
+);
+
+INSERT INTO authority.control_set_authority_field (id, control_set, main_entry, tag, sf_list, name) VALUES
+
+-- Main entries
+    (1, 1, NULL, '100', 'abcdefklmnopqrstvxyz', oils_i18n_gettext('1','Heading -- Personal Name','acsaf','name')),
+    (2, 1, NULL, '110', 'abcdefgklmnoprstvxyz', oils_i18n_gettext('2','Heading -- Corporate Name','acsaf','name')),
+    (3, 1, NULL, '111', 'acdefgklnpqstvxyz', oils_i18n_gettext('3','Heading -- Meeting Name','acsaf','name')),
+    (4, 1, NULL, '130', 'adfgklmnoprstvxyz', oils_i18n_gettext('4','Heading -- Uniform Title','acsaf','name')),
+    (5, 1, NULL, '150', 'abvxyz', oils_i18n_gettext('5','Heading -- Topical Term','acsaf','name')),
+    (6, 1, NULL, '151', 'avxyz', oils_i18n_gettext('6','Heading -- Geographic Name','acsaf','name')),
+    (7, 1, NULL, '155', 'avxyz', oils_i18n_gettext('7','Heading -- Genre/Form Term','acsaf','name')),
+    (8, 1, NULL, '180', 'vxyz', oils_i18n_gettext('8','Heading -- General Subdivision','acsaf','name')),
+    (9, 1, NULL, '181', 'vxyz', oils_i18n_gettext('9','Heading -- Geographic Subdivision','acsaf','name')),
+    (10, 1, NULL, '182', 'vxyz', oils_i18n_gettext('10','Heading -- Chronological Subdivision','acsaf','name')),
+    (11, 1, NULL, '185', 'vxyz', oils_i18n_gettext('11','Heading -- Form Subdivision','acsaf','name')),
+    (12, 1, NULL, '148', 'avxyz', oils_i18n_gettext('12','Heading -- Chronological Term','acsaf','name')),
+
+-- See Also tracings
+    (21, 1, 1, '500', 'abcdefiklmnopqrstvwxyz4', oils_i18n_gettext('21','See Also From Tracing -- Personal Name','acsaf','name')),
+    (22, 1, 2, '510', 'abcdefgiklmnoprstvwxyz4', oils_i18n_gettext('22','See Also From Tracing -- Corporate Name','acsaf','name')),
+    (23, 1, 3, '511', 'acdefgiklnpqstvwxyz4', oils_i18n_gettext('23','See Also From Tracing -- Meeting Name','acsaf','name')),
+    (24, 1, 4, '530', 'adfgiklmnoprstvwxyz4', oils_i18n_gettext('24','See Also From Tracing -- Uniform Title','acsaf','name')),
+    (25, 1, 5, '550', 'abivwxyz4', oils_i18n_gettext('25','See Also From Tracing -- Topical Term','acsaf','name')),
+    (26, 1, 6, '551', 'aivwxyz4', oils_i18n_gettext('26','See Also From Tracing -- Geographic Name','acsaf','name')),
+    (27, 1, 7, '555', 'aivwxyz4', oils_i18n_gettext('27','See Also From Tracing -- Genre/Form Term','acsaf','name')),
+    (28, 1, 8, '580', 'ivwxyz4', oils_i18n_gettext('28','See Also From Tracing -- General Subdivision','acsaf','name')),
+    (29, 1, 9, '581', 'ivwxyz4', oils_i18n_gettext('29','See Also From Tracing -- Geographic Subdivision','acsaf','name')),
+    (30, 1, 10, '582', 'ivwxyz4', oils_i18n_gettext('30','See Also From Tracing -- Chronological Subdivision','acsaf','name')),
+    (31, 1, 11, '585', 'ivwxyz4', oils_i18n_gettext('31','See Also From Tracing -- Form Subdivision','acsaf','name')),
+    (32, 1, 12, '548', 'aivwxyz4', oils_i18n_gettext('32','See Also From Tracing -- Chronological Term','acsaf','name')),
+
+-- Linking entries
+    (41, 1, 1, '700', 'abcdefghjklmnopqrstvwxyz25', oils_i18n_gettext('41','Established Heading Linking Entry -- Personal Name','acsaf','name')),
+    (42, 1, 2, '710', 'abcdefghklmnoprstvwxyz25', oils_i18n_gettext('42','Established Heading Linking Entry -- Corporate Name','acsaf','name')),
+    (43, 1, 3, '711', 'acdefghklnpqstvwxyz25', oils_i18n_gettext('43','Established Heading Linking Entry -- Meeting Name','acsaf','name')),
+    (44, 1, 4, '730', 'adfghklmnoprstvwxyz25', oils_i18n_gettext('44','Established Heading Linking Entry -- Uniform Title','acsaf','name')),
+    (45, 1, 5, '750', 'abvwxyz25', oils_i18n_gettext('45','Established Heading Linking Entry -- Topical Term','acsaf','name')),
+    (46, 1, 6, '751', 'avwxyz25', oils_i18n_gettext('46','Established Heading Linking Entry -- Geographic Name','acsaf','name')),
+    (47, 1, 7, '755', 'avwxyz25', oils_i18n_gettext('47','Established Heading Linking Entry -- Genre/Form Term','acsaf','name')),
+    (48, 1, 8, '780', 'vwxyz25', oils_i18n_gettext('48','Subdivision Linking Entry -- General Subdivision','acsaf','name')),
+    (49, 1, 9, '781', 'vwxyz25', oils_i18n_gettext('49','Subdivision Linking Entry -- Geographic Subdivision','acsaf','name')),
+    (50, 1, 10, '782', 'vwxyz25', oils_i18n_gettext('50','Subdivision Linking Entry -- Chronological Subdivision','acsaf','name')),
+    (51, 1, 11, '785', 'vwxyz25', oils_i18n_gettext('51','Subdivision Linking Entry -- Form Subdivision','acsaf','name')),
+    (52, 1, 12, '748', 'avwxyz25', oils_i18n_gettext('52','Established Heading Linking Entry -- Chronological Term','acsaf','name'));
+
+INSERT INTO authority.control_set_bib_field (tag, authority_field) VALUES
+    SELECT '100', id FROM authority.control_set_authority_field WHERE tag IN ('100','500','700')
+        UNION
+    SELECT '600', id FROM authority.control_set_authority_field WHERE tag IN ('100','500','700','180','181','182','185','580','581','582','585','780','781','782','785')
+        UNION
+    SELECT '700', id FROM authority.control_set_authority_field WHERE tag IN ('100','500','700')
+        UNION
+    SELECT '800', id FROM authority.control_set_authority_field WHERE tag IN ('100','500','700')
+        UNION
+
+    SELECT '110', id FROM authority.control_set_authority_field WHERE tag IN ('110','510','710')
+        UNION
+    SELECT '610', id FROM authority.control_set_authority_field WHERE tag IN ('110','510','710')
+        UNION
+    SELECT '710', id FROM authority.control_set_authority_field WHERE tag IN ('110','510','710')
+        UNION
+    SELECT '810', id FROM authority.control_set_authority_field WHERE tag IN ('110','510','710')
+        UNION
+
+    SELECT '111', id FROM authority.control_set_authority_field WHERE tag IN ('111','511','711')
+        UNION
+    SELECT '611', id FROM authority.control_set_authority_field WHERE tag IN ('111','511','711')
+        UNION
+    SELECT '711', id FROM authority.control_set_authority_field WHERE tag IN ('111','511','711')
+        UNION
+    SELECT '811', id FROM authority.control_set_authority_field WHERE tag IN ('111','511','711')
+        UNION
+
+    SELECT '130', id FROM authority.control_set_authority_field WHERE tag IN ('130','530','730')
+        UNION
+    SELECT '240', id FROM authority.control_set_authority_field WHERE tag IN ('130','530','730')
+        UNION
+    SELECT '630', id FROM authority.control_set_authority_field WHERE tag IN ('130','530','730')
+        UNION
+    SELECT '730', id FROM authority.control_set_authority_field WHERE tag IN ('130','530','730')
+        UNION
+    SELECT '830', id FROM authority.control_set_authority_field WHERE tag IN ('130','530','730')
+        UNION
+
+    SELECT '648', id FROM authority.control_set_authority_field WHERE tag IN ('148','548','748')
+        UNION
+
+    SELECT '650', id FROM authority.control_set_authority_field WHERE tag IN ('150','550','750','180','181','182','185','580','581','582','585','780','781','782','785')
+        UNION
+    SELECT '651', id FROM authority.control_set_authority_field WHERE tag IN ('151','551','751','180','181','182','185','580','581','582','585','780','781','782','785')
+        UNION
+    SELECT '655', id FROM authority.control_set_authority_field WHERE tag IN ('155','555','755','180','181','182','185','580','581','582','585','780','781','782','785')
+;
+
+INSERT INTO authority.thesaurus (code, name, control_set) VALUES
+    ('a', oils_i18n_gettext('a','Library of Congress Subject Headings','at','name'), 1),
+    ('b', oils_i18n_gettext('b',$$LC subject headings for children's literature$$,'at','name'), 1), -- silly vim '
+    ('c', oils_i18n_gettext('c','Medical Subject Headings','at','name'), 1),
+    ('d', oils_i18n_gettext('d','National Agricultural Library subject authority file','at','name'), 1),
+    ('k', oils_i18n_gettext('k','Canadian Subject Headings','at','name'), 1),
+    ('n', oils_i18n_gettext('n','Not applicable','at','name'), 1),
+    ('r', oils_i18n_gettext('r','Art and Architecture Thesaurus','at','name'), 1),
+    ('s', oils_i18n_gettext('s','Sears List of Subject Headings','at','name'), 1),
+    ('v', oils_i18n_gettext('v','Repertoire de vedettes-matiere','at','name'), 1),
+    ('z', oils_i18n_gettext('z','Other','at','name') 1),
+    ('|', oils_i18n_gettext('|','No attempt to code','at','name') 1);
 

commit bdbcc734d179f8c12a27ec65f49650667ed658cc
Author: Mike Rylander <mrylander at gmail.com>
Date:   Sun Apr 3 18:48:30 2011 -0400

    Reworking tables a bit to include subfield list on controlling tags, specify hierarchy of tags (main-entry pointers for non-main fields), and remove unneeded name/description on bib fields

diff --git a/Open-ILS/src/sql/Pg/011.schema.authority.sql b/Open-ILS/src/sql/Pg/011.schema.authority.sql
index 460d836..d2e5795 100644
--- a/Open-ILS/src/sql/Pg/011.schema.authority.sql
+++ b/Open-ILS/src/sql/Pg/011.schema.authority.sql
@@ -30,8 +30,10 @@ CREATE TABLE authority.control_set (
 
 CREATE TABLE authority.control_set_authority_field (
     id          SERIAL  PRIMARY KEY,
+    main_entry  INT     REFERENCES authority.control_set_authority_field (id) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
     control_set INT     NOT NULL REFERENCES authority.control_set (id) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
     tag         CHAR(3) NOT NULL,
+    sf_list     TEXT    NOT NULL,
     name        TEXT    NOT NULL, -- i18n
     description TEXT              -- i18n
 );
@@ -39,9 +41,7 @@ CREATE TABLE authority.control_set_authority_field (
 CREATE TABLE authority.control_set_bib_field (
     id              SERIAL  PRIMARY KEY,
     authority_field INT     NOT NULL REFERENCES authority.control_set_authority_field (id) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
-    tag             CHAR(3) NOT NULL,
-    name            TEXT    NOT NULL, -- i18n
-    description     TEXT              -- i18n
+    tag             CHAR(3) NOT NULL
 );
 
 CREATE TABLE authority.thesaurus (

commit 3ab55df32f5eefae941097a34f24cfb776c8508f
Author: Mike Rylander <mrylander at gmail.com>
Date:   Sun Apr 3 15:17:15 2011 -0400

    Fieldmapper additions for Authority Control Set tables/classes

diff --git a/Open-ILS/examples/fm_IDL.xml b/Open-ILS/examples/fm_IDL.xml
index 27cdcd7..6bd96cf 100644
--- a/Open-ILS/examples/fm_IDL.xml
+++ b/Open-ILS/examples/fm_IDL.xml
@@ -1757,6 +1757,93 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 			<link field="item" reltype="has_a" key="id" map="" class="ccbi"/>
 		</links>
 	</class>
+
+	<class id="acs" controller="open-ils.cstore" oils_obj:fieldmapper="authority::control_set" oils_persist:tablename="authority.control_set" reporter:label="Authority Control Set">
+		<fields oils_persist:primary="id" oils_persist:sequence="authority.contol_set_id_seq">
+			<field reporter:label="Control Set ID" name="id" reporter:datatype="id" reporter:selector="name"/>
+			<field reporter:label="Name" name="name" reporter:datatype="text" oils_persist:i18n="true" oils_obj:required="true" />
+			<field reporter:label="Description" name="description" reporter:datatype="text" oils_persist:i18n="true" />
+			<field reporter:label="Controlling Authority Fields" name="authority_fields" reporter:datatype="link" oils_persist:virtual="true"/>
+		</fields>
+		<links>
+			<link field="authority_fields" reltype="has_many" key="control_set" map="" class="acsaf"/>
+		</links>
+		<permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
+			<actions>
+				<create permission="CREATE_AUTHORITY_CONTROLSET" global_required="true"/>
+				<retrieve/>
+				<update permission="UPDATE_AUTHORITY_CONTROLSET" global_required="true"/>
+				<delete permission="DELETE_AUTHORITY_CONTROLSET" global_required="true"/>
+			</actions>
+		</permacrud>
+	</class>
+
+	<class id="acsaf" controller="open-ils.cstore" oils_obj:fieldmapper="authority::control_set_authority_field" oils_persist:tablename="authority.control_set_authority_field" reporter:label="Authority Control Set Authority Field">
+		<fields oils_persist:primary="id" oils_persist:sequence="authority.contol_set_authority_field_id_seq">
+			<field reporter:label="Control Set Authority Field ID" name="id" reporter:datatype="id" reporter:selector="name"/>
+			<field reporter:label="Control Set" name="control_set" reporter:datatype="link"/>
+			<field reporter:label="Tag" name="tag" reporter:datatype="text" oils_obj:required="true" oils_obj:validate="^.{3}$"/>
+			<field reporter:label="Name" name="name" reporter:datatype="text" oils_persist:i18n="true" oils_obj:required="true" />
+			<field reporter:label="Description" name="description" reporter:datatype="text" oils_persist:i18n="true" />
+			<field reporter:label="Controlled Bib Fields" name="bib_fields" reporter:datatype="link" oils_persist:virtual="true"/>
+			<field reporter:label="Thesauri" name="thesauri" reporter:datatype="link" oils_persist:virtual="true"/>
+		</fields>
+		<links>
+			<link field="control_set" reltype="has_a" key="id" map="" class="acs"/>
+			<link field="bib_fields" reltype="has_many" key="authority_field" map="" class="acsbf"/>
+			<link field="thesauri" reltype="has_many" key="control_set" map="" class="at"/>
+		</links>
+		<permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
+			<actions>
+				<create permission="CREATE_AUTHORITY_CONTROLSET" global_required="true"/>
+				<retrieve/>
+				<update permission="UPDATE_AUTHORITY_CONTROLSET" global_required="true"/>
+				<delete permission="UPDATE_AUTHORITY_CONTROLSET" global_required="true"/>
+			</actions>
+		</permacrud>
+	</class>
+
+	<class id="acsbf" controller="open-ils.cstore" oils_obj:fieldmapper="authority::control_set_bib_field" oils_persist:tablename="authority.control_set_bib_field" reporter:label="Authority Control Set Bib Field">
+		<fields oils_persist:primary="id" oils_persist:sequence="authority.contol_set_bib_field_id_seq">
+			<field reporter:label="Controlled Bib Field ID" name="id" reporter:datatype="id" reporter:selector="name"/>
+			<field reporter:label="Controlling Authority Field" name="authority_field" reporter:datatype="link"/>
+			<field reporter:label="Tag" name="tag" reporter:datatype="text" oils_obj:required="true" oils_obj:validate="^.{3}$"/>
+			<field reporter:label="Name" name="name" reporter:datatype="text" oils_persist:i18n="true" oils_obj:required="true" />
+			<field reporter:label="Description" name="description" reporter:datatype="text" oils_persist:i18n="true" />
+		</fields>
+		<links>
+			<link field="authority_field" reltype="has_a" key="id" map="" class="acsaf"/>
+		</links>
+		<permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
+			<actions>
+				<create permission="CREATE_AUTHORITY_CONTROLSET" global_required="true"/>
+				<retrieve/>
+				<update permission="UPDATE_AUTHORITY_CONTROLSET" global_required="true"/>
+				<delete permission="UPDATE_AUTHORITY_CONTROLSET" global_required="true"/>
+			</actions>
+		</permacrud>
+	</class>
+
+	<class id="at" controller="open-ils.cstore" oils_obj:fieldmapper="authority::thesaurus" oils_persist:tablename="authority.thesaurus" reporter:label="Authority Thesaurus">
+		<fields oils_persist:primary="code">
+			<field reporter:label="Thesaurus Code" name="code" reporter:datatype="id" reporter:selector="name"/>
+			<field reporter:label="Control Set" name="control_set" reporter:datatype="link"/>
+			<field reporter:label="Name" name="name" reporter:datatype="text" oils_persist:i18n="true" oils_obj:required="true" />
+			<field reporter:label="Description" name="description" reporter:datatype="text" oils_persist:i18n="true" />
+		</fields>
+		<links>
+			<link field="control_set" reltype="has_a" key="id" map="" class="acs"/>
+		</links>
+		<permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
+			<actions>
+				<create permission="CREATE_AUTHORITY_CONTROLSET" global_required="true"/>
+				<retrieve/>
+				<update permission="UPDATE_AUTHORITY_CONTROLSET" global_required="true"/>
+				<delete permission="UPDATE_AUTHORITY_CONTROLSET" global_required="true"/>
+			</actions>
+		</permacrud>
+	</class>
+
 	<class id="are" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="authority::record_entry" oils_persist:tablename="authority.record_entry" reporter:label="Authority Record Entry">
 		<fields oils_persist:primary="id" oils_persist:sequence="authority.record_entry_id_seq">
 			<field name="active" reporter:datatype="bool"/>
@@ -1769,12 +1856,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 			<field name="last_xact_id" />
 			<field name="marc" />
 			<field name="source" />
+			<field reporter:label="Control Set" name="control_set" reporter:datatype="link"/>
 			<field reporter:label="Owner" name="owner"  reporter:datatype="org_unit"/>
 			<field name="fixed_fields" oils_persist:virtual="true" reporter:datatype="link"/>
 			<field name="notes" oils_persist:virtual="true" reporter:datatype="link"/>
 			<field name="bib_links" oils_persist:virtual="true" reporter:datatype="link"/>
 		</fields>
 		<links>
+			<link field="control_set" reltype="has_a" key="id" map="" class="acs"/>
 			<link field="owner" reltype="has_a" key="id" map="" class="aou"/>
 			<link field="editor" reltype="has_a" key="id" map="" class="au"/>
 			<link field="creator" reltype="has_a" key="id" map="" class="au"/>
@@ -1797,9 +1886,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 			<field name="id" />
 			<field name="record" />
 			<field name="record_status" />
+			<field name="thesaurus" />
 		</fields>
 		<links>
 			<link field="record" reltype="has_a" key="id" map="" class="are"/>
+			<link field="thesaurus" reltype="might_have" key="code" map="" class="at"/>
 		</links>
 	</class>
 	<class id="abl" controller="open-ils.cstore" oils_obj:fieldmapper="authority::bib_linking" oils_persist:tablename="authority.bib_linking" reporter:label="Authority-Bibliographic Record Link">
diff --git a/Open-ILS/src/sql/Pg/999.functions.global.sql b/Open-ILS/src/sql/Pg/999.functions.global.sql
index 0faeea6..f1ea776 100644
--- a/Open-ILS/src/sql/Pg/999.functions.global.sql
+++ b/Open-ILS/src/sql/Pg/999.functions.global.sql
@@ -1378,11 +1378,69 @@ CREATE OR REPLACE FUNCTION authority.propagate_changes (aid BIGINT) RETURNS SETO
     SELECT authority.propagate_changes( authority, bib ) FROM authority.bib_linking WHERE authority = $1;
 $func$ LANGUAGE SQL;
 
--- authority.rec_descriptor appears to be unused currently
+CREATE OR REPLACE FUNCTION authority.flatten_marc ( TEXT ) RETURNS SETOF authority.full_rec AS $func$
+
+use MARC::Record;
+use MARC::File::XML (BinaryEncoding => 'UTF-8');
+
+my $xml = shift;
+my $r = MARC::Record->new_from_xml( $xml );
+
+return_next( { tag => 'LDR', value => $r->leader } );
+
+for my $f ( $r->fields ) {
+    if ($f->is_control_field) {
+        return_next({ tag => $f->tag, value => $f->data });
+    } else {
+        for my $s ($f->subfields) {
+            return_next({
+                tag      => $f->tag,
+                ind1     => $f->indicator(1),
+                ind2     => $f->indicator(2),
+                subfield => $s->[0],
+                value    => $s->[1]
+            });
+
+        }
+    }
+}
+
+return undef;
+
+$func$ LANGUAGE PLPERLU;
+
+CREATE OR REPLACE FUNCTION authority.flatten_marc ( rid BIGINT ) RETURNS SETOF authority.full_rec AS $func$
+DECLARE
+    auth    authority.record_entry%ROWTYPE;
+    output    authority.full_rec%ROWTYPE;
+    field    RECORD;
+BEGIN
+    SELECT INTO auth * FROM authority.record_entry WHERE id = rid;
+
+    FOR field IN SELECT * FROM authority.flatten_marc( auth.marc ) LOOP
+        output.record := rid;
+        output.ind1 := field.ind1;
+        output.ind2 := field.ind2;
+        output.tag := field.tag;
+        output.subfield := field.subfield;
+        IF field.subfield IS NOT NULL THEN
+            output.value := naco_normalize(field.value, field.subfield);
+        ELSE
+            output.value := field.value;
+        END IF;
+
+        CONTINUE WHEN output.value IS NULL;
+
+        RETURN NEXT output;
+    END LOOP;
+END;
+$func$ LANGUAGE PLPGSQL;
+
+-- authority.rec_descriptor appears to be unused currently XXX
 CREATE OR REPLACE FUNCTION authority.reingest_authority_rec_descriptor( auth_id BIGINT ) RETURNS VOID AS $func$
 BEGIN
     DELETE FROM authority.rec_descriptor WHERE record = auth_id;
---    INSERT INTO authority.rec_descriptor (record, record_status, char_encoding)
+--    INSERT INTO authority.rec_descriptor (record, record_status, char_encoding, thesaurus)
 --        SELECT  auth_id, ;
 
     RETURN;

commit 063e907ad504270efd34e063f4784aee8621e493
Author: Mike Rylander <mrylander at gmail.com>
Date:   Sun Apr 3 10:19:38 2011 -0400

    Initial schema changes for Authority Control Sets; some whitespace cleanup

diff --git a/Open-ILS/src/sql/Pg/011.schema.authority.sql b/Open-ILS/src/sql/Pg/011.schema.authority.sql
index f48e223..460d836 100644
--- a/Open-ILS/src/sql/Pg/011.schema.authority.sql
+++ b/Open-ILS/src/sql/Pg/011.schema.authority.sql
@@ -22,18 +22,48 @@ DROP SCHEMA IF EXISTS authority CASCADE;
 BEGIN;
 CREATE SCHEMA authority;
 
+CREATE TABLE authority.control_set (
+    id          SERIAL  PRIMARY KEY,
+    name        TEXT    NOT NULL UNIQUE, -- i18n
+    description TEXT                     -- i18n
+);
+
+CREATE TABLE authority.control_set_authority_field (
+    id          SERIAL  PRIMARY KEY,
+    control_set INT     NOT NULL REFERENCES authority.control_set (id) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
+    tag         CHAR(3) NOT NULL,
+    name        TEXT    NOT NULL, -- i18n
+    description TEXT              -- i18n
+);
+
+CREATE TABLE authority.control_set_bib_field (
+    id              SERIAL  PRIMARY KEY,
+    authority_field INT     NOT NULL REFERENCES authority.control_set_authority_field (id) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
+    tag             CHAR(3) NOT NULL,
+    name            TEXT    NOT NULL, -- i18n
+    description     TEXT              -- i18n
+);
+
+CREATE TABLE authority.thesaurus (
+    code        TEXT    PRIMARY KEY,     -- MARC21 thesaurus code
+    control_set INT     NOT NULL REFERENCES authority.control_set (id) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
+    name        TEXT    NOT NULL UNIQUE, -- i18n
+    description TEXT                     -- i18n
+);
+
 CREATE TABLE authority.record_entry (
-	id		BIGSERIAL	PRIMARY KEY,
-	creator		INT		NOT NULL DEFAULT 1,
-	editor		INT		NOT NULL DEFAULT 1,
-	create_date	TIMESTAMP WITH TIME ZONE	NOT NULL DEFAULT now(),
-	edit_date	TIMESTAMP WITH TIME ZONE	NOT NULL DEFAULT now(),
-	active		BOOL		NOT NULL DEFAULT TRUE,
-	deleted		BOOL		NOT NULL DEFAULT FALSE,
-	source		INT,
-	marc		TEXT		NOT NULL,
-	last_xact_id	TEXT		NOT NULL,
-	owner		INT
+    id              BIGSERIAL    PRIMARY KEY,
+    create_date     TIMESTAMP WITH TIME ZONE    NOT NULL DEFAULT now(),
+    edit_date       TIMESTAMP WITH TIME ZONE    NOT NULL DEFAULT now(),
+    creator         INT     NOT NULL DEFAULT 1,
+    editor          INT     NOT NULL DEFAULT 1,
+    active          BOOL    NOT NULL DEFAULT TRUE,
+    deleted         BOOL    NOT NULL DEFAULT FALSE,
+    source          INT,
+    control_set     INT     REFERENCES authority.control_set (id) ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED,
+    marc            TEXT    NOT NULL,
+    last_xact_id    TEXT    NOT NULL,
+    owner           INT
 );
 CREATE INDEX authority_record_entry_creator_idx ON authority.record_entry ( creator );
 CREATE INDEX authority_record_entry_editor_idx ON authority.record_entry ( editor );
@@ -52,71 +82,72 @@ CREATE INDEX authority_bl_bib_idx ON authority.bib_linking ( bib );
 CREATE UNIQUE INDEX authority_bl_bib_authority_once_idx ON authority.bib_linking ( authority, bib );
 
 CREATE TABLE authority.record_note (
-	id		BIGSERIAL	PRIMARY KEY,
-	record		BIGINT		NOT NULL REFERENCES authority.record_entry (id) DEFERRABLE INITIALLY DEFERRED,
-	value		TEXT		NOT NULL,
-	creator		INT		NOT NULL DEFAULT 1,
-	editor		INT		NOT NULL DEFAULT 1,
-	create_date	TIMESTAMP WITH TIME ZONE	NOT NULL DEFAULT now(),
-	edit_date	TIMESTAMP WITH TIME ZONE	NOT NULL DEFAULT now()
+    id          BIGSERIAL   PRIMARY KEY,
+    record      BIGINT      NOT NULL REFERENCES authority.record_entry (id) DEFERRABLE INITIALLY DEFERRED,
+    value       TEXT        NOT NULL,
+    creator     INT         NOT NULL DEFAULT 1,
+    editor      INT         NOT NULL DEFAULT 1,
+    create_date TIMESTAMP WITH TIME ZONE    NOT NULL DEFAULT now(),
+    edit_date   TIMESTAMP WITH TIME ZONE    NOT NULL DEFAULT now()
 );
 CREATE INDEX authority_record_note_record_idx ON authority.record_note ( record );
 CREATE INDEX authority_record_note_creator_idx ON authority.record_note ( creator );
 CREATE INDEX authority_record_note_editor_idx ON authority.record_note ( editor );
 
 CREATE TABLE authority.rec_descriptor (
-	id		BIGSERIAL PRIMARY KEY,
-	record		BIGINT,
-	record_status	TEXT,
-	char_encoding	TEXT
+    id              BIGSERIAL PRIMARY KEY,
+    record          BIGINT,
+    record_status   TEXT,
+    char_encoding   TEXT,
+    thesaurus       TEXT
 );
 CREATE INDEX authority_rec_descriptor_record_idx ON authority.rec_descriptor (record);
 
 CREATE TABLE authority.full_rec (
-	id		BIGSERIAL	PRIMARY KEY,
-	record		BIGINT		NOT NULL,
-	tag		CHAR(3)		NOT NULL,
-	ind1		TEXT,
-	ind2		TEXT,
-	subfield	TEXT,
-	value		TEXT		NOT NULL,
-	index_vector	tsvector	NOT NULL
+    id              BIGSERIAL   PRIMARY KEY,
+    record          BIGINT      NOT NULL,
+    tag             CHAR(3)     NOT NULL,
+    ind1            TEXT,
+    ind2            TEXT,
+    subfield        TEXT,
+    value           TEXT        NOT NULL,
+    index_vector    tsvector    NOT NULL
 );
 CREATE INDEX authority_full_rec_record_idx ON authority.full_rec (record);
 CREATE INDEX authority_full_rec_tag_subfield_idx ON authority.full_rec (tag, subfield);
 CREATE INDEX authority_full_rec_tag_part_idx ON authority.full_rec (SUBSTRING(tag FROM 2));
 CREATE INDEX authority_full_rec_subfield_a_idx ON authority.full_rec (value) WHERE subfield = 'a';
 CREATE TRIGGER authority_full_rec_fti_trigger
-	BEFORE UPDATE OR INSERT ON authority.full_rec
-	FOR EACH ROW EXECUTE PROCEDURE tsearch2(index_vector, value);
+    BEFORE UPDATE OR INSERT ON authority.full_rec
+    FOR EACH ROW EXECUTE PROCEDURE tsearch2(index_vector, value);
 
 CREATE INDEX authority_full_rec_index_vector_idx ON authority.full_rec USING GIST (index_vector);
 /* Enable LIKE to use an index for database clusters with locales other than C or POSIX */
 CREATE INDEX authority_full_rec_value_tpo_index ON authority.full_rec (value text_pattern_ops);
 
 CREATE OR REPLACE VIEW authority.tracing_links AS
-	SELECT	main.record AS record,
-		main.id AS main_id,
-		main.tag AS main_tag,
-		main.value AS main_value,
-		substr(link.value,1,1) AS relationship,
-		substr(link.value,2,1) AS use_restriction,
-		substr(link.value,3,1) AS deprecation,
-		substr(link.value,4,1) AS display_restriction,
-		link_value.id AS link_id,
-		link_value.tag AS link_tag,
-		link_value.value AS link_value
-	  FROM	authority.full_rec main
-		JOIN authority.full_rec link
-			ON (	link.record = main.record
-				AND link.tag in ((main.tag::int + 400)::text, (main.tag::int + 300)::text)
-				AND link.subfield = 'w' )
-		JOIN authority.full_rec link_value
-			ON (	link_value.record = main.record
-				AND link_value.tag = link.tag
-				AND link_value.subfield = 'a' )
-	  WHERE	main.tag IN ('100','110','111','130','150','151','155','180','181','182','185')
-		AND main.subfield = 'a';
+    SELECT  main.record AS record,
+            main.id AS main_id,
+            main.tag AS main_tag,
+            main.value AS main_value,
+            substr(link.value,1,1) AS relationship,
+            substr(link.value,2,1) AS use_restriction,
+            substr(link.value,3,1) AS deprecation,
+            substr(link.value,4,1) AS display_restriction,
+            link_value.id AS link_id,
+            link_value.tag AS link_tag,
+            link_value.value AS link_value
+      FROM  authority.full_rec main
+            JOIN authority.full_rec link
+                ON (link.record = main.record
+                    AND link.tag in ((main.tag::int + 400)::text, (main.tag::int + 300)::text)
+                    AND link.subfield = 'w' )
+            JOIN authority.full_rec link_value
+                ON (link_value.record = main.record
+                    AND link_value.tag = link.tag
+                    AND link_value.subfield = 'a' )
+      WHERE main.tag IN ('100','110','111','130','150','151','155','180','181','182','185')
+            AND main.subfield = 'a';
 
 -- Function to generate an ephemeral overlay template from an authority record
 CREATE OR REPLACE FUNCTION authority.generate_overlay_template ( TEXT, BIGINT ) RETURNS TEXT AS $func$
@@ -211,44 +242,49 @@ BEGIN
     --   replaced by the target record
 
     -- 1. Update all bib records with the ID from target_record in their $0
-    FOR bib_rec IN SELECT bre.* FROM biblio.record_entry bre 
-      INNER JOIN authority.bib_linking abl ON abl.bib = bre.id
-      WHERE abl.authority = source_record LOOP
-
-        UPDATE biblio.record_entry
-          SET marc = REGEXP_REPLACE(marc, 
-            E'(<subfield\\s+code="0"\\s*>[^<]*?\\))' || source_record || '<',
-            E'\\1' || target_record || '<', 'g')
+    FOR bib_rec IN
+            SELECT  bre.*
+              FROM  biblio.record_entry bre 
+                    JOIN authority.bib_linking abl ON abl.bib = bre.id
+              WHERE abl.authority = source_record
+        LOOP
+
+        UPDATE  biblio.record_entry
+          SET   marc = REGEXP_REPLACE(
+                    marc,
+                    E'(<subfield\\s+code="0"\\s*>[^<]*?\\))' || source_record || '<',
+                    E'\\1' || target_record || '<',
+                    'g'
+                )
           WHERE id = bib_rec.id;
 
           moved_objects := moved_objects + 1;
     END LOOP;
 
     -- 2. Grab the current value of reingest on same MARC flag
-    SELECT enabled INTO ingest_same
-      FROM config.internal_flag
+    SELECT  enabled INTO ingest_same
+      FROM  config.internal_flag
       WHERE name = 'ingest.reingest.force_on_same_marc'
     ;
 
     -- 3. Temporarily set reingest on same to TRUE
-    UPDATE config.internal_flag
-      SET enabled = TRUE
+    UPDATE  config.internal_flag
+      SET   enabled = TRUE
       WHERE name = 'ingest.reingest.force_on_same_marc'
     ;
 
     -- 4. Make a harmless update to target_record to trigger auto-update
     --    in linked bibliographic records
-    UPDATE authority.record_entry
-      SET deleted = FALSE
+    UPDATE  authority.record_entry
+      SET   deleted = FALSE
       WHERE id = target_record;
 
     -- 5. "Delete" source_record
-    DELETE FROM authority.record_entry
-      WHERE id = source_record;
+    DELETE FROM authority.record_entry WHERE id = source_record;
 
     -- 6. Set "reingest on same MARC" flag back to initial value
-    UPDATE config.internal_flag
-      SET enabled = ingest_same
+    UPDATE  config.internal_flag
+      SET   enabled = ingest_same
       WHERE name = 'ingest.reingest.force_on_same_marc'
     ;
 

-----------------------------------------------------------------------

Summary of changes:
 Open-ILS/examples/fm_IDL.xml                       |  142 ++
 Open-ILS/src/c-apps/oils_sql.c                     |   13 +-
 .../src/javascript/backend/catalog/fixed_fields.js |  647 +++++----
 .../lib/OpenILS/Application/Cat/Authority.pm       |  122 ++-
 .../lib/OpenILS/Application/Search/Authority.pm    |   55 +-
 .../perlmods/lib/OpenILS/Application/SuperCat.pm   |  165 ++-
 Open-ILS/src/perlmods/lib/OpenILS/WWW/SuperCat.pm  |   73 +-
 Open-ILS/src/sql/Pg/002.schema.config.sql          |    2 +-
 Open-ILS/src/sql/Pg/011.schema.authority.sql       |  389 +++--
 Open-ILS/src/sql/Pg/012.schema.vandelay.sql        |    2 +-
 Open-ILS/src/sql/Pg/020.schema.functions.sql       |   91 +--
 Open-ILS/src/sql/Pg/030.schema.metabib.sql         |   71 -
 Open-ILS/src/sql/Pg/800.fkeys.sql                  |    1 +
 Open-ILS/src/sql/Pg/950.data.seed-values.sql       |  162 ++
 Open-ILS/src/sql/Pg/999.functions.global.sql       |   33 +-
 .../upgrade/0575.schema.authority-control-sets.sql |  501 ++++++
 Open-ILS/web/Makefile.am                           |    2 +-
 Open-ILS/web/js/dojo/MARC/FixedFields.js           | 1665 ++++++++++++++++++++
 Open-ILS/web/js/dojo/MARC/Record.js                |   11 +-
 .../web/js/dojo/openils/AuthorityControlSet.js     |  581 +++++++
 .../web/js/dojo/openils/authority/nls/authority.js |    7 +-
 Open-ILS/web/js/dojo/openils/widget/AutoGrid.js    |    2 +-
 Open-ILS/web/js/ui/default/cat/authority/list.js   |    3 +-
 .../default/conify/global/cat/authority/common.js  |   36 +
 Open-ILS/web/opac/common/js/config.js              |    6 +
 Open-ILS/web/opac/locale/en-US/lang.dtd            |    9 +
 Open-ILS/web/opac/locale/en-US/opac.dtd            |    2 +
 Open-ILS/web/opac/skin/default/css/layout.css      |    7 +
 Open-ILS/web/opac/skin/default/js/advanced.js      |   31 +-
 Open-ILS/web/opac/skin/default/js/authbrowse.js    |  257 +++
 .../web/opac/skin/default/xml/common/js_common.xml |    2 +-
 .../web/opac/skin/default/xml/common/sidebar.xml   |   18 +
 .../web/opac/skin/default/xml/page_authbrowse.xml  |   13 +
 Open-ILS/web/opac/skin/default/xml/setenv.xml      |    3 +
 .../web/templates/default/cat/authority/list.tt2   |   19 +-
 .../conify/global/cat/authority/browse_axis.tt2    |   36 +
 .../authority/browse_axis_authority_field_map.tt2  |   71 +
 .../conify/global/cat/authority/control_set.tt2    |   88 +
 .../cat/authority/control_set_authority_field.tt2  |  132 ++
 .../global/cat/authority/control_set_bib_field.tt2 |   71 +
 .../conify/global/cat/authority/thesaurus.tt2      |  100 ++
 .../xul/staff_client/chrome/content/main/menu.js   |   19 +-
 .../chrome/content/main/menu_frame_menus.xul       |   14 +
 .../chrome/locale/en-US/offline.properties         |    1 +
 Open-ILS/xul/staff_client/server/cat/marcedit.js   | 1042 ++----------
 45 files changed, 5196 insertions(+), 1521 deletions(-)
 create mode 100644 Open-ILS/src/sql/Pg/upgrade/0575.schema.authority-control-sets.sql
 create mode 100644 Open-ILS/web/js/dojo/MARC/FixedFields.js
 create mode 100644 Open-ILS/web/js/dojo/openils/AuthorityControlSet.js
 create mode 100644 Open-ILS/web/js/ui/default/conify/global/cat/authority/common.js
 create mode 100644 Open-ILS/web/opac/skin/default/js/authbrowse.js
 create mode 100644 Open-ILS/web/opac/skin/default/xml/page_authbrowse.xml
 create mode 100644 Open-ILS/web/templates/default/conify/global/cat/authority/browse_axis.tt2
 create mode 100644 Open-ILS/web/templates/default/conify/global/cat/authority/browse_axis_authority_field_map.tt2
 create mode 100644 Open-ILS/web/templates/default/conify/global/cat/authority/control_set.tt2
 create mode 100644 Open-ILS/web/templates/default/conify/global/cat/authority/control_set_authority_field.tt2
 create mode 100644 Open-ILS/web/templates/default/conify/global/cat/authority/control_set_bib_field.tt2
 create mode 100644 Open-ILS/web/templates/default/conify/global/cat/authority/thesaurus.tt2


hooks/post-receive
-- 
Evergreen ILS


More information about the open-ils-commits mailing list