]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/perlmods/OpenILS/Application/Cat/BibCommon.pm
explicity use app::sesssion
[Evergreen.git] / Open-ILS / src / perlmods / OpenILS / Application / Cat / BibCommon.pm
1 package OpenILS::Application::Cat::BibCommon;
2 use strict; use warnings;
3 use OpenILS::Utils::CStoreEditor q/:funcs/;
4 use OpenSRF::Utils::Logger qw($logger);
5 use OpenILS::Application::AppUtils;
6 use OpenILS::Utils::Fieldmapper;
7 use OpenILS::Const qw/:const/;
8 use OpenSRF::AppSession;
9 use OpenILS::Event;
10 my $U = 'OpenILS::Application::AppUtils';
11 my $MARC_NAMESPACE = 'http://www.loc.gov/MARC21/slim';
12
13
14 # ---------------------------------------------------------------------------
15 # Shared bib mangling code.  Do not publish methods from here.
16 # ---------------------------------------------------------------------------
17
18
19 sub biblio_record_replace_marc  {
20         my($class, $e, $recid, $newxml, $source, $fixtcn, $override) = @_;
21
22         my $rec = $e->retrieve_biblio_record_entry($recid)
23                 or return $e->die_event;
24
25     # See if there is a different record in the database that has our TCN value
26     # If we're not updating the TCN, all we care about it the marcdoc
27     # XXX should .update even bother with the tcn_info if it's not going to replace it?
28     # there is the potential for returning a TCN_EXISTS event, even though no replacement happens
29
30         my( $tcn, $tsource, $marcdoc, $evt);
31
32     if($fixtcn or $override) {
33
34             ($tcn, $tsource, $marcdoc, $evt) = 
35                     _find_tcn_info($e, $newxml, $override, $recid);
36
37             return $evt if $evt;
38
39                 $rec->tcn_value($tcn) if ($tcn);
40                 $rec->tcn_source($tsource);
41
42     } else {
43
44         $marcdoc = __make_marc_doc($newxml);
45     }
46
47
48         $rec->source(bib_source_from_name($source)) if $source;
49         $rec->editor($e->requestor->id);
50         $rec->edit_date('now');
51         $rec->marc( $U->entityize( $marcdoc->documentElement->toString ) );
52         $e->update_biblio_record_entry($rec) or return $e->die_event;
53
54     # we don't care about the result, just fire off the request
55     my $ses = OpenSRF::AppSession->create('open-ils.ingest');
56     $ses->request('open-ils.ingest.full.biblio.record', $recid);
57
58         return $rec;
59 }
60
61 sub biblio_record_xml_import {
62         my($class, $e, $xml, $source, $auto_tcn, $override) = @_;
63
64         my( $evt, $tcn, $tcn_source, $marcdoc );
65
66         if( $auto_tcn ) {
67                 # auto_tcn forces a blank TCN value so the DB will have to generate one for us
68                 $marcdoc = __make_marc_doc($xml);
69         } else {
70                 ( $tcn, $tcn_source, $marcdoc, $evt ) = _find_tcn_info($e, $xml, $override);
71                 return $evt if $evt;
72         }
73
74         $logger->info("user ".$e->requestor->id.
75                 " creating new biblio entry with tcn=$tcn and tcn_source $tcn_source");
76
77         my $record = Fieldmapper::biblio::record_entry->new;
78
79         $record->source(bib_source_from_name($source)) if $source;
80         $record->tcn_source($tcn_source);
81         $record->tcn_value($tcn) if ($tcn);
82         $record->creator($e->requestor->id);
83         $record->editor($e->requestor->id);
84         $record->create_date('now');
85         $record->edit_date('now');
86         $record->marc($U->entityize($marcdoc->documentElement->toString));
87
88     $record = $e->create_biblio_record_entry($record) or return $e->die_event;
89         $logger->info("marc create/import created new record ".$record->id);
90
91     # we don't care about the result, just fire off the request
92     my $ses = OpenSRF::AppSession->create('open-ils.ingest');
93     $ses->request('open-ils.ingest.full.biblio.record', $record->id);
94
95         return $record;
96 }
97
98 sub __make_marc_doc {
99         my $xml = shift;
100         my $marcxml = XML::LibXML->new->parse_string($xml);
101         $marcxml->documentElement->setNamespace($MARC_NAMESPACE, "marc", 1 );
102         $marcxml->documentElement->setNamespace($MARC_NAMESPACE);
103         return $marcxml;
104 }
105
106
107 sub _find_tcn_info { 
108         my $editor              = shift;
109         my $xml                 = shift;
110         my $override    = shift;
111         my $existing_rec        = shift || 0;
112
113         # parse the XML
114         my $marcxml = __make_marc_doc($xml);
115
116         my $xpath = '//marc:controlfield[@tag="001"]';
117         my $tcn = $marcxml->documentElement->findvalue($xpath);
118         $logger->info("biblio import located 001 (tcn) value of $tcn");
119
120         $xpath = '//marc:controlfield[@tag="003"]';
121         my $tcn_source = $marcxml->documentElement->findvalue($xpath) || "System Local";
122
123         if(my $rec = _tcn_exists($editor, $tcn, $tcn_source, $existing_rec) ) {
124
125                 my $origtcn = $tcn;
126                 $tcn = find_free_tcn( $marcxml, $editor, $existing_rec );
127
128                 # if we're overriding, try to find a different TCN to use
129                 if( $override ) {
130
131          # XXX Create ALLOW_ALT_TCN permission check support 
132
133                         $logger->info("tcn value $tcn already exists, attempting to override");
134
135                         if(!$tcn) {
136                                 return ( 
137                                         undef, 
138                                         undef, 
139                                         undef,
140                                         OpenILS::Event->new(
141                                                 'OPEN_TCN_NOT_FOUND', 
142                                                         payload => $marcxml->toString())
143                                         );
144                         }
145
146                 } else {
147
148                         $logger->warn("tcn value $origtcn already exists in import/create");
149
150                         # otherwise, return event
151                         return ( 
152                                 undef, 
153                                 undef, 
154                                 undef,
155                                 OpenILS::Event->new( 
156                                         'TCN_EXISTS', payload => { 
157                                                 dup_record      => $rec, 
158                                                 tcn                     => $origtcn,
159                                                 new_tcn         => $tcn
160                                                 }
161                                         )
162                                 );
163                 }
164         }
165
166         return ($tcn, $tcn_source, $marcxml);
167 }
168
169 sub find_free_tcn {
170
171         my $marcxml = shift;
172         my $editor = shift;
173         my $existing_rec = shift;
174
175         my $add_039 = 0;
176
177         my $xpath = '//marc:datafield[@tag="039"]/subfield[@code="a"]';
178         my ($tcn) = $marcxml->documentElement->findvalue($xpath) =~ /(\w+)\s*$/o;
179         $xpath = '//marc:datafield[@tag="039"]/subfield[@code="b"]';
180         my $tcn_source = $marcxml->documentElement->findvalue($xpath) || "System Local";
181
182         if(_tcn_exists($editor, $tcn, $tcn_source, $existing_rec)) {
183                 $tcn = undef;
184         } else {
185                 $add_039++;
186         }
187
188
189         if(!$tcn) {
190                 $xpath = '//marc:datafield[@tag="020"]/subfield[@code="a"]';
191                 ($tcn) = $marcxml->documentElement->findvalue($xpath) =~ /(\w+)\s*$/o;
192                 $tcn_source = "ISBN";
193                 if(_tcn_exists($editor, $tcn, $tcn_source, $existing_rec)) {$tcn = undef;}
194         }
195
196         if(!$tcn) { 
197                 $xpath = '//marc:datafield[@tag="022"]/subfield[@code="a"]';
198                 ($tcn) = $marcxml->documentElement->findvalue($xpath) =~ /(\w+)\s*$/o;
199                 $tcn_source = "ISSN";
200                 if(_tcn_exists($editor, $tcn, $tcn_source, $existing_rec)) {$tcn = undef;}
201         }
202
203         if(!$tcn) {
204                 $xpath = '//marc:datafield[@tag="010"]';
205                 ($tcn) = $marcxml->documentElement->findvalue($xpath) =~ /(\w+)\s*$/o;
206                 $tcn_source = "LCCN";
207                 if(_tcn_exists($editor, $tcn, $tcn_source, $existing_rec)) {$tcn = undef;}
208         }
209
210         if(!$tcn) {
211                 $xpath = '//marc:datafield[@tag="035"]/subfield[@code="a"]';
212                 ($tcn) = $marcxml->documentElement->findvalue($xpath) =~ /(\w+)\s*$/o;
213                 $tcn_source = "System Legacy";
214                 if(_tcn_exists($editor, $tcn, $tcn_source, $existing_rec)) {$tcn = undef;}
215
216                 if($tcn) {
217                         $marcxml->documentElement->removeChild(
218                                 $marcxml->documentElement->findnodes( '//datafield[@tag="035"]' )
219                         );
220                 }
221         }
222
223         return undef unless $tcn;
224
225         if ($add_039) {
226                 my $df = $marcxml->createElementNS( 'http://www.loc.gov/MARC21/slim', 'datafield');
227                 $df->setAttribute( tag => '039' );
228                 $df->setAttribute( ind1 => ' ' );
229                 $df->setAttribute( ind2 => ' ' );
230                 $marcxml->documentElement->appendChild( $df );
231
232                 my $sfa = $marcxml->createElementNS( 'http://www.loc.gov/MARC21/slim', 'subfield');
233                 $sfa->setAttribute( code => 'a' );
234                 $sfa->appendChild( $marcxml->createTextNode( $tcn ) );
235                 $df->appendChild( $sfa );
236
237                 my $sfb = $marcxml->createElementNS( 'http://www.loc.gov/MARC21/slim', 'subfield');
238                 $sfb->setAttribute( code => 'b' );
239                 $sfb->appendChild( $marcxml->createTextNode( $tcn_source ) );
240                 $df->appendChild( $sfb );
241         }
242
243         return $tcn;
244 }
245
246
247
248 sub _tcn_exists {
249         my $editor = shift;
250         my $tcn = shift;
251         my $source = shift;
252         my $existing_rec = shift || 0;
253
254         if(!$tcn) {return 0;}
255
256         $logger->debug("tcn_exists search for tcn $tcn and source $source and id $existing_rec");
257
258         # XXX why does the source matter?
259 #       my $req = $session->request(      
260 #               { tcn_value => $tcn, tcn_source => $source, deleted => 'f' } );
261
262     my $recs = $editor->search_biblio_record_entry(
263         {tcn_value => $tcn, deleted => 'f', id => {'!=' => $existing_rec}}, {idlist =>1});
264
265         if(@$recs) {
266                 $logger->debug("_tcn_exists is true for tcn : $tcn ($source)");
267                 return $recs->[0];
268         }
269
270         $logger->debug("_tcn_exists is false for tcn : $tcn ($source)");
271         return 0;
272 }
273
274