From 4370592e9120b4cc5b717f51e49b77c0f4140123 Mon Sep 17 00:00:00 2001 From: miker Date: Tue, 29 Mar 2005 21:10:37 +0000 Subject: [PATCH 1/1] updated Storage server git-svn-id: svn://svn.open-ils.org/ILS/trunk@410 dcc99617-32d9-48b4-a31d-7c20da2025e4 --- .../perlmods/OpenILS/Application/Storage.pm | 7 +- .../OpenILS/Application/Storage/CDBI.pm | 43 ++- .../Application/Storage/CDBI/biblio.pm | 2 +- .../Application/Storage/CDBI/metabib.pm | 66 ++-- .../OpenILS/Application/Storage/Driver/Pg.pm | 95 ++++- .../OpenILS/Application/Storage/Publisher.pm | 47 +++ .../OpenILS/Application/Storage/WORM.pm | 362 ++++++++++++++++++ 7 files changed, 557 insertions(+), 65 deletions(-) create mode 100644 Open-ILS/src/perlmods/OpenILS/Application/Storage/WORM.pm diff --git a/Open-ILS/src/perlmods/OpenILS/Application/Storage.pm b/Open-ILS/src/perlmods/OpenILS/Application/Storage.pm index 9446909a13..99adc9326d 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/Storage.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/Storage.pm @@ -12,6 +12,7 @@ use OpenILS::Application::Storage::FTS; # Suck in the method publishing modules use OpenILS::Application::Storage::Publisher; +use OpenILS::Application::Storage::WORM; # the easy way to get to the logger... my $log = "OpenSRF::Utils::Logger"; @@ -31,7 +32,11 @@ sub initialize { $log->debug("Attempting to load $driver ...", DEBUG); eval "use $driver;"; - throw OpenILS::EX::PANIC ( "Can't load $driver! : $@" ) if ($@); + if ($@) { + $log->debug( "Can't load $driver! : $@", ERROR ); + $log->error( "Can't load $driver! : $@"); + throw OpenILS::EX::PANIC ( "Can't load $driver! : $@" ); + } $log->debug("$driver loaded successfully", DEBUG); diff --git a/Open-ILS/src/perlmods/OpenILS/Application/Storage/CDBI.pm b/Open-ILS/src/perlmods/OpenILS/Application/Storage/CDBI.pm index 5757130c33..1ceda15331 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/Storage/CDBI.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/Storage/CDBI.pm @@ -314,10 +314,11 @@ sub import { biblio::record_entry->has_many( call_numbers => 'asset::call_number' ); # should we have just one field entry per class for each record???? (xslt vs xpath) - #biblio::record_entry->has_a( title_field_entries => 'metabib::title_field_entry' ); - #biblio::record_entry->has_a( author_field_entries => 'metabib::author_field_entry' ); - #biblio::record_entry->has_a( subject_field_entries => 'metabib::subject_field_entry' ); - #biblio::record_entry->has_a( keyword_field_entries => 'metabib::keyword_field_entry' ); + #biblio::record_entry->has_a( item_type => 'config::item_type_map' ); + biblio::record_entry->has_many( title_field_entries => 'metabib::title_field_entry' ); + biblio::record_entry->has_many( author_field_entries => 'metabib::author_field_entry' ); + biblio::record_entry->has_many( subject_field_entries => 'metabib::subject_field_entry' ); + biblio::record_entry->has_many( keyword_field_entries => 'metabib::keyword_field_entry' ); #------------------------------------------------------------------------------- biblio::record_node->has_a( owner_doc => 'biblio::record_entry' ); #biblio::record_node->has_a( @@ -330,18 +331,18 @@ sub import { metabib::full_rec->has_a( record => 'biblio::record_entry' ); #------------------------------------------------------------------------------- metabib::metarecord->has_a( master_record => 'biblio::record_entry' ); - metabib::metarecord->has_many( source_records => [ 'metabib::metarecord_source_map' => 'source_record'] ); + metabib::metarecord->has_many( source_records => [ 'metabib::metarecord_source_map' => 'source'] ); #------------------------------------------------------------------------------- - metabib::title_field_entry->has_many( source_records => [ 'metabib::title_field_entry_source_map' => 'source_record'] ); + metabib::title_field_entry->has_many( source_records => [ 'metabib::title_field_entry_source_map' => 'source'] ); metabib::title_field_entry->has_a( field => 'config::metabib_field' ); #------------------------------------------------------------------------------- - metabib::author_field_entry->has_many( source_records => [ 'metabib::author_field_entry_source_map' => 'source_record'] ); + metabib::author_field_entry->has_many( source_records => [ 'metabib::author_field_entry_source_map' => 'source'] ); metabib::author_field_entry->has_a( field => 'config::metabib_field' ); #------------------------------------------------------------------------------- - metabib::subject_field_entry->has_many( source_records => [ 'metabib::title_field_entry_source_map' => 'source_record'] ); + metabib::subject_field_entry->has_many( source_records => [ 'metabib::title_field_entry_source_map' => 'source'] ); metabib::subject_field_entry->has_a( field => 'config::metabib_field' ); #------------------------------------------------------------------------------- - metabib::keyword_field_entry->has_many( source_records => [ 'metabib::keyword_field_entry_source_map' => 'source_record'] ); + metabib::keyword_field_entry->has_many( source_records => [ 'metabib::keyword_field_entry_source_map' => 'source'] ); metabib::keyword_field_entry->has_a( field => 'config::metabib_field' ); #------------------------------------------------------------------------------- metabib::metarecord_source_map->has_a( metarecord => 'metabib::metarecord' ); @@ -350,21 +351,21 @@ sub import { # should we have just one field entry per class for each record???? (xslt vs xpath) - metabib::title_field_entry_source_map->has_a( field_entry => 'metabib::title_field_entry' ); - metabib::title_field_entry_source_map->has_a( source_record => 'biblio::record_entry' ); - metabib::title_field_entry_source_map->has_a( metarecord => 'metabib::metarecord' ); + #metabib::title_field_entry_source_map->has_a( field_entry => 'metabib::title_field_entry' ); + #metabib::title_field_entry_source_map->has_a( source_record => 'biblio::record_entry' ); + #metabib::title_field_entry_source_map->has_a( metarecord => 'metabib::metarecord' ); #------------------------------------------------------------------------------- - metabib::subject_field_entry_source_map->has_a( field_entry => 'metabib::subject_field_entry' ); - metabib::subject_field_entry_source_map->has_a( source_record => 'biblio::record_entry' ); - metabib::subject_field_entry_source_map->has_a( metarecord => 'metabib::metarecord' ); + #metabib::subject_field_entry_source_map->has_a( field_entry => 'metabib::subject_field_entry' ); + #metabib::subject_field_entry_source_map->has_a( source_record => 'biblio::record_entry' ); + #metabib::subject_field_entry_source_map->has_a( metarecord => 'metabib::metarecord' ); #------------------------------------------------------------------------------- - metabib::author_field_entry_source_map->has_a( field_entry => 'metabib::author_field_entry' ); - metabib::author_field_entry_source_map->has_a( source_record => 'biblio::record_entry' ); - metabib::author_field_entry_source_map->has_a( metarecord => 'metabib::metarecord' ); + #metabib::author_field_entry_source_map->has_a( field_entry => 'metabib::author_field_entry' ); + #metabib::author_field_entry_source_map->has_a( source_record => 'biblio::record_entry' ); + #metabib::author_field_entry_source_map->has_a( metarecord => 'metabib::metarecord' ); #------------------------------------------------------------------------------- - metabib::keyword_field_entry_source_map->has_a( field_entry => 'metabib::keyword_field_entry' ); - metabib::keyword_field_entry_source_map->has_a( source_record => 'biblio::record_entry' ); - metabib::keyword_field_entry_source_map->has_a( metarecord => 'metabib::metarecord' ); + #metabib::keyword_field_entry_source_map->has_a( field_entry => 'metabib::keyword_field_entry' ); + #metabib::keyword_field_entry_source_map->has_a( source_record => 'biblio::record_entry' ); + #metabib::keyword_field_entry_source_map->has_a( metarecord => 'metabib::metarecord' ); #------------------------------------------------------------------------------- $VERSION = 1; } diff --git a/Open-ILS/src/perlmods/OpenILS/Application/Storage/CDBI/biblio.pm b/Open-ILS/src/perlmods/OpenILS/Application/Storage/CDBI/biblio.pm index fe21111b7f..a73e573078 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/Storage/CDBI/biblio.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/Storage/CDBI/biblio.pm @@ -11,7 +11,7 @@ use base qw/biblio/; biblio::record_entry->table( 'biblio_record_entry' ); biblio::record_entry->columns( All => qw/id tcn_source tcn_value creator - editor create_date edit_date + editor create_date edit_date item_type source active deleted last_xact_id/ ); #------------------------------------------------------------------------------- diff --git a/Open-ILS/src/perlmods/OpenILS/Application/Storage/CDBI/metabib.pm b/Open-ILS/src/perlmods/OpenILS/Application/Storage/CDBI/metabib.pm index e6e186983d..22fe035167 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/Storage/CDBI/metabib.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/Storage/CDBI/metabib.pm @@ -18,7 +18,7 @@ use base qw/metabib/; metabib::title_field_entry->table( 'metabib_title_field_entry' ); metabib::title_field_entry->columns( Primary => qw/id/ ); -metabib::title_field_entry->columns( Others => qw/field value/ ); +metabib::title_field_entry->columns( Others => qw/field value source/ ); #------------------------------------------------------------------------------- @@ -27,7 +27,7 @@ use base qw/metabib/; metabib::author_field_entry->table( 'metabib_author_field_entry' ); metabib::author_field_entry->columns( Primary => qw/id/ ); -metabib::author_field_entry->columns( Others => qw/field value/ ); +metabib::author_field_entry->columns( Others => qw/field value source/ ); #------------------------------------------------------------------------------- @@ -36,7 +36,7 @@ use base qw/metabib/; metabib::subject_field_entry->table( 'metabib_subject_field_entry' ); metabib::subject_field_entry->columns( Primary => qw/id/ ); -metabib::subject_field_entry->columns( Others => qw/field value/ ); +metabib::subject_field_entry->columns( Others => qw/field value source/ ); #------------------------------------------------------------------------------- @@ -45,47 +45,47 @@ use base qw/metabib/; metabib::keyword_field_entry->table( 'metabib_keyword_field_entry' ); metabib::keyword_field_entry->columns( Primary => qw/id/ ); -metabib::keyword_field_entry->columns( Others => qw/field value/ ); +metabib::keyword_field_entry->columns( Others => qw/field value source/ ); #------------------------------------------------------------------------------- -package metabib::title_field_entry_source_map; -use base qw/metabib/; - -metabib::title_field_entry_source_map->table( 'metabib_title_field_entry_source_map' ); -metabib::title_field_entry_source_map->columns( Primary => qw/id/ ); -metabib::title_field_entry_source_map->columns( Others => qw/field_entry metarecord source_record/ ); - +#package metabib::title_field_entry_source_map; +#use base qw/metabib/; +# +#metabib::title_field_entry_source_map->table( 'metabib_title_field_entry_source_map' ); +#metabib::title_field_entry_source_map->columns( Primary => qw/id/ ); +#metabib::title_field_entry_source_map->columns( Others => qw/field_entry metarecord source_record/ ); +# #------------------------------------------------------------------------------- -package metabib::author_field_entry_source_map; -use base qw/metabib/; - -metabib::author_field_entry_source_map->table( 'metabib_author_field_entry_source_map' ); -metabib::author_field_entry_source_map->columns( Primary => qw/id/ ); -metabib::author_field_entry_source_map->columns( Others => qw/field_entry metarecord source_record/ ); - +#package metabib::author_field_entry_source_map; +#use base qw/metabib/; +# +#metabib::author_field_entry_source_map->table( 'metabib_author_field_entry_source_map' ); +#metabib::author_field_entry_source_map->columns( Primary => qw/id/ ); +#metabib::author_field_entry_source_map->columns( Others => qw/field_entry metarecord source_record/ ); +# #------------------------------------------------------------------------------- -package metabib::subject_field_entry_source_map; -use base qw/metabib/; - -metabib::subject_field_entry_source_map->table( 'metabib_subject_field_entry_source_map' ); -metabib::subject_field_entry_source_map->columns( Primary => qw/id/ ); -metabib::subject_field_entry_source_map->columns( Others => qw/field_entry metarecord source_record/ ); - +#package metabib::subject_field_entry_source_map; +#use base qw/metabib/; +# +#metabib::subject_field_entry_source_map->table( 'metabib_subject_field_entry_source_map' ); +#metabib::subject_field_entry_source_map->columns( Primary => qw/id/ ); +#metabib::subject_field_entry_source_map->columns( Others => qw/field_entry metarecord source_record/ ); +# #------------------------------------------------------------------------------- -package metabib::keyword_field_entry_source_map; -use base qw/metabib/; - -metabib::keyword_field_entry_source_map->table( 'metabib_keyword_field_entry_source_map' ); -metabib::keyword_field_entry_source_map->columns( Primary => qw/id/ ); -metabib::keyword_field_entry_source_map->columns( Others => qw/field_entry metarecord source_record/ ); - +#package metabib::keyword_field_entry_source_map; +#use base qw/metabib/; +# +#metabib::keyword_field_entry_source_map->table( 'metabib_keyword_field_entry_source_map' ); +#metabib::keyword_field_entry_source_map->columns( Primary => qw/id/ ); +#metabib::keyword_field_entry_source_map->columns( Others => qw/field_entry metarecord source_record/ ); +# #------------------------------------------------------------------------------- package metabib::metarecord_source_map; use base qw/metabib/; metabib::metarecord_source_map->table( 'metabib_metarecord_source_map' ); metabib::metarecord_source_map->columns( Primary => qw/id/ ); -metabib::metarecord_source_map->columns( Others => qw/metarecord source_record/ ); +metabib::metarecord_source_map->columns( Others => qw/metarecord source/ ); #------------------------------------------------------------------------------- package metabib::full_rec; diff --git a/Open-ILS/src/perlmods/OpenILS/Application/Storage/Driver/Pg.pm b/Open-ILS/src/perlmods/OpenILS/Application/Storage/Driver/Pg.pm index 4992278f74..dc143dcd02 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/Storage/Driver/Pg.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/Storage/Driver/Pg.pm @@ -90,6 +90,8 @@ my $log = 'OpenSRF::Utils::Logger'; __PACKAGE__->set_sql( retrieve_limited => 'SELECT * FROM __TABLE__ ORDER BY id LIMIT ?' ); + __PACKAGE__->set_sql( copy_start => 'COPY %s (%s) FROM STDIN;' ); + __PACKAGE__->set_sql( copy_end => '\.' ); my $master_db; my @slave_dbs; @@ -289,6 +291,7 @@ sub pg_commit_xaction { my $self = shift; + my $xact_id = $pg->current_xact_id; try { $log->debug("Committing trasaction with Open-ILS XACT-ID [$xact_id]", INFO); @@ -359,6 +362,39 @@ argc => 0, ); + sub copy_create { + my $self = shift; + my $client = shift; + my @fm_nodes = @_; + + warn 'Inside copy_create...'; + + return undef unless ($pg->current_xact_session); + + my $cdbi = $self->{cdbi}; + + my $pri = $cdbi->columns('Primary'); + + my @cols = grep {$_ ne $pri} $cdbi->columns('All'); + + my $col_list = join ',', @cols; + + $log->debug('Starting COPY import for '.$cdbi->table, DEBUG); + $cdbi->sql_copy_start($cdbi->table, $col_list)->execute; + + my $dbh = $cdbi->db_Main; + for my $node ( @fm_nodes ) { + next unless ($node); + my $line = join("\t", map { defined($node->$_()) ? $node->$_() : '\N' } @cols); + $log->debug("COPY line: [$line]",DEBUG); + $dbh->func($line."\n", 'putline'); + } + + $dbh->func('endcopy'); + + return scalar(@fm_nodes); + } + } { @@ -458,6 +494,14 @@ # before_update => \&OpenILS::Application::Storage::Driver::Pg::tsearch2_trigger # ); + OpenILS::Application::Storage->register_method( + api_name => 'open-ils.storage.metabib.title_field_entry.batch.create', + method => 'copy_create', + api_level => 1, + 'package' => 'OpenILS::Application::Storage', + cdbi => 'metabib::title_field_entry', + ); + #------------------------------------------------------------------------------- #------------------------------------------------------------------------------- @@ -467,6 +511,14 @@ metabib::author_field_entry->sequence( 'metabib.author_field_entry_id_seq' ); metabib::author_field_entry->columns( 'FTS' => 'index_vector' ); + OpenILS::Application::Storage->register_method( + api_name => 'open-ils.storage.metabib.author_field_entry.batch.create', + method => 'copy_create', + api_level => 1, + 'package' => 'OpenILS::Application::Storage', + cdbi => 'metabib::author_field_entry', + ); + #------------------------------------------------------------------------------- #------------------------------------------------------------------------------- @@ -476,6 +528,14 @@ metabib::subject_field_entry->sequence( 'metabib.subject_field_entry_id_seq' ); metabib::subject_field_entry->columns( 'FTS' => 'index_vector' ); + OpenILS::Application::Storage->register_method( + api_name => 'open-ils.storage.metabib.subject_field_entry.batch.create', + method => 'copy_create', + api_level => 1, + 'package' => 'OpenILS::Application::Storage', + cdbi => 'metabib::subject_field_entry', + ); + #------------------------------------------------------------------------------- #------------------------------------------------------------------------------- @@ -485,40 +545,48 @@ metabib::keyword_field_entry->sequence( 'metabib.keyword_field_entry_id_seq' ); metabib::keyword_field_entry->columns( 'FTS' => 'index_vector' ); + OpenILS::Application::Storage->register_method( + api_name => 'open-ils.storage.metabib.keyword_field_entry.batch.create', + method => 'copy_create', + api_level => 1, + 'package' => 'OpenILS::Application::Storage', + cdbi => 'metabib::keyword_field_entry', + ); + #------------------------------------------------------------------------------- #------------------------------------------------------------------------------- - package metabib::title_field_entry_source_map; + #package metabib::title_field_entry_source_map; - metabib::title_field_entry_source_map->table( 'metabib.title_field_entry_source_map' ); + #metabib::title_field_entry_source_map->table( 'metabib.title_field_entry_source_map' ); #------------------------------------------------------------------------------- #------------------------------------------------------------------------------- - package metabib::author_field_entry_source_map; + #package metabib::author_field_entry_source_map; - metabib::author_field_entry_source_map->table( 'metabib.author_field_entry_source_map' ); + #metabib::author_field_entry_source_map->table( 'metabib.author_field_entry_source_map' ); #------------------------------------------------------------------------------- #------------------------------------------------------------------------------- - package metabib::subject_field_entry_source_map; + #package metabib::subject_field_entry_source_map; - metabib::subject_field_entry_source_map->table( 'metabib.subject_field_entry_source_map' ); + #metabib::subject_field_entry_source_map->table( 'metabib.subject_field_entry_source_map' ); #------------------------------------------------------------------------------- #------------------------------------------------------------------------------- - package metabib::keyword_field_entry_source_map; + #package metabib::keyword_field_entry_source_map; - metabib::keyword_field_entry_source_map->table( 'metabib.keyword_field_entry_source_map' ); + #metabib::keyword_field_entry_source_map->table( 'metabib.keyword_field_entry_source_map' ); #------------------------------------------------------------------------------- #------------------------------------------------------------------------------- package metabib::metarecord_source_map; - metabib::metarecord_source_map->table( 'metabib.full_rec' ); + metabib::metarecord_source_map->table( 'metabib.metarecord_source_map' ); #------------------------------------------------------------------------------- @@ -529,6 +597,15 @@ metabib::full_rec->sequence( 'metabib.full_rec_id_seq' ); metabib::full_rec->columns( 'FTS' => 'index_vector' ); + OpenILS::Application::Storage->register_method( + api_name => 'open-ils.storage.metabib.full_rec.batch.create', + method => 'copy_create', + api_level => 1, + 'package' => 'OpenILS::Application::Storage', + cdbi => 'metabib::full_rec', + ); + + #------------------------------------------------------------------------------- } diff --git a/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher.pm b/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher.pm index af71611360..e04600fbbe 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher.pm @@ -1,6 +1,7 @@ package OpenILS::Application::Storage::Publisher; use base qw/OpenILS::Application::Storage/; our $VERSION = 1; +my $pg = 'OpenILS::Application::Storage::Driver::Pg'; use OpenSRF::EX qw/:try/;; use OpenSRF::Utils::Logger; @@ -102,6 +103,42 @@ sub update_node { return $cdbi->update($node); } +sub mass_delete { + my $self = shift; + my $client = shift; + my $search = shift; + + my $where = 'WHERE '; + + my $cdbi = $self->{cdbi}; + my $table = $cdbi->table; + + my @keys = sort keys %$search; + + my @wheres; + for my $col ( @keys ) { + push @wheres, "$col = ?"; + } + $where .= join ' AND ', @wheres; + + my $delete = "DELETE FROM $table $where"; + + $log->debug("Performing MASS deletion : $delete",DEBUG); + + my $dbh = $cdbi->db_Main; + my $success = 1; + try { + my $sth = $dbh->prepare($delete); + $sth->execute( map { "$_" } @$search{@keys} ); + $sth->finish; + $log->debug("MASS Delete succeeded",DEBUG); + } catch Error with { + $log->debug("MASS Delete FAILED : ".shift(),DEBUG); + $success = 0; + }; + return $success; +} + sub delete_node { my $self = shift; my $client = shift; @@ -261,6 +298,16 @@ for my $fmclass ( Fieldmapper->classes ) { ); } + # Create the search-based mass delete method + unless ( __PACKAGE__->is_registered( $api_prefix.'.mass_delete' ) ) { + __PACKAGE__->register_method( + api_name => $api_prefix.'.mass_delete', + method => 'mass_delete', + api_level => 1, + cdbi => $cdbi, + ); + } + } 1; diff --git a/Open-ILS/src/perlmods/OpenILS/Application/Storage/WORM.pm b/Open-ILS/src/perlmods/OpenILS/Application/Storage/WORM.pm new file mode 100644 index 0000000000..9d42d41246 --- /dev/null +++ b/Open-ILS/src/perlmods/OpenILS/Application/Storage/WORM.pm @@ -0,0 +1,362 @@ +package OpenILS::Application::Storage::WORM; +use base qw/OpenILS::Application::Storage/; +use strict; use warnings; + +use OpenSRF::EX qw/:try/; + +use OpenILS::Utils::FlatXML; +use OpenILS::Utils::Fieldmapper; +use JSON; + +use XML::LibXML; +use XML::LibXSLT; +use Time::HiRes qw(time); + +my $xml_util = OpenILS::Utils::FlatXML->new(); + +my $parser = XML::LibXML->new(); +my $xslt = XML::LibXSLT->new(); +my $xslt_doc = $parser->parse_file( "/home/miker/cvs/OpenILS/app_server/stylesheets/MARC21slim2MODS.xsl" ); +#my $xslt_doc = $parser->parse_file( "/pines/cvs/ILS/Open-ILS/xsl/MARC21slim2MODS.xsl" ); +my $mods_sheet = $xslt->parse_stylesheet( $xslt_doc ); + +use open qw/:utf8/; + + +sub child_init { + #try { + # __PACKAGE__->method_lookup('i.do.not.exist'); + #} catch Error with { + # warn shift(); + #}; +} + + +# get me from the database +my $xpathset = { + + title => { + + abbreviated => + "//mods:mods/mods:titleInfo[mods:title and (\@type='abreviated')]", + + translated => + "//mods:mods/mods:titleInfo[mods:title and (\@type='translated')]", + + uniform => + "//mods:mods/mods:titleInfo[mods:title and (\@type='uniform')]", + + proper => + "//mods:mods/mods:titleInfo[mods:title and not (\@type)]", + }, + + author => { + + corporate => + "//mods:mods/mods:name[\@type='corporate']/mods:namePart". + "[../mods:role/mods:text[text()='creator']][1]", + + personal => + "//mods:mods/mods:name[\@type='personal']/mods:namePart". + "[../mods:role/mods:text[text()='creator']][1]", + + conference => + "//mods:mods/mods:name[\@type='conference']/mods:namePart". + "[../mods:role/mods:text[text()='creator']][1]", + + other => + "//mods:mods/mods:name[\@type='personal']/mods:namePart", + }, + + subject => { + + geographic => + "//mods:mods/mods:subject/mods:geographic", + + name => + "//mods:mods/mods:subject/mods:name", + + temporal => + "//mods:mods/mods:subject/mods:temporal", + + topic => + "//mods:mods/mods:subject/mods:topic", + + genre => + "//mods:mods/mods:genre", + + }, + + keyword => { keyword => "//mods:mods/*[not(local-name()='originInfo')]", }, + +}; + + +# -------------------------------------------------------------------------------- + +__PACKAGE__->register_method( + api_name => "open-ils.worm.wormize", + method => "wormize", + api_level => 1, + argc => 1, +); + +sub wormize { + + my( $self, $client, $docid ) = @_; + + # step -1: grab the doc from storage + my $meth = $self->method_lookup('open-ils.storage.biblio.record_marc.retrieve'); + my ($marc) = $meth->run($docid); + return undef unless ($marc); + return $self->wormize_marc( $client, $docid, $marc->marc ); +} + + +__PACKAGE__->register_method( + api_name => "open-ils.worm.wormize.marc", + method => "wormize", + api_level => 1, + argc => 1, +); + +my $rm_old_fr; +my $rm_old_tr; +my $rm_old_ar; +my $rm_old_sr; +my $rm_old_kr; + +my $fr_create; +my $create = {}; + +my $begin; +my $commit; +my $rollback; + +sub wormize_marc { + my( $self, $client, $docid, $xml) = @_; + + $rm_old_fr = $self->method_lookup( 'open-ils.storage.metabib.full_rec.mass_delete') + unless ($rm_old_fr); + + $rm_old_tr = $self->method_lookup( 'open-ils.storage.metabib.title_field_entry.mass_delete') + unless ($rm_old_tr); + + $rm_old_ar = $self->method_lookup( 'open-ils.storage.metabib.author_field_entry.mass_delete') + unless ($rm_old_ar); + + $rm_old_sr = $self->method_lookup( 'open-ils.storage.metabib.subject_field_entry.mass_delete') + unless ($rm_old_sr); + + $rm_old_kr = $self->method_lookup( 'open-ils.storage.metabib.keyword_field_entry.mass_delete') + unless ($rm_old_kr); + + $fr_create = $self->method_lookup( 'open-ils.storage.metabib.full_rec.batch.create') + unless ($fr_create); + $$create{title} = $self->method_lookup( 'open-ils.storage.metabib.title_field_entry.batch.create') + unless ($$create{title}); + $$create{author} = $self->method_lookup( 'open-ils.storage.metabib.author_field_entry.batch.create') + unless ($$create{author}); + $$create{subject} = $self->method_lookup( 'open-ils.storage.metabib.subject_field_entry.batch.create') + unless ($$create{subject}); + $$create{keyword} = $self->method_lookup( 'open-ils.storage.metabib.keyword_field_entry.batch.create') + unless ($$create{keyword}); + + $begin = $self->method_lookup( 'open-ils.storage.transaction.begin') + unless ($begin); + $commit = $self->method_lookup( 'open-ils.storage.transaction.commit') + unless ($commit); + $rollback = $self->method_lookup( 'open-ils.storage.transaction.rollback') + unless ($rollback); + + + my ($br) = $begin->run($client); + unless (defined $br) { + $rollback->run; + throw OpenSRF::EX::PANIC ("Couldn't BEGIN transaction!") + } + + # step 0: turn the doc into marcxml and delete old entries + my $marcdoc = $parser->parse_string($xml); + + my ($res) = $rm_old_fr->run( { record => $docid } ); + throw OpenSRF::EX::PANIC ("Couldn't remove old metabib::full_rec entries!") + unless (defined $res); + + undef $res; + ($res) = $rm_old_tr->run( { source => $docid } ); + throw OpenSRF::EX::PANIC ("Couldn't remove old metabib::title_field_entry entries!") + unless (defined $res); + + undef $res; + ($res) = $rm_old_ar->run( { source => $docid } ); + throw OpenSRF::EX::PANIC ("Couldn't remove old metabib::author_field_entry entries!") + unless (defined $res); + + undef $res; + ($res) = $rm_old_sr->run( { source => $docid } ); + throw OpenSRF::EX::PANIC ("Couldn't remove old metabib::subject_field_entry entries!") + unless (defined $res); + + undef $res; + ($res) = $rm_old_kr->run( { source => $docid } ); + throw OpenSRF::EX::PANIC ("Couldn't remove old metabib::keyword_field_entry entries!") + unless (defined $res); + + # step 2: build the KOHA rows + my @ns_list = _marcxml_to_full_rows( $marcdoc ); + $_->record( $docid ) for (@ns_list); + + + my ($fr) = $fr_create->run(@ns_list); + unless (defined $fr) { + $rollback->run; + throw OpenSRF::EX::PANIC ("Couldn't run open-ils.storage.metabib.full_rec.batch.create!") + } + + # step 4: get the MODS based metadata + my $data = $self->modsdoc_to_values( $mods_sheet->transform($marcdoc) ); + + # step 5: insert the new metadata + for my $class ( keys %$data ) { + + my $fm_constructor = "Fieldmapper::metabib::${class}_field_entry"; + my @md_list = (); + for my $row ( keys %{ $$data{$class} } ) { + next unless (exists $$data{$class}{$row}); + next unless ($$data{$class}{$row}); + my $fm_obj = $fm_constructor->new; + $fm_obj->value( $$data{$class}{$row} ); + $fm_obj->source( $docid ); + + # XXX This needs to be a real thing once the xpath is in the DB + $fm_obj->field( 1 ); + + push @md_list, $fm_obj; + } + + my ($cr) = $$create{$class}->run(@md_list); + unless (defined $cr) { + $rollback->run; + throw OpenSRF::EX::PANIC ("Couldn't run open-ils.storage.metabib.${class}_field_entry.batch.create!") + } + } + + my ($c) = $commit->run; + unless (defined $c) { + $rollback->run; + throw OpenSRF::EX::PANIC ("Couldn't COMMIT changes!") + } + + return 1; + +} + + + +# -------------------------------------------------------------------------------- + + +sub _marcxml_to_full_rows { + + my $marcxml = shift; + + my @ns_list; + + my $root = $marcxml->documentElement; + + for my $tagline ( @{$root->getChildrenByTagName("leader")} ) { + next unless $tagline; + + my $ns = new Fieldmapper::metabib::full_rec; + + $ns->tag( 'LDR' ); + my $val = $tagline->textContent; + $val =~ s/(\pM)//gso; + $ns->value( $val ); + + push @ns_list, $ns; + } + + for my $tagline ( @{$root->getChildrenByTagName("controlfield")} ) { + next unless $tagline; + + my $ns = new Fieldmapper::metabib::full_rec; + + $ns->tag( $tagline->getAttribute( "tag" ) ); + my $val = $tagline->textContent; + $val =~ s/(\pM)//gso; + $ns->value( $val ); + + push @ns_list, $ns; + } + + for my $tagline ( @{$root->getChildrenByTagName("datafield")} ) { + next unless $tagline; + + for my $data ( @{$tagline->getChildrenByTagName("subfield")} ) { + next unless $tagline; + + my $ns = new Fieldmapper::metabib::full_rec; + + $ns->tag( $tagline->getAttribute( "tag" ) ); + $ns->ind1( $tagline->getAttribute( "ind1" ) ); + $ns->ind2( $tagline->getAttribute( "ind2" ) ); + $ns->subfield( $data->getAttribute( "code" ) ); + my $val = $data->textContent; + $val =~ s/(\pM)//gso; + $ns->value( lc($val) ); + + push @ns_list, $ns; + } + } + return @ns_list; +} + +sub _get_field_value { + + my( $mods, $xpath ) = @_; + + my $string = ""; + my $root = $mods->documentElement; + $root->setNamespace( "http://www.loc.gov/mods/", "mods", 1 ); + + # grab the set of matching nodes + my @nodes = $root->findnodes( $xpath ); + for my $value (@nodes) { + + # grab all children of the node + my @children = $value->childNodes(); + for my $child (@children) { + + # add the childs content to the growing buffer + my $content = quotemeta($child->textContent); + next if ($string =~ /$content/); # uniquify the values + $string .= $child->textContent . " "; + } + if( ! @children ) { + $string .= $value->textContent . " "; + } + } + $string =~ s/(\pM)//gso; + return lc($string); +} + + +sub modsdoc_to_values { + my( $self, $mods ) = @_; + my $data = {}; + for my $class (keys %$xpathset) { + $data->{$class} = {}; + for my $type(keys %{$xpathset->{$class}}) { + my $value = _get_field_value( $mods, $xpathset->{$class}->{$type} ); + $data->{$class}->{$type} = $value; + } + } + return $data; +} + + +1; + + -- 2.43.2