[open-ils-commits] r10640 - in
trunk/Open-ILS/src/perlmods/OpenILS/Application: . Cat
svn at svn.open-ils.org
svn at svn.open-ils.org
Fri Sep 19 12:26:33 EDT 2008
Author: erickson
Date: 2008-09-19 12:26:30 -0400 (Fri, 19 Sep 2008)
New Revision: 10640
Added:
trunk/Open-ILS/src/perlmods/OpenILS/Application/Cat/BibCommon.pm
Modified:
trunk/Open-ILS/src/perlmods/OpenILS/Application/Cat.pm
Log:
moved marc edit/import functionaly out to an external module so it can be imported by other modules (namely, vandelay). this will allow said modules to manipulate bib records inside of a single transaction. cleaned out some old, unused code
Added: trunk/Open-ILS/src/perlmods/OpenILS/Application/Cat/BibCommon.pm
===================================================================
--- trunk/Open-ILS/src/perlmods/OpenILS/Application/Cat/BibCommon.pm (rev 0)
+++ trunk/Open-ILS/src/perlmods/OpenILS/Application/Cat/BibCommon.pm 2008-09-19 16:26:30 UTC (rev 10640)
@@ -0,0 +1,273 @@
+package OpenILS::Application::Cat::BibCommon;
+use strict; use warnings;
+use OpenILS::Utils::CStoreEditor q/:funcs/;
+use OpenSRF::Utils::Logger qw($logger);
+use OpenILS::Application::AppUtils;
+use OpenILS::Utils::Fieldmapper;
+use OpenILS::Const qw/:const/;
+use OpenILS::Event;
+my $U = 'OpenILS::Application::AppUtils';
+my $MARC_NAMESPACE = 'http://www.loc.gov/MARC21/slim';
+
+
+# ---------------------------------------------------------------------------
+# Shared bib mangling code. Do not publish methods from here.
+# ---------------------------------------------------------------------------
+
+
+sub biblio_record_replace_marc {
+ my($class, $e, $recid, $newxml, $source, $fixtcn, $override) = @_;
+
+ my $rec = $e->retrieve_biblio_record_entry($recid)
+ or return $e->die_event;
+
+ # See if there is a different record in the database that has our TCN value
+ # If we're not updating the TCN, all we care about it the marcdoc
+ # XXX should .update even bother with the tcn_info if it's not going to replace it?
+ # there is the potential for returning a TCN_EXISTS event, even though no replacement happens
+
+ my( $tcn, $tsource, $marcdoc, $evt);
+
+ if($fixtcn or $override) {
+
+ ($tcn, $tsource, $marcdoc, $evt) =
+ _find_tcn_info($e, $newxml, $override, $recid);
+
+ return $evt if $evt;
+
+ $rec->tcn_value($tcn) if ($tcn);
+ $rec->tcn_source($tsource);
+
+ } else {
+
+ $marcdoc = __make_marc_doc($newxml);
+ }
+
+
+ $rec->source(bib_source_from_name($source)) if $source;
+ $rec->editor($e->requestor->id);
+ $rec->edit_date('now');
+ $rec->marc( $U->entityize( $marcdoc->documentElement->toString ) );
+ $e->update_biblio_record_entry($rec) or return $e->die_event;
+
+ # we don't care about the result, just fire off the request
+ my $ses = OpenSRF::AppSession->create('open-ils.ingest');
+ $ses->request('open-ils.ingest.full.biblio.record', $recid);
+
+ return $rec;
+}
+
+sub biblio_record_xml_import {
+ my($class, $e, $xml, $source, $auto_tcn, $override) = @_;
+
+ my( $evt, $tcn, $tcn_source, $marcdoc );
+
+ if( $auto_tcn ) {
+ # auto_tcn forces a blank TCN value so the DB will have to generate one for us
+ $marcdoc = __make_marc_doc($xml);
+ } else {
+ ( $tcn, $tcn_source, $marcdoc, $evt ) = _find_tcn_info($e, $xml, $override);
+ return $evt if $evt;
+ }
+
+ $logger->info("user ".$e->requestor->id.
+ " creating new biblio entry with tcn=$tcn and tcn_source $tcn_source");
+
+ my $record = Fieldmapper::biblio::record_entry->new;
+
+ $record->source(bib_source_from_name($source)) if $source;
+ $record->tcn_source($tcn_source);
+ $record->tcn_value($tcn) if ($tcn);
+ $record->creator($e->requestor->id);
+ $record->editor($e->requestor->id);
+ $record->create_date('now');
+ $record->edit_date('now');
+ $record->marc($U->entityize($marcdoc->documentElement->toString));
+
+ $record = $e->create_biblio_record_entry($record) or return $e->die_event;
+ $logger->info("marc create/import created new record ".$record->id);
+
+ # we don't care about the result, just fire off the request
+ my $ses = OpenSRF::AppSession->create('open-ils.ingest');
+ $ses->request('open-ils.ingest.full.biblio.record', $record->id);
+
+ return $record;
+}
+
+sub __make_marc_doc {
+ my $xml = shift;
+ my $marcxml = XML::LibXML->new->parse_string($xml);
+ $marcxml->documentElement->setNamespace($MARC_NAMESPACE, "marc", 1 );
+ $marcxml->documentElement->setNamespace($MARC_NAMESPACE);
+ return $marcxml;
+}
+
+
+sub _find_tcn_info {
+ my $editor = shift;
+ my $xml = shift;
+ my $override = shift;
+ my $existing_rec = shift || 0;
+
+ # parse the XML
+ my $marcxml = __make_marc_doc($xml);
+
+ my $xpath = '//marc:controlfield[@tag="001"]';
+ my $tcn = $marcxml->documentElement->findvalue($xpath);
+ $logger->info("biblio import located 001 (tcn) value of $tcn");
+
+ $xpath = '//marc:controlfield[@tag="003"]';
+ my $tcn_source = $marcxml->documentElement->findvalue($xpath) || "System Local";
+
+ if(my $rec = _tcn_exists($editor, $tcn, $tcn_source, $existing_rec) ) {
+
+ my $origtcn = $tcn;
+ $tcn = find_free_tcn( $marcxml, $editor, $existing_rec );
+
+ # if we're overriding, try to find a different TCN to use
+ if( $override ) {
+
+ # XXX Create ALLOW_ALT_TCN permission check support
+
+ $logger->info("tcn value $tcn already exists, attempting to override");
+
+ if(!$tcn) {
+ return (
+ undef,
+ undef,
+ undef,
+ OpenILS::Event->new(
+ 'OPEN_TCN_NOT_FOUND',
+ payload => $marcxml->toString())
+ );
+ }
+
+ } else {
+
+ $logger->warn("tcn value $origtcn already exists in import/create");
+
+ # otherwise, return event
+ return (
+ undef,
+ undef,
+ undef,
+ OpenILS::Event->new(
+ 'TCN_EXISTS', payload => {
+ dup_record => $rec,
+ tcn => $origtcn,
+ new_tcn => $tcn
+ }
+ )
+ );
+ }
+ }
+
+ return ($tcn, $tcn_source, $marcxml);
+}
+
+sub find_free_tcn {
+
+ my $marcxml = shift;
+ my $editor = shift;
+ my $existing_rec = shift;
+
+ my $add_039 = 0;
+
+ my $xpath = '//marc:datafield[@tag="039"]/subfield[@code="a"]';
+ my ($tcn) = $marcxml->documentElement->findvalue($xpath) =~ /(\w+)\s*$/o;
+ $xpath = '//marc:datafield[@tag="039"]/subfield[@code="b"]';
+ my $tcn_source = $marcxml->documentElement->findvalue($xpath) || "System Local";
+
+ if(_tcn_exists($editor, $tcn, $tcn_source, $existing_rec)) {
+ $tcn = undef;
+ } else {
+ $add_039++;
+ }
+
+
+ if(!$tcn) {
+ $xpath = '//marc:datafield[@tag="020"]/subfield[@code="a"]';
+ ($tcn) = $marcxml->documentElement->findvalue($xpath) =~ /(\w+)\s*$/o;
+ $tcn_source = "ISBN";
+ if(_tcn_exists($editor, $tcn, $tcn_source, $existing_rec)) {$tcn = undef;}
+ }
+
+ if(!$tcn) {
+ $xpath = '//marc:datafield[@tag="022"]/subfield[@code="a"]';
+ ($tcn) = $marcxml->documentElement->findvalue($xpath) =~ /(\w+)\s*$/o;
+ $tcn_source = "ISSN";
+ if(_tcn_exists($editor, $tcn, $tcn_source, $existing_rec)) {$tcn = undef;}
+ }
+
+ if(!$tcn) {
+ $xpath = '//marc:datafield[@tag="010"]';
+ ($tcn) = $marcxml->documentElement->findvalue($xpath) =~ /(\w+)\s*$/o;
+ $tcn_source = "LCCN";
+ if(_tcn_exists($editor, $tcn, $tcn_source, $existing_rec)) {$tcn = undef;}
+ }
+
+ if(!$tcn) {
+ $xpath = '//marc:datafield[@tag="035"]/subfield[@code="a"]';
+ ($tcn) = $marcxml->documentElement->findvalue($xpath) =~ /(\w+)\s*$/o;
+ $tcn_source = "System Legacy";
+ if(_tcn_exists($editor, $tcn, $tcn_source, $existing_rec)) {$tcn = undef;}
+
+ if($tcn) {
+ $marcxml->documentElement->removeChild(
+ $marcxml->documentElement->findnodes( '//datafield[@tag="035"]' )
+ );
+ }
+ }
+
+ return undef unless $tcn;
+
+ if ($add_039) {
+ my $df = $marcxml->createElementNS( 'http://www.loc.gov/MARC21/slim', 'datafield');
+ $df->setAttribute( tag => '039' );
+ $df->setAttribute( ind1 => ' ' );
+ $df->setAttribute( ind2 => ' ' );
+ $marcxml->documentElement->appendChild( $df );
+
+ my $sfa = $marcxml->createElementNS( 'http://www.loc.gov/MARC21/slim', 'subfield');
+ $sfa->setAttribute( code => 'a' );
+ $sfa->appendChild( $marcxml->createTextNode( $tcn ) );
+ $df->appendChild( $sfa );
+
+ my $sfb = $marcxml->createElementNS( 'http://www.loc.gov/MARC21/slim', 'subfield');
+ $sfb->setAttribute( code => 'b' );
+ $sfb->appendChild( $marcxml->createTextNode( $tcn_source ) );
+ $df->appendChild( $sfb );
+ }
+
+ return $tcn;
+}
+
+
+
+sub _tcn_exists {
+ my $editor = shift;
+ my $tcn = shift;
+ my $source = shift;
+ my $existing_rec = shift || 0;
+
+ if(!$tcn) {return 0;}
+
+ $logger->debug("tcn_exists search for tcn $tcn and source $source and id $existing_rec");
+
+ # XXX why does the source matter?
+# my $req = $session->request(
+# { tcn_value => $tcn, tcn_source => $source, deleted => 'f' } );
+
+ my $recs = $editor->search_biblio_record_entry(
+ {tcn_value => $tcn, deleted => 'f', id => {'!=' => $existing_rec}}, {idlist =>1});
+
+ if(@$recs) {
+ $logger->debug("_tcn_exists is true for tcn : $tcn ($source)");
+ return $recs->[0];
+ }
+
+ $logger->debug("_tcn_exists is false for tcn : $tcn ($source)");
+ return 0;
+}
+
+
Modified: trunk/Open-ILS/src/perlmods/OpenILS/Application/Cat.pm
===================================================================
--- trunk/Open-ILS/src/perlmods/OpenILS/Application/Cat.pm 2008-09-19 15:33:23 UTC (rev 10639)
+++ trunk/Open-ILS/src/perlmods/OpenILS/Application/Cat.pm 2008-09-19 16:26:30 UTC (rev 10640)
@@ -4,6 +4,7 @@
use OpenILS::Application;
use OpenILS::Application::Cat::Merge;
use OpenILS::Application::Cat::Authority;
+use OpenILS::Application::Cat::BibCommon;
use base qw/OpenILS::Application/;
use Time::HiRes qw(time);
use OpenSRF::EX qw(:try);
@@ -170,55 +171,17 @@
sub biblio_record_replace_marc {
my( $self, $conn, $auth, $recid, $newxml, $source ) = @_;
-
my $e = new_editor(authtoken=>$auth, xact=>1);
return $e->die_event unless $e->checkauth;
return $e->die_event unless $e->allowed('CREATE_MARC', $e->requestor->ws_ou);
- my $rec = $e->retrieve_biblio_record_entry($recid)
- or return $e->die_event;
+ my $res = OpenILS::Application::Cat::BibCommon->biblio_record_replace_marc(
+ $e, $recid, $newxml, $source,
+ $self->api_name =~ /replace/o,
+ $self->api_name =~ /override/o);
- my $fixtcn = 1 if $self->api_name =~ /replace/o;
-
- # See if there is a different record in the database that has our TCN value
- # If we're not updating the TCN, all we care about it the marcdoc
- my $override = $self->api_name =~ /override/;
-
- # XXX should .update even bother with the tcn_info if it's not going to replace it?
- # there is the potential for returning a TCN_EXISTS event, even though no replacement happens
-
- my( $tcn, $tsource, $marcdoc, $evt);
-
- if($fixtcn or $override) {
-
- ($tcn, $tsource, $marcdoc, $evt) =
- _find_tcn_info($e, $newxml, $override, $recid);
-
- return $evt if $evt;
-
- $rec->tcn_value($tcn) if ($tcn);
- $rec->tcn_source($tsource);
-
- } else {
-
- $marcdoc = __make_marc_doc($newxml);
- }
-
-
- $rec->source(bib_source_from_name($source)) if $source;
- $rec->editor($e->requestor->id);
- $rec->edit_date('now');
- $rec->marc( $U->entityize( $marcdoc->documentElement->toString ) );
- $e->update_biblio_record_entry($rec) or return $e->die_event;
- $e->commit;
-
- $conn->respond_complete($rec);
-
- $U->simplereq(
- 'open-ils.ingest',
- 'open-ils.ingest.full.biblio.record', $recid );
-
- return undef;
+ $e->commit unless $U->event_code($res);
+ return $res;
}
__PACKAGE__->register_method(
@@ -297,230 +260,17 @@
sub biblio_record_xml_import {
my( $self, $client, $authtoken, $xml, $source, $auto_tcn) = @_;
-
- my $override = 1 if $self->api_name =~ /override/;
my $e = new_editor(xact=>1, authtoken=>$authtoken);
return $e->die_event unless $e->checkauth;
return $e->die_event unless $e->allowed('IMPORT_MARC', $e->requestor->ws_ou);
- my( $evt, $tcn, $tcn_source, $marcdoc );
+ my $res = OpenILS::Application::Cat::BibCommon->biblio_record_xml_import(
+ $e, $xml, $source, $auto_tcn, $self->api_name =~ /override/);
- if( $auto_tcn ) {
- # auto_tcn forces a blank TCN value so the DB will have to generate one for us
- $marcdoc = __make_marc_doc($xml);
- } else {
- ( $tcn, $tcn_source, $marcdoc, $evt ) = _find_tcn_info($e, $xml, $override);
- return $evt if $evt;
- }
-
- $logger->info("user ".$e->requestor->id.
- " creating new biblio entry with tcn=$tcn and tcn_source $tcn_source");
-
- my $record = Fieldmapper::biblio::record_entry->new;
-
- $record->source(bib_source_from_name($source)) if $source;
- $record->tcn_source($tcn_source);
- $record->tcn_value($tcn) if ($tcn);
- $record->creator($e->requestor->id);
- $record->editor($e->requestor->id);
- $record->create_date('now');
- $record->edit_date('now');
- $record->marc( $U->entityize( $marcdoc->documentElement->toString ) );
-
- $record = $e->create_biblio_record_entry($record) or return $e->die_event;
- $logger->info("marc create/import created new record ".$record->id);
-
- $e->commit;
-
- $logger->debug("Sending record off to be ingested and indexed");
-
- $client->respond_complete($record);
-
- $U->simplereq(
- 'open-ils.ingest',
- 'open-ils.ingest.full.biblio.record', $record->id );
-
- return undef;
+ $e->commit unless $U->event_code($res);
+ return $res;
}
-sub __make_marc_doc {
- my $xml = shift;
- my $marcxml = XML::LibXML->new->parse_string( $xml );
- $marcxml->documentElement->setNamespace(
- "http://www.loc.gov/MARC21/slim", "marc", 1 );
- $marcxml->documentElement->setNamespace("http://www.loc.gov/MARC21/slim");
- return $marcxml;
-}
-
-
-sub _find_tcn_info {
- my $editor = shift;
- my $xml = shift;
- my $override = shift;
- my $existing_rec = shift || 0;
-
- # parse the XML
- my $marcxml = __make_marc_doc($xml);
-
- my $xpath = '//marc:controlfield[@tag="001"]';
- my $tcn = $marcxml->documentElement->findvalue($xpath);
- $logger->info("biblio import located 001 (tcn) value of $tcn");
-
- $xpath = '//marc:controlfield[@tag="003"]';
- my $tcn_source = $marcxml->documentElement->findvalue($xpath) || "System Local";
-
- if(my $rec = _tcn_exists($editor, $tcn, $tcn_source, $existing_rec) ) {
-
- my $origtcn = $tcn;
- $tcn = find_free_tcn( $marcxml, $editor, $existing_rec );
-
- # if we're overriding, try to find a different TCN to use
- if( $override ) {
-
- # XXX Create ALLOW_ALT_TCN permission check support
-
- $logger->info("tcn value $tcn already exists, attempting to override");
-
- if(!$tcn) {
- return (
- undef,
- undef,
- undef,
- OpenILS::Event->new(
- 'OPEN_TCN_NOT_FOUND',
- payload => $marcxml->toString())
- );
- }
-
- } else {
-
- $logger->warn("tcn value $origtcn already exists in import/create");
-
- # otherwise, return event
- return (
- undef,
- undef,
- undef,
- OpenILS::Event->new(
- 'TCN_EXISTS', payload => {
- dup_record => $rec,
- tcn => $origtcn,
- new_tcn => $tcn
- }
- )
- );
- }
- }
-
- return ($tcn, $tcn_source, $marcxml);
-}
-
-sub find_free_tcn {
-
- my $marcxml = shift;
- my $editor = shift;
- my $existing_rec = shift;
-
- my $add_039 = 0;
-
- my $xpath = '//marc:datafield[@tag="039"]/subfield[@code="a"]';
- my ($tcn) = $marcxml->documentElement->findvalue($xpath) =~ /(\w+)\s*$/o;
- $xpath = '//marc:datafield[@tag="039"]/subfield[@code="b"]';
- my $tcn_source = $marcxml->documentElement->findvalue($xpath) || "System Local";
-
- if(_tcn_exists($editor, $tcn, $tcn_source, $existing_rec)) {
- $tcn = undef;
- } else {
- $add_039++;
- }
-
-
- if(!$tcn) {
- $xpath = '//marc:datafield[@tag="020"]/subfield[@code="a"]';
- ($tcn) = $marcxml->documentElement->findvalue($xpath) =~ /(\w+)\s*$/o;
- $tcn_source = "ISBN";
- if(_tcn_exists($editor, $tcn, $tcn_source, $existing_rec)) {$tcn = undef;}
- }
-
- if(!$tcn) {
- $xpath = '//marc:datafield[@tag="022"]/subfield[@code="a"]';
- ($tcn) = $marcxml->documentElement->findvalue($xpath) =~ /(\w+)\s*$/o;
- $tcn_source = "ISSN";
- if(_tcn_exists($editor, $tcn, $tcn_source, $existing_rec)) {$tcn = undef;}
- }
-
- if(!$tcn) {
- $xpath = '//marc:datafield[@tag="010"]';
- ($tcn) = $marcxml->documentElement->findvalue($xpath) =~ /(\w+)\s*$/o;
- $tcn_source = "LCCN";
- if(_tcn_exists($editor, $tcn, $tcn_source, $existing_rec)) {$tcn = undef;}
- }
-
- if(!$tcn) {
- $xpath = '//marc:datafield[@tag="035"]/subfield[@code="a"]';
- ($tcn) = $marcxml->documentElement->findvalue($xpath) =~ /(\w+)\s*$/o;
- $tcn_source = "System Legacy";
- if(_tcn_exists($editor, $tcn, $tcn_source, $existing_rec)) {$tcn = undef;}
-
- if($tcn) {
- $marcxml->documentElement->removeChild(
- $marcxml->documentElement->findnodes( '//datafield[@tag="035"]' )
- );
- }
- }
-
- return undef unless $tcn;
-
- if ($add_039) {
- my $df = $marcxml->createElementNS( 'http://www.loc.gov/MARC21/slim', 'datafield');
- $df->setAttribute( tag => '039' );
- $df->setAttribute( ind1 => ' ' );
- $df->setAttribute( ind2 => ' ' );
- $marcxml->documentElement->appendChild( $df );
-
- my $sfa = $marcxml->createElementNS( 'http://www.loc.gov/MARC21/slim', 'subfield');
- $sfa->setAttribute( code => 'a' );
- $sfa->appendChild( $marcxml->createTextNode( $tcn ) );
- $df->appendChild( $sfa );
-
- my $sfb = $marcxml->createElementNS( 'http://www.loc.gov/MARC21/slim', 'subfield');
- $sfb->setAttribute( code => 'b' );
- $sfb->appendChild( $marcxml->createTextNode( $tcn_source ) );
- $df->appendChild( $sfb );
- }
-
- return $tcn;
-}
-
-
-
-sub _tcn_exists {
- my $editor = shift;
- my $tcn = shift;
- my $source = shift;
- my $existing_rec = shift || 0;
-
- if(!$tcn) {return 0;}
-
- $logger->debug("tcn_exists search for tcn $tcn and source $source and id $existing_rec");
-
- # XXX why does the source matter?
-# my $req = $session->request(
-# { tcn_value => $tcn, tcn_source => $source, deleted => 'f' } );
-
- my $recs = $editor->search_biblio_record_entry(
- {tcn_value => $tcn, deleted => 'f', id => {'!=' => $existing_rec}}, {idlist =>1});
-
- if(@$recs) {
- $logger->debug("_tcn_exists is true for tcn : $tcn ($source)");
- return $recs->[0];
- }
-
- $logger->debug("_tcn_exists is false for tcn : $tcn ($source)");
- return 0;
-}
-
-
__PACKAGE__->register_method(
method => "biblio_record_record_metadata",
api_name => "open-ils.cat.biblio.record.metadata.retrieve",
@@ -585,66 +335,7 @@
return \@res
}
-sub _get_id_by_userid {
- my @users = @_;
- my @ids;
-
- my $session = OpenSRF::AppSession->create( "open-ils.cstore" );
- my $request = $session->request(
- "open-ils.cstore.direct.actor.user.search.atomic", { usrname => \@users } );
-
- $request->wait_complete;
- my $response = $request->recv();
- if(!$request->complete) {
- throw OpenSRF::EX::ERROR ("no response from cstore on user retrieve");
- }
-
- if(UNIVERSAL::isa( $response, "Error")){
- throw $response ($response);
- }
-
- for my $u (@{$response->content}) {
- next unless ref($u);
- push @ids, $u->id();
- }
-
- $request->finish;
- $session->disconnect;
- $session->kill_me();
-
- return @ids;
-}
-
-
-# commits metadata objects to the db
-sub _update_record_metadata {
-
- my ($session, @docs ) = @_;
-
- for my $doc (@docs) {
-
- my $user_obj = $doc->{user};
- my $docid = $doc->{docid};
-
- my $request = $session->request(
- "open-ils.storage.direct.biblio.record_entry.retrieve", $docid );
- my $record = $request->gather(1);
-
- my ($id) = _get_id_by_userid($user_obj->usrname);
-
- $record->editor($id);
-
- $request = $session->request(
- "open-ils.storage.direct.biblio.record_entry.update", $record );
- $request->gather(1);
- }
-
- return 1;
-}
-
-
-
__PACKAGE__->register_method(
method => "orgs_for_title",
authoritative => 1,
More information about the open-ils-commits
mailing list