1 package OpenILS::Application::WORM;
2 use base qw/OpenSRF::Application/;
3 use strict; use warnings;
5 use OpenSRF::EX qw/:try/;
7 use OpenILS::Utils::FlatXML;
8 use OpenILS::Utils::Fieldmapper;
13 use Time::HiRes qw(time);
15 my $xml_util = OpenILS::Utils::FlatXML->new();
17 my $parser = XML::LibXML->new();
18 my $xslt = XML::LibXSLT->new();
19 #my $xslt_doc = $parser->parse_file( "/home/miker/cvs/OpenILS/app_server/stylesheets/MARC21slim2MODS.xsl" );
20 my $xslt_doc = $parser->parse_file( "/pines/cvs/ILS/Open-ILS/xsl/MARC21slim2MODS.xsl" );
21 my $mods_sheet = $xslt->parse_stylesheet( $xslt_doc );
28 # __PACKAGE__->method_lookup('i.do.not.exist');
35 # get me from the database
41 "//mods:mods/mods:titleInfo[mods:title and (\@type='abreviated')]",
44 "//mods:mods/mods:titleInfo[mods:title and (\@type='translated')]",
47 "//mods:mods/mods:titleInfo[mods:title and (\@type='uniform')]",
50 "//mods:mods/mods:titleInfo[mods:title and not (\@type)]",
56 "//mods:mods/mods:name[\@type='corporate']/*[local-name()='namePart']".
57 "[../mods:role/mods:text[text()='creator']][1]",
60 "//mods:mods/mods:name[\@type='personal']/*[local-name()='namePart']".
61 "[../mods:role/mods:text[text()='creator']][1]",
64 "//mods:mods/mods:name[\@type='conference']/*[local-name()='namePart']".
65 "[../mods:role/mods:text[text()='creator']][1]",
68 "//mods:mods/mods:name[\@type='personal']/*[local-name()='namePart']",
74 "//mods:mods/*[local-name()='subject']/*[local-name()='geographic']",
77 "//mods:mods/*[local-name()='subject']/*[local-name()='name']",
80 "//mods:mods/*[local-name()='subject']/*[local-name()='temporal']",
83 "//mods:mods/*[local-name()='subject']/*[local-name()='topic']",
87 keyword => { keyword => "//mods:mods/*[not(local-name()='originInfo')]", },
92 # --------------------------------------------------------------------------------
94 __PACKAGE__->register_method(
95 api_name => "open-ils.worm.wormize",
103 my( $self, $client, $docid ) = @_;
105 # step -1: grab the doc from storage
106 my $meth = $self->method_lookup('open-ils.storage.biblio.record_marc.retrieve');
107 my ($marc) = $meth->run($docid);
108 return $self->wormize_marc( $client, $docid, $marc->marc );
112 __PACKAGE__->register_method(
113 api_name => "open-ils.worm.wormize.marc",
122 my( $self, $client, $docid, $xml) = @_;
124 # step 0: turn the doc into marcxml and mods
125 my $marcdoc = $parser->parse_string($xml);
128 # step 1: build the KOHA rows
129 my @ns_list = _marcxml_to_full_rows( $marcdoc );
130 $_->record( $docid ) for (@ns_list);
133 $get_old_fr = $self->method_lookup( 'open-ils.storage.metabib.full_rec.search.record')
134 unless ($get_old_fr);
135 $rm_old_fr = $self->method_lookup( 'open-ils.storage.metabib.full_rec.batch.delete')
138 my ($old_fr) = $get_old_fr->run( $docid );
140 my ($res) = $rm_old_fr->run( @$old_fr );
141 throw OpenSRF::EX::PANIC ("Couldn't remove old metabib::full_rec entries!")
145 # step 1.1: start the WORM transaction
146 my $st_ses = $client->session->create('open-ils.storage');
147 throw OpenSRF::EX::PANIC ("WORM can't connect to the open-is.storage server!")
148 if (!$st_ses->connect);
150 my $xact_req = $st_ses->request('open-ils.storage.transaction.begin');
151 $xact_req->wait_complete;
153 my $resp = $xact_req->recv;
154 throw OpenSRF::EX::PANIC ("Couldn't start a transaction! -- $resp")
155 unless (UNIVERSAL::can($resp, 'content'));
156 throw OpenSRF::EX::PANIC ("Transaction creation failed! -- ".$resp->content)
157 unless ($resp->content);
162 # step 1.2: insert the KOHA style data
163 my $fr_req = $st_ses->request( 'open-ils.storage.metabib.full_rec.batch.create', @ns_list );
164 $fr_req->wait_complete;
166 $resp = $fr_req->recv;
169 unless (UNIVERSAL::can($resp, 'content')) {
170 my $rb = $st_ses->request('open-ils.storage.biblio.transaction.rollback');
172 throw OpenSRF::EX::PANIC ("Couldn't run .full_rec.batch.create! -- $resp")
174 unless ($resp->content) {
175 my $rb = $st_ses->request('open-ils.storage.biblio.transaction.rollback');
177 throw OpenSRF::EX::PANIC ("Didn't create any full_rec entries! -- ".$resp->content)
182 # That's all for now!
183 my $commit_req = $st_ses->request( 'open-ils.storage.transaction.commit' );
184 $commit_req->wait_complete;
186 $resp = $commit_req->recv;
188 unless (UNIVERSAL::can($resp, 'content')) {
189 my $rb = $st_ses->request('open-ils.storage.transaction.rollback');
191 throw OpenSRF::EX::PANIC ("Error commiting transaction! -- $resp")
193 unless ($resp->content) {
194 my $rb = $st_ses->request('open-ils.storage.transaction.rollback');
196 throw OpenSRF::EX::PANIC ("Transaction commit failed! -- ".$resp->content)
199 $commit_req->finish();
202 $st_ses->disconnect();
207 my $mods = $mods_sheet->transform($marcdoc);
209 # step 2: get the MODS based metadata
210 for my $class (keys %$xpathset) {
211 for my $type(keys %{$xpathset->{$class}}) {
212 my $value = _get_field_value( $mods, $xpathset->{$class}->{$type} );
220 # --------------------------------------------------------------------------------
223 sub _marcxml_to_full_rows {
229 my $root = $marcxml->documentElement;
231 for my $tagline ( @{$root->getChildrenByTagName("leader")} ) {
232 next unless $tagline;
234 my $ns = new Fieldmapper::metabib::full_rec;
237 $ns->value( $tagline->textContent );
242 for my $tagline ( @{$root->getChildrenByTagName("controlfield")} ) {
243 next unless $tagline;
245 my $ns = new Fieldmapper::metabib::full_rec;
247 $ns->tag( $tagline->getAttribute( "tag" ) );
248 $ns->value( $tagline->textContent );
253 for my $tagline ( @{$root->getChildrenByTagName("datafield")} ) {
254 next unless $tagline;
256 for my $data ( @{$tagline->getChildrenByTagName("subfield")} ) {
257 next unless $tagline;
259 my $ns = new Fieldmapper::metabib::full_rec;
261 $ns->tag( $tagline->getAttribute( "tag" ) );
262 $ns->ind1( $tagline->getAttribute( "ind1" ) );
263 $ns->ind2( $tagline->getAttribute( "ind2" ) );
264 $ns->subfield( $data->getAttribute( "code" ) );
265 $ns->value( $data->textContent );
273 sub _get_field_value {
275 my( $mods, $xpath ) = @_;
278 my $root = $mods->documentElement;
279 $root->setNamespace( "http://www.loc.gov/mods/", "mods", 1 );
281 # grab the set of matching nodes
282 my @nodes = $root->findnodes( $xpath );
283 for my $value (@nodes) {
285 # grab all children of the node
286 my @children = $value->childNodes();
287 for my $child (@children) {
289 # add the childs content to the growing buffer
290 next if ($string =~ $child->textContent); # uniquify the values
291 $string .= $child->textContent . " ";
294 $string .= $value->textContent . " ";
301 sub modsdoc_to_values {
302 my( $self, $mods ) = @_;
304 for my $class (keys %$xpathset) {
305 $data->{$class} = {};
306 for my $type(keys %{$xpathset->{$class}}) {
307 my $value = _get_field_value( $mods, $xpathset->{$class}->{$type} );
308 $data->{$class}->{$type} = $value;