1 package OpenILS::Application::WoRM;
2 use base qw/OpenSRF::Application/;
5 use Unicode::Normalize;
6 use OpenSRF::EX qw/:try/;
8 use OpenSRF::Utils::SettingsClient;
9 use OpenSRF::Utils::Logger qw/:level/;
11 use OpenILS::Utils::FlatXML;
12 use OpenILS::Utils::Fieldmapper;
15 use OpenILS::Utils::Fieldmapper;
19 use Time::HiRes qw(time);
22 our $log = 'OpenSRF::Utils::Logger';
23 our $xml_util = OpenILS::Utils::FlatXML->new();
25 our $parser = XML::LibXML->new();
26 our $xslt = XML::LibXSLT->new();
34 $st_sess = $sess if ($sess);
44 $log->debug("Running post_init", DEBUG);
46 unless ($mods_sheet) {
47 $log->debug("Loading MODS XSLT", DEBUG);
48 my $xslt_doc = $parser->parse_file(
49 OpenSRF::Utils::SettingsClient->new->config_value(dirs => 'xsl') . "/MARC21slim2MODS.xsl");
50 $mods_sheet = $xslt->parse_stylesheet( $xslt_doc );
53 #if (!__PACKAGE__->st_sess()) {
54 # $log->debug("Creating cached storage server session", DEBUG);
55 # __PACKAGE__->st_sess( OpenSRF::AppSession->create('open-ils.storage') );
58 unless (keys %$xpathset) {
59 my $req = __PACKAGE__->storage_req('open-ils.storage.direct.config.metabib_field.retrieve.all.atomic');
61 $xpathset->{ $f->field_class }->{ $f->name }->{xpath} = $f->xpath;
62 $xpathset->{ $f->field_class }->{ $f->name }->{id} = $f->id;
63 $log->debug("Loaded XPath from DB: ".$f->field_class." => ".$f->name." : ".$f->xpath, DEBUG);
69 my $stuff = NFC(shift());
70 $stuff =~ s/([\x{0080}-\x{fffd}])/sprintf('&#x%X;',ord($1))/sgoe;
76 OpenILS::Application::WoRM->post_init();
77 return __PACKAGE__->storage_req( 'open-ils.storage.transaction.current' );
80 sub begin_transaction {
84 OpenILS::Application::WoRM->post_init();
85 my $outer_xact = __PACKAGE__->storage_req( 'open-ils.storage.transaction.current' );
89 $log->debug("WoRM isn't inside a transaction, starting one now.", INFO);
90 #__PACKAGE__->st_sess->connect;
91 my $r = __PACKAGE__->storage_req( 'open-ils.storage.transaction.begin', $client );
92 unless (defined $r and $r) {
93 __PACKAGE__->storage_req( 'open-ils.storage.transaction.rollback' );
94 #__PACKAGE__->st_sess->disconnect;
95 throw OpenSRF::EX::PANIC ("Couldn't BEGIN transaction!")
99 $log->debug("WoRM Couldn't BEGIN transaction!", ERROR)
102 return __PACKAGE__->storage_req( 'open-ils.storage.transaction.current' );
105 sub rollback_transaction {
109 OpenILS::Application::WoRM->post_init();
110 my $outer_xact = __PACKAGE__->storage_req( 'open-ils.storage.transaction.current' );
114 __PACKAGE__->storage_req( 'open-ils.storage.transaction.rollback' );
116 $log->debug("WoRM isn't inside a transaction.", INFO);
119 throw OpenSRF::EX::PANIC ("WoRM Couldn't COMMIT transaction!")
125 sub commit_transaction {
129 OpenILS::Application::WoRM->post_init();
130 my $outer_xact = __PACKAGE__->storage_req( 'open-ils.storage.transaction.current' );
133 #if (__PACKAGE__->st_sess->connected && $outer_xact) {
135 my $r = __PACKAGE__->storage_req( 'open-ils.storage.transaction.commit' );
136 unless (defined $r and $r) {
137 __PACKAGE__->storage_req( 'open-ils.storage.transaction.rollback' );
138 throw OpenSRF::EX::PANIC ("Couldn't COMMIT transaction!")
140 #__PACKAGE__->st_sess->disconnect;
142 $log->debug("WoRM isn't inside a transaction.", INFO);
145 throw OpenSRF::EX::PANIC ("WoRM Couldn't COMMIT transaction!")
154 my @res = __PACKAGE__->method_lookup( $method )->run( @_ );
155 return shift( @res );
158 sub scrub_authority_record {
164 if (!OpenILS::Application::WoRM->in_transaction) {
165 OpenILS::Application::WoRM->begin_transaction($client) || throw OpenSRF::EX::PANIC ("Couldn't BEGIN transaction!");
171 OpenILS::Application::WoRM->storage_req( 'open-ils.storage.savepoint.set', 'scrub_authority_record' );
173 OpenILS::Application::WoRM->storage_req( 'open-ils.storage.direct.authority.full_rec.mass_delete', { record => $rec } );
174 OpenILS::Application::WoRM->storage_req( 'open-ils.storage.direct.authority.record_descriptor.mass_delete', { record => $rec } );
176 OpenILS::Application::WoRM->storage_req( 'open-ils.storage.savepoint.release', 'scrub_authority_record' );
178 $log->debug('Scrubbing failed : '.shift(), ERROR);
179 OpenILS::Application::WoRM->storage_req( 'open-ils.storage.savepoint.rollback', 'scrub_authority_record' );
183 OpenILS::Application::WoRM->commit_transaction if ($commit && $success);
184 OpenILS::Application::WoRM->rollback_transaction if ($commit && !$success);
187 __PACKAGE__->register_method(
188 api_name => "open-ils.worm.scrub.authority",
189 method => "scrub_authority_record",
195 sub scrub_metabib_record {
201 if (!OpenILS::Application::WoRM->in_transaction) {
202 OpenILS::Application::WoRM->begin_transaction($client) || throw OpenSRF::EX::PANIC ("Couldn't BEGIN transaction!");
208 OpenILS::Application::WoRM->storage_req( 'open-ils.storage.savepoint.set', 'scrub_metabib_record' );
210 OpenILS::Application::WoRM->storage_req( 'open-ils.storage.direct.metabib.full_rec.mass_delete', { record => $rec } );
211 OpenILS::Application::WoRM->storage_req( 'open-ils.storage.direct.metabib.metarecord_source_map.mass_delete', { source => $rec } );
212 OpenILS::Application::WoRM->storage_req( 'open-ils.storage.direct.metabib.record_descriptor.mass_delete', { record => $rec } );
213 OpenILS::Application::WoRM->storage_req( 'open-ils.storage.direct.metabib.title_field_entry.mass_delete', { source => $rec } );
214 OpenILS::Application::WoRM->storage_req( 'open-ils.storage.direct.metabib.author_field_entry.mass_delete', { source => $rec } );
215 OpenILS::Application::WoRM->storage_req( 'open-ils.storage.direct.metabib.subject_field_entry.mass_delete', { source => $rec } );
216 OpenILS::Application::WoRM->storage_req( 'open-ils.storage.direct.metabib.keyword_field_entry.mass_delete', { source => $rec } );
217 OpenILS::Application::WoRM->storage_req( 'open-ils.storage.direct.metabib.series_field_entry.mass_delete', { source => $rec } );
219 $log->debug( "Looking for metarecords whose master is $rec", DEBUG);
220 my $masters = OpenILS::Application::WoRM->storage_req( 'open-ils.storage.direct.metabib.metarecord.search.master_record.atomic', $rec );
222 for my $mr (@$masters) {
223 $log->debug( "Found metarecord whose master is $rec", DEBUG);
224 my $others = OpenILS::Application::WoRM->storage_req(
225 'open-ils.storage.direct.metabib.metarecord_source_map.search.metarecord.atomic', $mr->id );
228 $log->debug("Metarecord ".$mr->id." had master of $rec, setting to ".$others->[0]->source, DEBUG);
229 $mr->master_record($others->[0]->source);
230 OpenILS::Application::WoRM->storage_req(
231 'open-ils.storage.direct.metabib.metarecord.remote_update',
233 { master_record => $others->[0]->source, mods => undef }
236 warn "Removing metarecord whose master is $rec";
237 $log->debug( "Removing metarecord whose master is $rec", DEBUG);
238 OpenILS::Application::WoRM->storage_req( 'open-ils.storage.direct.metabib.metarecord.delete', $mr->id );
239 warn "Metarecord removed";
240 $log->debug( "Metarecord removed", DEBUG);
244 OpenILS::Application::WoRM->storage_req( 'open-ils.storage.savepoint.release', 'scrub_metabib_record' );
247 $log->debug('Scrubbing failed : '.shift(), ERROR);
248 OpenILS::Application::WoRM->storage_req( 'open-ils.storage.savepoint.rollback', 'scrub_metabib_record' );
252 OpenILS::Application::WoRM->commit_transaction if ($commit && $success);
253 OpenILS::Application::WoRM->rollback_transaction if ($commit && !$success);
256 __PACKAGE__->register_method(
257 api_name => "open-ils.worm.scrub.biblio",
258 method => "scrub_metabib_record",
263 sub wormize_biblio_record {
269 if (!OpenILS::Application::WoRM->in_transaction) {
270 OpenILS::Application::WoRM->begin_transaction($client) || throw OpenSRF::EX::PANIC ("Couldn't BEGIN transaction!");
277 unless ($self->api_name =~ /noscrub/o) {
278 $self->method_lookup( 'open-ils.worm.scrub.biblio' )->run( $rec ) || throw OpenSRF::EX::PANIC ("Couldn't scrub record $rec!");
282 my $bibs = OpenILS::Application::WoRM->storage_req( 'open-ils.storage.direct.biblio.record_entry.search.id.atomic', $rec );
285 my @rec_descriptor = ();
296 my $xml = $parser->parse_string($r->marc);
299 for my $fr ( $self->method_lookup( 'open-ils.worm.flat_marc.biblio.xml' )->run( $xml ) ) {
300 $fr->record( $r->id );
304 # the rec_descriptor stuff
305 my ($rd) = $self->method_lookup( 'open-ils.worm.biblio_leader.xml' )->run( $xml );
306 $rd->record( $r->id );
307 push @rec_descriptor, $rd;
309 # the indexing field entry stuff
310 for my $class ( qw/title author subject keyword series/ ) {
311 for my $fe ( $self->method_lookup( 'open-ils.worm.field_entry.class.xml' )->run( $xml, $class ) ) {
312 $fe->source( $r->id );
313 push @{$field_entry{$class}}, $fe;
317 #update the fingerprint
318 my ($fp) = $self->method_lookup( 'open-ils.worm.fingerprint.marc' )->run( $xml );
319 OpenILS::Application::WoRM->storage_req(
320 'open-ils.storage.direct.biblio.record_entry.remote_update',
322 { fingerprint => $fp }
323 ) if ($fp ne $r->fingerprint);
325 unless ($self->api_name =~ /nomap/o) {
326 my $mr = OpenILS::Application::WoRM->storage_req( 'open-ils.storage.direct.metabib.metarecord.search.fingerprint.atomic', $fp )->[0];
329 $mr = Fieldmapper::metabib::metarecord->new;
330 $mr->fingerprint( $fp );
331 $mr->master_record( $r->id );
332 $mr->id( OpenILS::Application::WoRM->storage_req( 'open-ils.storage.direct.metabib.metarecord.create', $mr) );
335 my $mr_map = Fieldmapper::metabib::metarecord_source_map->new;
336 $mr_map->metarecord( $mr->id );
337 $mr_map->source( $r->id );
338 push @source_map, $mr_map;
343 OpenILS::Application::WoRM->storage_req( 'open-ils.storage.savepoint.set', 'wormize_record' );
345 OpenILS::Application::WoRM->storage_req( 'open-ils.storage.direct.metabib.metarecord_source_map.batch.create', @source_map ) if (@source_map);
346 OpenILS::Application::WoRM->storage_req( 'open-ils.storage.direct.metabib.record_descriptor.batch.create', @rec_descriptor ) if (@rec_descriptor);
347 OpenILS::Application::WoRM->storage_req( 'open-ils.storage.direct.metabib.full_rec.batch.create', @full_rec ) if (@full_rec);
348 OpenILS::Application::WoRM->storage_req( 'open-ils.storage.direct.metabib.title_field_entry.batch.create', @{ $field_entry{title} } ) if (@{ $field_entry{title} });
349 OpenILS::Application::WoRM->storage_req( 'open-ils.storage.direct.metabib.author_field_entry.batch.create', @{ $field_entry{author} } ) if (@{ $field_entry{author} });
350 OpenILS::Application::WoRM->storage_req( 'open-ils.storage.direct.metabib.subject_field_entry.batch.create', @{ $field_entry{subject} } ) if (@{ $field_entry{subject} });
351 OpenILS::Application::WoRM->storage_req( 'open-ils.storage.direct.metabib.keyword_field_entry.batch.create', @{ $field_entry{keyword} } ) if (@{ $field_entry{keyword} });
352 OpenILS::Application::WoRM->storage_req( 'open-ils.storage.direct.metabib.series_field_entry.batch.create', @{ $field_entry{series} } ) if (@{ $field_entry{series} });
354 OpenILS::Application::WoRM->storage_req( 'open-ils.storage.savepoint.release', 'wormize_record' );
357 $log->debug('Wormization failed : '.shift(), ERROR);
358 OpenILS::Application::WoRM->storage_req( 'open-ils.storage.savepoint.rollback', 'wormize_record' );
362 OpenILS::Application::WoRM->commit_transaction if ($commit && $success);
363 OpenILS::Application::WoRM->rollback_transaction if ($commit && !$success);
366 __PACKAGE__->register_method(
367 api_name => "open-ils.worm.wormize.biblio",
368 method => "wormize_biblio_record",
372 __PACKAGE__->register_method(
373 api_name => "open-ils.worm.wormize.biblio.nomap",
374 method => "wormize_biblio_record",
378 __PACKAGE__->register_method(
379 api_name => "open-ils.worm.wormize.biblio.noscrub",
380 method => "wormize_biblio_record",
384 __PACKAGE__->register_method(
385 api_name => "open-ils.worm.wormize.biblio.nomap.noscrub",
386 method => "wormize_biblio_record",
391 sub wormize_authority_record {
397 if (!OpenILS::Application::WoRM->in_transaction) {
398 OpenILS::Application::WoRM->begin_transaction($client) || throw OpenSRF::EX::PANIC ("Couldn't BEGIN transaction!");
405 unless ($self->api_name =~ /noscrub/o) {
406 $self->method_lookup( 'open-ils.worm.scrub.authority' )->run( $rec ) || throw OpenSRF::EX::PANIC ("Couldn't scrub record $rec!");
410 my $bibs = OpenILS::Application::WoRM->storage_req( 'open-ils.storage.direct.authority.record_entry.search.id.atomic', $rec );
413 my @rec_descriptor = ();
415 my $xml = $parser->parse_string($r->marc);
418 for my $fr ( $self->method_lookup( 'open-ils.worm.flat_marc.authority.xml' )->run( $xml ) ) {
419 $fr->record( $r->id );
423 # the rec_descriptor stuff -- XXX What does this mean for authority records?
424 #my ($rd) = $self->method_lookup( 'open-ils.worm.authority_leader.xml' )->run( $xml );
425 #$rd->record( $r->id );
426 #push @rec_descriptor, $rd;
430 OpenILS::Application::WoRM->storage_req( 'open-ils.storage.savepoint.set', 'wormize_authority_record' );
432 #OpenILS::Application::WoRM->storage_req( 'open-ils.storage.direct.authority.record_descriptor.batch.create', @rec_descriptor ) if (@rec_descriptor);
433 OpenILS::Application::WoRM->storage_req( 'open-ils.storage.direct.authority.full_rec.batch.create', @full_rec ) if (@full_rec);
435 OpenILS::Application::WoRM->storage_req( 'open-ils.storage.savepoint.release', 'wormize_authority_record' );
438 $log->debug('Wormization failed : '.shift(), ERROR);
439 OpenILS::Application::WoRM->storage_req( 'open-ils.storage.savepoint.rollback', 'wormize_authority_record' );
443 OpenILS::Application::WoRM->commit_transaction if ($commit && $success);
444 OpenILS::Application::WoRM->rollback_transaction if ($commit && !$success);
447 __PACKAGE__->register_method(
448 api_name => "open-ils.worm.wormize.authority",
449 method => "wormize_authority_record",
453 __PACKAGE__->register_method(
454 api_name => "open-ils.worm.wormize.authority.noscrub",
455 method => "wormize_authority_record",
461 # --------------------------------------------------------------------------------
462 # MARC index extraction
464 package OpenILS::Application::WoRM::XPATH;
465 use base qw/OpenILS::Application::WoRM/;
466 use Unicode::Normalize;
468 # give this a MODS documentElement and an XPATH expression
469 sub _xpath_to_string {
473 my $ns_prefix = shift;
476 $xml->setNamespace( $ns_uri, $ns_prefix, 1 ) if ($ns_uri && $ns_prefix);
480 # grab the set of matching nodes
481 my @nodes = $xml->findnodes( $xpath );
482 for my $value (@nodes) {
484 # grab all children of the node
485 my @children = $value->childNodes();
486 for my $child (@children) {
488 # add the childs content to the growing buffer
489 my $content = quotemeta($child->textContent);
490 next if ($unique && $string =~ /$content/); # uniquify the values
491 $string .= $child->textContent . " ";
494 $string .= $value->textContent . " ";
500 sub class_all_index_string_xml {
506 OpenILS::Application::WoRM->post_init();
507 $xml = $parser->parse_string($xml) unless (ref $xml);
509 my $class_constructor = "Fieldmapper::metabib::${class}_field_entry";
510 for my $type ( keys %{ $xpathset->{$class} } ) {
511 my $value = _xpath_to_string(
512 $mods_sheet->transform($xml)->documentElement,
513 $xpathset->{$class}->{$type}->{xpath},
514 "http://www.loc.gov/mods/",
521 $value =~ s/(\pM|\pC)//sgoe;
522 $value =~ s/[\x80-\xff]//sgoe;
525 my $fm = $class_constructor->new;
526 $fm->value( $value );
527 $fm->field( $xpathset->{$class}->{$type}->{id} );
528 $client->respond($fm);
532 __PACKAGE__->register_method(
533 api_name => "open-ils.worm.field_entry.class.xml",
534 method => "class_all_index_string_xml",
540 sub class_all_index_string_record {
546 OpenILS::Application::WoRM->post_init();
547 my $r = OpenILS::Application::WoRM->storage_req( "open-ils.storage.direct.biblio.record_entry.retrieve" => $rec );
549 for my $fm ($self->method_lookup("open-ils.worm.field_entry.class.xml")->run($r->marc, $class)) {
551 $client->respond($fm);
555 __PACKAGE__->register_method(
556 api_name => "open-ils.worm.field_entry.class.record",
557 method => "class_all_index_string_record",
564 sub class_index_string_xml {
571 OpenILS::Application::WoRM->post_init();
572 $xml = $parser->parse_string($xml) unless (ref $xml);
573 return _xpath_to_string( $mods_sheet->transform($xml)->documentElement, $xpathset->{$class}->{$type}->{xpath}, "http://www.loc.gov/mods/", "mods", 1 );
575 __PACKAGE__->register_method(
576 api_name => "open-ils.worm.class.type.xml",
577 method => "class_index_string_xml",
582 sub class_index_string_record {
589 OpenILS::Application::WoRM->post_init();
590 my $r = OpenILS::Application::WoRM->storage_req( "open-ils.storage.direct.biblio.record_entry.retrieve" => $rec );
592 my ($d) = $self->method_lookup("open-ils.worm.class.type.xml")->run($r->marc, $class => $type);
593 $log->debug("XPath $class->$type for bib rec $rec returns ($d)", DEBUG);
596 __PACKAGE__->register_method(
597 api_name => "open-ils.worm.class.type.record",
598 method => "class_index_string_record",
612 OpenILS::Application::WoRM->post_init();
613 $xml = $parser->parse_string($xml) unless (ref $xml);
614 return _xpath_to_string( $xml->documentElement, $xpath, $uri, $prefix, $unique );
616 __PACKAGE__->register_method(
617 api_name => "open-ils.worm.xpath.xml",
618 method => "xml_xpath",
632 OpenILS::Application::WoRM->post_init();
633 my $r = OpenILS::Application::WoRM->storage_req( "open-ils.storage.direct.biblio.record_entry.retrieve" => $rec );
635 my ($d) = $self->method_lookup("open-ils.worm.xpath.xml")->run($r->marc, $xpath, $uri, $prefix, $unique );
636 $log->debug("XPath [$xpath] bib rec $rec returns ($d)", DEBUG);
639 __PACKAGE__->register_method(
640 api_name => "open-ils.worm.xpath.record",
641 method => "record_xpath",
647 # --------------------------------------------------------------------------------
650 package OpenILS::Application::WoRM::Biblio::Leader;
651 use base qw/OpenILS::Application::WoRM/;
652 use Unicode::Normalize;
654 our %marc_type_groups = (
666 my $re = '^'. join('|', $marc_type_groups{@_}) .'$';
670 our %biblio_descriptor_code = (
671 item_type => sub { substr($ldr,6,1); },
674 if (substr($ldr,6,1) =~ _type_re( qw/MAP VIS/ )) {
675 return substr($oo8,29,1);
676 } elsif (substr($ldr,6,1) =~ _type_re( qw/BKS SER MIX SCO REC/ )) {
677 return substr($oo8,23,1);
681 bib_level => sub { substr($ldr,7,1); },
682 control_type => sub { substr($ldr,8,1); },
683 char_encoding => sub { substr($ldr,9,1); },
684 enc_level => sub { substr($ldr,17,1); },
685 cat_form => sub { substr($ldr,18,1); },
686 pub_status => sub { substr($ldr,5,1); },
687 item_lang => sub { substr($oo8,35,3); },
688 lit_form => sub { (substr($ldr,6,1) =~ _type_re('BKS')) ? substr($oo8,33,1) : ' '; },
689 type_mat => sub { (substr($ldr,6,1) =~ _type_re('VIS')) ? substr($oo8,33,1) : ' '; },
690 audience => sub { substr($oo8,22,1); },
693 sub _extract_biblio_descriptors {
696 local $ldr = $xml->findvalue('//*[local-name()="leader"]');
697 local $oo8 = $xml->findvalue('//*[local-name()="controlfield" and @tag="008"]');
699 my $rd_obj = Fieldmapper::metabib::record_descriptor->new;
700 for my $rd_field ( keys %biblio_descriptor_code ) {
701 $rd_obj->$rd_field( $biblio_descriptor_code{$rd_field}->() );
707 sub extract_biblio_desc_xml {
712 $xml = $parser->parse_string($xml) unless (ref $xml);
714 return _extract_biblio_descriptors( $xml );
716 __PACKAGE__->register_method(
717 api_name => "open-ils.worm.biblio_leader.xml",
718 method => "extract_biblio_desc_xml",
723 sub extract_biblio_desc_record {
728 OpenILS::Application::WoRM->post_init();
729 my $r = OpenILS::Application::WoRM->storage_req( "open-ils.storage.direct.biblio.record_entry.retrieve" => $rec );
731 my ($d) = $self->method_lookup("open-ils.worm.biblio_leader.xml")->run($r->marc);
732 $log->debug("Record descriptor for bib rec $rec is ".JSON->perl2JSON($d), DEBUG);
735 __PACKAGE__->register_method(
736 api_name => "open-ils.worm.biblio_leader.record",
737 method => "extract_biblio_desc_record",
742 # --------------------------------------------------------------------------------
745 package OpenILS::Application::WoRM::FlatMARC;
746 use base qw/OpenILS::Application::WoRM/;
747 use Unicode::Normalize;
750 sub _marcxml_to_full_rows {
753 my $xmltype = shift || 'metabib';
755 my $type = "Fieldmapper::${xmltype}::full_rec";
759 my ($root) = $marcxml->findnodes('//*[local-name()="record"]');
761 for my $tagline ( @{$root->getChildrenByTagName("leader")} ) {
762 next unless $tagline;
767 my $val = $tagline->textContent;
769 $val =~ s/(\pM+)//gso;
775 for my $tagline ( @{$root->getChildrenByTagName("controlfield")} ) {
776 next unless $tagline;
780 $ns->tag( $tagline->getAttribute( "tag" ) );
781 my $val = $tagline->textContent;
783 $val =~ s/(\pM+)//gso;
789 for my $tagline ( @{$root->getChildrenByTagName("datafield")} ) {
790 next unless $tagline;
792 my $tag = $tagline->getAttribute( "tag" );
793 my $ind1 = $tagline->getAttribute( "ind1" );
794 my $ind2 = $tagline->getAttribute( "ind2" );
796 for my $data ( $tagline->childNodes ) {
804 $ns->subfield( $data->getAttribute( "code" ) );
805 my $val = $data->textContent;
807 $val =~ s/(\pM+)//gso;
808 $ns->value( lc($val) );
814 $log->debug("Returning ".scalar(@ns_list)." Fieldmapper nodes from $xmltype xml", DEBUG);
823 $xml = $parser->parse_string($xml) unless (ref $xml);
825 my $type = 'metabib';
826 $type = 'authority' if ($self->api_name =~ /authority/o);
828 OpenILS::Application::WoRM->post_init();
830 $client->respond($_) for (_marcxml_to_full_rows($xml, $type));
833 __PACKAGE__->register_method(
834 api_name => "open-ils.worm.flat_marc.authority.xml",
835 method => "flat_marc_xml",
840 __PACKAGE__->register_method(
841 api_name => "open-ils.worm.flat_marc.biblio.xml",
842 method => "flat_marc_xml",
848 sub flat_marc_record {
854 $type = 'authority' if ($self->api_name =~ /authority/o);
856 OpenILS::Application::WoRM->post_init();
857 my $r = OpenILS::Application::WoRM->storage_req( "open-ils.storage.direct.${type}.record_entry.retrieve" => $rec );
859 $client->respond($_) for ($self->method_lookup("open-ils.worm.flat_marc.$type.xml")->run($r->marc));
862 __PACKAGE__->register_method(
863 api_name => "open-ils.worm.flat_marc.biblio.record_entry",
864 method => "flat_marc_record",
869 __PACKAGE__->register_method(
870 api_name => "open-ils.worm.flat_marc.authority.record_entry",
871 method => "flat_marc_record",
878 # --------------------------------------------------------------------------------
881 package OpenILS::Application::WoRM::Biblio::Fingerprint;
882 use base qw/OpenILS::Application::WoRM/;
883 use Unicode::Normalize;
884 use OpenSRF::EX qw/:try/;
886 my @fp_mods_xpath = (
887 '//mods:mods/mods:typeOfResource[text()="text"]' => [
890 '//mods:mods/mods:titleInfo[mods:title and (@type="uniform")]',
891 '//mods:mods/mods:titleInfo[mods:title and (@type="translated")]',
892 '//mods:mods/mods:titleInfo[mods:title and (@type="alternative")]',
893 '//mods:mods/mods:titleInfo[mods:title and not(@type)]',
896 $log->debug("Fingerprint text /durring/ fixup : [$text]", INTERNAL);
898 $log->debug("Fingerprint text /durring/ fixup : [$text]", INTERNAL);
899 $text =~ s/\pM+//gso;
900 $log->debug("Fingerprint text /durring/ fixup : [$text]", INTERNAL);
902 $log->debug("Fingerprint text /durring/ fixup : [$text]", INTERNAL);
903 $text =~ s/\s+/ /sgo;
904 $log->debug("Fingerprint text /durring/ fixup : [$text]", INTERNAL);
905 $text =~ s/^\s*(.+)\s*$/$1/sgo;
906 $log->debug("Fingerprint text /durring/ fixup : [$text]", INTERNAL);
907 $text =~ s/\b(?:the|an?)\b//sgo;
908 $log->debug("Fingerprint text /durring/ fixup : [$text]", INTERNAL);
909 $text =~ s/\[.[^\]]+\]//sgo;
910 $log->debug("Fingerprint text /durring/ fixup : [$text]", INTERNAL);
911 $text =~ s/\s*[;\/\.]*$//sgo;
912 $log->debug("Fingerprint text /durring/ fixup : [$text]", INTERNAL);
917 '//mods:mods/mods:name[mods:role/mods:text/text()="creator" and @type="personal"]/mods:namePart',
918 '//mods:mods/mods:name[mods:role/mods:text/text()="creator"]/mods:namePart',
921 $log->debug("Fingerprint text /durring/ fixup : [$text]", INTERNAL);
923 $log->debug("Fingerprint text /durring/ fixup : [$text]", INTERNAL);
924 $text =~ s/\pM+//gso;
925 $log->debug("Fingerprint text /durring/ fixup : [$text]", INTERNAL);
927 $log->debug("Fingerprint text /durring/ fixup : [$text]", INTERNAL);
928 $text =~ s/\s+/ /sgo;
929 $log->debug("Fingerprint text /durring/ fixup : [$text]", INTERNAL);
930 $text =~ s/^\s*(.+)\s*$/$1/sgo;
931 $log->debug("Fingerprint text /durring/ fixup : [$text]", INTERNAL);
932 $text =~ s/,?\s+.*$//sgo;
933 $log->debug("Fingerprint text /durring/ fixup : [$text]", INTERNAL);
938 '//mods:mods/mods:relatedItem[@type!="host" and @type!="series"]' => [
941 '//mods:mods/mods:relatedItem/mods:titleInfo[mods:title and (@type="uniform")]',
942 '//mods:mods/mods:relatedItem/mods:titleInfo[mods:title and (@type="translated")]',
943 '//mods:mods/mods:relatedItem/mods:titleInfo[mods:title and (@type="alternative")]',
944 '//mods:mods/mods:relatedItem/mods:titleInfo[mods:title and not(@type)]',
945 '//mods:mods/mods:titleInfo[mods:title and (@type="uniform")]',
946 '//mods:mods/mods:titleInfo[mods:title and (@type="translated")]',
947 '//mods:mods/mods:titleInfo[mods:title and (@type="alternative")]',
948 '//mods:mods/mods:titleInfo[mods:title and not(@type)]',
951 $log->debug("Fingerprint text /durring/ fixup : [$text]", INTERNAL);
953 $log->debug("Fingerprint text /durring/ fixup : [$text]", INTERNAL);
954 $text =~ s/\pM+//gso;
955 $log->debug("Fingerprint text /durring/ fixup : [$text]", INTERNAL);
957 $log->debug("Fingerprint text /durring/ fixup : [$text]", INTERNAL);
958 $text =~ s/\s+/ /sgo;
959 $log->debug("Fingerprint text /durring/ fixup : [$text]", INTERNAL);
960 $text =~ s/^\s*(.+)\s*$/$1/sgo;
961 $log->debug("Fingerprint text /durring/ fixup : [$text]", INTERNAL);
962 $text =~ s/\b(?:the|an?)\b//sgo;
963 $log->debug("Fingerprint text /durring/ fixup : [$text]", INTERNAL);
964 $text =~ s/\[.[^\]]+\]//sgo;
965 $log->debug("Fingerprint text /durring/ fixup : [$text]", INTERNAL);
966 $text =~ s/\s*[;\/\.]*$//sgo;
967 $log->debug("Fingerprint text /durring/ fixup : [$text]", INTERNAL);
972 '//mods:mods/mods:relatedItem/mods:name[mods:role/mods:text/text()="creator" and @type="personal"]/mods:namePart',
973 '//mods:mods/mods:relatedItem/mods:name[mods:role/mods:text/text()="creator"]/mods:namePart',
974 '//mods:mods/mods:name[mods:role/mods:text/text()="creator" and @type="personal"]/mods:namePart',
975 '//mods:mods/mods:name[mods:role/mods:text/text()="creator"]/mods:namePart',
978 $log->debug("Fingerprint text /durring/ fixup : [$text]", INTERNAL);
980 $log->debug("Fingerprint text /durring/ fixup : [$text]", INTERNAL);
981 $text =~ s/\pM+//gso;
982 $log->debug("Fingerprint text /durring/ fixup : [$text]", INTERNAL);
984 $log->debug("Fingerprint text /durring/ fixup : [$text]", INTERNAL);
985 $text =~ s/\s+/ /sgo;
986 $log->debug("Fingerprint text /durring/ fixup : [$text]", INTERNAL);
987 $text =~ s/^\s*(.+)\s*$/$1/sgo;
988 $log->debug("Fingerprint text /durring/ fixup : [$text]", INTERNAL);
989 $text =~ s/,?\s+.*$//sgo;
990 $log->debug("Fingerprint text /durring/ fixup : [$text]", INTERNAL);
997 push @fp_mods_xpath, '//mods:mods/mods:titleInfo' => $fp_mods_xpath[1];
1001 $mods->setNamespace( "http://www.loc.gov/mods/", "mods", 1 );
1005 my $match_index = 0;
1006 my $block_index = 1;
1007 while ( my $match_xpath = $fp_mods_xpath[$match_index] ) {
1008 if ( my @nodes = $mods->findnodes( $match_xpath ) ) {
1010 my $block_name_index = 0;
1011 my $block_value_index = 1;
1012 my $block = $fp_mods_xpath[$block_index];
1013 while ( my $part = $$block[$block_value_index] ) {
1015 for my $xpath ( @{ $part->{xpath} } ) {
1016 $text = $mods->findvalue( $xpath );
1020 $log->debug("Found fingerprint text using $$block[$block_name_index] : [$text]", DEBUG);
1024 $log->debug("Fingerprint text after fixup : [$text]", DEBUG);
1025 $fp_string .= $text;
1028 $block_name_index += 2;
1029 $block_value_index += 2;
1033 $fp_string =~ s/\W+//gso;
1034 $log->debug("Fingerprint is [$fp_string]", INFO);;
1044 sub refingerprint_bibrec {
1050 if (!OpenILS::Application::WoRM->in_transaction) {
1051 OpenILS::Application::WoRM->begin_transaction($client) || throw OpenSRF::EX::PANIC ("Couldn't BEGIN transaction!");
1057 my $bibs = OpenILS::Application::WoRM->storage_req( 'open-ils.storage.direct.biblio.record_entry.search.id.atomic', $rec );
1058 OpenILS::Application::WoRM->storage_req(
1059 'open-ils.storage.direct.biblio.record_entry.remote_update',
1061 { fingerprint => $self->method_lookup( 'open-ils.worm.fingerprint.marc' )->run( $_->marc ) }
1064 $log->debug('Fingerprinting failed : '.shift(), ERROR);
1068 OpenILS::Application::WoRM->commit_transaction if ($commit && $success);
1069 OpenILS::Application::WoRM->rollback_transaction if ($commit && !$success);
1072 __PACKAGE__->register_method(
1073 api_name => "open-ils.worm.fingerprint.record.update",
1074 method => "refingerprint_bibrec",
1080 sub fingerprint_bibrec {
1085 OpenILS::Application::WoRM->post_init();
1086 my $r = OpenILS::Application::WoRM->storage_req( 'open-ils.storage.direct.biblio.record_entry.retrieve' => $rec );
1088 my ($fp) = $self->method_lookup('open-ils.worm.fingerprint.marc')->run($r->marc);
1089 $log->debug("Returning [$fp] as fingerprint for record $rec", INFO);
1093 __PACKAGE__->register_method(
1094 api_name => "open-ils.worm.fingerprint.record",
1095 method => "fingerprint_bibrec",
1100 sub fingerprint_mods {
1105 OpenILS::Application::WoRM->post_init();
1106 my $mods = $parser->parse_string($xml)->documentElement;
1108 return _fp_mods( $mods );
1110 __PACKAGE__->register_method(
1111 api_name => "open-ils.worm.fingerprint.mods",
1112 method => "fingerprint_mods",
1118 sub biblio_fingerprint {
1123 OpenILS::Application::WoRM->post_init();
1125 my $marc = OpenILS::Application::WoRM::entityize(
1126 OpenILS::Application::WoRM
1127 ->storage_req( 'open-ils.storage.direct.biblio.record_entry.retrieve' => $rec )
1131 $log->internal("Got MARC [$marc]");
1133 my $mods = OpenILS::Application::WoRM::entityize(
1135 ->transform( $parser->parse_string($marc) )
1139 $log->internal("Created MODS [$mods]");
1142 my @pfx = ( "apps", "open-ils.storage","app_settings" );
1143 my $conf = OpenSRF::Utils::SettingsClient->new;
1145 my $libs = $conf->config_value(@pfx, 'script_path');
1146 my $script_file = $conf->config_value(@pfx, 'scripts', 'biblio_fingerprint');
1147 my $script_libs = (ref($libs)) ? $libs : [$libs];
1149 $log->debug("Loading script $script_file for biblio fingerprinting...");
1151 $fp_script = new OpenILS::Utils::ScriptRunner
1152 ( file => $script_file,
1153 paths => $script_libs,
1154 reset_count => 1000 );
1157 $log->debug("Applying environment for biblio fingerprinting...");
1159 my $env = {marc => $marc, mods => $mods};
1160 my $res = {fingerprint => '', quality => '0'};
1162 $fp_script->insert('environment' => $env);
1163 $fp_script->insert('result' => $res);
1165 $log->debug("Running script for biblio fingerprinting...");
1167 $fp_script->run || OpenSRF::EX::ERROR->throw( "Fingerprint script died! $@" );
1169 $log->debug("Script for biblio fingerprinting completed successfully...");
1173 __PACKAGE__->register_method(
1174 api_name => "open-ils.worm.fingerprint.record",
1175 method => "biblio_fingerprint",
1180 sub fingerprint_marc {
1185 $xml = $parser->parse_string($xml) unless (ref $xml);
1187 OpenILS::Application::WoRM->post_init();
1188 my $fp = _fp_mods( $mods_sheet->transform($xml)->documentElement );
1189 $log->debug("Returning [$fp] as fingerprint", INFO);
1192 __PACKAGE__->register_method(
1193 api_name => "open-ils.worm.fingerprint.marc",
1194 method => "fingerprint_marc",
1200 # --------------------------------------------------------------------------------
1214 my $create_source_map;
1229 my %descriptor_code = (
1230 item_type => 'substr($ldr,6,1)',
1231 item_form => '(substr($ldr,6,1) =~ /^(?:f|g|i|m|o|p|r)$/) ? substr($oo8,29,1) : substr($oo8,23,1)',
1232 bib_level => 'substr($ldr,7,1)',
1233 control_type => 'substr($ldr,8,1)',
1234 char_encoding => 'substr($ldr,9,1)',
1235 enc_level => 'substr($ldr,17,1)',
1236 cat_form => 'substr($ldr,18,1)',
1237 pub_status => 'substr($ldr,5,1)',
1238 item_lang => 'substr($oo8,35,3)',
1239 #lit_form => '(substr($ldr,6,1) =~ /^(?:f|g|i|m|o|p|r)$/) ? substr($oo8,33,1) : "0"',
1240 audience => 'substr($oo8,22,1)',
1250 if ($self->api_name =~ /no_map/o) {
1254 $in_xact = $self->method_lookup( 'open-ils.storage.transaction.current')
1256 $begin = $self->method_lookup( 'open-ils.storage.transaction.begin')
1258 $commit = $self->method_lookup( 'open-ils.storage.transaction.commit')
1260 $rollback = $self->method_lookup( 'open-ils.storage.transaction.rollback')
1262 $sm_lookup = $self->method_lookup('open-ils.storage.direct.metabib.metarecord_source_map.search.source')
1263 unless ($sm_lookup);
1264 $mr_lookup = $self->method_lookup('open-ils.storage.direct.metabib.metarecord.search.fingerprint')
1265 unless ($mr_lookup);
1266 $mr_update = $self->method_lookup('open-ils.storage.direct.metabib.metarecord.batch.update')
1267 unless ($mr_update);
1268 $lookup = $self->method_lookup('open-ils.storage.direct.biblio.record_entry.batch.retrieve')
1270 $update_entry = $self->method_lookup('open-ils.storage.direct.biblio.record_entry.batch.update')
1271 unless ($update_entry);
1272 $rm_old_sm = $self->method_lookup( 'open-ils.storage.direct.metabib.metarecord_source_map.mass_delete')
1273 unless ($rm_old_sm);
1274 $rm_old_rd = $self->method_lookup( 'open-ils.storage.direct.metabib.record_descriptor.mass_delete')
1275 unless ($rm_old_rd);
1276 $rm_old_fr = $self->method_lookup( 'open-ils.storage.direct.metabib.full_rec.mass_delete')
1277 unless ($rm_old_fr);
1278 $rm_old_tr = $self->method_lookup( 'open-ils.storage.direct.metabib.title_field_entry.mass_delete')
1279 unless ($rm_old_tr);
1280 $rm_old_ar = $self->method_lookup( 'open-ils.storage.direct.metabib.author_field_entry.mass_delete')
1281 unless ($rm_old_ar);
1282 $rm_old_sr = $self->method_lookup( 'open-ils.storage.direct.metabib.subject_field_entry.mass_delete')
1283 unless ($rm_old_sr);
1284 $rm_old_kr = $self->method_lookup( 'open-ils.storage.direct.metabib.keyword_field_entry.mass_delete')
1285 unless ($rm_old_kr);
1286 $rm_old_ser = $self->method_lookup( 'open-ils.storage.direct.metabib.series_field_entry.mass_delete')
1287 unless ($rm_old_ser);
1288 $mr_create = $self->method_lookup('open-ils.storage.direct.metabib.metarecord.create')
1289 unless ($mr_create);
1290 $create_source_map = $self->method_lookup('open-ils.storage.direct.metabib.metarecord_source_map.batch.create')
1291 unless ($create_source_map);
1292 $rd_create = $self->method_lookup( 'open-ils.storage.direct.metabib.record_descriptor.batch.create')
1293 unless ($rd_create);
1294 $fr_create = $self->method_lookup( 'open-ils.storage.direct.metabib.full_rec.batch.create')
1295 unless ($fr_create);
1296 $$create{title} = $self->method_lookup( 'open-ils.storage.direct.metabib.title_field_entry.batch.create')
1297 unless ($$create{title});
1298 $$create{author} = $self->method_lookup( 'open-ils.storage.direct.metabib.author_field_entry.batch.create')
1299 unless ($$create{author});
1300 $$create{subject} = $self->method_lookup( 'open-ils.storage.direct.metabib.subject_field_entry.batch.create')
1301 unless ($$create{subject});
1302 $$create{keyword} = $self->method_lookup( 'open-ils.storage.direct.metabib.keyword_field_entry.batch.create')
1303 unless ($$create{keyword});
1304 $$create{series} = $self->method_lookup( 'open-ils.storage.direct.metabib.series_field_entry.batch.create')
1305 unless ($$create{series});
1308 my ($outer_xact) = $in_xact->run;
1310 unless ($outer_xact) {
1311 $log->debug("WoRM isn't inside a transaction, starting one now.", INFO);
1312 my ($r) = $begin->run($client);
1313 unless (defined $r and $r) {
1315 throw OpenSRF::EX::PANIC ("Couldn't BEGIN transaction!")
1318 } catch Error with {
1319 throw OpenSRF::EX::PANIC ("WoRM Couldn't BEGIN transaction!")
1329 for my $entry ( $lookup->run(@docids) ) {
1330 # step -1: grab the doc from storage
1331 next unless ($entry);
1334 my $xslt_doc = $parser->parse_file(
1335 OpenSRF::Utils::SettingsClient->new->config_value(dirs => 'xsl') . "/MARC21slim2MODS.xsl");
1336 $mods_sheet = $xslt->parse_stylesheet( $xslt_doc );
1339 my $xml = $entry->marc;
1340 my $docid = $entry->id;
1341 my $marcdoc = $parser->parse_string($xml);
1342 my $modsdoc = $mods_sheet->transform($marcdoc);
1344 my $mods = $modsdoc->documentElement;
1345 $mods->setNamespace( "http://www.loc.gov/mods/", "mods", 1 );
1347 $entry->fingerprint( fingerprint_mods( $mods ) );
1348 push @entry_list, $entry;
1350 $log->debug("Fingerprint for Record Entry ".$docid." is [".$entry->fingerprint."]", INFO);
1353 my ($mr) = $mr_lookup->run( $entry->fingerprint );
1354 if (!$mr || !@$mr) {
1355 $log->debug("No metarecord found for fingerprint [".$entry->fingerprint."]; Creating a new one", INFO);
1356 $mr = new Fieldmapper::metabib::metarecord;
1357 $mr->fingerprint( $entry->fingerprint );
1358 $mr->master_record( $entry->id );
1359 my ($new_mr) = $mr_create->run($mr);
1361 unless (defined $mr) {
1362 throw OpenSRF::EX::PANIC ("Couldn't run open-ils.storage.direct.metabib.metarecord.create!")
1365 $log->debug("Retrieved metarecord, id is ".$mr->id, INFO);
1370 my $sm = new Fieldmapper::metabib::metarecord_source_map;
1371 $sm->metarecord( $mr->id );
1372 $sm->source( $entry->id );
1373 push @source_maps, $sm;
1376 my $ldr = $marcdoc->documentElement->getChildrenByTagName('leader')->pop->textContent;
1377 my $oo8 = $marcdoc->documentElement->findvalue('//*[local-name()="controlfield" and @tag="008"]');
1379 my $rd_obj = Fieldmapper::metabib::record_descriptor->new;
1380 for my $rd_field ( keys %descriptor_code ) {
1381 $rd_obj->$rd_field( eval "$descriptor_code{$rd_field};" );
1383 $rd_obj->record( $docid );
1384 push @rd_list, $rd_obj;
1386 push @mods_data, { $docid => $self->modsdoc_to_values( $mods ) };
1388 # step 2: build the KOHA rows
1389 my @tmp_list = _marcxml_to_full_rows( $marcdoc );
1390 $_->record( $docid ) for (@tmp_list);
1391 push @ns_list, @tmp_list;
1395 last unless ($self->api_name =~ /batch$/o);
1398 $rm_old_rd->run( { record => \@docids } );
1399 $rm_old_fr->run( { record => \@docids } );
1400 $rm_old_sm->run( { source => \@docids } ) unless ($no_map);
1401 $rm_old_tr->run( { source => \@docids } );
1402 $rm_old_ar->run( { source => \@docids } );
1403 $rm_old_sr->run( { source => \@docids } );
1404 $rm_old_kr->run( { source => \@docids } );
1405 $rm_old_ser->run( { source => \@docids } );
1408 my ($sm) = $create_source_map->run(@source_maps);
1409 unless (defined $sm) {
1410 throw OpenSRF::EX::PANIC ("Couldn't run open-ils.storage.direct.metabib.metarecord_source_map.batch.create!")
1412 my ($mr) = $mr_update->run(@mr_list);
1413 unless (defined $mr) {
1414 throw OpenSRF::EX::PANIC ("Couldn't run open-ils.storage.direct.metabib.metarecord.batch.update!")
1418 my ($re) = $update_entry->run(@entry_list);
1419 unless (defined $re) {
1420 throw OpenSRF::EX::PANIC ("Couldn't run open-ils.storage.direct.biblio.record_entry.batch.update!")
1423 my ($rd) = $rd_create->run(@rd_list);
1424 unless (defined $rd) {
1425 throw OpenSRF::EX::PANIC ("Couldn't run open-ils.storage.direct.metabib.record_descriptor.batch.create!")
1428 my ($fr) = $fr_create->run(@ns_list);
1429 unless (defined $fr) {
1430 throw OpenSRF::EX::PANIC ("Couldn't run open-ils.storage.direct.metabib.full_rec.batch.create!")
1433 # step 5: insert the new metadata
1434 for my $class ( qw/title author subject keyword series/ ) {
1436 for my $doc ( @mods_data ) {
1437 my ($did) = keys %$doc;
1438 my ($data) = values %$doc;
1440 my $fm_constructor = "Fieldmapper::metabib::${class}_field_entry";
1441 for my $row ( keys %{ $$data{$class} } ) {
1442 next unless (exists $$data{$class}{$row});
1443 next unless ($$data{$class}{$row}{value});
1444 my $fm_obj = $fm_constructor->new;
1445 $fm_obj->value( $$data{$class}{$row}{value} );
1446 $fm_obj->field( $$data{$class}{$row}{field_id} );
1447 $fm_obj->source( $did );
1448 $log->debug("$class entry: ".$fm_obj->source." => ".$fm_obj->field." : ".$fm_obj->value, DEBUG);
1450 push @md_list, $fm_obj;
1454 my ($cr) = $$create{$class}->run(@md_list);
1455 unless (defined $cr) {
1456 throw OpenSRF::EX::PANIC ("Couldn't run open-ils.storage.direct.metabib.${class}_field_entry.batch.create!")
1460 unless ($outer_xact) {
1461 $log->debug("Commiting transaction started by the WoRM.", INFO);
1462 my ($c) = $commit->run;
1463 unless (defined $c and $c) {
1465 throw OpenSRF::EX::PANIC ("Couldn't COMMIT changes!")
1471 __PACKAGE__->register_method(
1472 api_name => "open-ils.worm.wormize",
1473 method => "wormize",
1477 __PACKAGE__->register_method(
1478 api_name => "open-ils.worm.wormize.no_map",
1479 method => "wormize",
1483 __PACKAGE__->register_method(
1484 api_name => "open-ils.worm.wormize.batch",
1485 method => "wormize",
1489 __PACKAGE__->register_method(
1490 api_name => "open-ils.worm.wormize.no_map.batch",
1491 method => "wormize",
1506 my $acreate_source_map;
1521 sub authority_wormize {
1528 if ($self->api_name =~ /no_map/o) {
1532 $in_xact = $self->method_lookup( 'open-ils.storage.transaction.current')
1534 $begin = $self->method_lookup( 'open-ils.storage.transaction.begin')
1536 $commit = $self->method_lookup( 'open-ils.storage.transaction.commit')
1538 $rollback = $self->method_lookup( 'open-ils.storage.transaction.rollback')
1540 $alookup = $self->method_lookup('open-ils.storage.direct.authority.record_entry.batch.retrieve')
1542 $aupdate_entry = $self->method_lookup('open-ils.storage.direct.authority.record_entry.batch.update')
1543 unless ($aupdate_entry);
1544 $arm_old_rd = $self->method_lookup( 'open-ils.storage.direct.authority.record_descriptor.mass_delete')
1545 unless ($arm_old_rd);
1546 $arm_old_fr = $self->method_lookup( 'open-ils.storage.direct.authority.full_rec.mass_delete')
1547 unless ($arm_old_fr);
1548 $ard_create = $self->method_lookup( 'open-ils.storage.direct.authority.record_descriptor.batch.create')
1549 unless ($ard_create);
1550 $afr_create = $self->method_lookup( 'open-ils.storage.direct.authority.full_rec.batch.create')
1551 unless ($afr_create);
1554 my ($outer_xact) = $in_xact->run;
1556 unless ($outer_xact) {
1557 $log->debug("WoRM isn't inside a transaction, starting one now.", INFO);
1558 my ($r) = $begin->run($client);
1559 unless (defined $r and $r) {
1561 throw OpenSRF::EX::PANIC ("Couldn't BEGIN transaction!")
1564 } catch Error with {
1565 throw OpenSRF::EX::PANIC ("WoRM Couldn't BEGIN transaction!")
1575 for my $entry ( $lookup->run(@docids) ) {
1576 # step -1: grab the doc from storage
1577 next unless ($entry);
1580 # my $xslt_doc = $parser->parse_file(
1581 # OpenSRF::Utils::SettingsClient->new->config_value(dirs => 'xsl') . "/MARC21slim2MODS.xsl");
1582 # $mads_sheet = $xslt->parse_stylesheet( $xslt_doc );
1585 my $xml = $entry->marc;
1586 my $docid = $entry->id;
1587 my $marcdoc = $parser->parse_string($xml);
1588 #my $madsdoc = $mads_sheet->transform($marcdoc);
1590 #my $mads = $madsdoc->documentElement;
1591 #$mads->setNamespace( "http://www.loc.gov/mads/", "mads", 1 );
1593 push @entry_list, $entry;
1595 my $ldr = $marcdoc->documentElement->getChildrenByTagName('leader')->pop->textContent;
1596 my $oo8 = $marcdoc->documentElement->findvalue('//*[local-name()="controlfield" and @tag="008"]');
1598 my $rd_obj = Fieldmapper::authority::record_descriptor->new;
1599 for my $rd_field ( keys %descriptor_code ) {
1600 $rd_obj->$rd_field( eval "$descriptor_code{$rd_field};" );
1602 $rd_obj->record( $docid );
1603 push @rd_list, $rd_obj;
1605 # step 2: build the KOHA rows
1606 my @tmp_list = _marcxml_to_full_rows( $marcdoc, 'Fieldmapper::authority::full_rec' );
1607 $_->record( $docid ) for (@tmp_list);
1608 push @ns_list, @tmp_list;
1612 last unless ($self->api_name =~ /batch$/o);
1615 $arm_old_rd->run( { record => \@docids } );
1616 $arm_old_fr->run( { record => \@docids } );
1618 my ($rd) = $ard_create->run(@rd_list);
1619 unless (defined $rd) {
1620 throw OpenSRF::EX::PANIC ("Couldn't run open-ils.storage.direct.authority.record_descriptor.batch.create!")
1623 my ($fr) = $fr_create->run(@ns_list);
1624 unless (defined $fr) {
1625 throw OpenSRF::EX::PANIC ("Couldn't run open-ils.storage.direct.authority.full_rec.batch.create!")
1628 unless ($outer_xact) {
1629 $log->debug("Commiting transaction started by the WoRM.", INFO);
1630 my ($c) = $commit->run;
1631 unless (defined $c and $c) {
1633 throw OpenSRF::EX::PANIC ("Couldn't COMMIT changes!")
1639 __PACKAGE__->register_method(
1640 api_name => "open-ils.worm.authortiy.wormize",
1641 method => "wormize",
1645 __PACKAGE__->register_method(
1646 api_name => "open-ils.worm.authority.wormize.batch",
1647 method => "wormize",
1653 # --------------------------------------------------------------------------------
1656 sub _marcxml_to_full_rows {
1658 my $marcxml = shift;
1659 my $type = shift || 'Fieldmapper::metabib::full_rec';
1663 my $root = $marcxml->documentElement;
1665 for my $tagline ( @{$root->getChildrenByTagName("leader")} ) {
1666 next unless $tagline;
1668 my $ns = new Fieldmapper::metabib::full_rec;
1671 my $val = NFD($tagline->textContent);
1672 $val =~ s/(\pM+)//gso;
1678 for my $tagline ( @{$root->getChildrenByTagName("controlfield")} ) {
1679 next unless $tagline;
1681 my $ns = new Fieldmapper::metabib::full_rec;
1683 $ns->tag( $tagline->getAttribute( "tag" ) );
1684 my $val = NFD($tagline->textContent);
1685 $val =~ s/(\pM+)//gso;
1691 for my $tagline ( @{$root->getChildrenByTagName("datafield")} ) {
1692 next unless $tagline;
1694 my $tag = $tagline->getAttribute( "tag" );
1695 my $ind1 = $tagline->getAttribute( "ind1" );
1696 my $ind2 = $tagline->getAttribute( "ind2" );
1698 for my $data ( $tagline->childNodes ) {
1701 my $ns = $type->new;
1706 $ns->subfield( $data->getAttribute( "code" ) );
1707 my $val = NFD($data->textContent);
1708 $val =~ s/(\pM+)//gso;
1709 $ns->value( lc($val) );
1717 sub _get_field_value {
1719 my( $root, $xpath ) = @_;
1723 # grab the set of matching nodes
1724 my @nodes = $root->findnodes( $xpath );
1725 for my $value (@nodes) {
1727 # grab all children of the node
1728 my @children = $value->childNodes();
1729 for my $child (@children) {
1731 # add the childs content to the growing buffer
1732 my $content = quotemeta($child->textContent);
1733 next if ($string =~ /$content/); # uniquify the values
1734 $string .= $child->textContent . " ";
1737 $string .= $value->textContent . " ";
1740 $string = NFD($string);
1741 $string =~ s/(\pM)//gso;
1746 sub modsdoc_to_values {
1747 my( $self, $mods ) = @_;
1749 for my $class (keys %$xpathset) {
1750 $data->{$class} = {};
1751 for my $type (keys %{$xpathset->{$class}}) {
1752 $data->{$class}->{$type} = {};
1753 $data->{$class}->{$type}->{field_id} = $xpathset->{$class}->{$type}->{id};